blob: 7adf7af89f0dbd7fb821946e39c9770066ea5323 [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
Lucas Dupin8968f6a2019-08-09 17:41:15 -070020import static com.android.systemui.DejankUtils.whitelistIpcs;
Evan Laird25f02752019-08-14 19:25:06 -040021import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT;
Lucas Dupin8968f6a2019-08-09 17:41:15 -070022
Jason Monk297c04e2018-08-23 17:16:59 -040023import android.app.ActivityManager;
24import android.app.KeyguardManager;
25import android.app.Notification;
26import android.app.admin.DevicePolicyManager;
27import android.content.BroadcastReceiver;
28import android.content.Context;
29import android.content.Intent;
30import android.content.IntentFilter;
31import android.content.IntentSender;
32import android.content.pm.UserInfo;
33import android.database.ContentObserver;
34import android.os.RemoteException;
35import android.os.ServiceManager;
36import android.os.UserHandle;
37import android.os.UserManager;
38import android.provider.Settings;
Jason Monk297c04e2018-08-23 17:16:59 -040039import android.util.Log;
40import android.util.SparseArray;
41import android.util.SparseBooleanArray;
42
43import com.android.internal.statusbar.IStatusBarService;
44import com.android.internal.statusbar.NotificationVisibility;
45import com.android.internal.widget.LockPatternUtils;
46import com.android.keyguard.KeyguardUpdateMonitor;
47import com.android.systemui.Dependency;
48import com.android.systemui.Dumpable;
Beverly8fdb5332019-02-04 14:29:49 -050049import com.android.systemui.plugins.statusbar.StatusBarStateController;
50import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
Winson Chung2dbcf092018-10-24 13:00:41 -070051import com.android.systemui.recents.OverviewProxyService;
Jason Monk297c04e2018-08-23 17:16:59 -040052import com.android.systemui.statusbar.notification.NotificationEntryManager;
Gus Prevas415376b2018-11-08 10:43:27 -050053import com.android.systemui.statusbar.notification.NotificationUtils;
Ned Burnsf81c4c42019-01-07 14:10:43 -050054import com.android.systemui.statusbar.notification.collection.NotificationEntry;
Gustav Senntonf892fe92019-01-22 15:31:42 +000055import com.android.systemui.statusbar.notification.logging.NotificationLogger;
Jason Monk297c04e2018-08-23 17:16:59 -040056import com.android.systemui.statusbar.policy.DeviceProvisionedController;
Lucas Dupinc8f16e82019-09-17 18:24:50 -040057import com.android.systemui.statusbar.policy.KeyguardStateController;
Jason Monk297c04e2018-08-23 17:16:59 -040058
59import java.io.FileDescriptor;
60import java.io.PrintWriter;
Gus Prevasa18dc572019-01-14 16:11:22 -050061import java.util.ArrayList;
62import java.util.List;
Jason Monk297c04e2018-08-23 17:16:59 -040063
Govinda Wasserman2e86fb62019-08-13 11:35:44 -040064import javax.inject.Inject;
65import javax.inject.Singleton;
66
Jason Monk297c04e2018-08-23 17:16:59 -040067/**
68 * Handles keeping track of the current user, profiles, and various things related to hiding
69 * contents, redacting notifications, and the lockscreen.
70 */
Govinda Wasserman2e86fb62019-08-13 11:35:44 -040071@Singleton
Jason Monk297c04e2018-08-23 17:16:59 -040072public class NotificationLockscreenUserManagerImpl implements
73 Dumpable, NotificationLockscreenUserManager, StateListener {
74 private static final String TAG = "LockscreenUserManager";
75 private static final boolean ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT = false;
76
77 private final DeviceProvisionedController mDeviceProvisionedController =
78 Dependency.get(DeviceProvisionedController.class);
Lucas Dupinc8f16e82019-09-17 18:24:50 -040079 private final KeyguardStateController mKeyguardStateController = Dependency.get(
80 KeyguardStateController.class);
Jason Monk297c04e2018-08-23 17:16:59 -040081
82 // Lazy
83 private NotificationEntryManager mEntryManager;
84
85 private final DevicePolicyManager mDevicePolicyManager;
86 private final SparseBooleanArray mLockscreenPublicMode = new SparseBooleanArray();
Selim Cinek6f0a62a2019-04-09 18:40:12 -070087 private final SparseBooleanArray mUsersWithSeperateWorkChallenge = new SparseBooleanArray();
Jason Monk297c04e2018-08-23 17:16:59 -040088 private final SparseBooleanArray mUsersAllowingPrivateNotifications = new SparseBooleanArray();
89 private final SparseBooleanArray mUsersAllowingNotifications = new SparseBooleanArray();
90 private final UserManager mUserManager;
91 private final IStatusBarService mBarService;
Gus Prevasa18dc572019-01-14 16:11:22 -050092 private final List<UserChangedListener> mListeners = new ArrayList<>();
Jason Monk297c04e2018-08-23 17:16:59 -040093
94 private boolean mShowLockscreenNotifications;
95 private boolean mAllowLockscreenRemoteInput;
96 private LockPatternUtils mLockPatternUtils;
97 protected KeyguardManager mKeyguardManager;
98 private int mState = StatusBarState.SHADE;
99
100 protected final BroadcastReceiver mAllUsersReceiver = new BroadcastReceiver() {
101 @Override
102 public void onReceive(Context context, Intent intent) {
103 final String action = intent.getAction();
104
105 if (ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action) &&
106 isCurrentProfile(getSendingUserId())) {
107 mUsersAllowingPrivateNotifications.clear();
108 updateLockscreenNotificationSetting();
Beverly85d4c192019-09-30 11:40:39 -0400109 getEntryManager().updateNotifications("ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED");
Jason Monk297c04e2018-08-23 17:16:59 -0400110 }
111 }
112 };
113
114 protected final BroadcastReceiver mBaseBroadcastReceiver = new BroadcastReceiver() {
115 @Override
116 public void onReceive(Context context, Intent intent) {
117 String action = intent.getAction();
118 if (Intent.ACTION_USER_SWITCHED.equals(action)) {
119 mCurrentUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
120 updateCurrentProfilesCache();
121 Log.v(TAG, "userId " + mCurrentUserId + " is in the house");
122
123 updateLockscreenNotificationSetting();
124 updatePublicMode();
Selim Cinek4881f5f2019-04-26 16:59:03 -0700125 // The filtering needs to happen before the update call below in order to make sure
126 // the presenter has the updated notifications from the new user
Beverly85d4c192019-09-30 11:40:39 -0400127 getEntryManager().getNotificationData().filterAndSort("user switched");
Selim Cinek4881f5f2019-04-26 16:59:03 -0700128 mPresenter.onUserSwitched(mCurrentUserId);
Gus Prevasa18dc572019-01-14 16:11:22 -0500129
130 for (UserChangedListener listener : mListeners) {
131 listener.onUserChanged(mCurrentUserId);
132 }
Jason Monk297c04e2018-08-23 17:16:59 -0400133 } else if (Intent.ACTION_USER_ADDED.equals(action)) {
134 updateCurrentProfilesCache();
135 } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
136 // Start the overview connection to the launcher service
137 Dependency.get(OverviewProxyService.class).startConnectionToCurrentUser();
138 } else if (NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION.equals(action)) {
139 final IntentSender intentSender = intent.getParcelableExtra(Intent.EXTRA_INTENT);
140 final String notificationKey = intent.getStringExtra(Intent.EXTRA_INDEX);
141 if (intentSender != null) {
142 try {
143 mContext.startIntentSender(intentSender, null, 0, 0, 0);
144 } catch (IntentSender.SendIntentException e) {
145 /* ignore */
146 }
147 }
148 if (notificationKey != null) {
149 final int count =
150 getEntryManager().getNotificationData().getActiveNotifications().size();
151 final int rank = getEntryManager().getNotificationData().getRank(notificationKey);
Gustav Senntonf892fe92019-01-22 15:31:42 +0000152 NotificationVisibility.NotificationLocation location =
153 NotificationLogger.getNotificationLocation(
154 getEntryManager().getNotificationData().get(notificationKey));
Jason Monk297c04e2018-08-23 17:16:59 -0400155 final NotificationVisibility nv = NotificationVisibility.obtain(notificationKey,
Gustav Senntonf892fe92019-01-22 15:31:42 +0000156 rank, count, true, location);
Jason Monk297c04e2018-08-23 17:16:59 -0400157 try {
158 mBarService.onNotificationClick(notificationKey, nv);
159 } catch (RemoteException e) {
160 /* ignore */
161 }
162 }
163 }
164 }
165 };
166
167 protected final Context mContext;
168 protected final SparseArray<UserInfo> mCurrentProfiles = new SparseArray<>();
169
170 protected int mCurrentUserId = 0;
171 protected NotificationPresenter mPresenter;
172 protected ContentObserver mLockscreenSettingsObserver;
173 protected ContentObserver mSettingsObserver;
174
175 private NotificationEntryManager getEntryManager() {
176 if (mEntryManager == null) {
177 mEntryManager = Dependency.get(NotificationEntryManager.class);
178 }
179 return mEntryManager;
180 }
181
Govinda Wasserman2e86fb62019-08-13 11:35:44 -0400182 @Inject
Jason Monk297c04e2018-08-23 17:16:59 -0400183 public NotificationLockscreenUserManagerImpl(Context context) {
184 mContext = context;
185 mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService(
186 Context.DEVICE_POLICY_SERVICE);
187 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
188 mCurrentUserId = ActivityManager.getCurrentUser();
189 mBarService = IStatusBarService.Stub.asInterface(
190 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
Jason Monkaf08c152018-12-04 11:12:39 -0500191 Dependency.get(StatusBarStateController.class).addCallback(this);
Jason Monk297c04e2018-08-23 17:16:59 -0400192 mLockPatternUtils = new LockPatternUtils(context);
193 mKeyguardManager = context.getSystemService(KeyguardManager.class);
194 }
195
196 public void setUpWithPresenter(NotificationPresenter presenter) {
197 mPresenter = presenter;
198
199 mLockscreenSettingsObserver = new ContentObserver(Dependency.get(Dependency.MAIN_HANDLER)) {
200 @Override
201 public void onChange(boolean selfChange) {
202 // We don't know which user changed LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS or
203 // LOCK_SCREEN_SHOW_NOTIFICATIONS, so we just dump our cache ...
204 mUsersAllowingPrivateNotifications.clear();
205 mUsersAllowingNotifications.clear();
206 // ... and refresh all the notifications
207 updateLockscreenNotificationSetting();
Beverly85d4c192019-09-30 11:40:39 -0400208 getEntryManager().updateNotifications("LOCK_SCREEN_SHOW_NOTIFICATIONS,"
209 + " or LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS change");
Jason Monk297c04e2018-08-23 17:16:59 -0400210 }
211 };
212
213 mSettingsObserver = new ContentObserver(Dependency.get(Dependency.MAIN_HANDLER)) {
214 @Override
215 public void onChange(boolean selfChange) {
216 updateLockscreenNotificationSetting();
217 if (mDeviceProvisionedController.isDeviceProvisioned()) {
Beverly85d4c192019-09-30 11:40:39 -0400218 getEntryManager().updateNotifications("LOCK_SCREEN_ALLOW_REMOTE_INPUT"
219 + " or ZEN_MODE change");
Jason Monk297c04e2018-08-23 17:16:59 -0400220 }
221 }
222 };
223
224 mContext.getContentResolver().registerContentObserver(
225 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS), false,
226 mLockscreenSettingsObserver,
227 UserHandle.USER_ALL);
228
229 mContext.getContentResolver().registerContentObserver(
230 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS),
231 true,
232 mLockscreenSettingsObserver,
233 UserHandle.USER_ALL);
234
235 mContext.getContentResolver().registerContentObserver(
236 Settings.Global.getUriFor(Settings.Global.ZEN_MODE), false,
237 mSettingsObserver);
238
239 if (ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT) {
240 mContext.getContentResolver().registerContentObserver(
241 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT),
242 false,
243 mSettingsObserver,
244 UserHandle.USER_ALL);
245 }
246
247 mContext.registerReceiverAsUser(mAllUsersReceiver, UserHandle.ALL,
248 new IntentFilter(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
249 null, null);
250
251 IntentFilter filter = new IntentFilter();
252 filter.addAction(Intent.ACTION_USER_SWITCHED);
253 filter.addAction(Intent.ACTION_USER_ADDED);
254 filter.addAction(Intent.ACTION_USER_UNLOCKED);
255 mContext.registerReceiver(mBaseBroadcastReceiver, filter);
256
257 IntentFilter internalFilter = new IntentFilter();
258 internalFilter.addAction(NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION);
259 mContext.registerReceiver(mBaseBroadcastReceiver, internalFilter, PERMISSION_SELF, null);
260
261 updateCurrentProfilesCache();
262
263 mSettingsObserver.onChange(false); // set up
264 }
265
266 public boolean shouldShowLockscreenNotifications() {
267 return mShowLockscreenNotifications;
268 }
269
270 public boolean shouldAllowLockscreenRemoteInput() {
271 return mAllowLockscreenRemoteInput;
272 }
273
274 public boolean isCurrentProfile(int userId) {
275 synchronized (mCurrentProfiles) {
276 return userId == UserHandle.USER_ALL || mCurrentProfiles.get(userId) != null;
277 }
278 }
279
280 /**
281 * Returns true if notifications are temporarily disabled for this user for security reasons,
282 * regardless of the normal settings for that user.
283 */
284 private boolean shouldTemporarilyHideNotifications(int userId) {
285 if (userId == UserHandle.USER_ALL) {
286 userId = mCurrentUserId;
287 }
Dave Mankoffe2294692019-08-14 11:53:13 -0400288 return Dependency.get(KeyguardUpdateMonitor.class).isUserInLockdown(userId);
Jason Monk297c04e2018-08-23 17:16:59 -0400289 }
290
291 /**
292 * Returns true if we're on a secure lockscreen and the user wants to hide notification data.
293 * If so, notifications should be hidden.
294 */
295 public boolean shouldHideNotifications(int userId) {
296 return isLockscreenPublicMode(userId) && !userAllowsNotificationsInPublic(userId)
297 || (userId != mCurrentUserId && shouldHideNotifications(mCurrentUserId))
298 || shouldTemporarilyHideNotifications(userId);
299 }
300
301 /**
302 * Returns true if we're on a secure lockscreen and the user wants to hide notifications via
303 * package-specific override.
304 */
305 public boolean shouldHideNotifications(String key) {
306 if (getEntryManager() == null) {
307 Log.wtf(TAG, "mEntryManager was null!", new Throwable());
308 return true;
309 }
310 return isLockscreenPublicMode(mCurrentUserId)
311 && getEntryManager().getNotificationData().getVisibilityOverride(key) ==
312 Notification.VISIBILITY_SECRET;
313 }
314
Ned Burns8c1b7632019-07-19 14:26:15 -0400315 public boolean shouldShowOnKeyguard(NotificationEntry entry) {
Jason Monk297c04e2018-08-23 17:16:59 -0400316 if (getEntryManager() == null) {
317 Log.wtf(TAG, "mEntryManager was null!", new Throwable());
318 return false;
319 }
Gus Prevasdddef392018-11-02 15:41:43 -0400320 boolean exceedsPriorityThreshold;
Julia Reynolds5b655c32019-04-24 14:40:17 -0400321 if (NotificationUtils.useNewInterruptionModel(mContext)
322 && hideSilentNotificationsOnLockscreen()) {
Evan Laird25f02752019-08-14 19:25:06 -0400323 exceedsPriorityThreshold = entry.getBucket() != BUCKET_SILENT;
Gus Prevasdddef392018-11-02 15:41:43 -0400324 } else {
325 exceedsPriorityThreshold =
Ned Burns00b4b2d2019-10-17 22:09:27 -0400326 !getEntryManager().getNotificationData().isAmbient(entry.getKey());
Gus Prevasdddef392018-11-02 15:41:43 -0400327 }
328 return mShowLockscreenNotifications && exceedsPriorityThreshold;
Jason Monk297c04e2018-08-23 17:16:59 -0400329 }
330
Julia Reynolds5b655c32019-04-24 14:40:17 -0400331 private boolean hideSilentNotificationsOnLockscreen() {
Lucas Dupin8968f6a2019-08-09 17:41:15 -0700332 // TODO(b/140058091)
333 return whitelistIpcs(() -> Settings.Secure.getInt(mContext.getContentResolver(),
334 Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 1) == 0);
Julia Reynolds5b655c32019-04-24 14:40:17 -0400335 }
336
Jason Monk297c04e2018-08-23 17:16:59 -0400337 private void setShowLockscreenNotifications(boolean show) {
338 mShowLockscreenNotifications = show;
339 }
340
341 private void setLockscreenAllowRemoteInput(boolean allowLockscreenRemoteInput) {
342 mAllowLockscreenRemoteInput = allowLockscreenRemoteInput;
343 }
344
345 protected void updateLockscreenNotificationSetting() {
346 final boolean show = Settings.Secure.getIntForUser(mContext.getContentResolver(),
347 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS,
348 1,
349 mCurrentUserId) != 0;
350 final int dpmFlags = mDevicePolicyManager.getKeyguardDisabledFeatures(
351 null /* admin */, mCurrentUserId);
352 final boolean allowedByDpm = (dpmFlags
353 & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS) == 0;
354
355 setShowLockscreenNotifications(show && allowedByDpm);
356
357 if (ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT) {
358 final boolean remoteInput = Settings.Secure.getIntForUser(mContext.getContentResolver(),
359 Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT,
360 0,
361 mCurrentUserId) != 0;
362 final boolean remoteInputDpm =
363 (dpmFlags & DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT) == 0;
364
365 setLockscreenAllowRemoteInput(remoteInput && remoteInputDpm);
366 } else {
367 setLockscreenAllowRemoteInput(false);
368 }
369 }
370
371 /**
372 * Has the given user chosen to allow their private (full) notifications to be shown even
373 * when the lockscreen is in "public" (secure & locked) mode?
374 */
375 public boolean userAllowsPrivateNotificationsInPublic(int userHandle) {
376 if (userHandle == UserHandle.USER_ALL) {
377 return true;
378 }
379
380 if (mUsersAllowingPrivateNotifications.indexOfKey(userHandle) < 0) {
381 final boolean allowedByUser = 0 != Settings.Secure.getIntForUser(
382 mContext.getContentResolver(),
383 Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0, userHandle);
384 final boolean allowedByDpm = adminAllowsKeyguardFeature(userHandle,
385 DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
386 final boolean allowed = allowedByUser && allowedByDpm;
387 mUsersAllowingPrivateNotifications.append(userHandle, allowed);
388 return allowed;
389 }
390
391 return mUsersAllowingPrivateNotifications.get(userHandle);
392 }
393
394 private boolean adminAllowsKeyguardFeature(int userHandle, int feature) {
395 if (userHandle == UserHandle.USER_ALL) {
396 return true;
397 }
398 final int dpmFlags =
399 mDevicePolicyManager.getKeyguardDisabledFeatures(null /* admin */, userHandle);
400 return (dpmFlags & feature) == 0;
401 }
402
403 /**
404 * Save the current "public" (locked and secure) state of the lockscreen.
405 */
406 public void setLockscreenPublicMode(boolean publicMode, int userId) {
407 mLockscreenPublicMode.put(userId, publicMode);
408 }
409
410 public boolean isLockscreenPublicMode(int userId) {
411 if (userId == UserHandle.USER_ALL) {
412 return mLockscreenPublicMode.get(mCurrentUserId, false);
413 }
414 return mLockscreenPublicMode.get(userId, false);
415 }
416
Selim Cinek6f0a62a2019-04-09 18:40:12 -0700417 @Override
418 public boolean needsSeparateWorkChallenge(int userId) {
419 return mUsersWithSeperateWorkChallenge.get(userId, false);
420 }
421
Jason Monk297c04e2018-08-23 17:16:59 -0400422 /**
423 * Has the given user chosen to allow notifications to be shown even when the lockscreen is in
424 * "public" (secure & locked) mode?
425 */
426 private boolean userAllowsNotificationsInPublic(int userHandle) {
427 if (isCurrentProfile(userHandle) && userHandle != mCurrentUserId) {
428 return true;
429 }
430
431 if (mUsersAllowingNotifications.indexOfKey(userHandle) < 0) {
432 final boolean allowedByUser = 0 != Settings.Secure.getIntForUser(
433 mContext.getContentResolver(),
434 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, userHandle);
435 final boolean allowedByDpm = adminAllowsKeyguardFeature(userHandle,
436 DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
Zimuzob3b9c262018-10-31 11:54:20 +0000437 final boolean allowedBySystem = mKeyguardManager.getPrivateNotificationsAllowed();
438 final boolean allowed = allowedByUser && allowedByDpm && allowedBySystem;
Jason Monk297c04e2018-08-23 17:16:59 -0400439 mUsersAllowingNotifications.append(userHandle, allowed);
440 return allowed;
441 }
442
443 return mUsersAllowingNotifications.get(userHandle);
444 }
445
446 /** @return true if the entry needs redaction when on the lockscreen. */
Ned Burnsf81c4c42019-01-07 14:10:43 -0500447 public boolean needsRedaction(NotificationEntry ent) {
Ned Burns00b4b2d2019-10-17 22:09:27 -0400448 int userId = ent.getSbn().getUserId();
Jason Monk297c04e2018-08-23 17:16:59 -0400449
450 boolean currentUserWantsRedaction = !userAllowsPrivateNotificationsInPublic(mCurrentUserId);
451 boolean notiUserWantsRedaction = !userAllowsPrivateNotificationsInPublic(userId);
452 boolean redactedLockscreen = currentUserWantsRedaction || notiUserWantsRedaction;
453
454 boolean notificationRequestsRedaction =
Ned Burns00b4b2d2019-10-17 22:09:27 -0400455 ent.getSbn().getNotification().visibility == Notification.VISIBILITY_PRIVATE;
456 boolean userForcesRedaction = packageHasVisibilityOverride(ent.getSbn().getKey());
Jason Monk297c04e2018-08-23 17:16:59 -0400457
458 return userForcesRedaction || notificationRequestsRedaction && redactedLockscreen;
459 }
460
461 private boolean packageHasVisibilityOverride(String key) {
462 if (getEntryManager() == null) {
463 Log.wtf(TAG, "mEntryManager was null!", new Throwable());
464 return true;
465 }
466 return getEntryManager().getNotificationData().getVisibilityOverride(key) ==
467 Notification.VISIBILITY_PRIVATE;
468 }
469
470 private void updateCurrentProfilesCache() {
471 synchronized (mCurrentProfiles) {
472 mCurrentProfiles.clear();
473 if (mUserManager != null) {
474 for (UserInfo user : mUserManager.getProfiles(mCurrentUserId)) {
475 mCurrentProfiles.put(user.id, user);
476 }
477 }
478 }
479 }
480
481 public boolean isAnyProfilePublicMode() {
482 for (int i = mCurrentProfiles.size() - 1; i >= 0; i--) {
483 if (isLockscreenPublicMode(mCurrentProfiles.valueAt(i).id)) {
484 return true;
485 }
486 }
487 return false;
488 }
489
490 /**
491 * Returns the current user id. This can change if the user is switched.
492 */
493 public int getCurrentUserId() {
494 return mCurrentUserId;
495 }
496
497 public SparseArray<UserInfo> getCurrentProfiles() {
498 return mCurrentProfiles;
499 }
500
501 @Override
502 public void onStateChanged(int newState) {
503 mState = newState;
504 updatePublicMode();
505 }
506
507 public void updatePublicMode() {
508 //TODO: I think there may be a race condition where mKeyguardViewManager.isShowing() returns
509 // false when it should be true. Therefore, if we are not on the SHADE, don't even bother
510 // asking if the keyguard is showing. We still need to check it though because showing the
511 // camera on the keyguard has a state of SHADE but the keyguard is still showing.
512 final boolean showingKeyguard = mState != StatusBarState.SHADE
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400513 || mKeyguardStateController.isShowing();
514 final boolean devicePublic = showingKeyguard && mKeyguardStateController.isMethodSecure();
Jason Monk297c04e2018-08-23 17:16:59 -0400515
516
517 // Look for public mode users. Users are considered public in either case of:
518 // - device keyguard is shown in secure mode;
519 // - profile is locked with a work challenge.
520 SparseArray<UserInfo> currentProfiles = getCurrentProfiles();
Selim Cinek6f0a62a2019-04-09 18:40:12 -0700521 mUsersWithSeperateWorkChallenge.clear();
Jason Monk297c04e2018-08-23 17:16:59 -0400522 for (int i = currentProfiles.size() - 1; i >= 0; i--) {
523 final int userId = currentProfiles.valueAt(i).id;
524 boolean isProfilePublic = devicePublic;
Lucas Dupin8968f6a2019-08-09 17:41:15 -0700525 // TODO(b/140058091)
526 boolean needsSeparateChallenge = whitelistIpcs(() ->
527 mLockPatternUtils.isSeparateProfileChallengeEnabled(userId));
Pavel Grafov85384122019-05-23 15:39:49 +0100528 if (!devicePublic && userId != getCurrentUserId()
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400529 && needsSeparateChallenge && mLockPatternUtils.isSecure(userId)) {
Pavel Grafov85384122019-05-23 15:39:49 +0100530 // Keyguard.isDeviceLocked is updated asynchronously, assume that all profiles
531 // with separate challenge are locked when keyguard is visible to avoid race.
532 isProfilePublic = showingKeyguard || mKeyguardManager.isDeviceLocked(userId);
Jason Monk297c04e2018-08-23 17:16:59 -0400533 }
534 setLockscreenPublicMode(isProfilePublic, userId);
Selim Cinek6f0a62a2019-04-09 18:40:12 -0700535 mUsersWithSeperateWorkChallenge.put(userId, needsSeparateChallenge);
Jason Monk297c04e2018-08-23 17:16:59 -0400536 }
Beverly85d4c192019-09-30 11:40:39 -0400537 getEntryManager().updateNotifications("NotificationLockscreenUserManager.updatePublicMode");
Jason Monk297c04e2018-08-23 17:16:59 -0400538 }
539
Gus Prevasa18dc572019-01-14 16:11:22 -0500540 @Override
541 public void addUserChangedListener(UserChangedListener listener) {
542 mListeners.add(listener);
543 }
Jason Monk297c04e2018-08-23 17:16:59 -0400544
545// public void updatePublicMode() {
546// //TODO: I think there may be a race condition where mKeyguardViewManager.isShowing() returns
547// // false when it should be true. Therefore, if we are not on the SHADE, don't even bother
548// // asking if the keyguard is showing. We still need to check it though because showing the
549// // camera on the keyguard has a state of SHADE but the keyguard is still showing.
550// final boolean showingKeyguard = mState != StatusBarState.SHADE
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400551// || mKeyguardStateController.isShowing();
Jason Monk297c04e2018-08-23 17:16:59 -0400552// final boolean devicePublic = showingKeyguard && isSecure(getCurrentUserId());
553//
554//
555// // Look for public mode users. Users are considered public in either case of:
556// // - device keyguard is shown in secure mode;
557// // - profile is locked with a work challenge.
558// SparseArray<UserInfo> currentProfiles = getCurrentProfiles();
559// for (int i = currentProfiles.size() - 1; i >= 0; i--) {
560// final int userId = currentProfiles.valueAt(i).id;
561// boolean isProfilePublic = devicePublic;
562// if (!devicePublic && userId != getCurrentUserId()) {
563// // We can't rely on KeyguardManager#isDeviceLocked() for unified profile challenge
564// // due to a race condition where this code could be called before
565// // TrustManagerService updates its internal records, resulting in an incorrect
566// // state being cached in mLockscreenPublicMode. (b/35951989)
567// if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
568// && isSecure(userId)) {
569// isProfilePublic = mKeyguardManager.isDeviceLocked(userId);
570// }
571// }
572// setLockscreenPublicMode(isProfilePublic, userId);
573// }
574// }
575
Jason Monk297c04e2018-08-23 17:16:59 -0400576 @Override
577 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
578 pw.println("NotificationLockscreenUserManager state:");
579 pw.print(" mCurrentUserId=");
580 pw.println(mCurrentUserId);
581 pw.print(" mShowLockscreenNotifications=");
582 pw.println(mShowLockscreenNotifications);
583 pw.print(" mAllowLockscreenRemoteInput=");
584 pw.println(mAllowLockscreenRemoteInput);
585 pw.print(" mCurrentProfiles=");
586 for (int i = mCurrentProfiles.size() - 1; i >= 0; i--) {
587 final int userId = mCurrentProfiles.valueAt(i).id;
588 pw.print("" + userId + " ");
589 }
590 pw.println();
591 }
592}