OSDN Git Service

SystemUI support for notification visibility.
authorDan Sandler <dsandler@android.com>
Thu, 23 Jan 2014 20:11:54 +0000 (15:11 -0500)
committerDan Sandler <dsandler@android.com>
Thu, 30 Jan 2014 18:23:14 +0000 (13:23 -0500)
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
core/java/android/provider/Settings.java
packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java
packages/SystemUI/res/layout/status_bar_notification_row.xml
packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java

index 2045ed8..a6a04d1 100644 (file)
@@ -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;
index ee37045..b9a898e 100644 (file)
@@ -3468,6 +3468,14 @@ public final class Settings {
             "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.
          * @deprecated This identifier is poorly initialized and has
index e2219d4..914fdc4 100644 (file)
@@ -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;
 
@@ -246,6 +258,11 @@ public class KeyguardViewMediator {
     private int mLockSoundStreamId;
 
     /**
+     * Tracks value of {@link Settings.Secure#LOCK_SCREEN_ALLOW_NOTIFICATIONS}.
+     */
+    private boolean mAllowNotificationsWhenSecure;
+
+    /**
      * The volume applied to the lock/unlock sounds.
      */
     private final float mLockSoundVolume;
@@ -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;
index f827967..e74e568 100644 (file)
@@ -25,7 +25,7 @@
         android:paddingStart="8dp"
         />
 
-    <com.android.systemui.statusbar.LatestItemView android:id="@+id/content"
+    <com.android.systemui.statusbar.LatestItemView android:id="@+id/container"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginBottom="@dimen/notification_divider_height"
         android:clickable="true"
         >
 
-        <com.android.internal.widget.SizeAdaptiveLayout android:id="@+id/adaptive"
+        <com.android.internal.widget.SizeAdaptiveLayout android:id="@+id/expanded"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
 
+        <com.android.internal.widget.SizeAdaptiveLayout android:id="@+id/expandedPublic"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" />
     </com.android.systemui.statusbar.LatestItemView>
 
     <View
index ed00398..a7cfaba 100644 (file)
@@ -26,6 +26,7 @@ import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Configuration;
 import android.database.ContentObserver;
@@ -130,6 +131,7 @@ public abstract class BaseStatusBar extends SystemUI implements
     protected IDreamManager mDreamManager;
     PowerManager mPowerManager;
     protected int mRowHeight;
+    private boolean mPublicMode = false;
 
     // UI-specific methods
 
@@ -548,6 +550,14 @@ public abstract class BaseStatusBar extends SystemUI implements
 
     public abstract void resetHeadsUpDecayTimer();
 
+    public void setPublicMode(boolean publicMode) {
+        mPublicMode = publicMode;
+    }
+
+    public boolean isPublicMode() {
+        return mPublicMode;
+    }
+
     protected class H extends Handler {
         public void handleMessage(Message m) {
             Intent intent;
@@ -625,6 +635,11 @@ public abstract class BaseStatusBar extends SystemUI implements
             return false;
         }
 
+        Log.v(TAG, "publicNotification: "
+                + sbn.getNotification().publicVersion);
+
+        Notification publicNotification = sbn.getNotification().publicVersion;
+
         // create the row view
         LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(
                 Context.LAYOUT_INFLATER_SERVICE);
@@ -642,8 +657,10 @@ public abstract class BaseStatusBar extends SystemUI implements
         // NB: the large icon is now handled entirely by the template
 
         // bind the click event to the content area
-        ViewGroup content = (ViewGroup)row.findViewById(R.id.content);
-        ViewGroup adaptive = (ViewGroup)row.findViewById(R.id.adaptive);
+        ViewGroup content = (ViewGroup)row.findViewById(R.id.container);
+        SizeAdaptiveLayout expanded = (SizeAdaptiveLayout)row.findViewById(R.id.expanded);
+        SizeAdaptiveLayout expandedPublic
+                = (SizeAdaptiveLayout)row.findViewById(R.id.expandedPublic);
 
         content.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
 
@@ -656,12 +673,13 @@ public abstract class BaseStatusBar extends SystemUI implements
             content.setOnClickListener(null);
         }
 
+        // set up the adaptive layout
         View contentViewLocal = null;
         View bigContentViewLocal = null;
         try {
-            contentViewLocal = contentView.apply(mContext, adaptive, mOnClickHandler);
+            contentViewLocal = contentView.apply(mContext, expanded, mOnClickHandler);
             if (bigContentView != null) {
-                bigContentViewLocal = bigContentView.apply(mContext, adaptive, mOnClickHandler);
+                bigContentViewLocal = bigContentView.apply(mContext, expanded, mOnClickHandler);
             }
         }
         catch (RuntimeException e) {
@@ -675,15 +693,70 @@ public abstract class BaseStatusBar extends SystemUI implements
                     new SizeAdaptiveLayout.LayoutParams(contentViewLocal.getLayoutParams());
             params.minHeight = minHeight;
             params.maxHeight = minHeight;
-            adaptive.addView(contentViewLocal, params);
+            expanded.addView(contentViewLocal, params);
         }
         if (bigContentViewLocal != null) {
             SizeAdaptiveLayout.LayoutParams params =
                     new SizeAdaptiveLayout.LayoutParams(bigContentViewLocal.getLayoutParams());
             params.minHeight = minHeight+1;
             params.maxHeight = maxHeight;
-            adaptive.addView(bigContentViewLocal, params);
+            expanded.addView(bigContentViewLocal, params);
+        }
+
+        PackageManager pm = mContext.getPackageManager();
+
+        // now the public version
+        View publicViewLocal = null;
+        if (publicNotification != null) {
+            try {
+                publicViewLocal = publicNotification.contentView.apply(mContext,
+                        expandedPublic, mOnClickHandler);
+
+                if (publicViewLocal != null) {
+                    SizeAdaptiveLayout.LayoutParams params =
+                            new SizeAdaptiveLayout.LayoutParams(publicViewLocal.getLayoutParams());
+                    params.minHeight = minHeight;
+                    params.maxHeight = minHeight;
+                    expandedPublic.addView(publicViewLocal, params);
+                }
+            }
+            catch (RuntimeException e) {
+                final String ident = sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId());
+                Log.e(TAG, "couldn't inflate public view for notification " + ident, e);
+                publicViewLocal = null;
+            }
         }
+
+        if (publicViewLocal == null) {
+            // Add a basic notification template
+            publicViewLocal = LayoutInflater.from(mContext).inflate(
+                    com.android.internal.R.layout.notification_template_base, expandedPublic, true);
+
+            final TextView title = (TextView) publicViewLocal.findViewById(com.android.internal.R.id.title);
+            try {
+                title.setText(pm.getApplicationLabel(
+                        pm.getApplicationInfo(entry.notification.getPackageName(), 0)));
+            } catch (NameNotFoundException e) {
+                title.setText(entry.notification.getPackageName());
+            }
+
+            final ImageView icon = (ImageView) publicViewLocal.findViewById(com.android.internal.R.id.icon);
+
+            final StatusBarIcon ic = new StatusBarIcon(entry.notification.getPackageName(),
+                    entry.notification.getUser(),
+                    entry.notification.getNotification().icon,
+                    entry.notification.getNotification().iconLevel,
+                    entry.notification.getNotification().number,
+                    entry.notification.getNotification().tickerText);
+
+            icon.setImageDrawable(StatusBarIconView.getIcon(mContext, ic));
+
+            final TextView text = (TextView) publicViewLocal.findViewById(com.android.internal.R.id.text);
+            text.setText("Unlock your device to see this notification.");
+
+            // TODO: fill out "time" as well
+        }
+
         row.setDrawingCacheEnabled(true);
 
         applyLegacyRowBackground(sbn, content);
@@ -699,6 +772,7 @@ public abstract class BaseStatusBar extends SystemUI implements
         entry.row.setRowHeight(mRowHeight);
         entry.content = content;
         entry.expanded = contentViewLocal;
+        entry.expandedPublic = publicViewLocal;
         entry.setBigContentView(bigContentViewLocal);
 
         return true;
@@ -904,6 +978,12 @@ public abstract class BaseStatusBar extends SystemUI implements
         final RemoteViews contentView = notification.getNotification().contentView;
         final RemoteViews oldBigContentView = oldNotification.getNotification().bigContentView;
         final RemoteViews bigContentView = notification.getNotification().bigContentView;
+        final Notification oldPublicNotification = oldNotification.getNotification().publicVersion;
+        final RemoteViews oldPublicContentView = oldPublicNotification != null
+                ? oldPublicNotification.contentView : null;
+        final Notification publicNotification = notification.getNotification().publicVersion;
+        final RemoteViews publicContentView = publicNotification != null
+                ? publicNotification.contentView : null;
 
         if (DEBUG) {
             Log.d(TAG, "old notification: when=" + oldNotification.getNotification().when
@@ -911,11 +991,13 @@ public abstract class BaseStatusBar extends SystemUI implements
                     + " expanded=" + oldEntry.expanded
                     + " contentView=" + oldContentView
                     + " bigContentView=" + oldBigContentView
+                    + " publicView=" + oldPublicContentView
                     + " rowParent=" + oldEntry.row.getParent());
             Log.d(TAG, "new notification: when=" + notification.getNotification().when
                     + " ongoing=" + oldNotification.isOngoing()
                     + " contentView=" + contentView
-                    + " bigContentView=" + bigContentView);
+                    + " bigContentView=" + bigContentView
+                    + " publicView=" + publicContentView);
         }
 
         // Can we just reapply the RemoteViews in place?  If when didn't change, the order
@@ -935,8 +1017,17 @@ public abstract class BaseStatusBar extends SystemUI implements
                     && oldBigContentView.getPackage() != null
                     && oldBigContentView.getPackage().equals(bigContentView.getPackage())
                     && oldBigContentView.getLayoutId() == bigContentView.getLayoutId());
+        boolean publicUnchanged  =
+                (oldPublicContentView == null && publicContentView == null)
+                || ((oldPublicContentView != null && publicContentView != null)
+                        && publicContentView.getPackage() != null
+                        && oldPublicContentView.getPackage() != null
+                        && oldPublicContentView.getPackage().equals(publicContentView.getPackage())
+                        && oldPublicContentView.getLayoutId() == publicContentView.getLayoutId());
+
         ViewGroup rowParent = (ViewGroup) oldEntry.row.getParent();
-        boolean orderUnchanged = notification.getNotification().when== oldNotification.getNotification().when
+        boolean orderUnchanged =
+                   notification.getNotification().when == oldNotification.getNotification().when
                 && notification.getScore() == oldNotification.getScore();
                 // score now encompasses/supersedes isOngoing()
 
@@ -944,7 +1035,8 @@ public abstract class BaseStatusBar extends SystemUI implements
                 && !TextUtils.equals(notification.getNotification().tickerText,
                         oldEntry.notification.getNotification().tickerText);
         boolean isTopAnyway = isTopNotification(rowParent, oldEntry);
-        if (contentsUnchanged && bigContentsUnchanged && (orderUnchanged || isTopAnyway)) {
+        if (contentsUnchanged && bigContentsUnchanged && publicUnchanged
+                && (orderUnchanged || isTopAnyway)) {
             if (DEBUG) Log.d(TAG, "reusing notification for key: " + key);
             oldEntry.notification = notification;
             try {
@@ -1018,11 +1110,17 @@ public abstract class BaseStatusBar extends SystemUI implements
             StatusBarNotification notification) {
         final RemoteViews contentView = notification.getNotification().contentView;
         final RemoteViews bigContentView = notification.getNotification().bigContentView;
+        final RemoteViews publicContentView
+                = notification.getNotification().publicVersion.contentView;
+
         // Reapply the RemoteViews
         contentView.reapply(mContext, entry.expanded, mOnClickHandler);
         if (bigContentView != null && entry.getBigContentView() != null) {
             bigContentView.reapply(mContext, entry.getBigContentView(), mOnClickHandler);
         }
+        if (publicContentView != null && entry.getPublicContentView() != null) {
+            publicContentView.reapply(mContext, entry.getPublicContentView(), mOnClickHandler);
+        }
         // update the contentIntent
         final PendingIntent contentIntent = notification.getNotification().contentIntent;
         if (contentIntent != null) {
index cd6495f..b3d8688 100644 (file)
@@ -18,9 +18,12 @@ package com.android.systemui.statusbar;
 
 import android.content.Context;
 import android.util.AttributeSet;
+import android.view.View;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
+import com.android.systemui.R;
+
 public class ExpandableNotificationRow extends FrameLayout {
     private int mRowHeight;
 
@@ -30,6 +33,8 @@ public class ExpandableNotificationRow extends FrameLayout {
     private boolean mUserExpanded;
     /** is the user touching this row */
     private boolean mUserLocked;
+    /** are we showing the "public" version */
+    private boolean mShowingPublic;
 
     public ExpandableNotificationRow(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -76,4 +81,16 @@ public class ExpandableNotificationRow extends FrameLayout {
         }
         setLayoutParams(lp);
     }
+
+    public void setShowingPublic(boolean show) {
+        mShowingPublic = show;
+        final ViewGroup publicLayout = (ViewGroup) findViewById(R.id.expandedPublic);
+
+        // bail out if no public version
+        if (publicLayout.getChildCount() == 0) return;
+
+        // TODO: animation?
+        publicLayout.setVisibility(show ? View.VISIBLE : View.GONE);
+        findViewById(R.id.expanded).setVisibility(show ? View.GONE : View.VISIBLE);
+    }
 }
index 44b3843..4427466 100644 (file)
@@ -35,6 +35,7 @@ public class NotificationData {
         public ExpandableNotificationRow row; // the outer expanded view
         public View content; // takes the click events and sends the PendingIntent
         public View expanded; // the inflated RemoteViews
+        public View expandedPublic; // for insecure lockscreens
         public ImageView largeIcon;
         private View expandedBig;
         private boolean interruption;
@@ -51,6 +52,7 @@ public class NotificationData {
         public View getBigContentView() {
             return expandedBig;
         }
+        public View getPublicContentView() { return expandedPublic; }
         /**
          * Set the flag indicating that this is being touched by the user.
          */
@@ -108,19 +110,6 @@ public class NotificationData {
         return i;
     }
 
-    public int add(IBinder key, StatusBarNotification notification, ExpandableNotificationRow row,
-            View content, View expanded, StatusBarIconView icon) {
-        Entry entry = new Entry();
-        entry.key = key;
-        entry.notification = notification;
-        entry.row = row;
-        entry.content = content;
-        entry.expanded = expanded;
-        entry.icon = icon;
-        entry.largeIcon = null; // TODO add support for large icons
-        return add(entry);
-    }
-
     public Entry remove(IBinder key) {
         Entry e = findByKey(key);
         if (e != null) {
index 124a6bc..b72c25d 100644 (file)
@@ -514,7 +514,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
         mScrollView.setVerticalScrollBarEnabled(false); // less drawing during pulldowns
         if (!mNotificationPanelIsFullScreenWidth) {
             mScrollView.setSystemUiVisibility(
-                    View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER |
                     View.STATUS_BAR_DISABLE_NOTIFICATION_ICONS |
                     View.STATUS_BAR_DISABLE_CLOCK);
         }
@@ -621,7 +620,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
                 mQS = new QuickSettings(mContext, mSettingsContainer);
                 if (!mNotificationPanelIsFullScreenWidth) {
                     mSettingsContainer.setSystemUiVisibility(
-                            View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER
+                            View.STATUS_BAR_DISABLE_NOTIFICATION_ICONS
                             | View.STATUS_BAR_DISABLE_SYSTEM_INFO);
                 }
                 if (mSettingsPanel != null) {
@@ -1031,7 +1030,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
             Entry ent = mNotificationData.get(N-i-1);
             if (!(provisioned || showNotificationEvenIfUnprovisioned(ent.notification))) continue;
             if (!notificationIsForCurrentUser(ent.notification)) continue;
-            toShow.add(ent.row);
+            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);
+                toShow.add(ent.row);
+            }
         }
 
         ArrayList<View> toRemove = new ArrayList<View>();
@@ -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();
         }
     }