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