From fd16d56419649b885f2e18dc37a18add0fe91e01 Mon Sep 17 00:00:00 2001 From: Dan Sandler Date: Thu, 13 Feb 2014 18:43:31 -0800 Subject: [PATCH] Allow a user to elect to see private notifications in public. Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, if set and nonzero, will show that user's notifications on the secure lockscreen (assuming LOCK_SCREEN_ALLOW_NOTIFICATIONS is also set). Note that this applies only to a particular user's notifications, so if multiple users' notifications are shown at once (currently this only applies to the current user and USER_ALL) only that user's notifications are affected. USER_ALL is assumed to always allow private notifications in public (because they can't be user-specific). Change-Id: I32bb7939066c4919191e74161ca48ead01a88c7f --- core/java/android/provider/Settings.java | 8 +++ .../systemui/statusbar/BaseStatusBar.java | 56 +++++++++++++++++-- .../statusbar/phone/PhoneStatusBar.java | 15 +++-- 3 files changed, 67 insertions(+), 12 deletions(-) diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 9332578b62422..6c33492ee72b7 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -3475,6 +3475,14 @@ public final class Settings { public static final String LOCK_SCREEN_ALLOW_NOTIFICATIONS = "lock_screen_allow_notifications"; + /** + * When set in conjunction with {@link #LOCK_SCREEN_ALLOW_NOTIFICATIONS}, shows + * notifications in their "private" form (same as when the device is unlocked). + * @hide + */ + public static final String LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS = + "lock_screen_allow_private_notifications"; + /** * The Logging ID (a unique 64-bit value) as a hex string. * Used as a pseudonymous identifier for logging. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index 649b51bf5e02b..7ff52de0c1b0c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -46,6 +46,7 @@ import android.service.dreams.IDreamManager; import android.service.notification.StatusBarNotification; import android.text.TextUtils; import android.util.Log; +import android.util.SparseBooleanArray; import android.view.Display; import android.view.IWindowManager; import android.view.LayoutInflater; @@ -131,7 +132,10 @@ public abstract class BaseStatusBar extends SystemUI implements protected IDreamManager mDreamManager; PowerManager mPowerManager; protected int mRowHeight; - private boolean mPublicMode = false; + + // public mode, private notifications, etc + private boolean mLockscreenPublicMode = false; + private final SparseBooleanArray mUsersAllowingPrivateNotifications = new SparseBooleanArray(); // UI-specific methods @@ -159,7 +163,7 @@ public abstract class BaseStatusBar extends SystemUI implements return mDeviceProvisioned; } - private ContentObserver mProvisioningObserver = new ContentObserver(new Handler()) { + private final ContentObserver mProvisioningObserver = new ContentObserver(mHandler) { @Override public void onChange(boolean selfChange) { final boolean provisioned = 0 != Settings.Global.getInt( @@ -171,6 +175,17 @@ public abstract class BaseStatusBar extends SystemUI implements } }; + private final ContentObserver mLockscreenSettingsObserver = new ContentObserver(mHandler) { + @Override + public void onChange(boolean selfChange) { + // We don't know which user changed LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, + // so we just dump our cache ... + mUsersAllowingPrivateNotifications.clear(); + // ... and refresh all the notifications + updateNotificationIcons(); + } + }; + private RemoteViews.OnClickHandler mOnClickHandler = new RemoteViews.OnClickHandler() { @Override public boolean onClickHandler(View view, PendingIntent pendingIntent, Intent fillInIntent) { @@ -229,6 +244,12 @@ public abstract class BaseStatusBar extends SystemUI implements Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED), true, mProvisioningObserver); + mContext.getContentResolver().registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS), + true, + mLockscreenSettingsObserver, + UserHandle.USER_ALL); + mBarService = IStatusBarService.Stub.asInterface( ServiceManager.getService(Context.STATUS_BAR_SERVICE)); @@ -550,12 +571,35 @@ public abstract class BaseStatusBar extends SystemUI implements public abstract void resetHeadsUpDecayTimer(); - public void setPublicMode(boolean publicMode) { - mPublicMode = publicMode; + /** + * Save the current "public" (locked and secure) state of the lockscreen. + */ + public void setLockscreenPublicMode(boolean publicMode) { + mLockscreenPublicMode = publicMode; } - public boolean isPublicMode() { - return mPublicMode; + public boolean isLockscreenPublicMode() { + return mLockscreenPublicMode; + } + + /** + * Has the given user chosen to allow their private (full) notifications to be shown even + * when the lockscreen is in "public" (secure & locked) mode? + */ + public boolean userAllowsPrivateNotificationsInPublic(int userHandle) { + if (userHandle == UserHandle.USER_ALL) { + return true; + } + + if (mUsersAllowingPrivateNotifications.indexOfKey(userHandle) < 0) { + final boolean allowed = 0 != Settings.Secure.getIntForUser( + mContext.getContentResolver(), + Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0, userHandle); + mUsersAllowingPrivateNotifications.append(userHandle, allowed); + return allowed; + } + + return mUsersAllowingPrivateNotifications.get(userHandle); } protected class H extends Handler { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index e5bdd59a1d21f..2114991327413 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -1033,8 +1033,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { if (!notificationIsForCurrentUser(ent.notification)) continue; final int vis = ent.notification.getNotification().visibility; if (vis != Notification.VISIBILITY_SECRET) { - // when isPublicMode() we show the public form of VISIBILITY_PRIVATE notifications - ent.row.setShowingPublic(isPublicMode() && vis == Notification.VISIBILITY_PRIVATE); + // when isLockscreenPublicMode() we show the public form of VISIBILITY_PRIVATE notifications + ent.row.setShowingPublic(isLockscreenPublicMode() + && vis == Notification.VISIBILITY_PRIVATE + && !userAllowsPrivateNotificationsInPublic(ent.notification.getUserId())); toShow.add(ent.row); } } @@ -1087,9 +1089,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { if (!((provisioned && ent.notification.getScore() >= HIDE_ICONS_BELOW_SCORE) || showNotificationEvenIfUnprovisioned(ent.notification))) continue; if (!notificationIsForCurrentUser(ent.notification)) continue; - if (isPublicMode() + if (isLockscreenPublicMode() && ent.notification.getNotification().visibility - == Notification.VISIBILITY_SECRET) { + == Notification.VISIBILITY_SECRET + && !userAllowsPrivateNotificationsInPublic(ent.notification.getUserId())) { // in "public" mode (atop a secure keyguard), secret notifs are totally hidden continue; } @@ -1343,10 +1346,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { } else if ((diff & StatusBarManager.DISABLE_PRIVATE_NOTIFICATIONS) != 0) { if ((state & StatusBarManager.DISABLE_PRIVATE_NOTIFICATIONS) != 0) { // we are outside a secure keyguard, so we need to switch to "public" mode - setPublicMode(true); + setLockscreenPublicMode(true); } else { // user has authenticated the device; full notifications may be shown - setPublicMode(false); + setLockscreenPublicMode(false); } updateNotificationIcons(); }