From a5e0f415d351ad1a9c0ffde8d93df91a2384591f Mon Sep 17 00:00:00 2001 From: Dan Sandler Date: Thu, 23 Jan 2014 15:11:54 -0500 Subject: [PATCH] SystemUI support for notification visibility. In this implementation, DISABLE_NOTIFICATION_TICKER (which was never really used on its own and can be safely subsumed by DISABLE_NOTIFICATION_ICONS) is now DISABLE_PRIVATE_NOTIFICATIONS; when this SystemUI bit is set by the keyguard, SystemUI knows to switch its presentation into "public" mode, in which VISIBILITY_PRIVATE notifications are replaced with their publicVersion's contentView (or a placeholder view, synthesized by SystemUI, that leaks no additional information about the notification). VISIBILITY_SECRET notifications are suppressed altogether in this mode. This behavior is enabled but not activated by default. To turn it on, run: $ adb shell settings put secure lock_screen_allow_notifications 1 and restart SystemUI. Change-Id: Id660bef7737580e16a83f60567c22b53ee81c602 --- core/java/android/app/StatusBarManager.java | 3 + core/java/android/provider/Settings.java | 8 ++ .../keyguard/KeyguardViewMediator.java | 32 ++++- .../layout/status_bar_notification_row.xml | 7 +- .../systemui/statusbar/BaseStatusBar.java | 116 ++++++++++++++++-- .../statusbar/ExpandableNotificationRow.java | 17 +++ .../systemui/statusbar/NotificationData.java | 15 +-- .../statusbar/phone/PhoneStatusBar.java | 31 +++-- 8 files changed, 194 insertions(+), 35 deletions(-) diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java index 2045ed8411a30..a6a04d11ee16a 100644 --- a/core/java/android/app/StatusBarManager.java +++ b/core/java/android/app/StatusBarManager.java @@ -38,8 +38,11 @@ public class StatusBarManager { public static final int DISABLE_NOTIFICATION_ICONS = View.STATUS_BAR_DISABLE_NOTIFICATION_ICONS; public static final int DISABLE_NOTIFICATION_ALERTS = View.STATUS_BAR_DISABLE_NOTIFICATION_ALERTS; + @Deprecated public static final int DISABLE_NOTIFICATION_TICKER = View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER; + public static final int DISABLE_PRIVATE_NOTIFICATIONS + = View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER; public static final int DISABLE_SYSTEM_INFO = View.STATUS_BAR_DISABLE_SYSTEM_INFO; public static final int DISABLE_HOME = View.STATUS_BAR_DISABLE_HOME; public static final int DISABLE_RECENT = View.STATUS_BAR_DISABLE_RECENT; diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index ee370451bb772..b9a898e42b7b3 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -3467,6 +3467,14 @@ public final class Settings { public static final String LOCK_SCREEN_OWNER_INFO_ENABLED = "lock_screen_owner_info_enabled"; + /** + * This preference enables expanding the notification panel even over a securely + * locked screen, showing only "public" notifications in this case. + * @hide + */ + public static final String LOCK_SCREEN_ALLOW_NOTIFICATIONS = + "lock_screen_allow_notifications"; + /** * The Logging ID (a unique 64-bit value) as a hex string. * Used as a pseudonymous identifier for logging. diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java index e2219d439a86f..914fdc4fd89b7 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java @@ -149,6 +149,18 @@ public class KeyguardViewMediator { */ private static final boolean ENABLE_INSECURE_STATUS_BAR_EXPAND = true; + /** + * Allow the user to expand the status bar when a SECURE keyguard is engaged + * and {@link Settings.Secure#LOCK_SCREEN_ALLOW_NOTIFICATIONS} is set + * (private notifications will be masked). + */ + private static final boolean ENABLE_SECURE_STATUS_BAR_EXPAND = true; + + /** + * Default value of {@link Settings.Secure#LOCK_SCREEN_ALLOW_NOTIFICATIONS}. + */ + private static final boolean ALLOW_NOTIFICATIONS_DEFAULT = false; + /** The stream type that the lock sounds are tied to. */ private int mMasterStreamType; @@ -245,6 +257,11 @@ public class KeyguardViewMediator { private int mUnlockSoundId; private int mLockSoundStreamId; + /** + * Tracks value of {@link Settings.Secure#LOCK_SCREEN_ALLOW_NOTIFICATIONS}. + */ + private boolean mAllowNotificationsWhenSecure; + /** * The volume applied to the lock/unlock sounds. */ @@ -894,6 +911,13 @@ public class KeyguardViewMediator { return; } + // note whether notification access should be allowed + mAllowNotificationsWhenSecure = ENABLE_SECURE_STATUS_BAR_EXPAND + && 0 != Settings.Secure.getInt( + mContext.getContentResolver(), + Settings.Secure.LOCK_SCREEN_ALLOW_NOTIFICATIONS, + ALLOW_NOTIFICATIONS_DEFAULT ? 1 : 0); + // if the keyguard is already showing, don't bother if (mKeyguardViewManager.isShowing()) { if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing"); @@ -1278,13 +1302,15 @@ public class KeyguardViewMediator { // (like recents). Temporary enable/disable (e.g. the "back" button) are // done in KeyguardHostView. flags |= StatusBarManager.DISABLE_RECENT; - if (isSecure() || !ENABLE_INSECURE_STATUS_BAR_EXPAND) { + if ((isSecure() && !mAllowNotificationsWhenSecure) + || !ENABLE_INSECURE_STATUS_BAR_EXPAND) { // showing secure lockscreen; disable expanding. flags |= StatusBarManager.DISABLE_EXPAND; } if (isSecure()) { - // showing secure lockscreen; disable ticker. - flags |= StatusBarManager.DISABLE_NOTIFICATION_TICKER; + // showing secure lockscreen; disable ticker and switch private notifications + // to show their public versions, if available. + flags |= StatusBarManager.DISABLE_PRIVATE_NOTIFICATIONS; } if (!isAssistantAvailable()) { flags |= StatusBarManager.DISABLE_SEARCH; diff --git a/packages/SystemUI/res/layout/status_bar_notification_row.xml b/packages/SystemUI/res/layout/status_bar_notification_row.xml index f8279672efff7..e74e5684710d4 100644 --- a/packages/SystemUI/res/layout/status_bar_notification_row.xml +++ b/packages/SystemUI/res/layout/status_bar_notification_row.xml @@ -25,7 +25,7 @@ android:paddingStart="8dp" /> - - + toRemove = new ArrayList(); @@ -1082,6 +1086,12 @@ 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() + && ent.notification.getNotification().visibility + == Notification.VISIBILITY_SECRET) { + // in "public" mode (atop a secure keyguard), secret notifs are totally hidden + continue; + } toShow.add(ent.icon); } @@ -1243,8 +1253,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { flagdbg.append(((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) ? "* " : " "); flagdbg.append(((state & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) ? "ALERTS" : "alerts"); flagdbg.append(((diff & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) ? "* " : " "); - flagdbg.append(((state & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) ? "TICKER" : "ticker"); - flagdbg.append(((diff & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) ? "* " : " "); + flagdbg.append(((state & StatusBarManager.DISABLE_PRIVATE_NOTIFICATIONS) != 0) ? "PRIVATE" : "private"); + flagdbg.append(((diff & StatusBarManager.DISABLE_PRIVATE_NOTIFICATIONS) != 0) ? "* " : " "); flagdbg.append(((state & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) ? "SYSTEM_INFO" : "system_info"); flagdbg.append(((diff & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) ? "* " : " "); flagdbg.append(((state & StatusBarManager.DISABLE_BACK) != 0) ? "BACK" : "back"); @@ -1329,10 +1339,15 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { .setDuration(175) .start(); } - } else if ((diff & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) { - if (mTicking && (state & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) { - haltTicker(); + } 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); + } else { + // user has authenticated the device; full notifications may be shown + setPublicMode(false); } + updateNotificationIcons(); } }