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.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
19 
20 import android.app.ActivityManager;
21 import android.app.KeyguardManager;
22 import android.app.Notification;
23 import android.app.admin.DevicePolicyManager;
24 import android.content.BroadcastReceiver;
25 import android.content.Context;
26 import android.content.Intent;
27 import android.content.IntentFilter;
28 import android.content.IntentSender;
29 import android.content.pm.UserInfo;
30 import android.database.ContentObserver;
31 import android.os.RemoteException;
32 import android.os.ServiceManager;
33 import android.os.UserHandle;
34 import android.os.UserManager;
35 import android.provider.Settings;
36 import android.util.Log;
37 import android.util.SparseArray;
38 import android.util.SparseBooleanArray;
39 
40 import com.android.internal.statusbar.IStatusBarService;
41 import com.android.internal.statusbar.NotificationVisibility;
42 import com.android.internal.widget.LockPatternUtils;
43 import com.android.keyguard.KeyguardUpdateMonitor;
44 import com.android.systemui.Dependency;
45 import com.android.systemui.Dumpable;
46 import com.android.systemui.plugins.statusbar.StatusBarStateController;
47 import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
48 import com.android.systemui.recents.OverviewProxyService;
49 import com.android.systemui.statusbar.notification.NotificationEntryManager;
50 import com.android.systemui.statusbar.notification.NotificationUtils;
51 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
52 import com.android.systemui.statusbar.notification.logging.NotificationLogger;
53 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
54 import com.android.systemui.statusbar.policy.KeyguardMonitor;
55 
56 import java.io.FileDescriptor;
57 import java.io.PrintWriter;
58 import java.util.ArrayList;
59 import java.util.List;
60 
61 import javax.inject.Inject;
62 import javax.inject.Singleton;
63 
64 /**
65  * Handles keeping track of the current user, profiles, and various things related to hiding
66  * contents, redacting notifications, and the lockscreen.
67  */
68 @Singleton
69 public 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();
83     private final SparseBooleanArray mUsersWithSeperateWorkChallenge = new SparseBooleanArray();
84     private final SparseBooleanArray mUsersAllowingPrivateNotifications = new SparseBooleanArray();
85     private final SparseBooleanArray mUsersAllowingNotifications = new SparseBooleanArray();
86     private final UserManager mUserManager;
87     private final IStatusBarService mBarService;
88     private final List<UserChangedListener> mListeners = new ArrayList<>();
89 
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();
121                 // 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
123                 getEntryManager().getNotificationData().filterAndSort();
124                 mPresenter.onUserSwitched(mCurrentUserId);
125 
126                 for (UserChangedListener listener : mListeners) {
127                     listener.onUserChanged(mCurrentUserId);
128                 }
129             } 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);
148                     NotificationVisibility.NotificationLocation location =
149                             NotificationLogger.getNotificationLocation(
150                                     getEntryManager().getNotificationData().get(notificationKey));
151                     final NotificationVisibility nv = NotificationVisibility.obtain(notificationKey,
152                             rank, count, true, location);
153                     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 
getEntryManager()171     private NotificationEntryManager getEntryManager() {
172         if (mEntryManager == null) {
173             mEntryManager = Dependency.get(NotificationEntryManager.class);
174         }
175         return mEntryManager;
176     }
177 
178     @Inject
NotificationLockscreenUserManagerImpl(Context context)179     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));
187         Dependency.get(StatusBarStateController.class).addCallback(this);
188         mLockPatternUtils = new LockPatternUtils(context);
189         mKeyguardManager = context.getSystemService(KeyguardManager.class);
190     }
191 
setUpWithPresenter(NotificationPresenter presenter)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 
shouldShowLockscreenNotifications()260     public boolean shouldShowLockscreenNotifications() {
261         return mShowLockscreenNotifications;
262     }
263 
shouldAllowLockscreenRemoteInput()264     public boolean shouldAllowLockscreenRemoteInput() {
265         return mAllowLockscreenRemoteInput;
266     }
267 
isCurrentProfile(int userId)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      */
shouldTemporarilyHideNotifications(int userId)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      */
shouldHideNotifications(int userId)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      */
shouldHideNotifications(String key)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 
shouldShowOnKeyguard(NotificationEntry entry)309     public boolean shouldShowOnKeyguard(NotificationEntry entry) {
310         if (getEntryManager() == null) {
311             Log.wtf(TAG, "mEntryManager was null!", new Throwable());
312             return false;
313         }
314         boolean exceedsPriorityThreshold;
315         if (NotificationUtils.useNewInterruptionModel(mContext)
316                 && hideSilentNotificationsOnLockscreen()) {
317             exceedsPriorityThreshold = entry.isTopBucket();
318         } else {
319             exceedsPriorityThreshold =
320                     !getEntryManager().getNotificationData().isAmbient(entry.key);
321         }
322         return mShowLockscreenNotifications && exceedsPriorityThreshold;
323     }
324 
hideSilentNotificationsOnLockscreen()325     private boolean hideSilentNotificationsOnLockscreen() {
326         return Settings.Secure.getInt(mContext.getContentResolver(),
327                 Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 1) == 0;
328     }
329 
setShowLockscreenNotifications(boolean show)330     private void setShowLockscreenNotifications(boolean show) {
331         mShowLockscreenNotifications = show;
332     }
333 
setLockscreenAllowRemoteInput(boolean allowLockscreenRemoteInput)334     private void setLockscreenAllowRemoteInput(boolean allowLockscreenRemoteInput) {
335         mAllowLockscreenRemoteInput = allowLockscreenRemoteInput;
336     }
337 
updateLockscreenNotificationSetting()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      */
userAllowsPrivateNotificationsInPublic(int userHandle)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 
adminAllowsKeyguardFeature(int userHandle, int feature)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      */
setLockscreenPublicMode(boolean publicMode, int userId)399     public void setLockscreenPublicMode(boolean publicMode, int userId) {
400         mLockscreenPublicMode.put(userId, publicMode);
401     }
402 
isLockscreenPublicMode(int userId)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 
410     @Override
needsSeparateWorkChallenge(int userId)411     public boolean needsSeparateWorkChallenge(int userId) {
412         return mUsersWithSeperateWorkChallenge.get(userId, false);
413     }
414 
415     /**
416      * Has the given user chosen to allow notifications to be shown even when the lockscreen is in
417      * "public" (secure & locked) mode?
418      */
userAllowsNotificationsInPublic(int userHandle)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);
430             final boolean allowedBySystem = mKeyguardManager.getPrivateNotificationsAllowed();
431             final boolean allowed = allowedByUser && allowedByDpm && allowedBySystem;
432             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. */
needsRedaction(NotificationEntry ent)440     public boolean needsRedaction(NotificationEntry ent) {
441         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 
packageHasVisibilityOverride(String key)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 
updateCurrentProfilesCache()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 
isAnyProfilePublicMode()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      */
getCurrentUserId()486     public int getCurrentUserId() {
487         return mCurrentUserId;
488     }
489 
getCurrentProfiles()490     public SparseArray<UserInfo> getCurrentProfiles() {
491         return mCurrentProfiles;
492     }
493 
494     @Override
onStateChanged(int newState)495     public void onStateChanged(int newState) {
496         mState = newState;
497         updatePublicMode();
498     }
499 
updatePublicMode()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();
514         mUsersWithSeperateWorkChallenge.clear();
515         for (int i = currentProfiles.size() - 1; i >= 0; i--) {
516             final int userId = currentProfiles.valueAt(i).id;
517             boolean isProfilePublic = devicePublic;
518             boolean needsSeparateChallenge = mLockPatternUtils.isSeparateProfileChallengeEnabled(
519                     userId);
520             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);
525             }
526             setLockscreenPublicMode(isProfilePublic, userId);
527             mUsersWithSeperateWorkChallenge.put(userId, needsSeparateChallenge);
528         }
529         getEntryManager().updateNotifications();
530     }
531 
532     @Override
addUserChangedListener(UserChangedListener listener)533     public void addUserChangedListener(UserChangedListener listener) {
534         mListeners.add(listener);
535     }
536 
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 
isSecure(int userId)568     private boolean isSecure(int userId) {
569         return mKeyguardMonitor.isSecure() || mLockPatternUtils.isSecure(userId);
570     }
571 
572     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)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 }
589