• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 /**
62  * Handles keeping track of the current user, profiles, and various things related to hiding
63  * contents, redacting notifications, and the lockscreen.
64  */
65 public 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();
79     private final SparseBooleanArray mUsersWithSeperateWorkChallenge = new SparseBooleanArray();
80     private final SparseBooleanArray mUsersAllowingPrivateNotifications = new SparseBooleanArray();
81     private final SparseBooleanArray mUsersAllowingNotifications = new SparseBooleanArray();
82     private final UserManager mUserManager;
83     private final IStatusBarService mBarService;
84     private final List<UserChangedListener> mListeners = new ArrayList<>();
85 
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();
117                 // 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
119                 getEntryManager().getNotificationData().filterAndSort();
120                 mPresenter.onUserSwitched(mCurrentUserId);
121 
122                 for (UserChangedListener listener : mListeners) {
123                     listener.onUserChanged(mCurrentUserId);
124                 }
125             } 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);
144                     NotificationVisibility.NotificationLocation location =
145                             NotificationLogger.getNotificationLocation(
146                                     getEntryManager().getNotificationData().get(notificationKey));
147                     final NotificationVisibility nv = NotificationVisibility.obtain(notificationKey,
148                             rank, count, true, location);
149                     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 
getEntryManager()167     private NotificationEntryManager getEntryManager() {
168         if (mEntryManager == null) {
169             mEntryManager = Dependency.get(NotificationEntryManager.class);
170         }
171         return mEntryManager;
172     }
173 
NotificationLockscreenUserManagerImpl(Context context)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));
182         Dependency.get(StatusBarStateController.class).addCallback(this);
183         mLockPatternUtils = new LockPatternUtils(context);
184         mKeyguardManager = context.getSystemService(KeyguardManager.class);
185     }
186 
setUpWithPresenter(NotificationPresenter presenter)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 
shouldShowLockscreenNotifications()255     public boolean shouldShowLockscreenNotifications() {
256         return mShowLockscreenNotifications;
257     }
258 
shouldAllowLockscreenRemoteInput()259     public boolean shouldAllowLockscreenRemoteInput() {
260         return mAllowLockscreenRemoteInput;
261     }
262 
isCurrentProfile(int userId)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      */
shouldTemporarilyHideNotifications(int userId)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      */
shouldHideNotifications(int userId)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      */
shouldHideNotifications(String key)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 
shouldShowOnKeyguard(NotificationEntry entry)304     public boolean shouldShowOnKeyguard(NotificationEntry entry) {
305         if (getEntryManager() == null) {
306             Log.wtf(TAG, "mEntryManager was null!", new Throwable());
307             return false;
308         }
309         boolean exceedsPriorityThreshold;
310         if (NotificationUtils.useNewInterruptionModel(mContext)
311                 && hideSilentNotificationsOnLockscreen()) {
312             exceedsPriorityThreshold = entry.isTopBucket();
313         } else {
314             exceedsPriorityThreshold =
315                     !getEntryManager().getNotificationData().isAmbient(entry.key);
316         }
317         return mShowLockscreenNotifications && exceedsPriorityThreshold;
318     }
319 
hideSilentNotificationsOnLockscreen()320     private boolean hideSilentNotificationsOnLockscreen() {
321         return Settings.Secure.getInt(mContext.getContentResolver(),
322                 Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 1) == 0;
323     }
324 
setShowLockscreenNotifications(boolean show)325     private void setShowLockscreenNotifications(boolean show) {
326         mShowLockscreenNotifications = show;
327     }
328 
setLockscreenAllowRemoteInput(boolean allowLockscreenRemoteInput)329     private void setLockscreenAllowRemoteInput(boolean allowLockscreenRemoteInput) {
330         mAllowLockscreenRemoteInput = allowLockscreenRemoteInput;
331     }
332 
updateLockscreenNotificationSetting()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      */
userAllowsPrivateNotificationsInPublic(int userHandle)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 
adminAllowsKeyguardFeature(int userHandle, int feature)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      */
setLockscreenPublicMode(boolean publicMode, int userId)394     public void setLockscreenPublicMode(boolean publicMode, int userId) {
395         mLockscreenPublicMode.put(userId, publicMode);
396     }
397 
isLockscreenPublicMode(int userId)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 
405     @Override
needsSeparateWorkChallenge(int userId)406     public boolean needsSeparateWorkChallenge(int userId) {
407         return mUsersWithSeperateWorkChallenge.get(userId, false);
408     }
409 
410     /**
411      * Has the given user chosen to allow notifications to be shown even when the lockscreen is in
412      * "public" (secure & locked) mode?
413      */
userAllowsNotificationsInPublic(int userHandle)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);
425             final boolean allowedBySystem = mKeyguardManager.getPrivateNotificationsAllowed();
426             final boolean allowed = allowedByUser && allowedByDpm && allowedBySystem;
427             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. */
needsRedaction(NotificationEntry ent)435     public boolean needsRedaction(NotificationEntry ent) {
436         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 
packageHasVisibilityOverride(String key)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 
updateCurrentProfilesCache()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 
isAnyProfilePublicMode()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      */
getCurrentUserId()481     public int getCurrentUserId() {
482         return mCurrentUserId;
483     }
484 
getCurrentProfiles()485     public SparseArray<UserInfo> getCurrentProfiles() {
486         return mCurrentProfiles;
487     }
488 
489     @Override
onStateChanged(int newState)490     public void onStateChanged(int newState) {
491         mState = newState;
492         updatePublicMode();
493     }
494 
updatePublicMode()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();
509         mUsersWithSeperateWorkChallenge.clear();
510         for (int i = currentProfiles.size() - 1; i >= 0; i--) {
511             final int userId = currentProfiles.valueAt(i).id;
512             boolean isProfilePublic = devicePublic;
513             boolean needsSeparateChallenge = mLockPatternUtils.isSeparateProfileChallengeEnabled(
514                     userId);
515             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);
520             }
521             setLockscreenPublicMode(isProfilePublic, userId);
522             mUsersWithSeperateWorkChallenge.put(userId, needsSeparateChallenge);
523         }
524         getEntryManager().updateNotifications();
525     }
526 
527     @Override
addUserChangedListener(UserChangedListener listener)528     public void addUserChangedListener(UserChangedListener listener) {
529         mListeners.add(listener);
530     }
531 
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 
isSecure(int userId)563     private boolean isSecure(int userId) {
564         return mKeyguardMonitor.isSecure() || mLockPatternUtils.isSecure(userId);
565     }
566 
567     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)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 }
584