blob: 802a7d29a7a5f5aeb0b783316fc2b25385f8a29e [file] [log] [blame]
Jason Monk297c04e2018-08-23 17:16:59 -04001/*
2 * Copyright (C) 2018 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 */
16package com.android.systemui.statusbar;
17
18import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
19
20import android.app.ActivityManager;
21import android.app.KeyguardManager;
22import android.app.Notification;
23import android.app.admin.DevicePolicyManager;
24import android.content.BroadcastReceiver;
25import android.content.Context;
26import android.content.Intent;
27import android.content.IntentFilter;
28import android.content.IntentSender;
29import android.content.pm.UserInfo;
30import android.database.ContentObserver;
31import android.os.RemoteException;
32import android.os.ServiceManager;
33import android.os.UserHandle;
34import android.os.UserManager;
35import android.provider.Settings;
Jason Monk297c04e2018-08-23 17:16:59 -040036import android.util.Log;
37import android.util.SparseArray;
38import android.util.SparseBooleanArray;
39
40import com.android.internal.statusbar.IStatusBarService;
41import com.android.internal.statusbar.NotificationVisibility;
42import com.android.internal.widget.LockPatternUtils;
43import com.android.keyguard.KeyguardUpdateMonitor;
44import com.android.systemui.Dependency;
45import com.android.systemui.Dumpable;
Beverly8fdb5332019-02-04 14:29:49 -050046import com.android.systemui.plugins.statusbar.StatusBarStateController;
47import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
Winson Chung2dbcf092018-10-24 13:00:41 -070048import com.android.systemui.recents.OverviewProxyService;
Jason Monk297c04e2018-08-23 17:16:59 -040049import com.android.systemui.statusbar.notification.NotificationEntryManager;
Gus Prevas415376b2018-11-08 10:43:27 -050050import com.android.systemui.statusbar.notification.NotificationUtils;
Ned Burnsf81c4c42019-01-07 14:10:43 -050051import com.android.systemui.statusbar.notification.collection.NotificationEntry;
Gustav Senntonf892fe92019-01-22 15:31:42 +000052import com.android.systemui.statusbar.notification.logging.NotificationLogger;
Jason Monk297c04e2018-08-23 17:16:59 -040053import com.android.systemui.statusbar.policy.DeviceProvisionedController;
54import com.android.systemui.statusbar.policy.KeyguardMonitor;
55
56import java.io.FileDescriptor;
57import java.io.PrintWriter;
Gus Prevasa18dc572019-01-14 16:11:22 -050058import java.util.ArrayList;
59import java.util.List;
Jason Monk297c04e2018-08-23 17:16:59 -040060
Govinda Wasserman3e7ce552019-08-13 11:35:44 -040061import javax.inject.Inject;
62import javax.inject.Singleton;
63
Jason Monk297c04e2018-08-23 17:16:59 -040064/**
65 * Handles keeping track of the current user, profiles, and various things related to hiding
66 * contents, redacting notifications, and the lockscreen.
67 */
Govinda Wasserman3e7ce552019-08-13 11:35:44 -040068@Singleton
Jason Monk297c04e2018-08-23 17:16:59 -040069public class NotificationLockscreenUserManagerImpl implements
70 Dumpable, NotificationLockscreenUserManager, StateListener {
71 private static final String TAG = "LockscreenUserManager";
72 private static final boolean ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT = false;
73
74 private final DeviceProvisionedController mDeviceProvisionedController =
75 Dependency.get(DeviceProvisionedController.class);
76 private final KeyguardMonitor mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
77
78 // Lazy
79 private NotificationEntryManager mEntryManager;
80
81 private final DevicePolicyManager mDevicePolicyManager;
82 private final SparseBooleanArray mLockscreenPublicMode = new SparseBooleanArray();
Selim Cinek6f0a62a2019-04-09 18:40:12 -070083 private final SparseBooleanArray mUsersWithSeperateWorkChallenge = new SparseBooleanArray();
Jason Monk297c04e2018-08-23 17:16:59 -040084 private final SparseBooleanArray mUsersAllowingPrivateNotifications = new SparseBooleanArray();
85 private final SparseBooleanArray mUsersAllowingNotifications = new SparseBooleanArray();
86 private final UserManager mUserManager;
87 private final IStatusBarService mBarService;
Gus Prevasa18dc572019-01-14 16:11:22 -050088 private final List<UserChangedListener> mListeners = new ArrayList<>();
Jason Monk297c04e2018-08-23 17:16:59 -040089
90 private boolean mShowLockscreenNotifications;
91 private boolean mAllowLockscreenRemoteInput;
92 private LockPatternUtils mLockPatternUtils;
93 protected KeyguardManager mKeyguardManager;
94 private int mState = StatusBarState.SHADE;
95
96 protected final BroadcastReceiver mAllUsersReceiver = new BroadcastReceiver() {
97 @Override
98 public void onReceive(Context context, Intent intent) {
99 final String action = intent.getAction();
100
101 if (ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action) &&
102 isCurrentProfile(getSendingUserId())) {
103 mUsersAllowingPrivateNotifications.clear();
104 updateLockscreenNotificationSetting();
105 getEntryManager().updateNotifications();
106 }
107 }
108 };
109
110 protected final BroadcastReceiver mBaseBroadcastReceiver = new BroadcastReceiver() {
111 @Override
112 public void onReceive(Context context, Intent intent) {
113 String action = intent.getAction();
114 if (Intent.ACTION_USER_SWITCHED.equals(action)) {
115 mCurrentUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
116 updateCurrentProfilesCache();
117 Log.v(TAG, "userId " + mCurrentUserId + " is in the house");
118
119 updateLockscreenNotificationSetting();
120 updatePublicMode();
Selim Cinek4881f5f2019-04-26 16:59:03 -0700121 // The filtering needs to happen before the update call below in order to make sure
122 // the presenter has the updated notifications from the new user
Jason Monk297c04e2018-08-23 17:16:59 -0400123 getEntryManager().getNotificationData().filterAndSort();
Selim Cinek4881f5f2019-04-26 16:59:03 -0700124 mPresenter.onUserSwitched(mCurrentUserId);
Gus Prevasa18dc572019-01-14 16:11:22 -0500125
126 for (UserChangedListener listener : mListeners) {
127 listener.onUserChanged(mCurrentUserId);
128 }
Jason Monk297c04e2018-08-23 17:16:59 -0400129 } else if (Intent.ACTION_USER_ADDED.equals(action)) {
130 updateCurrentProfilesCache();
131 } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
132 // Start the overview connection to the launcher service
133 Dependency.get(OverviewProxyService.class).startConnectionToCurrentUser();
134 } else if (NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION.equals(action)) {
135 final IntentSender intentSender = intent.getParcelableExtra(Intent.EXTRA_INTENT);
136 final String notificationKey = intent.getStringExtra(Intent.EXTRA_INDEX);
137 if (intentSender != null) {
138 try {
139 mContext.startIntentSender(intentSender, null, 0, 0, 0);
140 } catch (IntentSender.SendIntentException e) {
141 /* ignore */
142 }
143 }
144 if (notificationKey != null) {
145 final int count =
146 getEntryManager().getNotificationData().getActiveNotifications().size();
147 final int rank = getEntryManager().getNotificationData().getRank(notificationKey);
Gustav Senntonf892fe92019-01-22 15:31:42 +0000148 NotificationVisibility.NotificationLocation location =
149 NotificationLogger.getNotificationLocation(
150 getEntryManager().getNotificationData().get(notificationKey));
Jason Monk297c04e2018-08-23 17:16:59 -0400151 final NotificationVisibility nv = NotificationVisibility.obtain(notificationKey,
Gustav Senntonf892fe92019-01-22 15:31:42 +0000152 rank, count, true, location);
Jason Monk297c04e2018-08-23 17:16:59 -0400153 try {
154 mBarService.onNotificationClick(notificationKey, nv);
155 } catch (RemoteException e) {
156 /* ignore */
157 }
158 }
159 }
160 }
161 };
162
163 protected final Context mContext;
164 protected final SparseArray<UserInfo> mCurrentProfiles = new SparseArray<>();
165
166 protected int mCurrentUserId = 0;
167 protected NotificationPresenter mPresenter;
168 protected ContentObserver mLockscreenSettingsObserver;
169 protected ContentObserver mSettingsObserver;
170
171 private NotificationEntryManager getEntryManager() {
172 if (mEntryManager == null) {
173 mEntryManager = Dependency.get(NotificationEntryManager.class);
174 }
175 return mEntryManager;
176 }
177
Govinda Wasserman3e7ce552019-08-13 11:35:44 -0400178 @Inject
Jason Monk297c04e2018-08-23 17:16:59 -0400179 public NotificationLockscreenUserManagerImpl(Context context) {
180 mContext = context;
181 mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService(
182 Context.DEVICE_POLICY_SERVICE);
183 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
184 mCurrentUserId = ActivityManager.getCurrentUser();
185 mBarService = IStatusBarService.Stub.asInterface(
186 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
Jason Monkaf08c152018-12-04 11:12:39 -0500187 Dependency.get(StatusBarStateController.class).addCallback(this);
Jason Monk297c04e2018-08-23 17:16:59 -0400188 mLockPatternUtils = new LockPatternUtils(context);
189 mKeyguardManager = context.getSystemService(KeyguardManager.class);
190 }
191
192 public void setUpWithPresenter(NotificationPresenter presenter) {
193 mPresenter = presenter;
194
195 mLockscreenSettingsObserver = new ContentObserver(Dependency.get(Dependency.MAIN_HANDLER)) {
196 @Override
197 public void onChange(boolean selfChange) {
198 // We don't know which user changed LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS or
199 // LOCK_SCREEN_SHOW_NOTIFICATIONS, so we just dump our cache ...
200 mUsersAllowingPrivateNotifications.clear();
201 mUsersAllowingNotifications.clear();
202 // ... and refresh all the notifications
203 updateLockscreenNotificationSetting();
204 getEntryManager().updateNotifications();
205 }
206 };
207
208 mSettingsObserver = new ContentObserver(Dependency.get(Dependency.MAIN_HANDLER)) {
209 @Override
210 public void onChange(boolean selfChange) {
211 updateLockscreenNotificationSetting();
212 if (mDeviceProvisionedController.isDeviceProvisioned()) {
213 getEntryManager().updateNotifications();
214 }
215 }
216 };
217
218 mContext.getContentResolver().registerContentObserver(
219 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS), false,
220 mLockscreenSettingsObserver,
221 UserHandle.USER_ALL);
222
223 mContext.getContentResolver().registerContentObserver(
224 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS),
225 true,
226 mLockscreenSettingsObserver,
227 UserHandle.USER_ALL);
228
229 mContext.getContentResolver().registerContentObserver(
230 Settings.Global.getUriFor(Settings.Global.ZEN_MODE), false,
231 mSettingsObserver);
232
233 if (ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT) {
234 mContext.getContentResolver().registerContentObserver(
235 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT),
236 false,
237 mSettingsObserver,
238 UserHandle.USER_ALL);
239 }
240
241 mContext.registerReceiverAsUser(mAllUsersReceiver, UserHandle.ALL,
242 new IntentFilter(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
243 null, null);
244
245 IntentFilter filter = new IntentFilter();
246 filter.addAction(Intent.ACTION_USER_SWITCHED);
247 filter.addAction(Intent.ACTION_USER_ADDED);
248 filter.addAction(Intent.ACTION_USER_UNLOCKED);
249 mContext.registerReceiver(mBaseBroadcastReceiver, filter);
250
251 IntentFilter internalFilter = new IntentFilter();
252 internalFilter.addAction(NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION);
253 mContext.registerReceiver(mBaseBroadcastReceiver, internalFilter, PERMISSION_SELF, null);
254
255 updateCurrentProfilesCache();
256
257 mSettingsObserver.onChange(false); // set up
258 }
259
260 public boolean shouldShowLockscreenNotifications() {
261 return mShowLockscreenNotifications;
262 }
263
264 public boolean shouldAllowLockscreenRemoteInput() {
265 return mAllowLockscreenRemoteInput;
266 }
267
268 public boolean isCurrentProfile(int userId) {
269 synchronized (mCurrentProfiles) {
270 return userId == UserHandle.USER_ALL || mCurrentProfiles.get(userId) != null;
271 }
272 }
273
274 /**
275 * Returns true if notifications are temporarily disabled for this user for security reasons,
276 * regardless of the normal settings for that user.
277 */
278 private boolean shouldTemporarilyHideNotifications(int userId) {
279 if (userId == UserHandle.USER_ALL) {
280 userId = mCurrentUserId;
281 }
282 return KeyguardUpdateMonitor.getInstance(mContext).isUserInLockdown(userId);
283 }
284
285 /**
286 * Returns true if we're on a secure lockscreen and the user wants to hide notification data.
287 * If so, notifications should be hidden.
288 */
289 public boolean shouldHideNotifications(int userId) {
290 return isLockscreenPublicMode(userId) && !userAllowsNotificationsInPublic(userId)
291 || (userId != mCurrentUserId && shouldHideNotifications(mCurrentUserId))
292 || shouldTemporarilyHideNotifications(userId);
293 }
294
295 /**
296 * Returns true if we're on a secure lockscreen and the user wants to hide notifications via
297 * package-specific override.
298 */
299 public boolean shouldHideNotifications(String key) {
300 if (getEntryManager() == null) {
301 Log.wtf(TAG, "mEntryManager was null!", new Throwable());
302 return true;
303 }
304 return isLockscreenPublicMode(mCurrentUserId)
305 && getEntryManager().getNotificationData().getVisibilityOverride(key) ==
306 Notification.VISIBILITY_SECRET;
307 }
308
Ned Burns8c1b7632019-07-19 14:26:15 -0400309 public boolean shouldShowOnKeyguard(NotificationEntry entry) {
Jason Monk297c04e2018-08-23 17:16:59 -0400310 if (getEntryManager() == null) {
311 Log.wtf(TAG, "mEntryManager was null!", new Throwable());
312 return false;
313 }
Gus Prevasdddef392018-11-02 15:41:43 -0400314 boolean exceedsPriorityThreshold;
Julia Reynolds5b655c32019-04-24 14:40:17 -0400315 if (NotificationUtils.useNewInterruptionModel(mContext)
316 && hideSilentNotificationsOnLockscreen()) {
Ned Burns8c1b7632019-07-19 14:26:15 -0400317 exceedsPriorityThreshold = entry.isTopBucket();
Gus Prevasdddef392018-11-02 15:41:43 -0400318 } else {
319 exceedsPriorityThreshold =
Ned Burns8c1b7632019-07-19 14:26:15 -0400320 !getEntryManager().getNotificationData().isAmbient(entry.key);
Gus Prevasdddef392018-11-02 15:41:43 -0400321 }
322 return mShowLockscreenNotifications && exceedsPriorityThreshold;
Jason Monk297c04e2018-08-23 17:16:59 -0400323 }
324
Julia Reynolds5b655c32019-04-24 14:40:17 -0400325 private boolean hideSilentNotificationsOnLockscreen() {
326 return Settings.Secure.getInt(mContext.getContentResolver(),
Julia Reynolds837ed9a2019-06-06 11:17:20 -0400327 Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 1) == 0;
Julia Reynolds5b655c32019-04-24 14:40:17 -0400328 }
329
Jason Monk297c04e2018-08-23 17:16:59 -0400330 private void setShowLockscreenNotifications(boolean show) {
331 mShowLockscreenNotifications = show;
332 }
333
334 private void setLockscreenAllowRemoteInput(boolean allowLockscreenRemoteInput) {
335 mAllowLockscreenRemoteInput = allowLockscreenRemoteInput;
336 }
337
338 protected void updateLockscreenNotificationSetting() {
339 final boolean show = Settings.Secure.getIntForUser(mContext.getContentResolver(),
340 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS,
341 1,
342 mCurrentUserId) != 0;
343 final int dpmFlags = mDevicePolicyManager.getKeyguardDisabledFeatures(
344 null /* admin */, mCurrentUserId);
345 final boolean allowedByDpm = (dpmFlags
346 & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS) == 0;
347
348 setShowLockscreenNotifications(show && allowedByDpm);
349
350 if (ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT) {
351 final boolean remoteInput = Settings.Secure.getIntForUser(mContext.getContentResolver(),
352 Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT,
353 0,
354 mCurrentUserId) != 0;
355 final boolean remoteInputDpm =
356 (dpmFlags & DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT) == 0;
357
358 setLockscreenAllowRemoteInput(remoteInput && remoteInputDpm);
359 } else {
360 setLockscreenAllowRemoteInput(false);
361 }
362 }
363
364 /**
365 * Has the given user chosen to allow their private (full) notifications to be shown even
366 * when the lockscreen is in "public" (secure & locked) mode?
367 */
368 public boolean userAllowsPrivateNotificationsInPublic(int userHandle) {
369 if (userHandle == UserHandle.USER_ALL) {
370 return true;
371 }
372
373 if (mUsersAllowingPrivateNotifications.indexOfKey(userHandle) < 0) {
374 final boolean allowedByUser = 0 != Settings.Secure.getIntForUser(
375 mContext.getContentResolver(),
376 Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0, userHandle);
377 final boolean allowedByDpm = adminAllowsKeyguardFeature(userHandle,
378 DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
379 final boolean allowed = allowedByUser && allowedByDpm;
380 mUsersAllowingPrivateNotifications.append(userHandle, allowed);
381 return allowed;
382 }
383
384 return mUsersAllowingPrivateNotifications.get(userHandle);
385 }
386
387 private boolean adminAllowsKeyguardFeature(int userHandle, int feature) {
388 if (userHandle == UserHandle.USER_ALL) {
389 return true;
390 }
391 final int dpmFlags =
392 mDevicePolicyManager.getKeyguardDisabledFeatures(null /* admin */, userHandle);
393 return (dpmFlags & feature) == 0;
394 }
395
396 /**
397 * Save the current "public" (locked and secure) state of the lockscreen.
398 */
399 public void setLockscreenPublicMode(boolean publicMode, int userId) {
400 mLockscreenPublicMode.put(userId, publicMode);
401 }
402
403 public boolean isLockscreenPublicMode(int userId) {
404 if (userId == UserHandle.USER_ALL) {
405 return mLockscreenPublicMode.get(mCurrentUserId, false);
406 }
407 return mLockscreenPublicMode.get(userId, false);
408 }
409
Selim Cinek6f0a62a2019-04-09 18:40:12 -0700410 @Override
411 public boolean needsSeparateWorkChallenge(int userId) {
412 return mUsersWithSeperateWorkChallenge.get(userId, false);
413 }
414
Jason Monk297c04e2018-08-23 17:16:59 -0400415 /**
416 * Has the given user chosen to allow notifications to be shown even when the lockscreen is in
417 * "public" (secure & locked) mode?
418 */
419 private boolean userAllowsNotificationsInPublic(int userHandle) {
420 if (isCurrentProfile(userHandle) && userHandle != mCurrentUserId) {
421 return true;
422 }
423
424 if (mUsersAllowingNotifications.indexOfKey(userHandle) < 0) {
425 final boolean allowedByUser = 0 != Settings.Secure.getIntForUser(
426 mContext.getContentResolver(),
427 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, userHandle);
428 final boolean allowedByDpm = adminAllowsKeyguardFeature(userHandle,
429 DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
Zimuzob3b9c262018-10-31 11:54:20 +0000430 final boolean allowedBySystem = mKeyguardManager.getPrivateNotificationsAllowed();
431 final boolean allowed = allowedByUser && allowedByDpm && allowedBySystem;
Jason Monk297c04e2018-08-23 17:16:59 -0400432 mUsersAllowingNotifications.append(userHandle, allowed);
433 return allowed;
434 }
435
436 return mUsersAllowingNotifications.get(userHandle);
437 }
438
439 /** @return true if the entry needs redaction when on the lockscreen. */
Ned Burnsf81c4c42019-01-07 14:10:43 -0500440 public boolean needsRedaction(NotificationEntry ent) {
Jason Monk297c04e2018-08-23 17:16:59 -0400441 int userId = ent.notification.getUserId();
442
443 boolean currentUserWantsRedaction = !userAllowsPrivateNotificationsInPublic(mCurrentUserId);
444 boolean notiUserWantsRedaction = !userAllowsPrivateNotificationsInPublic(userId);
445 boolean redactedLockscreen = currentUserWantsRedaction || notiUserWantsRedaction;
446
447 boolean notificationRequestsRedaction =
448 ent.notification.getNotification().visibility == Notification.VISIBILITY_PRIVATE;
449 boolean userForcesRedaction = packageHasVisibilityOverride(ent.notification.getKey());
450
451 return userForcesRedaction || notificationRequestsRedaction && redactedLockscreen;
452 }
453
454 private boolean packageHasVisibilityOverride(String key) {
455 if (getEntryManager() == null) {
456 Log.wtf(TAG, "mEntryManager was null!", new Throwable());
457 return true;
458 }
459 return getEntryManager().getNotificationData().getVisibilityOverride(key) ==
460 Notification.VISIBILITY_PRIVATE;
461 }
462
463 private void updateCurrentProfilesCache() {
464 synchronized (mCurrentProfiles) {
465 mCurrentProfiles.clear();
466 if (mUserManager != null) {
467 for (UserInfo user : mUserManager.getProfiles(mCurrentUserId)) {
468 mCurrentProfiles.put(user.id, user);
469 }
470 }
471 }
472 }
473
474 public boolean isAnyProfilePublicMode() {
475 for (int i = mCurrentProfiles.size() - 1; i >= 0; i--) {
476 if (isLockscreenPublicMode(mCurrentProfiles.valueAt(i).id)) {
477 return true;
478 }
479 }
480 return false;
481 }
482
483 /**
484 * Returns the current user id. This can change if the user is switched.
485 */
486 public int getCurrentUserId() {
487 return mCurrentUserId;
488 }
489
490 public SparseArray<UserInfo> getCurrentProfiles() {
491 return mCurrentProfiles;
492 }
493
494 @Override
495 public void onStateChanged(int newState) {
496 mState = newState;
497 updatePublicMode();
498 }
499
500 public void updatePublicMode() {
501 //TODO: I think there may be a race condition where mKeyguardViewManager.isShowing() returns
502 // false when it should be true. Therefore, if we are not on the SHADE, don't even bother
503 // asking if the keyguard is showing. We still need to check it though because showing the
504 // camera on the keyguard has a state of SHADE but the keyguard is still showing.
505 final boolean showingKeyguard = mState != StatusBarState.SHADE
506 || mKeyguardMonitor.isShowing();
507 final boolean devicePublic = showingKeyguard && isSecure(getCurrentUserId());
508
509
510 // Look for public mode users. Users are considered public in either case of:
511 // - device keyguard is shown in secure mode;
512 // - profile is locked with a work challenge.
513 SparseArray<UserInfo> currentProfiles = getCurrentProfiles();
Selim Cinek6f0a62a2019-04-09 18:40:12 -0700514 mUsersWithSeperateWorkChallenge.clear();
Jason Monk297c04e2018-08-23 17:16:59 -0400515 for (int i = currentProfiles.size() - 1; i >= 0; i--) {
516 final int userId = currentProfiles.valueAt(i).id;
517 boolean isProfilePublic = devicePublic;
Selim Cinek6f0a62a2019-04-09 18:40:12 -0700518 boolean needsSeparateChallenge = mLockPatternUtils.isSeparateProfileChallengeEnabled(
519 userId);
Pavel Grafov85384122019-05-23 15:39:49 +0100520 if (!devicePublic && userId != getCurrentUserId()
521 && needsSeparateChallenge && isSecure(userId)) {
522 // Keyguard.isDeviceLocked is updated asynchronously, assume that all profiles
523 // with separate challenge are locked when keyguard is visible to avoid race.
524 isProfilePublic = showingKeyguard || mKeyguardManager.isDeviceLocked(userId);
Jason Monk297c04e2018-08-23 17:16:59 -0400525 }
526 setLockscreenPublicMode(isProfilePublic, userId);
Selim Cinek6f0a62a2019-04-09 18:40:12 -0700527 mUsersWithSeperateWorkChallenge.put(userId, needsSeparateChallenge);
Jason Monk297c04e2018-08-23 17:16:59 -0400528 }
Pavel Grafove2cf85a2019-05-17 13:11:01 +0100529 getEntryManager().updateNotifications();
Jason Monk297c04e2018-08-23 17:16:59 -0400530 }
531
Gus Prevasa18dc572019-01-14 16:11:22 -0500532 @Override
533 public void addUserChangedListener(UserChangedListener listener) {
534 mListeners.add(listener);
535 }
Jason Monk297c04e2018-08-23 17:16:59 -0400536
537// public void updatePublicMode() {
538// //TODO: I think there may be a race condition where mKeyguardViewManager.isShowing() returns
539// // false when it should be true. Therefore, if we are not on the SHADE, don't even bother
540// // asking if the keyguard is showing. We still need to check it though because showing the
541// // camera on the keyguard has a state of SHADE but the keyguard is still showing.
542// final boolean showingKeyguard = mState != StatusBarState.SHADE
543// || mKeyguardMonitor.isShowing();
544// final boolean devicePublic = showingKeyguard && isSecure(getCurrentUserId());
545//
546//
547// // Look for public mode users. Users are considered public in either case of:
548// // - device keyguard is shown in secure mode;
549// // - profile is locked with a work challenge.
550// SparseArray<UserInfo> currentProfiles = getCurrentProfiles();
551// for (int i = currentProfiles.size() - 1; i >= 0; i--) {
552// final int userId = currentProfiles.valueAt(i).id;
553// boolean isProfilePublic = devicePublic;
554// if (!devicePublic && userId != getCurrentUserId()) {
555// // We can't rely on KeyguardManager#isDeviceLocked() for unified profile challenge
556// // due to a race condition where this code could be called before
557// // TrustManagerService updates its internal records, resulting in an incorrect
558// // state being cached in mLockscreenPublicMode. (b/35951989)
559// if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
560// && isSecure(userId)) {
561// isProfilePublic = mKeyguardManager.isDeviceLocked(userId);
562// }
563// }
564// setLockscreenPublicMode(isProfilePublic, userId);
565// }
566// }
567
568 private boolean isSecure(int userId) {
569 return mKeyguardMonitor.isSecure() || mLockPatternUtils.isSecure(userId);
570 }
571
Jason Monk297c04e2018-08-23 17:16:59 -0400572 @Override
573 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
574 pw.println("NotificationLockscreenUserManager state:");
575 pw.print(" mCurrentUserId=");
576 pw.println(mCurrentUserId);
577 pw.print(" mShowLockscreenNotifications=");
578 pw.println(mShowLockscreenNotifications);
579 pw.print(" mAllowLockscreenRemoteInput=");
580 pw.println(mAllowLockscreenRemoteInput);
581 pw.print(" mCurrentProfiles=");
582 for (int i = mCurrentProfiles.size() - 1; i >= 0; i--) {
583 final int userId = mCurrentProfiles.valueAt(i).id;
584 pw.print("" + userId + " ");
585 }
586 pw.println();
587 }
588}