1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5  * except in compliance with the License. You may obtain a copy of the License at
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the
10  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11  * KIND, either express or implied. See the License for the specific language governing
12  * permissions and limitations under the License.
13  */
14 
15 package com.android.systemui.qs;
16 
17 import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_DEFAULT;
18 import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
19 
20 import static com.google.common.truth.Truth.assertThat;
21 
22 import static junit.framework.Assert.assertEquals;
23 import static junit.framework.Assert.assertNotNull;
24 import static junit.framework.Assert.assertNull;
25 
26 import static org.junit.Assert.assertFalse;
27 import static org.junit.Assert.assertTrue;
28 import static org.mockito.Matchers.any;
29 import static org.mockito.Mockito.mock;
30 import static org.mockito.Mockito.verify;
31 import static org.mockito.Mockito.when;
32 
33 import android.annotation.IdRes;
34 import android.app.AlertDialog;
35 import android.app.admin.DevicePolicyManager;
36 import android.content.ComponentName;
37 import android.content.DialogInterface;
38 import android.content.pm.UserInfo;
39 import android.graphics.drawable.Drawable;
40 import android.graphics.drawable.VectorDrawable;
41 import android.os.Handler;
42 import android.os.Looper;
43 import android.provider.DeviceConfig;
44 import android.provider.Settings;
45 import android.test.suitebuilder.annotation.SmallTest;
46 import android.testing.AndroidTestingRunner;
47 import android.testing.TestableLooper;
48 import android.testing.TestableLooper.RunWithLooper;
49 import android.text.SpannableStringBuilder;
50 import android.view.LayoutInflater;
51 import android.view.View;
52 import android.widget.TextView;
53 
54 import androidx.annotation.Nullable;
55 
56 import com.android.systemui.R;
57 import com.android.systemui.SysuiTestCase;
58 import com.android.systemui.animation.DialogLaunchAnimator;
59 import com.android.systemui.animation.Expandable;
60 import com.android.systemui.broadcast.BroadcastDispatcher;
61 import com.android.systemui.common.shared.model.Icon;
62 import com.android.systemui.plugins.ActivityStarter;
63 import com.android.systemui.qs.footer.domain.model.SecurityButtonConfig;
64 import com.android.systemui.security.data.model.SecurityModel;
65 import com.android.systemui.settings.UserTracker;
66 import com.android.systemui.statusbar.policy.SecurityController;
67 
68 import org.junit.Before;
69 import org.junit.Test;
70 import org.junit.runner.RunWith;
71 import org.mockito.ArgumentCaptor;
72 import org.mockito.Mock;
73 import org.mockito.Mockito;
74 import org.mockito.MockitoAnnotations;
75 
76 /*
77  * Compile and run the whole SystemUI test suite:
78    runtest --path frameworks/base/packages/SystemUI/tests
79  *
80  * Compile and run just this class:
81    runtest --path \
82    frameworks/base/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
83 */
84 
85 @SmallTest
86 @RunWith(AndroidTestingRunner.class)
87 @RunWithLooper
88 public class QSSecurityFooterTest extends SysuiTestCase {
89 
90     private final String MANAGING_ORGANIZATION = "organization";
91     private final String DEVICE_OWNER_PACKAGE = "TestDPC";
92     private final String VPN_PACKAGE = "TestVPN";
93     private final String VPN_PACKAGE_2 = "TestVPN 2";
94     private static final String PARENTAL_CONTROLS_LABEL = "Parental Control App";
95     private static final ComponentName DEVICE_OWNER_COMPONENT =
96             new ComponentName("TestDPC", "Test");
97     private static final int DEFAULT_ICON_ID = R.drawable.ic_info_outline;
98 
99     private QSSecurityFooterUtils mFooterUtils;
100     @Mock
101     private SecurityController mSecurityController;
102     @Mock
103     private UserTracker mUserTracker;
104     @Mock
105     private ActivityStarter mActivityStarter;
106     @Mock
107     private DialogLaunchAnimator mDialogLaunchAnimator;
108     @Mock
109     private BroadcastDispatcher mBroadcastDispatcher;
110 
111     private TestableLooper mTestableLooper;
112 
113     @Before
setUp()114     public void setUp() {
115         MockitoAnnotations.initMocks(this);
116         mTestableLooper = TestableLooper.get(this);
117         Looper looper = mTestableLooper.getLooper();
118         Handler mainHandler = new Handler(looper);
119         // TODO(b/259908270): remove
120         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_DEVICE_POLICY_MANAGER,
121                 DevicePolicyManager.ADD_ISFINANCED_DEVICE_FLAG, "true",
122                 /* makeDefault= */ false);
123         when(mUserTracker.getUserInfo()).thenReturn(mock(UserInfo.class));
124         mFooterUtils = new QSSecurityFooterUtils(getContext(),
125                 getContext().getSystemService(DevicePolicyManager.class), mUserTracker,
126                 mainHandler, mActivityStarter, mSecurityController, looper, mDialogLaunchAnimator);
127 
128         when(mSecurityController.getDeviceOwnerComponentOnAnyUser())
129                 .thenReturn(DEVICE_OWNER_COMPONENT);
130         when(mSecurityController.isFinancedDevice()).thenReturn(false);
131         // TODO(b/259908270): remove
132         when(mSecurityController.getDeviceOwnerType(DEVICE_OWNER_COMPONENT))
133                 .thenReturn(DEVICE_OWNER_TYPE_DEFAULT);
134     }
135 
136     @Nullable
getButtonConfig()137     private SecurityButtonConfig getButtonConfig() {
138         SecurityModel securityModel = SecurityModel.create(mSecurityController);
139         return mFooterUtils.getButtonConfig(securityModel);
140     }
141 
assertIsDefaultIcon(Icon icon)142     private void assertIsDefaultIcon(Icon icon) {
143         assertIsIconResource(icon, DEFAULT_ICON_ID);
144     }
145 
assertIsIconResource(Icon icon, @IdRes int res)146     private void assertIsIconResource(Icon icon, @IdRes int res) {
147         assertThat(icon).isInstanceOf(Icon.Resource.class);
148         assertEquals(res, ((Icon.Resource) icon).getRes());
149     }
150 
assertIsIconDrawable(Icon icon, Drawable drawable)151     private void assertIsIconDrawable(Icon icon, Drawable drawable) {
152         assertThat(icon).isInstanceOf(Icon.Loaded.class);
153         assertEquals(drawable, ((Icon.Loaded) icon).getDrawable());
154     }
155 
156     @Test
testUnmanaged()157     public void testUnmanaged() {
158         when(mSecurityController.isDeviceManaged()).thenReturn(false);
159         when(mSecurityController.isProfileOwnerOfOrganizationOwnedDevice()).thenReturn(false);
160         assertNull(getButtonConfig());
161     }
162 
163     @Test
testManagedNoOwnerName()164     public void testManagedNoOwnerName() {
165         when(mSecurityController.isDeviceManaged()).thenReturn(true);
166         when(mSecurityController.getDeviceOwnerOrganizationName()).thenReturn(null);
167 
168         SecurityButtonConfig buttonConfig = getButtonConfig();
169         assertNotNull(buttonConfig);
170         assertEquals(mContext.getString(R.string.quick_settings_disclosure_management),
171                      buttonConfig.getText());
172         assertIsDefaultIcon(buttonConfig.getIcon());
173     }
174 
175     @Test
testManagedOwnerName()176     public void testManagedOwnerName() {
177         when(mSecurityController.isDeviceManaged()).thenReturn(true);
178         when(mSecurityController.getDeviceOwnerOrganizationName())
179                 .thenReturn(MANAGING_ORGANIZATION);
180 
181         SecurityButtonConfig buttonConfig = getButtonConfig();
182         assertNotNull(buttonConfig);
183         assertEquals(mContext.getString(R.string.quick_settings_disclosure_named_management,
184                         MANAGING_ORGANIZATION),
185                 buttonConfig.getText());
186         assertIsDefaultIcon(buttonConfig.getIcon());
187     }
188 
189     @Test
testManagedFinancedDeviceWithOwnerName()190     public void testManagedFinancedDeviceWithOwnerName() {
191         when(mSecurityController.isDeviceManaged()).thenReturn(true);
192         when(mSecurityController.getDeviceOwnerOrganizationName())
193                 .thenReturn(MANAGING_ORGANIZATION);
194         when(mSecurityController.isFinancedDevice()).thenReturn(true);
195         // TODO(b/259908270): remove
196         when(mSecurityController.getDeviceOwnerType(DEVICE_OWNER_COMPONENT))
197                 .thenReturn(DEVICE_OWNER_TYPE_FINANCED);
198 
199         SecurityButtonConfig buttonConfig = getButtonConfig();
200         assertNotNull(buttonConfig);
201         assertEquals(mContext.getString(
202                         R.string.quick_settings_financed_disclosure_named_management,
203                         MANAGING_ORGANIZATION),
204                 buttonConfig.getText());
205         assertIsDefaultIcon(buttonConfig.getIcon());
206     }
207 
208     @Test
testManagedDemoMode()209     public void testManagedDemoMode() {
210         when(mSecurityController.isDeviceManaged()).thenReturn(true);
211         when(mSecurityController.getDeviceOwnerOrganizationName()).thenReturn(null);
212         final UserInfo mockUserInfo = Mockito.mock(UserInfo.class);
213         when(mockUserInfo.isDemo()).thenReturn(true);
214         when(mUserTracker.getUserInfo()).thenReturn(mockUserInfo);
215         Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVICE_DEMO_MODE, 1);
216 
217         assertNull(getButtonConfig());
218     }
219 
220     @Test
testUntappableView_profileOwnerOfOrgOwnedDevice()221     public void testUntappableView_profileOwnerOfOrgOwnedDevice() {
222         when(mSecurityController.isProfileOwnerOfOrganizationOwnedDevice()).thenReturn(true);
223 
224         SecurityButtonConfig buttonConfig = getButtonConfig();
225         assertNotNull(buttonConfig);
226         assertFalse(buttonConfig.isClickable());
227     }
228 
229     @Test
testTappableView_profileOwnerOfOrgOwnedDevice_networkLoggingEnabled()230     public void testTappableView_profileOwnerOfOrgOwnedDevice_networkLoggingEnabled() {
231         when(mSecurityController.isProfileOwnerOfOrganizationOwnedDevice()).thenReturn(true);
232         when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
233         when(mSecurityController.isWorkProfileOn()).thenReturn(true);
234         when(mSecurityController.hasWorkProfile()).thenReturn(true);
235 
236         SecurityButtonConfig buttonConfig = getButtonConfig();
237         assertNotNull(buttonConfig);
238         assertTrue(buttonConfig.isClickable());
239     }
240 
241     @Test
testUntappableView_profileOwnerOfOrgOwnedDevice_workProfileOff()242     public void testUntappableView_profileOwnerOfOrgOwnedDevice_workProfileOff() {
243         when(mSecurityController.isProfileOwnerOfOrganizationOwnedDevice()).thenReturn(true);
244         when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
245         when(mSecurityController.isWorkProfileOn()).thenReturn(false);
246 
247         SecurityButtonConfig buttonConfig = getButtonConfig();
248         assertNotNull(buttonConfig);
249         assertFalse(buttonConfig.isClickable());
250     }
251 
252     @Test
testNetworkLoggingEnabled_deviceOwner()253     public void testNetworkLoggingEnabled_deviceOwner() {
254         when(mSecurityController.isDeviceManaged()).thenReturn(true);
255         when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
256 
257         SecurityButtonConfig buttonConfig = getButtonConfig();
258         assertNotNull(buttonConfig);
259         assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_monitoring),
260                 buttonConfig.getText());
261         assertIsDefaultIcon(buttonConfig.getIcon());
262 
263         // Same situation, but with organization name set
264         when(mSecurityController.getDeviceOwnerOrganizationName())
265                 .thenReturn(MANAGING_ORGANIZATION);
266         buttonConfig = getButtonConfig();
267         assertNotNull(buttonConfig);
268         assertEquals(mContext.getString(
269                         R.string.quick_settings_disclosure_named_management_monitoring,
270                         MANAGING_ORGANIZATION),
271                 buttonConfig.getText());
272     }
273 
274     @Test
testNetworkLoggingEnabled_managedProfileOwner_workProfileOn()275     public void testNetworkLoggingEnabled_managedProfileOwner_workProfileOn() {
276         when(mSecurityController.hasWorkProfile()).thenReturn(true);
277         when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
278         when(mSecurityController.isWorkProfileOn()).thenReturn(true);
279 
280         SecurityButtonConfig buttonConfig = getButtonConfig();
281         assertNotNull(buttonConfig);
282         assertEquals(mContext.getString(
283                         R.string.quick_settings_disclosure_managed_profile_network_activity),
284                 buttonConfig.getText());
285     }
286 
287     @Test
testNetworkLoggingEnabled_managedProfileOwner_workProfileOff()288     public void testNetworkLoggingEnabled_managedProfileOwner_workProfileOff() {
289         when(mSecurityController.hasWorkProfile()).thenReturn(true);
290         when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
291         when(mSecurityController.isWorkProfileOn()).thenReturn(false);
292 
293         assertNull(getButtonConfig());
294     }
295 
296     @Test
testManagedCACertsInstalled()297     public void testManagedCACertsInstalled() {
298         when(mSecurityController.isDeviceManaged()).thenReturn(true);
299         when(mSecurityController.hasCACertInCurrentUser()).thenReturn(true);
300 
301         SecurityButtonConfig buttonConfig = getButtonConfig();
302         assertNotNull(buttonConfig);
303         assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_monitoring),
304                 buttonConfig.getText());
305     }
306 
307     @Test
testManagedOneVpnEnabled()308     public void testManagedOneVpnEnabled() {
309         when(mSecurityController.isDeviceManaged()).thenReturn(true);
310         when(mSecurityController.isVpnEnabled()).thenReturn(true);
311         when(mSecurityController.getPrimaryVpnName()).thenReturn(VPN_PACKAGE);
312 
313         SecurityButtonConfig buttonConfig = getButtonConfig();
314         assertNotNull(buttonConfig);
315         assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_named_vpn,
316                         VPN_PACKAGE),
317                 buttonConfig.getText());
318         assertIsIconResource(buttonConfig.getIcon(), R.drawable.stat_sys_vpn_ic);
319 
320         // Same situation, but with organization name set
321         when(mSecurityController.getDeviceOwnerOrganizationName())
322                 .thenReturn(MANAGING_ORGANIZATION);
323         buttonConfig = getButtonConfig();
324         assertNotNull(buttonConfig);
325         assertEquals(mContext.getString(
326                         R.string.quick_settings_disclosure_named_management_named_vpn,
327                         MANAGING_ORGANIZATION, VPN_PACKAGE),
328                 buttonConfig.getText());
329     }
330 
331     @Test
testManagedTwoVpnsEnabled()332     public void testManagedTwoVpnsEnabled() {
333         when(mSecurityController.isDeviceManaged()).thenReturn(true);
334         when(mSecurityController.isVpnEnabled()).thenReturn(true);
335         when(mSecurityController.getPrimaryVpnName()).thenReturn(VPN_PACKAGE);
336         when(mSecurityController.getWorkProfileVpnName()).thenReturn(VPN_PACKAGE_2);
337 
338         SecurityButtonConfig buttonConfig = getButtonConfig();
339         assertNotNull(buttonConfig);
340         assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_vpns),
341                      buttonConfig.getText());
342         assertIsIconResource(buttonConfig.getIcon(), R.drawable.stat_sys_vpn_ic);
343 
344         // Same situation, but with organization name set
345         when(mSecurityController.getDeviceOwnerOrganizationName())
346                 .thenReturn(MANAGING_ORGANIZATION);
347         buttonConfig = getButtonConfig();
348         assertNotNull(buttonConfig);
349         assertEquals(mContext.getString(R.string.quick_settings_disclosure_named_management_vpns,
350                                         MANAGING_ORGANIZATION),
351                      buttonConfig.getText());
352     }
353 
354     @Test
testNetworkLoggingAndVpnEnabled()355     public void testNetworkLoggingAndVpnEnabled() {
356         when(mSecurityController.isDeviceManaged()).thenReturn(true);
357         when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
358         when(mSecurityController.isVpnEnabled()).thenReturn(true);
359         when(mSecurityController.getPrimaryVpnName()).thenReturn("VPN Test App");
360 
361         SecurityButtonConfig buttonConfig = getButtonConfig();
362         assertNotNull(buttonConfig);
363         assertIsIconResource(buttonConfig.getIcon(), R.drawable.stat_sys_vpn_ic);
364         assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_monitoring),
365                 buttonConfig.getText());
366     }
367 
368     @Test
testWorkProfileCACertsInstalled_workProfileOn()369     public void testWorkProfileCACertsInstalled_workProfileOn() {
370         when(mSecurityController.isDeviceManaged()).thenReturn(false);
371         when(mSecurityController.hasCACertInWorkProfile()).thenReturn(true);
372         when(mSecurityController.isWorkProfileOn()).thenReturn(true);
373 
374         SecurityButtonConfig buttonConfig = getButtonConfig();
375         assertNotNull(buttonConfig);
376         assertIsDefaultIcon(buttonConfig.getIcon());
377         assertEquals(mContext.getString(
378                              R.string.quick_settings_disclosure_managed_profile_monitoring),
379                      buttonConfig.getText());
380 
381         // Same situation, but with organization name set
382         when(mSecurityController.getWorkProfileOrganizationName())
383                 .thenReturn(MANAGING_ORGANIZATION);
384         buttonConfig = getButtonConfig();
385         assertNotNull(buttonConfig);
386         assertEquals(mContext.getString(
387                              R.string.quick_settings_disclosure_named_managed_profile_monitoring,
388                              MANAGING_ORGANIZATION),
389                      buttonConfig.getText());
390     }
391 
392     @Test
testWorkProfileCACertsInstalled_workProfileOff()393     public void testWorkProfileCACertsInstalled_workProfileOff() {
394         when(mSecurityController.isDeviceManaged()).thenReturn(false);
395         when(mSecurityController.hasCACertInWorkProfile()).thenReturn(true);
396         when(mSecurityController.isWorkProfileOn()).thenReturn(false);
397 
398         assertNull(getButtonConfig());
399     }
400 
401     @Test
testCACertsInstalled()402     public void testCACertsInstalled() {
403         when(mSecurityController.isDeviceManaged()).thenReturn(false);
404         when(mSecurityController.hasCACertInCurrentUser()).thenReturn(true);
405 
406         SecurityButtonConfig buttonConfig = getButtonConfig();
407         assertNotNull(buttonConfig);
408         assertIsDefaultIcon(buttonConfig.getIcon());
409         assertEquals(mContext.getString(R.string.quick_settings_disclosure_monitoring),
410                      buttonConfig.getText());
411     }
412 
413     @Test
testTwoVpnsEnabled()414     public void testTwoVpnsEnabled() {
415         when(mSecurityController.isVpnEnabled()).thenReturn(true);
416         when(mSecurityController.getPrimaryVpnName()).thenReturn(VPN_PACKAGE);
417         when(mSecurityController.getWorkProfileVpnName()).thenReturn(VPN_PACKAGE_2);
418 
419         SecurityButtonConfig buttonConfig = getButtonConfig();
420         assertNotNull(buttonConfig);
421         assertIsIconResource(buttonConfig.getIcon(), R.drawable.stat_sys_vpn_ic);
422         assertEquals(mContext.getString(R.string.quick_settings_disclosure_vpns),
423                      buttonConfig.getText());
424     }
425 
426     @Test
testWorkProfileVpnEnabled_workProfileOn()427     public void testWorkProfileVpnEnabled_workProfileOn() {
428         when(mSecurityController.isVpnEnabled()).thenReturn(true);
429         when(mSecurityController.getWorkProfileVpnName()).thenReturn(VPN_PACKAGE_2);
430         when(mSecurityController.isWorkProfileOn()).thenReturn(true);
431 
432         SecurityButtonConfig buttonConfig = getButtonConfig();
433         assertNotNull(buttonConfig);
434         assertIsIconResource(buttonConfig.getIcon(), R.drawable.stat_sys_vpn_ic);
435         assertEquals(mContext.getString(
436                              R.string.quick_settings_disclosure_managed_profile_named_vpn,
437                              VPN_PACKAGE_2),
438                      buttonConfig.getText());
439     }
440 
441     @Test
testWorkProfileVpnEnabled_workProfileOff()442     public void testWorkProfileVpnEnabled_workProfileOff() {
443         when(mSecurityController.isVpnEnabled()).thenReturn(true);
444         when(mSecurityController.getWorkProfileVpnName()).thenReturn(VPN_PACKAGE_2);
445         when(mSecurityController.isWorkProfileOn()).thenReturn(false);
446 
447         assertNull(getButtonConfig());
448     }
449 
450     @Test
testProfileOwnerOfOrganizationOwnedDeviceNoName()451     public void testProfileOwnerOfOrganizationOwnedDeviceNoName() {
452         when(mSecurityController.isProfileOwnerOfOrganizationOwnedDevice()).thenReturn(true);
453 
454         SecurityButtonConfig buttonConfig = getButtonConfig();
455         assertNotNull(buttonConfig);
456         assertEquals(mContext.getString(
457                 R.string.quick_settings_disclosure_management),
458                 buttonConfig.getText());
459     }
460 
461     @Test
testProfileOwnerOfOrganizationOwnedDeviceWithName()462     public void testProfileOwnerOfOrganizationOwnedDeviceWithName() {
463         when(mSecurityController.isProfileOwnerOfOrganizationOwnedDevice()).thenReturn(true);
464         when(mSecurityController.getWorkProfileOrganizationName())
465                 .thenReturn(MANAGING_ORGANIZATION);
466 
467         SecurityButtonConfig buttonConfig = getButtonConfig();
468         assertNotNull(buttonConfig);
469         assertEquals(mContext.getString(
470                 R.string.quick_settings_disclosure_named_management,
471                 MANAGING_ORGANIZATION),
472                 buttonConfig.getText());
473     }
474 
475     @Test
testVpnEnabled()476     public void testVpnEnabled() {
477         when(mSecurityController.isVpnEnabled()).thenReturn(true);
478         when(mSecurityController.getPrimaryVpnName()).thenReturn(VPN_PACKAGE);
479 
480         SecurityButtonConfig buttonConfig = getButtonConfig();
481         assertNotNull(buttonConfig);
482         assertIsIconResource(buttonConfig.getIcon(), R.drawable.stat_sys_vpn_ic);
483         assertEquals(mContext.getString(R.string.quick_settings_disclosure_named_vpn,
484                                         VPN_PACKAGE),
485                      buttonConfig.getText());
486 
487         when(mSecurityController.hasWorkProfile()).thenReturn(true);
488         buttonConfig = getButtonConfig();
489         assertNotNull(buttonConfig);
490         assertEquals(mContext.getString(
491                              R.string.quick_settings_disclosure_personal_profile_named_vpn,
492                              VPN_PACKAGE),
493                      buttonConfig.getText());
494     }
495 
496     @Test
testGetManagementTitleForNonFinancedDevice()497     public void testGetManagementTitleForNonFinancedDevice() {
498         when(mSecurityController.isDeviceManaged()).thenReturn(true);
499 
500         assertEquals(mContext.getString(R.string.monitoring_title_device_owned),
501                 mFooterUtils.getManagementTitle(MANAGING_ORGANIZATION));
502     }
503 
504     @Test
testGetManagementTitleForFinancedDevice()505     public void testGetManagementTitleForFinancedDevice() {
506         when(mSecurityController.isDeviceManaged()).thenReturn(true);
507         when(mSecurityController.isFinancedDevice()).thenReturn(true);
508         // TODO(b/259908270): remove
509         when(mSecurityController.getDeviceOwnerType(DEVICE_OWNER_COMPONENT))
510                 .thenReturn(DEVICE_OWNER_TYPE_FINANCED);
511 
512         assertEquals(mContext.getString(R.string.monitoring_title_financed_device,
513                 MANAGING_ORGANIZATION),
514                 mFooterUtils.getManagementTitle(MANAGING_ORGANIZATION));
515     }
516 
517     @Test
testGetManagementMessage_noManagement()518     public void testGetManagementMessage_noManagement() {
519         assertEquals(null, mFooterUtils.getManagementMessage(
520                 /* isDeviceManaged= */ false, MANAGING_ORGANIZATION));
521     }
522 
523     @Test
testGetManagementMessage_deviceOwner()524     public void testGetManagementMessage_deviceOwner() {
525         assertEquals(mContext.getString(R.string.monitoring_description_named_management,
526                                         MANAGING_ORGANIZATION),
527                 mFooterUtils.getManagementMessage(
528                              /* isDeviceManaged= */ true, MANAGING_ORGANIZATION));
529         assertEquals(mContext.getString(R.string.monitoring_description_management),
530                 mFooterUtils.getManagementMessage(
531                              /* isDeviceManaged= */ true,
532                              /* organizationName= */ null));
533     }
534 
535     @Test
testGetManagementMessage_deviceOwner_asFinancedDevice()536     public void testGetManagementMessage_deviceOwner_asFinancedDevice() {
537         when(mSecurityController.isDeviceManaged()).thenReturn(true);
538         when(mSecurityController.isFinancedDevice()).thenReturn(true);
539         // TODO(b/259908270): remove
540         when(mSecurityController.getDeviceOwnerType(DEVICE_OWNER_COMPONENT))
541                 .thenReturn(DEVICE_OWNER_TYPE_FINANCED);
542 
543         assertEquals(mContext.getString(R.string.monitoring_financed_description_named_management,
544                 MANAGING_ORGANIZATION, MANAGING_ORGANIZATION),
545                 mFooterUtils.getManagementMessage(
546                         /* isDeviceManaged= */ true, MANAGING_ORGANIZATION));
547     }
548 
549     @Test
testGetCaCertsMessage()550     public void testGetCaCertsMessage() {
551         assertEquals(null, mFooterUtils.getCaCertsMessage(true, false, false));
552         assertEquals(null, mFooterUtils.getCaCertsMessage(false, false, false));
553         assertEquals(mContext.getString(R.string.monitoring_description_management_ca_certificate),
554                 mFooterUtils.getCaCertsMessage(true, true, true));
555         assertEquals(mContext.getString(R.string.monitoring_description_management_ca_certificate),
556                 mFooterUtils.getCaCertsMessage(true, false, true));
557         assertEquals(mContext.getString(
558                          R.string.monitoring_description_managed_profile_ca_certificate),
559                 mFooterUtils.getCaCertsMessage(false, false, true));
560         assertEquals(mContext.getString(
561                          R.string.monitoring_description_ca_certificate),
562                 mFooterUtils.getCaCertsMessage(false, true, false));
563     }
564 
565     @Test
testGetNetworkLoggingMessage()566     public void testGetNetworkLoggingMessage() {
567         // Test network logging message on a device with a device owner.
568         // Network traffic may be monitored on the device.
569         assertEquals(null, mFooterUtils.getNetworkLoggingMessage(true, false));
570         assertEquals(mContext.getString(R.string.monitoring_description_management_network_logging),
571                 mFooterUtils.getNetworkLoggingMessage(true, true));
572 
573         // Test network logging message on a device with a managed profile owner
574         // Network traffic may be monitored on the work profile.
575         assertEquals(null, mFooterUtils.getNetworkLoggingMessage(false, false));
576         assertEquals(
577                 mContext.getString(R.string.monitoring_description_managed_profile_network_logging),
578                 mFooterUtils.getNetworkLoggingMessage(false, true));
579     }
580 
581     @Test
testGetVpnMessage()582     public void testGetVpnMessage() {
583         assertEquals(null, mFooterUtils.getVpnMessage(true, true, null, null));
584         assertEquals(addLink(mContext.getString(R.string.monitoring_description_two_named_vpns,
585                                  VPN_PACKAGE, VPN_PACKAGE_2)),
586                 mFooterUtils.getVpnMessage(true, true, VPN_PACKAGE, VPN_PACKAGE_2));
587         assertEquals(addLink(mContext.getString(R.string.monitoring_description_two_named_vpns,
588                                  VPN_PACKAGE, VPN_PACKAGE_2)),
589                 mFooterUtils.getVpnMessage(false, true, VPN_PACKAGE, VPN_PACKAGE_2));
590         assertEquals(addLink(mContext.getString(
591                 R.string.monitoring_description_managed_device_named_vpn, VPN_PACKAGE)),
592                 mFooterUtils.getVpnMessage(true, false, VPN_PACKAGE, null));
593         assertEquals(addLink(mContext.getString(R.string.monitoring_description_named_vpn,
594                                  VPN_PACKAGE)),
595                 mFooterUtils.getVpnMessage(false, false, VPN_PACKAGE, null));
596         assertEquals(addLink(mContext.getString(
597                 R.string.monitoring_description_managed_device_named_vpn, VPN_PACKAGE_2)),
598                 mFooterUtils.getVpnMessage(true, true, null, VPN_PACKAGE_2));
599         assertEquals(addLink(mContext.getString(
600                                  R.string.monitoring_description_managed_profile_named_vpn,
601                                  VPN_PACKAGE_2)),
602                 mFooterUtils.getVpnMessage(false, true, null, VPN_PACKAGE_2));
603         assertEquals(addLink(mContext.getString(
604                                  R.string.monitoring_description_personal_profile_named_vpn,
605                                  VPN_PACKAGE)),
606                 mFooterUtils.getVpnMessage(false, true, VPN_PACKAGE, null));
607     }
608 
609     @Test
testConfigSubtitleVisibility()610     public void testConfigSubtitleVisibility() {
611         View view = LayoutInflater.from(mContext)
612                 .inflate(R.layout.quick_settings_footer_dialog, null);
613 
614         // Device Management subtitle should be shown when there is Device Management section only
615         // Other sections visibility will be set somewhere else so it will not be tested here
616         mFooterUtils.configSubtitleVisibility(true, false, false, false, view);
617         assertEquals(View.VISIBLE,
618                 view.findViewById(R.id.device_management_subtitle).getVisibility());
619 
620         // If there are multiple sections, all subtitles should be shown
621         mFooterUtils.configSubtitleVisibility(true, true, false, false, view);
622         assertEquals(View.VISIBLE,
623                 view.findViewById(R.id.device_management_subtitle).getVisibility());
624         assertEquals(View.VISIBLE,
625                 view.findViewById(R.id.ca_certs_subtitle).getVisibility());
626 
627         // If there are multiple sections, all subtitles should be shown
628         mFooterUtils.configSubtitleVisibility(true, true, true, true, view);
629         assertEquals(View.VISIBLE,
630                 view.findViewById(R.id.device_management_subtitle).getVisibility());
631         assertEquals(View.VISIBLE,
632                 view.findViewById(R.id.ca_certs_subtitle).getVisibility());
633         assertEquals(View.VISIBLE,
634                 view.findViewById(R.id.network_logging_subtitle).getVisibility());
635         assertEquals(View.VISIBLE,
636                 view.findViewById(R.id.vpn_subtitle).getVisibility());
637 
638         // If there are multiple sections, all subtitles should be shown, event if there is no
639         // Device Management section
640         mFooterUtils.configSubtitleVisibility(false, true, true, true, view);
641         assertEquals(View.VISIBLE,
642                 view.findViewById(R.id.ca_certs_subtitle).getVisibility());
643         assertEquals(View.VISIBLE,
644                 view.findViewById(R.id.network_logging_subtitle).getVisibility());
645         assertEquals(View.VISIBLE,
646                 view.findViewById(R.id.vpn_subtitle).getVisibility());
647 
648         // If there is only 1 section, the title should be hidden
649         mFooterUtils.configSubtitleVisibility(false, true, false, false, view);
650         assertEquals(View.GONE,
651                 view.findViewById(R.id.ca_certs_subtitle).getVisibility());
652         mFooterUtils.configSubtitleVisibility(false, false, true, false, view);
653         assertEquals(View.GONE,
654                 view.findViewById(R.id.network_logging_subtitle).getVisibility());
655         mFooterUtils.configSubtitleVisibility(false, false, false, true, view);
656         assertEquals(View.GONE,
657                 view.findViewById(R.id.vpn_subtitle).getVisibility());
658     }
659 
660     @Test
testParentalControls()661     public void testParentalControls() {
662         // Make sure the security footer is visible, so that the images are updated.
663         when(mSecurityController.isProfileOwnerOfOrganizationOwnedDevice()).thenReturn(true);
664         when(mSecurityController.isParentalControlsEnabled()).thenReturn(true);
665 
666         // We use the default icon when there is no admin icon.
667         when(mSecurityController.getIcon(any())).thenReturn(null);
668         SecurityButtonConfig buttonConfig = getButtonConfig();
669         assertEquals(mContext.getString(R.string.quick_settings_disclosure_parental_controls),
670                 buttonConfig.getText());
671         assertIsDefaultIcon(buttonConfig.getIcon());
672 
673         Drawable testDrawable = new VectorDrawable();
674         when(mSecurityController.getIcon(any())).thenReturn(testDrawable);
675         assertNotNull(mSecurityController.getIcon(null));
676 
677         buttonConfig = getButtonConfig();
678         assertNotNull(buttonConfig);
679         assertEquals(mContext.getString(R.string.quick_settings_disclosure_parental_controls),
680                 buttonConfig.getText());
681         assertIsIconDrawable(buttonConfig.getIcon(), testDrawable);
682 
683         // Ensure the primary icon is back to default after parental controls are gone
684         when(mSecurityController.isParentalControlsEnabled()).thenReturn(false);
685         buttonConfig = getButtonConfig();
686         assertNotNull(buttonConfig);
687         assertIsDefaultIcon(buttonConfig.getIcon());
688     }
689 
690     @Test
testParentalControlsDialog()691     public void testParentalControlsDialog() {
692         when(mSecurityController.isParentalControlsEnabled()).thenReturn(true);
693         when(mSecurityController.getLabel(any())).thenReturn(PARENTAL_CONTROLS_LABEL);
694 
695         View view = mFooterUtils.createDialogView(getContext());
696         TextView textView = (TextView) view.findViewById(R.id.parental_controls_title);
697         assertEquals(PARENTAL_CONTROLS_LABEL, textView.getText());
698     }
699 
700     @Test
testCreateDialogViewForFinancedDevice()701     public void testCreateDialogViewForFinancedDevice() {
702         when(mSecurityController.isDeviceManaged()).thenReturn(true);
703         when(mSecurityController.getDeviceOwnerOrganizationName())
704                 .thenReturn(MANAGING_ORGANIZATION);
705         when(mSecurityController.isFinancedDevice()).thenReturn(true);
706         // TODO(b/259908270): remove
707         when(mSecurityController.getDeviceOwnerType(DEVICE_OWNER_COMPONENT))
708                 .thenReturn(DEVICE_OWNER_TYPE_FINANCED);
709 
710         View view = mFooterUtils.createDialogView(getContext());
711 
712         TextView managementSubtitle = view.findViewById(R.id.device_management_subtitle);
713         assertEquals(View.VISIBLE, managementSubtitle.getVisibility());
714         assertEquals(mContext.getString(R.string.monitoring_title_financed_device,
715                 MANAGING_ORGANIZATION), managementSubtitle.getText());
716         TextView managementMessage = view.findViewById(R.id.device_management_warning);
717         assertEquals(View.VISIBLE, managementMessage.getVisibility());
718         assertEquals(mContext.getString(R.string.monitoring_financed_description_named_management,
719                 MANAGING_ORGANIZATION, MANAGING_ORGANIZATION), managementMessage.getText());
720         assertEquals(mContext.getString(R.string.monitoring_button_view_policies),
721                 mFooterUtils.getSettingsButton());
722     }
723 
724     @Test
testFinancedDeviceUsesSettingsButtonText()725     public void testFinancedDeviceUsesSettingsButtonText() {
726         when(mSecurityController.isDeviceManaged()).thenReturn(true);
727         when(mSecurityController.getDeviceOwnerOrganizationName())
728                 .thenReturn(MANAGING_ORGANIZATION);
729         when(mSecurityController.isFinancedDevice()).thenReturn(true);
730         // TODO(b/259908270): remove
731         when(mSecurityController.getDeviceOwnerType(DEVICE_OWNER_COMPONENT))
732                 .thenReturn(DEVICE_OWNER_TYPE_FINANCED);
733 
734         Expandable expandable = mock(Expandable.class);
735         when(expandable.dialogLaunchController(any())).thenReturn(
736                 mock(DialogLaunchAnimator.Controller.class));
737         mFooterUtils.showDeviceMonitoringDialog(getContext(), expandable);
738         ArgumentCaptor<AlertDialog> dialogCaptor = ArgumentCaptor.forClass(AlertDialog.class);
739 
740         mTestableLooper.processAllMessages();
741         verify(mDialogLaunchAnimator).show(dialogCaptor.capture(), any());
742 
743         AlertDialog dialog = dialogCaptor.getValue();
744         dialog.create();
745 
746         assertEquals(mFooterUtils.getSettingsButton(),
747                 dialog.getButton(DialogInterface.BUTTON_NEGATIVE).getText());
748 
749         dialog.dismiss();
750     }
751 
addLink(CharSequence description)752     private CharSequence addLink(CharSequence description) {
753         final SpannableStringBuilder message = new SpannableStringBuilder();
754         message.append(description);
755         message.append(mContext.getString(R.string.monitoring_description_vpn_settings_separator));
756         message.append(mContext.getString(R.string.monitoring_description_vpn_settings),
757                 mFooterUtils.new VpnSpan(), 0);
758         return message;
759     }
760 }
761