1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.statusbar;
18 
19 import static junit.framework.Assert.assertFalse;
20 import static junit.framework.Assert.assertTrue;
21 
22 import static org.mockito.Mockito.clearInvocations;
23 import static org.mockito.Mockito.mock;
24 import static org.mockito.Mockito.never;
25 import static org.mockito.Mockito.times;
26 import static org.mockito.Mockito.verify;
27 import static org.mockito.Mockito.when;
28 
29 import android.app.ActivityManager;
30 import android.app.KeyguardManager;
31 import android.app.Notification;
32 import android.app.admin.DevicePolicyManager;
33 import android.content.BroadcastReceiver;
34 import android.content.Context;
35 import android.content.pm.UserInfo;
36 import android.database.ContentObserver;
37 import android.os.Handler;
38 import android.os.Looper;
39 import android.os.UserHandle;
40 import android.os.UserManager;
41 import android.provider.Settings;
42 import android.testing.AndroidTestingRunner;
43 import android.testing.TestableLooper;
44 
45 import androidx.test.filters.SmallTest;
46 
47 import com.android.internal.widget.LockPatternUtils;
48 import com.android.systemui.Dependency;
49 import com.android.systemui.SysuiTestCase;
50 import com.android.systemui.broadcast.BroadcastDispatcher;
51 import com.android.systemui.dump.DumpManager;
52 import com.android.systemui.flags.FakeFeatureFlags;
53 import com.android.systemui.flags.Flags;
54 import com.android.systemui.plugins.statusbar.StatusBarStateController;
55 import com.android.systemui.recents.OverviewProxyService;
56 import com.android.systemui.settings.UserTracker;
57 import com.android.systemui.statusbar.NotificationLockscreenUserManager.NotificationStateChangedListener;
58 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
59 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
60 import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
61 import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
62 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
63 import com.android.systemui.statusbar.policy.KeyguardStateController;
64 import com.android.systemui.util.settings.FakeSettings;
65 
66 import com.google.android.collect.Lists;
67 
68 import org.junit.Before;
69 import org.junit.Test;
70 import org.junit.runner.RunWith;
71 import org.mockito.Mock;
72 import org.mockito.MockitoAnnotations;
73 
74 @SmallTest
75 @RunWith(AndroidTestingRunner.class)
76 @TestableLooper.RunWithLooper
77 public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
78     @Mock
79     private NotificationPresenter mPresenter;
80     @Mock
81     private UserManager mUserManager;
82     @Mock
83     private UserTracker mUserTracker;
84 
85     // Dependency mocks:
86     @Mock
87     private NotificationVisibilityProvider mVisibilityProvider;
88     @Mock
89     private CommonNotifCollection mNotifCollection;
90     @Mock
91     private DevicePolicyManager mDevicePolicyManager;
92     @Mock
93     private NotificationClickNotifier mClickNotifier;
94     @Mock
95     private OverviewProxyService mOverviewProxyService;
96     @Mock
97     private KeyguardManager mKeyguardManager;
98     @Mock
99     private DeviceProvisionedController mDeviceProvisionedController;
100     @Mock
101     private StatusBarStateController mStatusBarStateController;
102     @Mock
103     private BroadcastDispatcher mBroadcastDispatcher;
104     @Mock
105     private KeyguardStateController mKeyguardStateController;
106 
107     private UserInfo mCurrentUser;
108     private UserInfo mSecondaryUser;
109     private UserInfo mWorkUser;
110     private FakeSettings mSettings;
111     private TestNotificationLockscreenUserManager mLockscreenUserManager;
112     private NotificationEntry mCurrentUserNotif;
113     private NotificationEntry mSecondaryUserNotif;
114     private NotificationEntry mWorkProfileNotif;
115     private final FakeFeatureFlags mFakeFeatureFlags = new FakeFeatureFlags();
116 
117     @Before
setUp()118     public void setUp() {
119         MockitoAnnotations.initMocks(this);
120 
121         int currentUserId = ActivityManager.getCurrentUser();
122         when(mUserTracker.getUserId()).thenReturn(currentUserId);
123         mSettings = new FakeSettings();
124         mSettings.setUserId(ActivityManager.getCurrentUser());
125         mCurrentUser = new UserInfo(currentUserId, "", 0);
126         mSecondaryUser = new UserInfo(currentUserId + 1, "", 0);
127         mWorkUser = new UserInfo(currentUserId + 2, "" /* name */, null /* iconPath */, 0,
128                 UserManager.USER_TYPE_PROFILE_MANAGED);
129 
130         when(mUserManager.getProfiles(currentUserId)).thenReturn(Lists.newArrayList(
131                 mCurrentUser, mSecondaryUser, mWorkUser));
132         mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
133                 Handler.createAsync(Looper.myLooper()));
134 
135         Notification notifWithPrivateVisibility = new Notification();
136         notifWithPrivateVisibility.visibility = Notification.VISIBILITY_PRIVATE;
137         mCurrentUserNotif = new NotificationEntryBuilder()
138                 .setNotification(notifWithPrivateVisibility)
139                 .setUser(new UserHandle(mCurrentUser.id))
140                 .build();
141         mSecondaryUserNotif = new NotificationEntryBuilder()
142                 .setNotification(notifWithPrivateVisibility)
143                 .setUser(new UserHandle(mSecondaryUser.id))
144                 .build();
145         mWorkProfileNotif = new NotificationEntryBuilder()
146                 .setNotification(notifWithPrivateVisibility)
147                 .setUser(new UserHandle(mWorkUser.id))
148                 .build();
149 
150         mLockscreenUserManager = new TestNotificationLockscreenUserManager(mContext);
151         mLockscreenUserManager.setUpWithPresenter(mPresenter);
152     }
153 
154     @Test
testLockScreenShowNotificationsFalse()155     public void testLockScreenShowNotificationsFalse() {
156         mSettings.putInt(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0);
157         mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
158         assertFalse(mLockscreenUserManager.shouldShowLockscreenNotifications());
159     }
160 
161     @Test
testLockScreenShowNotificationsTrue()162     public void testLockScreenShowNotificationsTrue() {
163         mSettings.putInt(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 1);
164         mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
165         assertTrue(mLockscreenUserManager.shouldShowLockscreenNotifications());
166     }
167 
168     @Test
testLockScreenAllowPrivateNotificationsTrue()169     public void testLockScreenAllowPrivateNotificationsTrue() {
170         mSettings.putInt(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1);
171         mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
172         assertTrue(mLockscreenUserManager.userAllowsPrivateNotificationsInPublic(mCurrentUser.id));
173     }
174 
175     @Test
testLockScreenAllowPrivateNotificationsFalse()176     public void testLockScreenAllowPrivateNotificationsFalse() {
177         mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
178                 mCurrentUser.id);
179         mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
180         assertFalse(mLockscreenUserManager.userAllowsPrivateNotificationsInPublic(mCurrentUser.id));
181     }
182 
183     @Test
testLockScreenAllowsWorkPrivateNotificationsFalse()184     public void testLockScreenAllowsWorkPrivateNotificationsFalse() {
185         mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
186                 mWorkUser.id);
187         mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
188         assertFalse(mLockscreenUserManager.userAllowsPrivateNotificationsInPublic(mWorkUser.id));
189     }
190 
191     @Test
testLockScreenAllowsWorkPrivateNotificationsTrue()192     public void testLockScreenAllowsWorkPrivateNotificationsTrue() {
193         mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
194                 mWorkUser.id);
195         mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
196         assertTrue(mLockscreenUserManager.userAllowsPrivateNotificationsInPublic(mWorkUser.id));
197     }
198 
199     @Test
testCurrentUserPrivateNotificationsNotRedacted()200     public void testCurrentUserPrivateNotificationsNotRedacted() {
201         // GIVEN current user doesn't allow private notifications to show
202         mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
203                 mCurrentUser.id);
204         mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
205 
206         // THEN current user's notification is redacted
207         assertTrue(mLockscreenUserManager.needsRedaction(mCurrentUserNotif));
208     }
209 
210     @Test
testCurrentUserPrivateNotificationsRedacted()211     public void testCurrentUserPrivateNotificationsRedacted() {
212         // GIVEN current user allows private notifications to show
213         mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
214                 mCurrentUser.id);
215         mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
216 
217         // THEN current user's notification isn't redacted
218         assertFalse(mLockscreenUserManager.needsRedaction(mCurrentUserNotif));
219     }
220 
221     @Test
testWorkPrivateNotificationsRedacted()222     public void testWorkPrivateNotificationsRedacted() {
223         // GIVEN work profile doesn't private notifications to show
224         mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
225                 mWorkUser.id);
226         mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
227 
228         // THEN work profile notification is redacted
229         assertTrue(mLockscreenUserManager.needsRedaction(mWorkProfileNotif));
230     }
231 
232     @Test
testWorkPrivateNotificationsNotRedacted()233     public void testWorkPrivateNotificationsNotRedacted() {
234         // GIVEN work profile allows private notifications to show
235         mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
236                 mWorkUser.id);
237         mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
238 
239         // THEN work profile notification isn't redacted
240         assertFalse(mLockscreenUserManager.needsRedaction(mWorkProfileNotif));
241     }
242 
243     @Test
testWorkPrivateNotificationsNotRedacted_otherUsersRedacted()244     public void testWorkPrivateNotificationsNotRedacted_otherUsersRedacted() {
245         // GIVEN work profile allows private notifications to show but the other users don't
246         mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
247                 mWorkUser.id);
248         mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
249                 mCurrentUser.id);
250         mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
251                 mSecondaryUser.id);
252         mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
253 
254         // THEN the work profile notification doesn't need to be redacted
255         assertFalse(mLockscreenUserManager.needsRedaction(mWorkProfileNotif));
256 
257         // THEN the current user and secondary user notifications do need to be redacted
258         assertTrue(mLockscreenUserManager.needsRedaction(mCurrentUserNotif));
259         assertTrue(mLockscreenUserManager.needsRedaction(mSecondaryUserNotif));
260     }
261 
262     @Test
testWorkProfileRedacted_otherUsersNotRedacted()263     public void testWorkProfileRedacted_otherUsersNotRedacted() {
264         // GIVEN work profile doesn't allow private notifications to show but the other users do
265         mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
266                 mWorkUser.id);
267         mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
268                 mCurrentUser.id);
269         mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
270                 mSecondaryUser.id);
271         mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
272 
273         // THEN the work profile notification needs to be redacted
274         assertTrue(mLockscreenUserManager.needsRedaction(mWorkProfileNotif));
275 
276         // THEN the current user and secondary user notifications don't need to be redacted
277         assertFalse(mLockscreenUserManager.needsRedaction(mCurrentUserNotif));
278         assertFalse(mLockscreenUserManager.needsRedaction(mSecondaryUserNotif));
279     }
280 
281     @Test
testSecondaryUserNotRedacted_currentUserRedacted()282     public void testSecondaryUserNotRedacted_currentUserRedacted() {
283         // GIVEN secondary profile allows private notifications to show but the current user
284         // doesn't allow private notifications to show
285         mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0,
286                 mCurrentUser.id);
287         mSettings.putIntForUser(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
288                 mSecondaryUser.id);
289         mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
290 
291         // THEN the secondary profile notification still needs to be redacted because the current
292         // user's setting takes precedence
293         assertTrue(mLockscreenUserManager.needsRedaction(mSecondaryUserNotif));
294     }
295 
296     @Test
testUserSwitchedCallsOnUserSwitching()297     public void testUserSwitchedCallsOnUserSwitching() {
298         mFakeFeatureFlags.set(Flags.LOAD_NOTIFICATIONS_BEFORE_THE_USER_SWITCH_IS_COMPLETE, true);
299         mLockscreenUserManager.getUserTrackerCallbackForTest().onUserChanging(mSecondaryUser.id,
300                 mContext);
301         verify(mPresenter, times(1)).onUserSwitched(mSecondaryUser.id);
302     }
303 
304     @Test
testUserSwitchedCallsOnUserSwitched()305     public void testUserSwitchedCallsOnUserSwitched() {
306         mFakeFeatureFlags.set(Flags.LOAD_NOTIFICATIONS_BEFORE_THE_USER_SWITCH_IS_COMPLETE, false);
307         mLockscreenUserManager.getUserTrackerCallbackForTest().onUserChanged(mSecondaryUser.id,
308                 mContext);
309         verify(mPresenter, times(1)).onUserSwitched(mSecondaryUser.id);
310     }
311 
312     @Test
testIsLockscreenPublicMode()313     public void testIsLockscreenPublicMode() {
314         assertFalse(mLockscreenUserManager.isLockscreenPublicMode(mCurrentUser.id));
315         mLockscreenUserManager.setLockscreenPublicMode(true, mCurrentUser.id);
316         assertTrue(mLockscreenUserManager.isLockscreenPublicMode(mCurrentUser.id));
317     }
318 
319     @Test
testUpdateIsPublicMode()320     public void testUpdateIsPublicMode() {
321         when(mKeyguardStateController.isMethodSecure()).thenReturn(true);
322 
323         NotificationStateChangedListener listener = mock(NotificationStateChangedListener.class);
324         mLockscreenUserManager.addNotificationStateChangedListener(listener);
325         mLockscreenUserManager.mCurrentProfiles.append(0, mock(UserInfo.class));
326 
327         // first call explicitly sets user 0 to not public; notifies
328         mLockscreenUserManager.updatePublicMode();
329         assertFalse(mLockscreenUserManager.isLockscreenPublicMode(0));
330         verify(listener).onNotificationStateChanged();
331         clearInvocations(listener);
332 
333         // calling again has no changes; does not notify
334         mLockscreenUserManager.updatePublicMode();
335         assertFalse(mLockscreenUserManager.isLockscreenPublicMode(0));
336         verify(listener, never()).onNotificationStateChanged();
337 
338         // Calling again with keyguard now showing makes user 0 public; notifies
339         when(mKeyguardStateController.isShowing()).thenReturn(true);
340         mLockscreenUserManager.updatePublicMode();
341         assertTrue(mLockscreenUserManager.isLockscreenPublicMode(0));
342         verify(listener).onNotificationStateChanged();
343         clearInvocations(listener);
344 
345         // calling again has no changes; does not notify
346         mLockscreenUserManager.updatePublicMode();
347         assertTrue(mLockscreenUserManager.isLockscreenPublicMode(0));
348         verify(listener, never()).onNotificationStateChanged();
349     }
350 
351     private class TestNotificationLockscreenUserManager
352             extends NotificationLockscreenUserManagerImpl {
TestNotificationLockscreenUserManager(Context context)353         public TestNotificationLockscreenUserManager(Context context) {
354             super(
355                     context,
356                     mBroadcastDispatcher,
357                     mDevicePolicyManager,
358                     mUserManager,
359                     mUserTracker,
360                     (() -> mVisibilityProvider),
361                     (() -> mNotifCollection),
362                     mClickNotifier,
363                     (() -> mOverviewProxyService),
364                     NotificationLockscreenUserManagerTest.this.mKeyguardManager,
365                     mStatusBarStateController,
366                     Handler.createAsync(Looper.myLooper()),
367                     mDeviceProvisionedController,
368                     mKeyguardStateController,
369                     mSettings,
370                     mock(DumpManager.class),
371                     mock(LockPatternUtils.class),
372                     mFakeFeatureFlags);
373         }
374 
getBaseBroadcastReceiverForTest()375         public BroadcastReceiver getBaseBroadcastReceiverForTest() {
376             return mBaseBroadcastReceiver;
377         }
378 
getUserTrackerCallbackForTest()379         public UserTracker.Callback getUserTrackerCallbackForTest() {
380             return mUserChangedCallback;
381         }
382 
getLockscreenSettingsObserverForTest()383         public ContentObserver getLockscreenSettingsObserverForTest() {
384             return mLockscreenSettingsObserver;
385         }
386 
getSettingsObserverForTest()387         public ContentObserver getSettingsObserverForTest() {
388             return mSettingsObserver;
389         }
390     }
391 }
392