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.testing.TestableLooper;
46 import android.testing.TestableLooper.RunWithLooper;
47 import android.text.SpannableStringBuilder;
48 import android.view.LayoutInflater;
49 import android.view.View;
50 import android.widget.TextView;
51 
52 import androidx.annotation.Nullable;
53 import androidx.test.ext.junit.runners.AndroidJUnit4;
54 import androidx.test.filters.SmallTest;
55 
56 import com.android.systemui.SysuiTestCase;
57 import com.android.systemui.animation.DialogTransitionAnimator;
58 import com.android.systemui.animation.Expandable;
59 import com.android.systemui.broadcast.BroadcastDispatcher;
60 import com.android.systemui.common.shared.model.Icon;
61 import com.android.systemui.plugins.ActivityStarter;
62 import com.android.systemui.qs.footer.domain.model.SecurityButtonConfig;
63 import com.android.systemui.res.R;
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(AndroidJUnit4.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 DialogTransitionAnimator mDialogTransitionAnimator;
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,
127                 mDialogTransitionAnimator);
128 
129         when(mSecurityController.getDeviceOwnerComponentOnAnyUser())
130                 .thenReturn(DEVICE_OWNER_COMPONENT);
131         when(mSecurityController.isFinancedDevice()).thenReturn(false);
132         // TODO(b/259908270): remove
133         when(mSecurityController.getDeviceOwnerType(DEVICE_OWNER_COMPONENT))
134                 .thenReturn(DEVICE_OWNER_TYPE_DEFAULT);
135     }
136 
137     @Nullable
getButtonConfig()138     private SecurityButtonConfig getButtonConfig() {
139         SecurityModel securityModel = SecurityModel.create(mSecurityController);
140         return mFooterUtils.getButtonConfig(securityModel);
141     }
142 
assertIsDefaultIcon(Icon icon)143     private void assertIsDefaultIcon(Icon icon) {
144         assertIsIconResource(icon, DEFAULT_ICON_ID);
145     }
146 
assertIsIconResource(Icon icon, @IdRes int res)147     private void assertIsIconResource(Icon icon, @IdRes int res) {
148         assertThat(icon).isInstanceOf(Icon.Resource.class);
149         assertEquals(res, ((Icon.Resource) icon).getRes());
150     }
151 
assertIsIconDrawable(Icon icon, Drawable drawable)152     private void assertIsIconDrawable(Icon icon, Drawable drawable) {
153         assertThat(icon).isInstanceOf(Icon.Loaded.class);
154         assertEquals(drawable, ((Icon.Loaded) icon).getDrawable());
155     }
156 
157     @Test
testUnmanaged()158     public void testUnmanaged() {
159         when(mSecurityController.isDeviceManaged()).thenReturn(false);
160         when(mSecurityController.isProfileOwnerOfOrganizationOwnedDevice()).thenReturn(false);
161         assertNull(getButtonConfig());
162     }
163 
164     @Test
testManagedNoOwnerName()165     public void testManagedNoOwnerName() {
166         when(mSecurityController.isDeviceManaged()).thenReturn(true);
167         when(mSecurityController.getDeviceOwnerOrganizationName()).thenReturn(null);
168 
169         SecurityButtonConfig buttonConfig = getButtonConfig();
170         assertNotNull(buttonConfig);
171         assertEquals(mContext.getString(R.string.quick_settings_disclosure_management),
172                      buttonConfig.getText());
173         assertIsDefaultIcon(buttonConfig.getIcon());
174     }
175 
176     @Test
testManagedOwnerName()177     public void testManagedOwnerName() {
178         when(mSecurityController.isDeviceManaged()).thenReturn(true);
179         when(mSecurityController.getDeviceOwnerOrganizationName())
180                 .thenReturn(MANAGING_ORGANIZATION);
181 
182         SecurityButtonConfig buttonConfig = getButtonConfig();
183         assertNotNull(buttonConfig);
184         assertEquals(mContext.getString(R.string.quick_settings_disclosure_named_management,
185                         MANAGING_ORGANIZATION),
186                 buttonConfig.getText());
187         assertIsDefaultIcon(buttonConfig.getIcon());
188     }
189 
190     @Test
testManagedFinancedDeviceWithOwnerName()191     public void testManagedFinancedDeviceWithOwnerName() {
192         when(mSecurityController.isDeviceManaged()).thenReturn(true);
193         when(mSecurityController.getDeviceOwnerOrganizationName())
194                 .thenReturn(MANAGING_ORGANIZATION);
195         when(mSecurityController.isFinancedDevice()).thenReturn(true);
196         // TODO(b/259908270): remove
197         when(mSecurityController.getDeviceOwnerType(DEVICE_OWNER_COMPONENT))
198                 .thenReturn(DEVICE_OWNER_TYPE_FINANCED);
199 
200         SecurityButtonConfig buttonConfig = getButtonConfig();
201         assertNotNull(buttonConfig);
202         assertEquals(mContext.getString(
203                         R.string.quick_settings_financed_disclosure_named_management,
204                         MANAGING_ORGANIZATION),
205                 buttonConfig.getText());
206         assertIsDefaultIcon(buttonConfig.getIcon());
207     }
208 
209     @Test
testManagedDemoMode()210     public void testManagedDemoMode() {
211         when(mSecurityController.isDeviceManaged()).thenReturn(true);
212         when(mSecurityController.getDeviceOwnerOrganizationName()).thenReturn(null);
213         final UserInfo mockUserInfo = Mockito.mock(UserInfo.class);
214         when(mockUserInfo.isDemo()).thenReturn(true);
215         when(mUserTracker.getUserInfo()).thenReturn(mockUserInfo);
216         Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVICE_DEMO_MODE, 1);
217 
218         assertNull(getButtonConfig());
219     }
220 
221     @Test
testUntappableView_profileOwnerOfOrgOwnedDevice()222     public void testUntappableView_profileOwnerOfOrgOwnedDevice() {
223         when(mSecurityController.isProfileOwnerOfOrganizationOwnedDevice()).thenReturn(true);
224 
225         SecurityButtonConfig buttonConfig = getButtonConfig();
226         assertNotNull(buttonConfig);
227         assertFalse(buttonConfig.isClickable());
228     }
229 
230     @Test
testTappableView_profileOwnerOfOrgOwnedDevice_networkLoggingEnabled()231     public void testTappableView_profileOwnerOfOrgOwnedDevice_networkLoggingEnabled() {
232         when(mSecurityController.isProfileOwnerOfOrganizationOwnedDevice()).thenReturn(true);
233         when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
234         when(mSecurityController.isWorkProfileOn()).thenReturn(true);
235         when(mSecurityController.hasWorkProfile()).thenReturn(true);
236 
237         SecurityButtonConfig buttonConfig = getButtonConfig();
238         assertNotNull(buttonConfig);
239         assertTrue(buttonConfig.isClickable());
240     }
241 
242     @Test
testUntappableView_profileOwnerOfOrgOwnedDevice_workProfileOff()243     public void testUntappableView_profileOwnerOfOrgOwnedDevice_workProfileOff() {
244         when(mSecurityController.isProfileOwnerOfOrganizationOwnedDevice()).thenReturn(true);
245         when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
246         when(mSecurityController.isWorkProfileOn()).thenReturn(false);
247 
248         SecurityButtonConfig buttonConfig = getButtonConfig();
249         assertNotNull(buttonConfig);
250         assertFalse(buttonConfig.isClickable());
251     }
252 
253     @Test
testNetworkLoggingEnabled_deviceOwner()254     public void testNetworkLoggingEnabled_deviceOwner() {
255         when(mSecurityController.isDeviceManaged()).thenReturn(true);
256         when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
257 
258         SecurityButtonConfig buttonConfig = getButtonConfig();
259         assertNotNull(buttonConfig);
260         assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_monitoring),
261                 buttonConfig.getText());
262         assertIsDefaultIcon(buttonConfig.getIcon());
263 
264         // Same situation, but with organization name set
265         when(mSecurityController.getDeviceOwnerOrganizationName())
266                 .thenReturn(MANAGING_ORGANIZATION);
267         buttonConfig = getButtonConfig();
268         assertNotNull(buttonConfig);
269         assertEquals(mContext.getString(
270                         R.string.quick_settings_disclosure_named_management_monitoring,
271                         MANAGING_ORGANIZATION),
272                 buttonConfig.getText());
273     }
274 
275     @Test
testNetworkLoggingEnabled_managedProfileOwner_workProfileOn()276     public void testNetworkLoggingEnabled_managedProfileOwner_workProfileOn() {
277         when(mSecurityController.hasWorkProfile()).thenReturn(true);
278         when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
279         when(mSecurityController.isWorkProfileOn()).thenReturn(true);
280 
281         SecurityButtonConfig buttonConfig = getButtonConfig();
282         assertNotNull(buttonConfig);
283         assertEquals(mContext.getString(
284                         R.string.quick_settings_disclosure_managed_profile_network_activity),
285                 buttonConfig.getText());
286     }
287 
288     @Test
testNetworkLoggingEnabled_managedProfileOwner_workProfileOff()289     public void testNetworkLoggingEnabled_managedProfileOwner_workProfileOff() {
290         when(mSecurityController.hasWorkProfile()).thenReturn(true);
291         when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
292         when(mSecurityController.isWorkProfileOn()).thenReturn(false);
293 
294         assertNull(getButtonConfig());
295     }
296 
297     @Test
testManagedCACertsInstalled()298     public void testManagedCACertsInstalled() {
299         when(mSecurityController.isDeviceManaged()).thenReturn(true);
300         when(mSecurityController.hasCACertInCurrentUser()).thenReturn(true);
301 
302         SecurityButtonConfig buttonConfig = getButtonConfig();
303         assertNotNull(buttonConfig);
304         assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_monitoring),
305                 buttonConfig.getText());
306     }
307 
308     @Test
testManagedOneVpnEnabled()309     public void testManagedOneVpnEnabled() {
310         when(mSecurityController.isDeviceManaged()).thenReturn(true);
311         when(mSecurityController.isVpnEnabled()).thenReturn(true);
312         when(mSecurityController.getPrimaryVpnName()).thenReturn(VPN_PACKAGE);
313 
314         SecurityButtonConfig buttonConfig = getButtonConfig();
315         assertNotNull(buttonConfig);
316         assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_named_vpn,
317                         VPN_PACKAGE),
318                 buttonConfig.getText());
319         assertIsIconResource(buttonConfig.getIcon(), R.drawable.stat_sys_vpn_ic);
320 
321         // Same situation, but with organization name set
322         when(mSecurityController.getDeviceOwnerOrganizationName())
323                 .thenReturn(MANAGING_ORGANIZATION);
324         buttonConfig = getButtonConfig();
325         assertNotNull(buttonConfig);
326         assertEquals(mContext.getString(
327                         R.string.quick_settings_disclosure_named_management_named_vpn,
328                         MANAGING_ORGANIZATION, VPN_PACKAGE),
329                 buttonConfig.getText());
330     }
331 
332     @Test
testManagedTwoVpnsEnabled()333     public void testManagedTwoVpnsEnabled() {
334         when(mSecurityController.isDeviceManaged()).thenReturn(true);
335         when(mSecurityController.isVpnEnabled()).thenReturn(true);
336         when(mSecurityController.getPrimaryVpnName()).thenReturn(VPN_PACKAGE);
337         when(mSecurityController.getWorkProfileVpnName()).thenReturn(VPN_PACKAGE_2);
338 
339         SecurityButtonConfig buttonConfig = getButtonConfig();
340         assertNotNull(buttonConfig);
341         assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_vpns),
342                      buttonConfig.getText());
343         assertIsIconResource(buttonConfig.getIcon(), R.drawable.stat_sys_vpn_ic);
344 
345         // Same situation, but with organization name set
346         when(mSecurityController.getDeviceOwnerOrganizationName())
347                 .thenReturn(MANAGING_ORGANIZATION);
348         buttonConfig = getButtonConfig();
349         assertNotNull(buttonConfig);
350         assertEquals(mContext.getString(R.string.quick_settings_disclosure_named_management_vpns,
351                                         MANAGING_ORGANIZATION),
352                      buttonConfig.getText());
353     }
354 
355     @Test
testNetworkLoggingAndVpnEnabled()356     public void testNetworkLoggingAndVpnEnabled() {
357         when(mSecurityController.isDeviceManaged()).thenReturn(true);
358         when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
359         when(mSecurityController.isVpnEnabled()).thenReturn(true);
360         when(mSecurityController.getPrimaryVpnName()).thenReturn("VPN Test App");
361 
362         SecurityButtonConfig buttonConfig = getButtonConfig();
363         assertNotNull(buttonConfig);
364         assertIsIconResource(buttonConfig.getIcon(), R.drawable.stat_sys_vpn_ic);
365         assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_monitoring),
366                 buttonConfig.getText());
367     }
368 
369     @Test
testWorkProfileCACertsInstalled_workProfileOn()370     public void testWorkProfileCACertsInstalled_workProfileOn() {
371         when(mSecurityController.isDeviceManaged()).thenReturn(false);
372         when(mSecurityController.hasCACertInWorkProfile()).thenReturn(true);
373         when(mSecurityController.isWorkProfileOn()).thenReturn(true);
374 
375         SecurityButtonConfig buttonConfig = getButtonConfig();
376         assertNotNull(buttonConfig);
377         assertIsDefaultIcon(buttonConfig.getIcon());
378         assertEquals(mContext.getString(
379                              R.string.quick_settings_disclosure_managed_profile_monitoring),
380                      buttonConfig.getText());
381 
382         // Same situation, but with organization name set
383         when(mSecurityController.getWorkProfileOrganizationName())
384                 .thenReturn(MANAGING_ORGANIZATION);
385         buttonConfig = getButtonConfig();
386         assertNotNull(buttonConfig);
387         assertEquals(mContext.getString(
388                              R.string.quick_settings_disclosure_named_managed_profile_monitoring,
389                              MANAGING_ORGANIZATION),
390                      buttonConfig.getText());
391     }
392 
393     @Test
testWorkProfileCACertsInstalled_workProfileOff()394     public void testWorkProfileCACertsInstalled_workProfileOff() {
395         when(mSecurityController.isDeviceManaged()).thenReturn(false);
396         when(mSecurityController.hasCACertInWorkProfile()).thenReturn(true);
397         when(mSecurityController.isWorkProfileOn()).thenReturn(false);
398 
399         assertNull(getButtonConfig());
400     }
401 
402     @Test
testCACertsInstalled()403     public void testCACertsInstalled() {
404         when(mSecurityController.isDeviceManaged()).thenReturn(false);
405         when(mSecurityController.hasCACertInCurrentUser()).thenReturn(true);
406 
407         SecurityButtonConfig buttonConfig = getButtonConfig();
408         assertNotNull(buttonConfig);
409         assertIsDefaultIcon(buttonConfig.getIcon());
410         assertEquals(mContext.getString(R.string.quick_settings_disclosure_monitoring),
411                      buttonConfig.getText());
412     }
413 
414     @Test
testTwoVpnsEnabled()415     public void testTwoVpnsEnabled() {
416         when(mSecurityController.isVpnEnabled()).thenReturn(true);
417         when(mSecurityController.getPrimaryVpnName()).thenReturn(VPN_PACKAGE);
418         when(mSecurityController.getWorkProfileVpnName()).thenReturn(VPN_PACKAGE_2);
419 
420         SecurityButtonConfig buttonConfig = getButtonConfig();
421         assertNotNull(buttonConfig);
422         assertIsIconResource(buttonConfig.getIcon(), R.drawable.stat_sys_vpn_ic);
423         assertEquals(mContext.getString(R.string.quick_settings_disclosure_vpns),
424                      buttonConfig.getText());
425     }
426 
427     @Test
testWorkProfileVpnEnabled_workProfileOn()428     public void testWorkProfileVpnEnabled_workProfileOn() {
429         when(mSecurityController.isVpnEnabled()).thenReturn(true);
430         when(mSecurityController.getWorkProfileVpnName()).thenReturn(VPN_PACKAGE_2);
431         when(mSecurityController.isWorkProfileOn()).thenReturn(true);
432 
433         SecurityButtonConfig buttonConfig = getButtonConfig();
434         assertNotNull(buttonConfig);
435         assertIsIconResource(buttonConfig.getIcon(), R.drawable.stat_sys_vpn_ic);
436         assertEquals(mContext.getString(
437                              R.string.quick_settings_disclosure_managed_profile_named_vpn,
438                              VPN_PACKAGE_2),
439                      buttonConfig.getText());
440     }
441 
442     @Test
testWorkProfileVpnEnabled_workProfileOff()443     public void testWorkProfileVpnEnabled_workProfileOff() {
444         when(mSecurityController.isVpnEnabled()).thenReturn(true);
445         when(mSecurityController.getWorkProfileVpnName()).thenReturn(VPN_PACKAGE_2);
446         when(mSecurityController.isWorkProfileOn()).thenReturn(false);
447 
448         assertNull(getButtonConfig());
449     }
450 
451     @Test
testProfileOwnerOfOrganizationOwnedDeviceNoName()452     public void testProfileOwnerOfOrganizationOwnedDeviceNoName() {
453         when(mSecurityController.isProfileOwnerOfOrganizationOwnedDevice()).thenReturn(true);
454 
455         SecurityButtonConfig buttonConfig = getButtonConfig();
456         assertNotNull(buttonConfig);
457         assertEquals(mContext.getString(
458                 R.string.quick_settings_disclosure_management),
459                 buttonConfig.getText());
460     }
461 
462     @Test
testProfileOwnerOfOrganizationOwnedDeviceWithName()463     public void testProfileOwnerOfOrganizationOwnedDeviceWithName() {
464         when(mSecurityController.isProfileOwnerOfOrganizationOwnedDevice()).thenReturn(true);
465         when(mSecurityController.getWorkProfileOrganizationName())
466                 .thenReturn(MANAGING_ORGANIZATION);
467 
468         SecurityButtonConfig buttonConfig = getButtonConfig();
469         assertNotNull(buttonConfig);
470         assertEquals(mContext.getString(
471                 R.string.quick_settings_disclosure_named_management,
472                 MANAGING_ORGANIZATION),
473                 buttonConfig.getText());
474     }
475 
476     @Test
testVpnEnabled()477     public void testVpnEnabled() {
478         when(mSecurityController.isVpnEnabled()).thenReturn(true);
479         when(mSecurityController.getPrimaryVpnName()).thenReturn(VPN_PACKAGE);
480 
481         SecurityButtonConfig buttonConfig = getButtonConfig();
482         assertNotNull(buttonConfig);
483         assertIsIconResource(buttonConfig.getIcon(), R.drawable.stat_sys_vpn_ic);
484         assertEquals(mContext.getString(R.string.quick_settings_disclosure_named_vpn,
485                                         VPN_PACKAGE),
486                      buttonConfig.getText());
487 
488         when(mSecurityController.hasWorkProfile()).thenReturn(true);
489         buttonConfig = getButtonConfig();
490         assertNotNull(buttonConfig);
491         assertEquals(mContext.getString(
492                              R.string.quick_settings_disclosure_personal_profile_named_vpn,
493                              VPN_PACKAGE),
494                      buttonConfig.getText());
495     }
496 
497     @Test
testGetManagementTitleForNonFinancedDevice()498     public void testGetManagementTitleForNonFinancedDevice() {
499         when(mSecurityController.isDeviceManaged()).thenReturn(true);
500 
501         assertEquals(mContext.getString(R.string.monitoring_title_device_owned),
502                 mFooterUtils.getManagementTitle(MANAGING_ORGANIZATION));
503     }
504 
505     @Test
testGetManagementTitleForFinancedDevice()506     public void testGetManagementTitleForFinancedDevice() {
507         when(mSecurityController.isDeviceManaged()).thenReturn(true);
508         when(mSecurityController.isFinancedDevice()).thenReturn(true);
509         // TODO(b/259908270): remove
510         when(mSecurityController.getDeviceOwnerType(DEVICE_OWNER_COMPONENT))
511                 .thenReturn(DEVICE_OWNER_TYPE_FINANCED);
512 
513         assertEquals(mContext.getString(R.string.monitoring_title_financed_device,
514                 MANAGING_ORGANIZATION),
515                 mFooterUtils.getManagementTitle(MANAGING_ORGANIZATION));
516     }
517 
518     @Test
testGetManagementMessage_noManagement()519     public void testGetManagementMessage_noManagement() {
520         assertEquals(null, mFooterUtils.getManagementMessage(
521                 /* isDeviceManaged= */ false, MANAGING_ORGANIZATION));
522     }
523 
524     @Test
testGetManagementMessage_deviceOwner()525     public void testGetManagementMessage_deviceOwner() {
526         assertEquals(mContext.getString(R.string.monitoring_description_named_management,
527                                         MANAGING_ORGANIZATION),
528                 mFooterUtils.getManagementMessage(
529                              /* isDeviceManaged= */ true, MANAGING_ORGANIZATION));
530         assertEquals(mContext.getString(R.string.monitoring_description_management),
531                 mFooterUtils.getManagementMessage(
532                              /* isDeviceManaged= */ true,
533                              /* organizationName= */ null));
534     }
535 
536     @Test
testGetManagementMessage_deviceOwner_asFinancedDevice()537     public void testGetManagementMessage_deviceOwner_asFinancedDevice() {
538         when(mSecurityController.isDeviceManaged()).thenReturn(true);
539         when(mSecurityController.isFinancedDevice()).thenReturn(true);
540         // TODO(b/259908270): remove
541         when(mSecurityController.getDeviceOwnerType(DEVICE_OWNER_COMPONENT))
542                 .thenReturn(DEVICE_OWNER_TYPE_FINANCED);
543 
544         assertEquals(mContext.getString(R.string.monitoring_financed_description_named_management,
545                 MANAGING_ORGANIZATION, MANAGING_ORGANIZATION),
546                 mFooterUtils.getManagementMessage(
547                         /* isDeviceManaged= */ true, MANAGING_ORGANIZATION));
548     }
549 
550     @Test
testGetCaCertsMessage()551     public void testGetCaCertsMessage() {
552         assertEquals(null, mFooterUtils.getCaCertsMessage(true, false, false));
553         assertEquals(null, mFooterUtils.getCaCertsMessage(false, false, false));
554         assertEquals(mContext.getString(R.string.monitoring_description_management_ca_certificate),
555                 mFooterUtils.getCaCertsMessage(true, true, true));
556         assertEquals(mContext.getString(R.string.monitoring_description_management_ca_certificate),
557                 mFooterUtils.getCaCertsMessage(true, false, true));
558         assertEquals(mContext.getString(
559                          R.string.monitoring_description_managed_profile_ca_certificate),
560                 mFooterUtils.getCaCertsMessage(false, false, true));
561         assertEquals(mContext.getString(
562                          R.string.monitoring_description_ca_certificate),
563                 mFooterUtils.getCaCertsMessage(false, true, false));
564     }
565 
566     @Test
testGetNetworkLoggingMessage()567     public void testGetNetworkLoggingMessage() {
568         // Test network logging message on a device with a device owner.
569         // Network traffic may be monitored on the device.
570         assertEquals(null, mFooterUtils.getNetworkLoggingMessage(true, false));
571         assertEquals(mContext.getString(R.string.monitoring_description_management_network_logging),
572                 mFooterUtils.getNetworkLoggingMessage(true, true));
573 
574         // Test network logging message on a device with a managed profile owner
575         // Network traffic may be monitored on the work profile.
576         assertEquals(null, mFooterUtils.getNetworkLoggingMessage(false, false));
577         assertEquals(
578                 mContext.getString(R.string.monitoring_description_managed_profile_network_logging),
579                 mFooterUtils.getNetworkLoggingMessage(false, true));
580     }
581 
582     @Test
testGetVpnMessage()583     public void testGetVpnMessage() {
584         assertEquals(null, mFooterUtils.getVpnMessage(true, true, null, null));
585         assertEquals(addLink(mContext.getString(R.string.monitoring_description_two_named_vpns,
586                                  VPN_PACKAGE, VPN_PACKAGE_2)),
587                 mFooterUtils.getVpnMessage(true, true, VPN_PACKAGE, VPN_PACKAGE_2));
588         assertEquals(addLink(mContext.getString(R.string.monitoring_description_two_named_vpns,
589                                  VPN_PACKAGE, VPN_PACKAGE_2)),
590                 mFooterUtils.getVpnMessage(false, true, VPN_PACKAGE, VPN_PACKAGE_2));
591         assertEquals(addLink(mContext.getString(
592                 R.string.monitoring_description_managed_device_named_vpn, VPN_PACKAGE)),
593                 mFooterUtils.getVpnMessage(true, false, VPN_PACKAGE, null));
594         assertEquals(addLink(mContext.getString(R.string.monitoring_description_named_vpn,
595                                  VPN_PACKAGE)),
596                 mFooterUtils.getVpnMessage(false, false, VPN_PACKAGE, null));
597         assertEquals(addLink(mContext.getString(
598                 R.string.monitoring_description_managed_device_named_vpn, VPN_PACKAGE_2)),
599                 mFooterUtils.getVpnMessage(true, true, null, VPN_PACKAGE_2));
600         assertEquals(addLink(mContext.getString(
601                                  R.string.monitoring_description_managed_profile_named_vpn,
602                                  VPN_PACKAGE_2)),
603                 mFooterUtils.getVpnMessage(false, true, null, VPN_PACKAGE_2));
604         assertEquals(addLink(mContext.getString(
605                                  R.string.monitoring_description_personal_profile_named_vpn,
606                                  VPN_PACKAGE)),
607                 mFooterUtils.getVpnMessage(false, true, VPN_PACKAGE, null));
608     }
609 
610     @Test
testConfigSubtitleVisibility()611     public void testConfigSubtitleVisibility() {
612         View view = LayoutInflater.from(mContext)
613                 .inflate(R.layout.quick_settings_footer_dialog, null);
614 
615         // Device Management subtitle should be shown when there is Device Management section only
616         // Other sections visibility will be set somewhere else so it will not be tested here
617         mFooterUtils.configSubtitleVisibility(true, false, false, false, view);
618         assertEquals(View.VISIBLE,
619                 view.findViewById(R.id.device_management_subtitle).getVisibility());
620 
621         // If there are multiple sections, all subtitles should be shown
622         mFooterUtils.configSubtitleVisibility(true, true, false, false, view);
623         assertEquals(View.VISIBLE,
624                 view.findViewById(R.id.device_management_subtitle).getVisibility());
625         assertEquals(View.VISIBLE,
626                 view.findViewById(R.id.ca_certs_subtitle).getVisibility());
627 
628         // If there are multiple sections, all subtitles should be shown
629         mFooterUtils.configSubtitleVisibility(true, true, true, true, view);
630         assertEquals(View.VISIBLE,
631                 view.findViewById(R.id.device_management_subtitle).getVisibility());
632         assertEquals(View.VISIBLE,
633                 view.findViewById(R.id.ca_certs_subtitle).getVisibility());
634         assertEquals(View.VISIBLE,
635                 view.findViewById(R.id.network_logging_subtitle).getVisibility());
636         assertEquals(View.VISIBLE,
637                 view.findViewById(R.id.vpn_subtitle).getVisibility());
638 
639         // If there are multiple sections, all subtitles should be shown, event if there is no
640         // Device Management section
641         mFooterUtils.configSubtitleVisibility(false, true, true, true, view);
642         assertEquals(View.VISIBLE,
643                 view.findViewById(R.id.ca_certs_subtitle).getVisibility());
644         assertEquals(View.VISIBLE,
645                 view.findViewById(R.id.network_logging_subtitle).getVisibility());
646         assertEquals(View.VISIBLE,
647                 view.findViewById(R.id.vpn_subtitle).getVisibility());
648 
649         // If there is only 1 section, the title should be hidden
650         mFooterUtils.configSubtitleVisibility(false, true, false, false, view);
651         assertEquals(View.GONE,
652                 view.findViewById(R.id.ca_certs_subtitle).getVisibility());
653         mFooterUtils.configSubtitleVisibility(false, false, true, false, view);
654         assertEquals(View.GONE,
655                 view.findViewById(R.id.network_logging_subtitle).getVisibility());
656         mFooterUtils.configSubtitleVisibility(false, false, false, true, view);
657         assertEquals(View.GONE,
658                 view.findViewById(R.id.vpn_subtitle).getVisibility());
659     }
660 
661     @Test
testParentalControls()662     public void testParentalControls() {
663         // Make sure the security footer is visible, so that the images are updated.
664         when(mSecurityController.isProfileOwnerOfOrganizationOwnedDevice()).thenReturn(true);
665         when(mSecurityController.isParentalControlsEnabled()).thenReturn(true);
666 
667         // We use the default icon when there is no admin icon.
668         when(mSecurityController.getIcon(any())).thenReturn(null);
669         SecurityButtonConfig buttonConfig = getButtonConfig();
670         assertEquals(mContext.getString(R.string.quick_settings_disclosure_parental_controls),
671                 buttonConfig.getText());
672         assertIsDefaultIcon(buttonConfig.getIcon());
673 
674         Drawable testDrawable = new VectorDrawable();
675         when(mSecurityController.getIcon(any())).thenReturn(testDrawable);
676         assertNotNull(mSecurityController.getIcon(null));
677 
678         buttonConfig = getButtonConfig();
679         assertNotNull(buttonConfig);
680         assertEquals(mContext.getString(R.string.quick_settings_disclosure_parental_controls),
681                 buttonConfig.getText());
682         assertIsIconDrawable(buttonConfig.getIcon(), testDrawable);
683 
684         // Ensure the primary icon is back to default after parental controls are gone
685         when(mSecurityController.isParentalControlsEnabled()).thenReturn(false);
686         buttonConfig = getButtonConfig();
687         assertNotNull(buttonConfig);
688         assertIsDefaultIcon(buttonConfig.getIcon());
689     }
690 
691     @Test
testParentalControlsDialog()692     public void testParentalControlsDialog() {
693         when(mSecurityController.isParentalControlsEnabled()).thenReturn(true);
694         when(mSecurityController.getLabel(any())).thenReturn(PARENTAL_CONTROLS_LABEL);
695 
696         View view = mFooterUtils.createDialogView(getContext());
697         TextView textView = (TextView) view.findViewById(R.id.parental_controls_title);
698         assertEquals(PARENTAL_CONTROLS_LABEL, textView.getText());
699     }
700 
701     @Test
testCreateDialogViewForFinancedDevice()702     public void testCreateDialogViewForFinancedDevice() {
703         when(mSecurityController.isDeviceManaged()).thenReturn(true);
704         when(mSecurityController.getDeviceOwnerOrganizationName())
705                 .thenReturn(MANAGING_ORGANIZATION);
706         when(mSecurityController.isFinancedDevice()).thenReturn(true);
707         // TODO(b/259908270): remove
708         when(mSecurityController.getDeviceOwnerType(DEVICE_OWNER_COMPONENT))
709                 .thenReturn(DEVICE_OWNER_TYPE_FINANCED);
710 
711         View view = mFooterUtils.createDialogView(getContext());
712 
713         TextView managementSubtitle = view.findViewById(R.id.device_management_subtitle);
714         assertEquals(View.VISIBLE, managementSubtitle.getVisibility());
715         assertEquals(mContext.getString(R.string.monitoring_title_financed_device,
716                 MANAGING_ORGANIZATION), managementSubtitle.getText());
717         TextView managementMessage = view.findViewById(R.id.device_management_warning);
718         assertEquals(View.VISIBLE, managementMessage.getVisibility());
719         assertEquals(mContext.getString(R.string.monitoring_financed_description_named_management,
720                 MANAGING_ORGANIZATION, MANAGING_ORGANIZATION), managementMessage.getText());
721         assertEquals(mContext.getString(R.string.monitoring_button_view_policies),
722                 mFooterUtils.getSettingsButton());
723     }
724 
725     @Test
testFinancedDeviceUsesSettingsButtonText()726     public void testFinancedDeviceUsesSettingsButtonText() {
727         when(mSecurityController.isDeviceManaged()).thenReturn(true);
728         when(mSecurityController.getDeviceOwnerOrganizationName())
729                 .thenReturn(MANAGING_ORGANIZATION);
730         when(mSecurityController.isFinancedDevice()).thenReturn(true);
731         // TODO(b/259908270): remove
732         when(mSecurityController.getDeviceOwnerType(DEVICE_OWNER_COMPONENT))
733                 .thenReturn(DEVICE_OWNER_TYPE_FINANCED);
734 
735         Expandable expandable = mock(Expandable.class);
736         when(expandable.dialogTransitionController(any())).thenReturn(
737                 mock(DialogTransitionAnimator.Controller.class));
738         mFooterUtils.showDeviceMonitoringDialog(getContext(), expandable);
739         ArgumentCaptor<AlertDialog> dialogCaptor = ArgumentCaptor.forClass(AlertDialog.class);
740 
741         mTestableLooper.processAllMessages();
742         verify(mDialogTransitionAnimator).show(dialogCaptor.capture(), any());
743 
744         AlertDialog dialog = dialogCaptor.getValue();
745         dialog.create();
746 
747         assertEquals(mFooterUtils.getSettingsButton(),
748                 dialog.getButton(DialogInterface.BUTTON_NEGATIVE).getText());
749 
750         dialog.dismiss();
751     }
752 
addLink(CharSequence description)753     private CharSequence addLink(CharSequence description) {
754         final SpannableStringBuilder message = new SpannableStringBuilder();
755         message.append(description);
756         message.append(mContext.getString(R.string.monitoring_description_vpn_settings_separator));
757         message.append(mContext.getString(R.string.monitoring_description_vpn_settings),
758                 mFooterUtils.new VpnSpan(), 0);
759         return message;
760     }
761 }
762