1 /* 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 */ 16 package com.android.systemui.statusbar; 17 18 import static android.app.Notification.VISIBILITY_SECRET; 19 import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED; 20 21 import static com.android.systemui.DejankUtils.whitelistIpcs; 22 import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_MEDIA_CONTROLS; 23 import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_SILENT; 24 25 import android.app.ActivityManager; 26 import android.app.KeyguardManager; 27 import android.app.Notification; 28 import android.app.NotificationManager; 29 import android.app.admin.DevicePolicyManager; 30 import android.content.BroadcastReceiver; 31 import android.content.Context; 32 import android.content.Intent; 33 import android.content.IntentFilter; 34 import android.content.IntentSender; 35 import android.content.pm.UserInfo; 36 import android.database.ContentObserver; 37 import android.os.Handler; 38 import android.os.UserHandle; 39 import android.os.UserManager; 40 import android.provider.Settings; 41 import android.util.Log; 42 import android.util.SparseArray; 43 import android.util.SparseBooleanArray; 44 45 import com.android.internal.statusbar.NotificationVisibility; 46 import com.android.internal.widget.LockPatternUtils; 47 import com.android.keyguard.KeyguardUpdateMonitor; 48 import com.android.systemui.Dependency; 49 import com.android.systemui.Dumpable; 50 import com.android.systemui.broadcast.BroadcastDispatcher; 51 import com.android.systemui.dagger.SysUISingleton; 52 import com.android.systemui.dagger.qualifiers.Main; 53 import com.android.systemui.dump.DumpManager; 54 import com.android.systemui.plugins.statusbar.StatusBarStateController; 55 import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; 56 import com.android.systemui.recents.OverviewProxyService; 57 import com.android.systemui.statusbar.notification.NotificationEntryManager; 58 import com.android.systemui.statusbar.notification.collection.NotificationEntry; 59 import com.android.systemui.statusbar.notification.logging.NotificationLogger; 60 import com.android.systemui.statusbar.policy.DeviceProvisionedController; 61 import com.android.systemui.statusbar.policy.KeyguardStateController; 62 63 import java.io.FileDescriptor; 64 import java.io.PrintWriter; 65 import java.util.ArrayList; 66 import java.util.List; 67 68 import javax.inject.Inject; 69 70 /** 71 * Handles keeping track of the current user, profiles, and various things related to hiding 72 * contents, redacting notifications, and the lockscreen. 73 */ 74 @SysUISingleton 75 public class NotificationLockscreenUserManagerImpl implements 76 Dumpable, 77 NotificationLockscreenUserManager, 78 StateListener { 79 private static final String TAG = "LockscreenUserManager"; 80 private static final boolean ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT = false; 81 82 private final DeviceProvisionedController mDeviceProvisionedController; 83 private final KeyguardStateController mKeyguardStateController; 84 private final Object mLock = new Object(); 85 86 // Lazy 87 private NotificationEntryManager mEntryManager; 88 89 private final DevicePolicyManager mDevicePolicyManager; 90 private final SparseBooleanArray mLockscreenPublicMode = new SparseBooleanArray(); 91 private final SparseBooleanArray mUsersWithSeparateWorkChallenge = new SparseBooleanArray(); 92 private final SparseBooleanArray mUsersAllowingPrivateNotifications = new SparseBooleanArray(); 93 private final SparseBooleanArray mUsersAllowingNotifications = new SparseBooleanArray(); 94 private final SparseBooleanArray mUsersInLockdownLatestResult = new SparseBooleanArray(); 95 private final SparseBooleanArray mShouldHideNotifsLatestResult = new SparseBooleanArray(); 96 private final UserManager mUserManager; 97 private final List<UserChangedListener> mListeners = new ArrayList<>(); 98 private final BroadcastDispatcher mBroadcastDispatcher; 99 private final NotificationClickNotifier mClickNotifier; 100 101 private boolean mShowLockscreenNotifications; 102 private boolean mAllowLockscreenRemoteInput; 103 private LockPatternUtils mLockPatternUtils; 104 protected KeyguardManager mKeyguardManager; 105 private int mState = StatusBarState.SHADE; 106 private List<KeyguardNotificationSuppressor> mKeyguardSuppressors = new ArrayList<>(); 107 108 protected final BroadcastReceiver mAllUsersReceiver = new BroadcastReceiver() { 109 @Override 110 public void onReceive(Context context, Intent intent) { 111 final String action = intent.getAction(); 112 113 if (ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action) && 114 isCurrentProfile(getSendingUserId())) { 115 mUsersAllowingPrivateNotifications.clear(); 116 updateLockscreenNotificationSetting(); 117 getEntryManager().updateNotifications("ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED"); 118 } 119 } 120 }; 121 122 protected final BroadcastReceiver mBaseBroadcastReceiver = new BroadcastReceiver() { 123 @Override 124 public void onReceive(Context context, Intent intent) { 125 String action = intent.getAction(); 126 switch (action) { 127 case Intent.ACTION_USER_SWITCHED: 128 mCurrentUserId = intent.getIntExtra( 129 Intent.EXTRA_USER_HANDLE, UserHandle.USER_ALL); 130 updateCurrentProfilesCache(); 131 132 Log.v(TAG, "userId " + mCurrentUserId + " is in the house"); 133 134 updateLockscreenNotificationSetting(); 135 updatePublicMode(); 136 // The filtering needs to happen before the update call below in order to 137 // make sure 138 // the presenter has the updated notifications from the new user 139 getEntryManager().reapplyFilterAndSort("user switched"); 140 mPresenter.onUserSwitched(mCurrentUserId); 141 142 for (UserChangedListener listener : mListeners) { 143 listener.onUserChanged(mCurrentUserId); 144 } 145 break; 146 case Intent.ACTION_USER_ADDED: 147 case Intent.ACTION_MANAGED_PROFILE_AVAILABLE: 148 case Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE: 149 updateCurrentProfilesCache(); 150 break; 151 case Intent.ACTION_USER_UNLOCKED: 152 // Start the overview connection to the launcher service 153 Dependency.get(OverviewProxyService.class).startConnectionToCurrentUser(); 154 break; 155 case NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION: 156 final IntentSender intentSender = intent.getParcelableExtra( 157 Intent.EXTRA_INTENT); 158 final String notificationKey = intent.getStringExtra(Intent.EXTRA_INDEX); 159 if (intentSender != null) { 160 try { 161 mContext.startIntentSender(intentSender, null, 0, 0, 0); 162 } catch (IntentSender.SendIntentException e) { 163 /* ignore */ 164 } 165 } 166 if (notificationKey != null) { 167 NotificationEntry entry = 168 getEntryManager().getActiveNotificationUnfiltered(notificationKey); 169 final int count = getEntryManager().getActiveNotificationsCount(); 170 final int rank = entry != null ? entry.getRanking().getRank() : 0; 171 NotificationVisibility.NotificationLocation location = 172 NotificationLogger.getNotificationLocation(entry); 173 final NotificationVisibility nv = NotificationVisibility.obtain( 174 notificationKey, 175 rank, count, true, location); 176 mClickNotifier.onNotificationClick(notificationKey, nv); 177 } 178 break; 179 } 180 } 181 }; 182 183 protected final Context mContext; 184 private final Handler mMainHandler; 185 protected final SparseArray<UserInfo> mCurrentProfiles = new SparseArray<>(); 186 protected final SparseArray<UserInfo> mCurrentManagedProfiles = new SparseArray<>(); 187 188 protected int mCurrentUserId = 0; 189 protected NotificationPresenter mPresenter; 190 protected ContentObserver mLockscreenSettingsObserver; 191 protected ContentObserver mSettingsObserver; 192 getEntryManager()193 private NotificationEntryManager getEntryManager() { 194 if (mEntryManager == null) { 195 mEntryManager = Dependency.get(NotificationEntryManager.class); 196 } 197 return mEntryManager; 198 } 199 200 @Inject NotificationLockscreenUserManagerImpl(Context context, BroadcastDispatcher broadcastDispatcher, DevicePolicyManager devicePolicyManager, UserManager userManager, NotificationClickNotifier clickNotifier, KeyguardManager keyguardManager, StatusBarStateController statusBarStateController, @Main Handler mainHandler, DeviceProvisionedController deviceProvisionedController, KeyguardStateController keyguardStateController, DumpManager dumpManager)201 public NotificationLockscreenUserManagerImpl(Context context, 202 BroadcastDispatcher broadcastDispatcher, 203 DevicePolicyManager devicePolicyManager, 204 UserManager userManager, 205 NotificationClickNotifier clickNotifier, 206 KeyguardManager keyguardManager, 207 StatusBarStateController statusBarStateController, 208 @Main Handler mainHandler, 209 DeviceProvisionedController deviceProvisionedController, 210 KeyguardStateController keyguardStateController, 211 DumpManager dumpManager) { 212 mContext = context; 213 mMainHandler = mainHandler; 214 mDevicePolicyManager = devicePolicyManager; 215 mUserManager = userManager; 216 mCurrentUserId = ActivityManager.getCurrentUser(); 217 mClickNotifier = clickNotifier; 218 statusBarStateController.addCallback(this); 219 mLockPatternUtils = new LockPatternUtils(context); 220 mKeyguardManager = keyguardManager; 221 mBroadcastDispatcher = broadcastDispatcher; 222 mDeviceProvisionedController = deviceProvisionedController; 223 mKeyguardStateController = keyguardStateController; 224 225 dumpManager.registerDumpable(this); 226 } 227 setUpWithPresenter(NotificationPresenter presenter)228 public void setUpWithPresenter(NotificationPresenter presenter) { 229 mPresenter = presenter; 230 231 mLockscreenSettingsObserver = new ContentObserver(mMainHandler) { 232 @Override 233 public void onChange(boolean selfChange) { 234 // We don't know which user changed LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS or 235 // LOCK_SCREEN_SHOW_NOTIFICATIONS, so we just dump our cache ... 236 mUsersAllowingPrivateNotifications.clear(); 237 mUsersAllowingNotifications.clear(); 238 // ... and refresh all the notifications 239 updateLockscreenNotificationSetting(); 240 getEntryManager().updateNotifications("LOCK_SCREEN_SHOW_NOTIFICATIONS," 241 + " or LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS change"); 242 } 243 }; 244 245 mSettingsObserver = new ContentObserver(mMainHandler) { 246 @Override 247 public void onChange(boolean selfChange) { 248 updateLockscreenNotificationSetting(); 249 if (mDeviceProvisionedController.isDeviceProvisioned()) { 250 getEntryManager().updateNotifications("LOCK_SCREEN_ALLOW_REMOTE_INPUT" 251 + " or ZEN_MODE change"); 252 } 253 } 254 }; 255 256 mContext.getContentResolver().registerContentObserver( 257 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS), false, 258 mLockscreenSettingsObserver, 259 UserHandle.USER_ALL); 260 261 mContext.getContentResolver().registerContentObserver( 262 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS), 263 true, 264 mLockscreenSettingsObserver, 265 UserHandle.USER_ALL); 266 267 mContext.getContentResolver().registerContentObserver( 268 Settings.Global.getUriFor(Settings.Global.ZEN_MODE), false, 269 mSettingsObserver); 270 271 if (ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT) { 272 mContext.getContentResolver().registerContentObserver( 273 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT), 274 false, 275 mSettingsObserver, 276 UserHandle.USER_ALL); 277 } 278 279 mBroadcastDispatcher.registerReceiver(mAllUsersReceiver, 280 new IntentFilter(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED), 281 null /* handler */, UserHandle.ALL); 282 283 IntentFilter filter = new IntentFilter(); 284 filter.addAction(Intent.ACTION_USER_SWITCHED); 285 filter.addAction(Intent.ACTION_USER_ADDED); 286 filter.addAction(Intent.ACTION_USER_UNLOCKED); 287 filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE); 288 filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE); 289 mBroadcastDispatcher.registerReceiver(mBaseBroadcastReceiver, filter, 290 null /* executor */, UserHandle.ALL); 291 292 IntentFilter internalFilter = new IntentFilter(); 293 internalFilter.addAction(NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION); 294 mContext.registerReceiver(mBaseBroadcastReceiver, internalFilter, PERMISSION_SELF, null); 295 296 updateCurrentProfilesCache(); 297 298 mSettingsObserver.onChange(false); // set up 299 } 300 shouldShowLockscreenNotifications()301 public boolean shouldShowLockscreenNotifications() { 302 return mShowLockscreenNotifications; 303 } 304 shouldAllowLockscreenRemoteInput()305 public boolean shouldAllowLockscreenRemoteInput() { 306 return mAllowLockscreenRemoteInput; 307 } 308 isCurrentProfile(int userId)309 public boolean isCurrentProfile(int userId) { 310 synchronized (mLock) { 311 return userId == UserHandle.USER_ALL || mCurrentProfiles.get(userId) != null; 312 } 313 } 314 315 /** 316 * Returns true if notifications are temporarily disabled for this user for security reasons, 317 * regardless of the normal settings for that user. 318 */ shouldTemporarilyHideNotifications(int userId)319 private boolean shouldTemporarilyHideNotifications(int userId) { 320 if (userId == UserHandle.USER_ALL) { 321 userId = mCurrentUserId; 322 } 323 boolean inLockdown = Dependency.get(KeyguardUpdateMonitor.class).isUserInLockdown(userId); 324 mUsersInLockdownLatestResult.put(userId, inLockdown); 325 return inLockdown; 326 } 327 328 /** 329 * Returns true if we're on a secure lockscreen and the user wants to hide notification data. 330 * If so, notifications should be hidden. 331 */ shouldHideNotifications(int userId)332 public boolean shouldHideNotifications(int userId) { 333 boolean hide = isLockscreenPublicMode(userId) && !userAllowsNotificationsInPublic(userId) 334 || (userId != mCurrentUserId && shouldHideNotifications(mCurrentUserId)) 335 || shouldTemporarilyHideNotifications(userId); 336 mShouldHideNotifsLatestResult.put(userId, hide); 337 return hide; 338 } 339 340 /** 341 * Returns true if we're on a secure lockscreen and the user wants to hide notifications via 342 * package-specific override. 343 */ shouldHideNotifications(String key)344 public boolean shouldHideNotifications(String key) { 345 if (getEntryManager() == null) { 346 Log.wtf(TAG, "mEntryManager was null!", new Throwable()); 347 return true; 348 } 349 NotificationEntry visibleEntry = getEntryManager().getActiveNotificationUnfiltered(key); 350 return isLockscreenPublicMode(mCurrentUserId) && visibleEntry != null 351 && visibleEntry.getRanking().getLockscreenVisibilityOverride() == VISIBILITY_SECRET; 352 } 353 shouldShowOnKeyguard(NotificationEntry entry)354 public boolean shouldShowOnKeyguard(NotificationEntry entry) { 355 if (getEntryManager() == null) { 356 Log.wtf(TAG, "mEntryManager was null!", new Throwable()); 357 return false; 358 } 359 for (int i = 0; i < mKeyguardSuppressors.size(); i++) { 360 if (mKeyguardSuppressors.get(i).shouldSuppressOnKeyguard(entry)) { 361 return false; 362 } 363 } 364 boolean exceedsPriorityThreshold; 365 if (hideSilentNotificationsOnLockscreen()) { 366 exceedsPriorityThreshold = 367 entry.getBucket() == BUCKET_MEDIA_CONTROLS 368 || (entry.getBucket() != BUCKET_SILENT 369 && entry.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT); 370 } else { 371 exceedsPriorityThreshold = !entry.getRanking().isAmbient(); 372 } 373 return mShowLockscreenNotifications && exceedsPriorityThreshold; 374 } 375 hideSilentNotificationsOnLockscreen()376 private boolean hideSilentNotificationsOnLockscreen() { 377 return whitelistIpcs(() -> Settings.Secure.getInt(mContext.getContentResolver(), 378 Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 1) == 0); 379 } 380 setShowLockscreenNotifications(boolean show)381 private void setShowLockscreenNotifications(boolean show) { 382 mShowLockscreenNotifications = show; 383 } 384 setLockscreenAllowRemoteInput(boolean allowLockscreenRemoteInput)385 private void setLockscreenAllowRemoteInput(boolean allowLockscreenRemoteInput) { 386 mAllowLockscreenRemoteInput = allowLockscreenRemoteInput; 387 } 388 updateLockscreenNotificationSetting()389 protected void updateLockscreenNotificationSetting() { 390 final boolean show = Settings.Secure.getIntForUser(mContext.getContentResolver(), 391 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 392 1, 393 mCurrentUserId) != 0; 394 final int dpmFlags = mDevicePolicyManager.getKeyguardDisabledFeatures( 395 null /* admin */, mCurrentUserId); 396 final boolean allowedByDpm = (dpmFlags 397 & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS) == 0; 398 399 setShowLockscreenNotifications(show && allowedByDpm); 400 401 if (ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT) { 402 final boolean remoteInput = Settings.Secure.getIntForUser(mContext.getContentResolver(), 403 Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT, 404 0, 405 mCurrentUserId) != 0; 406 final boolean remoteInputDpm = 407 (dpmFlags & DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT) == 0; 408 409 setLockscreenAllowRemoteInput(remoteInput && remoteInputDpm); 410 } else { 411 setLockscreenAllowRemoteInput(false); 412 } 413 } 414 415 /** 416 * Has the given user chosen to allow their private (full) notifications to be shown even 417 * when the lockscreen is in "public" (secure & locked) mode? 418 */ userAllowsPrivateNotificationsInPublic(int userHandle)419 public boolean userAllowsPrivateNotificationsInPublic(int userHandle) { 420 if (userHandle == UserHandle.USER_ALL) { 421 return true; 422 } 423 424 if (mUsersAllowingPrivateNotifications.indexOfKey(userHandle) < 0) { 425 final boolean allowedByUser = 0 != Settings.Secure.getIntForUser( 426 mContext.getContentResolver(), 427 Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0, userHandle); 428 final boolean allowedByDpm = adminAllowsKeyguardFeature(userHandle, 429 DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS); 430 final boolean allowed = allowedByUser && allowedByDpm; 431 mUsersAllowingPrivateNotifications.append(userHandle, allowed); 432 return allowed; 433 } 434 435 return mUsersAllowingPrivateNotifications.get(userHandle); 436 } 437 438 /** 439 * If all managed profiles (work profiles) can show private data in public (secure & locked.) 440 */ allowsManagedPrivateNotificationsInPublic()441 public boolean allowsManagedPrivateNotificationsInPublic() { 442 synchronized (mLock) { 443 for (int i = mCurrentManagedProfiles.size() - 1; i >= 0; i--) { 444 if (!userAllowsPrivateNotificationsInPublic( 445 mCurrentManagedProfiles.valueAt(i).id)) { 446 return false; 447 } 448 } 449 } 450 return true; 451 } 452 adminAllowsKeyguardFeature(int userHandle, int feature)453 private boolean adminAllowsKeyguardFeature(int userHandle, int feature) { 454 if (userHandle == UserHandle.USER_ALL) { 455 return true; 456 } 457 final int dpmFlags = 458 mDevicePolicyManager.getKeyguardDisabledFeatures(null /* admin */, userHandle); 459 return (dpmFlags & feature) == 0; 460 } 461 462 /** 463 * Save the current "public" (locked and secure) state of the lockscreen. 464 */ setLockscreenPublicMode(boolean publicMode, int userId)465 public void setLockscreenPublicMode(boolean publicMode, int userId) { 466 mLockscreenPublicMode.put(userId, publicMode); 467 } 468 isLockscreenPublicMode(int userId)469 public boolean isLockscreenPublicMode(int userId) { 470 if (userId == UserHandle.USER_ALL) { 471 return mLockscreenPublicMode.get(mCurrentUserId, false); 472 } 473 return mLockscreenPublicMode.get(userId, false); 474 } 475 476 @Override needsSeparateWorkChallenge(int userId)477 public boolean needsSeparateWorkChallenge(int userId) { 478 return mUsersWithSeparateWorkChallenge.get(userId, false); 479 } 480 481 /** 482 * Has the given user chosen to allow notifications to be shown even when the lockscreen is in 483 * "public" (secure & locked) mode? 484 */ userAllowsNotificationsInPublic(int userHandle)485 public boolean userAllowsNotificationsInPublic(int userHandle) { 486 if (isCurrentProfile(userHandle) && userHandle != mCurrentUserId) { 487 return true; 488 } 489 490 if (mUsersAllowingNotifications.indexOfKey(userHandle) < 0) { 491 final boolean allowedByUser = 0 != Settings.Secure.getIntForUser( 492 mContext.getContentResolver(), 493 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, userHandle); 494 final boolean allowedByDpm = adminAllowsKeyguardFeature(userHandle, 495 DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS); 496 final boolean allowedBySystem = mKeyguardManager.getPrivateNotificationsAllowed(); 497 final boolean allowed = allowedByUser && allowedByDpm && allowedBySystem; 498 mUsersAllowingNotifications.append(userHandle, allowed); 499 return allowed; 500 } 501 502 return mUsersAllowingNotifications.get(userHandle); 503 } 504 505 /** @return true if the entry needs redaction when on the lockscreen. */ needsRedaction(NotificationEntry ent)506 public boolean needsRedaction(NotificationEntry ent) { 507 int userId = ent.getSbn().getUserId(); 508 509 boolean isCurrentUserRedactingNotifs = 510 !userAllowsPrivateNotificationsInPublic(mCurrentUserId); 511 boolean isNotifForManagedProfile = mCurrentManagedProfiles.contains(userId); 512 boolean isNotifUserRedacted = !userAllowsPrivateNotificationsInPublic(userId); 513 514 // redact notifications if the current user is redacting notifications; however if the 515 // notification is associated with a managed profile, we rely on the managed profile 516 // setting to determine whether to redact it 517 boolean isNotifRedacted = (!isNotifForManagedProfile && isCurrentUserRedactingNotifs) 518 || isNotifUserRedacted; 519 520 boolean notificationRequestsRedaction = 521 ent.getSbn().getNotification().visibility == Notification.VISIBILITY_PRIVATE; 522 boolean userForcesRedaction = packageHasVisibilityOverride(ent.getSbn().getKey()); 523 524 return userForcesRedaction || notificationRequestsRedaction && isNotifRedacted; 525 } 526 packageHasVisibilityOverride(String key)527 private boolean packageHasVisibilityOverride(String key) { 528 if (getEntryManager() == null) { 529 Log.wtf(TAG, "mEntryManager was null!", new Throwable()); 530 return true; 531 } 532 NotificationEntry entry = getEntryManager().getActiveNotificationUnfiltered(key); 533 return entry != null 534 && entry.getRanking().getLockscreenVisibilityOverride() 535 == Notification.VISIBILITY_PRIVATE; 536 } 537 updateCurrentProfilesCache()538 private void updateCurrentProfilesCache() { 539 synchronized (mLock) { 540 mCurrentProfiles.clear(); 541 mCurrentManagedProfiles.clear(); 542 if (mUserManager != null) { 543 for (UserInfo user : mUserManager.getProfiles(mCurrentUserId)) { 544 mCurrentProfiles.put(user.id, user); 545 if (UserManager.USER_TYPE_PROFILE_MANAGED.equals(user.userType)) { 546 mCurrentManagedProfiles.put(user.id, user); 547 } 548 } 549 } 550 } 551 mMainHandler.post(() -> { 552 for (UserChangedListener listener : mListeners) { 553 listener.onCurrentProfilesChanged(mCurrentProfiles); 554 } 555 }); 556 } 557 558 /** 559 * If any of the profiles are in public mode. 560 */ isAnyProfilePublicMode()561 public boolean isAnyProfilePublicMode() { 562 synchronized (mLock) { 563 for (int i = mCurrentProfiles.size() - 1; i >= 0; i--) { 564 if (isLockscreenPublicMode(mCurrentProfiles.valueAt(i).id)) { 565 return true; 566 } 567 } 568 } 569 return false; 570 } 571 572 /** 573 * If any managed/work profiles are in public mode. 574 */ isAnyManagedProfilePublicMode()575 public boolean isAnyManagedProfilePublicMode() { 576 synchronized (mLock) { 577 for (int i = mCurrentManagedProfiles.size() - 1; i >= 0; i--) { 578 if (isLockscreenPublicMode(mCurrentManagedProfiles.valueAt(i).id)) { 579 return true; 580 } 581 } 582 } 583 return false; 584 } 585 586 /** 587 * Returns the current user id. This can change if the user is switched. 588 */ getCurrentUserId()589 public int getCurrentUserId() { 590 return mCurrentUserId; 591 } 592 getCurrentProfiles()593 public SparseArray<UserInfo> getCurrentProfiles() { 594 return mCurrentProfiles; 595 } 596 597 @Override onStateChanged(int newState)598 public void onStateChanged(int newState) { 599 mState = newState; 600 updatePublicMode(); 601 } 602 updatePublicMode()603 public void updatePublicMode() { 604 //TODO: I think there may be a race condition where mKeyguardViewManager.isShowing() returns 605 // false when it should be true. Therefore, if we are not on the SHADE, don't even bother 606 // asking if the keyguard is showing. We still need to check it though because showing the 607 // camera on the keyguard has a state of SHADE but the keyguard is still showing. 608 final boolean showingKeyguard = mState != StatusBarState.SHADE 609 || mKeyguardStateController.isShowing(); 610 final boolean devicePublic = showingKeyguard && mKeyguardStateController.isMethodSecure(); 611 612 613 // Look for public mode users. Users are considered public in either case of: 614 // - device keyguard is shown in secure mode; 615 // - profile is locked with a work challenge. 616 SparseArray<UserInfo> currentProfiles = getCurrentProfiles(); 617 mUsersWithSeparateWorkChallenge.clear(); 618 for (int i = currentProfiles.size() - 1; i >= 0; i--) { 619 final int userId = currentProfiles.valueAt(i).id; 620 boolean isProfilePublic = devicePublic; 621 // TODO(b/140058091) 622 boolean needsSeparateChallenge = whitelistIpcs(() -> 623 mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)); 624 if (!devicePublic && userId != getCurrentUserId() 625 && needsSeparateChallenge && mLockPatternUtils.isSecure(userId)) { 626 // Keyguard.isDeviceLocked is updated asynchronously, assume that all profiles 627 // with separate challenge are locked when keyguard is visible to avoid race. 628 isProfilePublic = showingKeyguard || mKeyguardManager.isDeviceLocked(userId); 629 } 630 setLockscreenPublicMode(isProfilePublic, userId); 631 mUsersWithSeparateWorkChallenge.put(userId, needsSeparateChallenge); 632 } 633 getEntryManager().updateNotifications("NotificationLockscreenUserManager.updatePublicMode"); 634 } 635 636 @Override addUserChangedListener(UserChangedListener listener)637 public void addUserChangedListener(UserChangedListener listener) { 638 mListeners.add(listener); 639 } 640 641 @Override addKeyguardNotificationSuppressor(KeyguardNotificationSuppressor suppressor)642 public void addKeyguardNotificationSuppressor(KeyguardNotificationSuppressor suppressor) { 643 mKeyguardSuppressors.add(suppressor); 644 } 645 646 @Override removeUserChangedListener(UserChangedListener listener)647 public void removeUserChangedListener(UserChangedListener listener) { 648 mListeners.remove(listener); 649 } 650 651 // public void updatePublicMode() { 652 // //TODO: I think there may be a race condition where mKeyguardViewManager.isShowing() returns 653 // // false when it should be true. Therefore, if we are not on the SHADE, don't even bother 654 // // asking if the keyguard is showing. We still need to check it though because showing the 655 // // camera on the keyguard has a state of SHADE but the keyguard is still showing. 656 // final boolean showingKeyguard = mState != StatusBarState.SHADE 657 // || mKeyguardStateController.isShowing(); 658 // final boolean devicePublic = showingKeyguard && isSecure(getCurrentUserId()); 659 // 660 // 661 // // Look for public mode users. Users are considered public in either case of: 662 // // - device keyguard is shown in secure mode; 663 // // - profile is locked with a work challenge. 664 // SparseArray<UserInfo> currentProfiles = getCurrentProfiles(); 665 // for (int i = currentProfiles.size() - 1; i >= 0; i--) { 666 // final int userId = currentProfiles.valueAt(i).id; 667 // boolean isProfilePublic = devicePublic; 668 // if (!devicePublic && userId != getCurrentUserId()) { 669 // // We can't rely on KeyguardManager#isDeviceLocked() for unified profile challenge 670 // // due to a race condition where this code could be called before 671 // // TrustManagerService updates its internal records, resulting in an incorrect 672 // // state being cached in mLockscreenPublicMode. (b/35951989) 673 // if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId) 674 // && isSecure(userId)) { 675 // isProfilePublic = mKeyguardManager.isDeviceLocked(userId); 676 // } 677 // } 678 // setLockscreenPublicMode(isProfilePublic, userId); 679 // } 680 // } 681 682 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)683 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 684 pw.println("NotificationLockscreenUserManager state:"); 685 pw.print(" mCurrentUserId="); 686 pw.println(mCurrentUserId); 687 pw.print(" mShowLockscreenNotifications="); 688 pw.println(mShowLockscreenNotifications); 689 pw.print(" mAllowLockscreenRemoteInput="); 690 pw.println(mAllowLockscreenRemoteInput); 691 pw.print(" mCurrentProfiles="); 692 synchronized (mLock) { 693 for (int i = mCurrentProfiles.size() - 1; i >= 0; i--) { 694 final int userId = mCurrentProfiles.valueAt(i).id; 695 pw.print("" + userId + " "); 696 } 697 } 698 pw.println(); 699 pw.print(" mCurrentManagedProfiles="); 700 synchronized (mLock) { 701 for (int i = mCurrentManagedProfiles.size() - 1; i >= 0; i--) { 702 pw.print("" + mCurrentManagedProfiles.valueAt(i).id + " "); 703 } 704 } 705 pw.println(); 706 pw.print(" mLockscreenPublicMode="); 707 pw.println(mLockscreenPublicMode); 708 pw.print(" mUsersWithSeparateWorkChallenge="); 709 pw.println(mUsersWithSeparateWorkChallenge); 710 pw.print(" mUsersAllowingPrivateNotifications="); 711 pw.println(mUsersAllowingPrivateNotifications); 712 pw.print(" mUsersAllowingNotifications="); 713 pw.println(mUsersAllowingNotifications); 714 pw.print(" mUsersInLockdownLatestResult="); 715 pw.println(mUsersInLockdownLatestResult); 716 pw.print(" mShouldHideNotifsLatestResult="); 717 pw.println(mShouldHideNotifsLatestResult); 718 } 719 } 720