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
15package com.android.systemui.qs;
16
17import static junit.framework.Assert.assertEquals;
18
19import static org.mockito.ArgumentMatchers.anyInt;
20import static org.mockito.Mockito.mock;
21import static org.mockito.Mockito.when;
22
23import android.content.Context;
24import android.content.pm.UserInfo;
25import android.os.Handler;
26import android.os.Looper;
27import android.os.UserManager;
28import android.provider.Settings;
29import android.support.test.runner.AndroidJUnit4;
30import android.test.suitebuilder.annotation.SmallTest;
31import android.text.SpannableStringBuilder;
32import android.view.LayoutInflater;
33import android.view.View;
34import android.view.ViewGroup;
35import android.widget.TextView;
36
37import com.android.systemui.Dependency;
38import com.android.systemui.R;
39import com.android.systemui.SysuiTestCase;
40import com.android.systemui.statusbar.policy.SecurityController;
41import android.testing.LayoutInflaterBuilder;
42import android.testing.TestableImageView;
43
44import org.junit.Before;
45import org.junit.Test;
46import org.junit.runner.RunWith;
47import org.mockito.Mockito;
48
49/*
50 * Compile and run the whole SystemUI test suite:
51   runtest --path frameworks/base/packages/SystemUI/tests
52 *
53 * Compile and run just this class:
54   runtest --path \
55   frameworks/base/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
56*/
57
58@SmallTest
59@RunWith(AndroidJUnit4.class)
60public class QSSecurityFooterTest extends SysuiTestCase {
61
62    private final String MANAGING_ORGANIZATION = "organization";
63    private final String DEVICE_OWNER_PACKAGE = "TestDPC";
64    private final String VPN_PACKAGE = "TestVPN";
65    private final String VPN_PACKAGE_2 = "TestVPN 2";
66
67    private ViewGroup mRootView;
68    private TextView mFooterText;
69    private TestableImageView mFooterIcon;
70    private QSSecurityFooter mFooter;
71    private SecurityController mSecurityController = mock(SecurityController.class);
72    private UserManager mUserManager;
73
74    @Before
75    public void setUp() {
76        mDependency.injectTestDependency(SecurityController.class, mSecurityController);
77        mDependency.injectTestDependency(Dependency.BG_LOOPER, Looper.getMainLooper());
78        mContext.addMockSystemService(Context.LAYOUT_INFLATER_SERVICE,
79                new LayoutInflaterBuilder(mContext)
80                        .replace("ImageView", TestableImageView.class)
81                        .build());
82        mUserManager = Mockito.mock(UserManager.class);
83        mContext.addMockSystemService(Context.USER_SERVICE, mUserManager);
84        Handler h = new Handler(Looper.getMainLooper());
85        h.post(() -> mFooter = new QSSecurityFooter(null, mContext));
86        waitForIdleSync(h);
87        mRootView = (ViewGroup) mFooter.getView();
88        mFooterText = (TextView) mRootView.findViewById(R.id.footer_text);
89        mFooterIcon = (TestableImageView) mRootView.findViewById(R.id.footer_icon);
90        mFooter.setHostEnvironment(null);
91    }
92
93    @Test
94    public void testUnmanaged() {
95        when(mSecurityController.isDeviceManaged()).thenReturn(false);
96        mFooter.refreshState();
97
98        waitForIdleSync(mFooter.mHandler);
99        assertEquals(View.GONE, mRootView.getVisibility());
100    }
101
102    @Test
103    public void testManagedNoOwnerName() {
104        when(mSecurityController.isDeviceManaged()).thenReturn(true);
105        when(mSecurityController.getDeviceOwnerOrganizationName()).thenReturn(null);
106        mFooter.refreshState();
107
108        waitForIdleSync(mFooter.mHandler);
109        assertEquals(mContext.getString(R.string.quick_settings_disclosure_management),
110                     mFooterText.getText());
111        assertEquals(View.VISIBLE, mRootView.getVisibility());
112        assertEquals(View.VISIBLE, mFooterIcon.getVisibility());
113        // -1 == never set.
114        assertEquals(-1, mFooterIcon.getLastImageResource());
115    }
116
117    @Test
118    public void testManagedOwnerName() {
119        when(mSecurityController.isDeviceManaged()).thenReturn(true);
120        when(mSecurityController.getDeviceOwnerOrganizationName())
121                .thenReturn(MANAGING_ORGANIZATION);
122        mFooter.refreshState();
123
124        waitForIdleSync(mFooter.mHandler);
125        assertEquals(mContext.getString(R.string.quick_settings_disclosure_named_management,
126                                        MANAGING_ORGANIZATION),
127                mFooterText.getText());
128        assertEquals(View.VISIBLE, mRootView.getVisibility());
129        assertEquals(View.VISIBLE, mFooterIcon.getVisibility());
130        // -1 == never set.
131        assertEquals(-1, mFooterIcon.getLastImageResource());
132    }
133
134    @Test
135    public void testManagedDemoMode() {
136        when(mSecurityController.isDeviceManaged()).thenReturn(true);
137        when(mSecurityController.getDeviceOwnerOrganizationName()).thenReturn(null);
138        final UserInfo mockUserInfo = Mockito.mock(UserInfo.class);
139        when(mockUserInfo.isDemo()).thenReturn(true);
140        when(mUserManager.getUserInfo(anyInt())).thenReturn(mockUserInfo);
141        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVICE_DEMO_MODE, 1);
142
143        mFooter.refreshState();
144
145        waitForIdleSync(mFooter.mHandler);
146        assertEquals(View.GONE, mRootView.getVisibility());
147    }
148
149    @Test
150    public void testNetworkLoggingEnabled() {
151        when(mSecurityController.isDeviceManaged()).thenReturn(true);
152        when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
153        mFooter.refreshState();
154
155        waitForIdleSync(mFooter.mHandler);
156        assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_monitoring),
157                mFooterText.getText());
158        assertEquals(View.VISIBLE, mFooterIcon.getVisibility());
159        // -1 == never set.
160        assertEquals(-1, mFooterIcon.getLastImageResource());
161
162        // Same situation, but with organization name set
163        when(mSecurityController.getDeviceOwnerOrganizationName())
164                .thenReturn(MANAGING_ORGANIZATION);
165        mFooter.refreshState();
166
167        waitForIdleSync(mFooter.mHandler);
168        assertEquals(mContext.getString(
169                             R.string.quick_settings_disclosure_named_management_monitoring,
170                             MANAGING_ORGANIZATION),
171                     mFooterText.getText());
172    }
173
174    @Test
175    public void testManagedCACertsInstalled() {
176        when(mSecurityController.isDeviceManaged()).thenReturn(true);
177        when(mSecurityController.hasCACertInCurrentUser()).thenReturn(true);
178        mFooter.refreshState();
179
180        waitForIdleSync(mFooter.mHandler);
181        assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_monitoring),
182                mFooterText.getText());
183    }
184
185    @Test
186    public void testManagedOneVpnEnabled() {
187        when(mSecurityController.isDeviceManaged()).thenReturn(true);
188        when(mSecurityController.isVpnEnabled()).thenReturn(true);
189        when(mSecurityController.getPrimaryVpnName()).thenReturn(VPN_PACKAGE);
190        mFooter.refreshState();
191
192        waitForIdleSync(mFooter.mHandler);
193        assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_named_vpn,
194                                        VPN_PACKAGE),
195                     mFooterText.getText());
196        assertEquals(View.VISIBLE, mFooterIcon.getVisibility());
197        assertEquals(R.drawable.ic_qs_vpn, mFooterIcon.getLastImageResource());
198
199        // Same situation, but with organization name set
200        when(mSecurityController.getDeviceOwnerOrganizationName())
201                .thenReturn(MANAGING_ORGANIZATION);
202        mFooter.refreshState();
203
204        waitForIdleSync(mFooter.mHandler);
205        assertEquals(mContext.getString(
206                              R.string.quick_settings_disclosure_named_management_named_vpn,
207                              MANAGING_ORGANIZATION, VPN_PACKAGE),
208                     mFooterText.getText());
209    }
210
211    @Test
212    public void testManagedTwoVpnsEnabled() {
213        when(mSecurityController.isDeviceManaged()).thenReturn(true);
214        when(mSecurityController.isVpnEnabled()).thenReturn(true);
215        when(mSecurityController.getPrimaryVpnName()).thenReturn(VPN_PACKAGE);
216        when(mSecurityController.getWorkProfileVpnName()).thenReturn(VPN_PACKAGE_2);
217        mFooter.refreshState();
218
219        waitForIdleSync(mFooter.mHandler);
220        assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_vpns),
221                     mFooterText.getText());
222        assertEquals(View.VISIBLE, mFooterIcon.getVisibility());
223        assertEquals(R.drawable.ic_qs_vpn, mFooterIcon.getLastImageResource());
224
225        // Same situation, but with organization name set
226        when(mSecurityController.getDeviceOwnerOrganizationName())
227                .thenReturn(MANAGING_ORGANIZATION);
228        mFooter.refreshState();
229
230        waitForIdleSync(mFooter.mHandler);
231        assertEquals(mContext.getString(R.string.quick_settings_disclosure_named_management_vpns,
232                                        MANAGING_ORGANIZATION),
233                     mFooterText.getText());
234    }
235
236    @Test
237    public void testNetworkLoggingAndVpnEnabled() {
238        when(mSecurityController.isDeviceManaged()).thenReturn(true);
239        when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
240        when(mSecurityController.isVpnEnabled()).thenReturn(true);
241        when(mSecurityController.getPrimaryVpnName()).thenReturn("VPN Test App");
242        mFooter.refreshState();
243
244        waitForIdleSync(mFooter.mHandler);
245        assertEquals(View.VISIBLE, mFooterIcon.getVisibility());
246        assertEquals(R.drawable.ic_qs_vpn, mFooterIcon.getLastImageResource());
247        assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_monitoring),
248                mFooterText.getText());
249    }
250
251    @Test
252    public void testWorkProfileCACertsInstalled() {
253        when(mSecurityController.isDeviceManaged()).thenReturn(false);
254        when(mSecurityController.hasCACertInWorkProfile()).thenReturn(true);
255        mFooter.refreshState();
256
257        waitForIdleSync(mFooter.mHandler);
258        // -1 == never set.
259        assertEquals(-1, mFooterIcon.getLastImageResource());
260        assertEquals(mContext.getString(
261                             R.string.quick_settings_disclosure_managed_profile_monitoring),
262                     mFooterText.getText());
263
264        // Same situation, but with organization name set
265        when(mSecurityController.getWorkProfileOrganizationName())
266                .thenReturn(MANAGING_ORGANIZATION);
267        mFooter.refreshState();
268
269        waitForIdleSync(mFooter.mHandler);
270        assertEquals(mContext.getString(
271                             R.string.quick_settings_disclosure_named_managed_profile_monitoring,
272                             MANAGING_ORGANIZATION),
273                     mFooterText.getText());
274    }
275
276    @Test
277    public void testCACertsInstalled() {
278        when(mSecurityController.isDeviceManaged()).thenReturn(false);
279        when(mSecurityController.hasCACertInCurrentUser()).thenReturn(true);
280        mFooter.refreshState();
281
282        waitForIdleSync(mFooter.mHandler);
283        // -1 == never set.
284        assertEquals(-1, mFooterIcon.getLastImageResource());
285        assertEquals(mContext.getString(R.string.quick_settings_disclosure_monitoring),
286                     mFooterText.getText());
287    }
288
289    @Test
290    public void testTwoVpnsEnabled() {
291        when(mSecurityController.isVpnEnabled()).thenReturn(true);
292        when(mSecurityController.getPrimaryVpnName()).thenReturn(VPN_PACKAGE);
293        when(mSecurityController.getWorkProfileVpnName()).thenReturn(VPN_PACKAGE_2);
294        mFooter.refreshState();
295
296        waitForIdleSync(mFooter.mHandler);
297        assertEquals(R.drawable.ic_qs_vpn, mFooterIcon.getLastImageResource());
298        assertEquals(mContext.getString(R.string.quick_settings_disclosure_vpns),
299                     mFooterText.getText());
300    }
301
302    @Test
303    public void testWorkProfileVpnEnabled() {
304        when(mSecurityController.isVpnEnabled()).thenReturn(true);
305        when(mSecurityController.getWorkProfileVpnName()).thenReturn(VPN_PACKAGE_2);
306        mFooter.refreshState();
307
308        waitForIdleSync(mFooter.mHandler);
309        assertEquals(R.drawable.ic_qs_vpn, mFooterIcon.getLastImageResource());
310        assertEquals(mContext.getString(
311                             R.string.quick_settings_disclosure_managed_profile_named_vpn,
312                             VPN_PACKAGE_2),
313                     mFooterText.getText());
314    }
315
316    @Test
317    public void testVpnEnabled() {
318        when(mSecurityController.isVpnEnabled()).thenReturn(true);
319        when(mSecurityController.getPrimaryVpnName()).thenReturn(VPN_PACKAGE);
320        mFooter.refreshState();
321
322        waitForIdleSync(mFooter.mHandler);
323        assertEquals(R.drawable.ic_qs_vpn, mFooterIcon.getLastImageResource());
324        assertEquals(mContext.getString(R.string.quick_settings_disclosure_named_vpn,
325                                        VPN_PACKAGE),
326                     mFooterText.getText());
327
328        when(mSecurityController.hasWorkProfile()).thenReturn(true);
329        mFooter.refreshState();
330
331        waitForIdleSync(mFooter.mHandler);
332        assertEquals(mContext.getString(
333                             R.string.quick_settings_disclosure_personal_profile_named_vpn,
334                             VPN_PACKAGE),
335                     mFooterText.getText());
336    }
337
338    @Test
339    public void testGetManagementMessage() {
340        assertEquals(null, mFooter.getManagementMessage(false, MANAGING_ORGANIZATION));
341        assertEquals(mContext.getString(R.string.monitoring_description_named_management,
342                                        MANAGING_ORGANIZATION),
343                     mFooter.getManagementMessage(true, MANAGING_ORGANIZATION));
344        assertEquals(mContext.getString(R.string.monitoring_description_management),
345                     mFooter.getManagementMessage(true, null));
346    }
347
348    @Test
349    public void testGetCaCertsMessage() {
350        assertEquals(null, mFooter.getCaCertsMessage(true, false, false));
351        assertEquals(null, mFooter.getCaCertsMessage(false, false, false));
352        assertEquals(mContext.getString(R.string.monitoring_description_management_ca_certificate),
353                     mFooter.getCaCertsMessage(true, true, true));
354        assertEquals(mContext.getString(R.string.monitoring_description_management_ca_certificate),
355                     mFooter.getCaCertsMessage(true, false, true));
356        assertEquals(mContext.getString(
357                         R.string.monitoring_description_managed_profile_ca_certificate),
358                     mFooter.getCaCertsMessage(false, false, true));
359        assertEquals(mContext.getString(
360                         R.string.monitoring_description_ca_certificate),
361                     mFooter.getCaCertsMessage(false, true, false));
362    }
363
364    @Test
365    public void testGetNetworkLoggingMessage() {
366        assertEquals(null, mFooter.getNetworkLoggingMessage(false));
367        assertEquals(mContext.getString(R.string.monitoring_description_management_network_logging),
368                     mFooter.getNetworkLoggingMessage(true));
369    }
370
371    @Test
372    public void testGetVpnMessage() {
373        assertEquals(null, mFooter.getVpnMessage(true, true, null, null));
374        assertEquals(addLink(mContext.getString(R.string.monitoring_description_two_named_vpns,
375                                 VPN_PACKAGE, VPN_PACKAGE_2)),
376                     mFooter.getVpnMessage(true, true, VPN_PACKAGE, VPN_PACKAGE_2));
377        assertEquals(addLink(mContext.getString(R.string.monitoring_description_two_named_vpns,
378                                 VPN_PACKAGE, VPN_PACKAGE_2)),
379                     mFooter.getVpnMessage(false, true, VPN_PACKAGE, VPN_PACKAGE_2));
380        assertEquals(addLink(mContext.getString(R.string.monitoring_description_named_vpn,
381                                 VPN_PACKAGE)),
382                     mFooter.getVpnMessage(true, false, VPN_PACKAGE, null));
383        assertEquals(addLink(mContext.getString(R.string.monitoring_description_named_vpn,
384                                 VPN_PACKAGE)),
385                     mFooter.getVpnMessage(false, false, VPN_PACKAGE, null));
386        assertEquals(addLink(mContext.getString(R.string.monitoring_description_named_vpn,
387                                 VPN_PACKAGE_2)),
388                     mFooter.getVpnMessage(true, true, null, VPN_PACKAGE_2));
389        assertEquals(addLink(mContext.getString(
390                                 R.string.monitoring_description_managed_profile_named_vpn,
391                                 VPN_PACKAGE_2)),
392                     mFooter.getVpnMessage(false, true, null, VPN_PACKAGE_2));
393        assertEquals(addLink(mContext.getString(
394                                 R.string.monitoring_description_personal_profile_named_vpn,
395                                 VPN_PACKAGE)),
396                     mFooter.getVpnMessage(false, true, VPN_PACKAGE, null));
397    }
398
399    @Test
400    public void testConfigSubtitleVisibility() {
401        View view = LayoutInflater.from(mContext)
402                .inflate(R.layout.quick_settings_footer_dialog, null);
403
404        // Device Management subtitle should be shown when there is Device Management section only
405        // Other sections visibility will be set somewhere else so it will not be tested here
406        mFooter.configSubtitleVisibility(true, false, false, false, view);
407        assertEquals(View.VISIBLE,
408                view.findViewById(R.id.device_management_subtitle).getVisibility());
409
410        // If there are multiple sections, all subtitles should be shown
411        mFooter.configSubtitleVisibility(true, true, false, false, view);
412        assertEquals(View.VISIBLE,
413                view.findViewById(R.id.device_management_subtitle).getVisibility());
414        assertEquals(View.VISIBLE,
415                view.findViewById(R.id.ca_certs_subtitle).getVisibility());
416
417        // If there are multiple sections, all subtitles should be shown
418        mFooter.configSubtitleVisibility(true, true, true, true, view);
419        assertEquals(View.VISIBLE,
420                view.findViewById(R.id.device_management_subtitle).getVisibility());
421        assertEquals(View.VISIBLE,
422                view.findViewById(R.id.ca_certs_subtitle).getVisibility());
423        assertEquals(View.VISIBLE,
424                view.findViewById(R.id.network_logging_subtitle).getVisibility());
425        assertEquals(View.VISIBLE,
426                view.findViewById(R.id.vpn_subtitle).getVisibility());
427
428        // If there are multiple sections, all subtitles should be shown, event if there is no
429        // Device Management section
430        mFooter.configSubtitleVisibility(false, true, true, true, view);
431        assertEquals(View.VISIBLE,
432                view.findViewById(R.id.ca_certs_subtitle).getVisibility());
433        assertEquals(View.VISIBLE,
434                view.findViewById(R.id.network_logging_subtitle).getVisibility());
435        assertEquals(View.VISIBLE,
436                view.findViewById(R.id.vpn_subtitle).getVisibility());
437
438        // If there is only 1 section, the title should be hidden
439        mFooter.configSubtitleVisibility(false, true, false, false, view);
440        assertEquals(View.GONE,
441                view.findViewById(R.id.ca_certs_subtitle).getVisibility());
442        mFooter.configSubtitleVisibility(false, false, true, false, view);
443        assertEquals(View.GONE,
444                view.findViewById(R.id.network_logging_subtitle).getVisibility());
445        mFooter.configSubtitleVisibility(false, false, false, true, view);
446        assertEquals(View.GONE,
447                view.findViewById(R.id.vpn_subtitle).getVisibility());
448    }
449
450    private CharSequence addLink(CharSequence description) {
451        final SpannableStringBuilder message = new SpannableStringBuilder();
452        message.append(description);
453        message.append(mContext.getString(R.string.monitoring_description_vpn_settings_separator));
454        message.append(mContext.getString(R.string.monitoring_description_vpn_settings),
455                mFooter.new VpnSpan(), 0);
456        return message;
457    }
458}
459