Allow the status bar disable flags to be used as View's system ui visibility fields.

Bug: 3363046
Change-Id: I50ba06ed9a4d2f5d0e0c807437aea9900f44fee9
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index 97e6931..46b52e1 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -22,6 +22,7 @@
 import android.os.RemoteException;
 import android.os.IBinder;
 import android.os.ServiceManager;
+import android.view.View;
 
 import com.android.internal.statusbar.IStatusBarService;
 
@@ -31,52 +32,23 @@
  * @hide
  */
 public class StatusBarManager {
-    /**
-     * Flag for {@link #disable} to make the status bar not expandable.  Unless you also
-     * set {@link #DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
-     */
-    public static final int DISABLE_EXPAND = 0x00000001;
 
-    /**
-     * Flag for {@link #disable} to hide notification icons and scrolling ticker text.
-     */
-    public static final int DISABLE_NOTIFICATION_ICONS = 0x00000002;
+    public static final int DISABLE_EXPAND = View.STATUS_BAR_DISABLE_EXPAND;
+    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;
+    public static final int DISABLE_NOTIFICATION_TICKER
+            = View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER;
+    public static final int DISABLE_SYSTEM_INFO = View.STATUS_BAR_DISABLE_SYSTEM_INFO;
+    public static final int DISABLE_NAVIGATION = View.STATUS_BAR_DISABLE_NAVIGATION;
+    public static final int DISABLE_CLOCK = View.STATUS_BAR_DISABLE_CLOCK;
 
-    /**
-     * Flag for {@link #disable} to disable incoming notification alerts.  This will not block
-     * icons, but it will block sound, vibrating and other visual or aural notifications.
-     */
-    public static final int DISABLE_NOTIFICATION_ALERTS = 0x00000004;
-
-    /**
-     * Flag for {@link #disable} to hide only the scrolling ticker.  Note that
-     * {@link #DISABLE_NOTIFICATION_ICONS} implies {@link #DISABLE_NOTIFICATION_TICKER}.
-     */
-    public static final int DISABLE_NOTIFICATION_TICKER = 0x00000008;
-
-    /**
-     * Flag for {@link #disable} to hide the center system info area.
-     */
-    public static final int DISABLE_SYSTEM_INFO = 0x00000010;
-
-    /**
-     * Flag for {@link #disable} to hide only the navigation buttons.  Don't use this
-     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
-     */
-    public static final int DISABLE_NAVIGATION = 0x00000020;
-
-    /**
-     * Flag for {@link #disable} to hide only the clock.  You might use this if your activity has
-     * its own clock making the status bar's clock redundant.
-     */
-    public static final int DISABLE_CLOCK = 0x00000040;
-
-
-    /**
-     * Re-enable all of the status bar features that you've disabled.
-     */
     public static final int DISABLE_NONE = 0x00000000;
 
+    public static final int DISABLE_MASK = DISABLE_EXPAND | DISABLE_NOTIFICATION_ICONS
+            | DISABLE_NOTIFICATION_ALERTS | DISABLE_NOTIFICATION_TICKER
+            | DISABLE_SYSTEM_INFO| DISABLE_NAVIGATION | DISABLE_CLOCK;
+
     private Context mContext;
     private IStatusBarService mService;
     private IBinder mToken = new Binder();
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index d0b150b..75791d5 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1732,6 +1732,88 @@
     public static final int STATUS_BAR_HIDDEN = 0x00000001;
 
     /**
+     * @hide
+     *
+     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
+     * out of the public fields to keep the undefined bits out of the developer's way.
+     *
+     * Flag to make the status bar not expandable.  Unless you also
+     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
+     */
+    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
+
+    /**
+     * @hide
+     *
+     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
+     * out of the public fields to keep the undefined bits out of the developer's way.
+     *
+     * Flag to hide notification icons and scrolling ticker text.
+     */
+    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
+
+    /**
+     * @hide
+     *
+     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
+     * out of the public fields to keep the undefined bits out of the developer's way.
+     *
+     * Flag to disable incoming notification alerts.  This will not block
+     * icons, but it will block sound, vibrating and other visual or aural notifications.
+     */
+    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
+
+    /**
+     * @hide
+     *
+     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
+     * out of the public fields to keep the undefined bits out of the developer's way.
+     *
+     * Flag to hide only the scrolling ticker.  Note that
+     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
+     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
+     */
+    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
+
+    /**
+     * @hide
+     *
+     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
+     * out of the public fields to keep the undefined bits out of the developer's way.
+     *
+     * Flag to hide the center system info area.
+     */
+    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
+
+    /**
+     * @hide
+     *
+     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
+     * out of the public fields to keep the undefined bits out of the developer's way.
+     *
+     * Flag to hide only the navigation buttons.  Don't use this
+     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
+     */
+    public static final int STATUS_BAR_DISABLE_NAVIGATION = 0x00200000;
+
+    /**
+     * @hide
+     *
+     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
+     * out of the public fields to keep the undefined bits out of the developer's way.
+     *
+     * Flag to hide only the clock.  You might use this if your activity has
+     * its own clock making the status bar's clock redundant.
+     */
+    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00400000;
+
+    /**
+     * @hide
+     */
+    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = STATUS_BAR_HIDDEN;
+    
+
+    /**
      * Controls the over-scroll mode for this view.
      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
@@ -10839,7 +10921,8 @@
     public void dispatchSystemUiVisibilityChanged(int visibility) {
         mSystemUiVisibility = visibility;
         if (mOnSystemUiVisibilityChangeListener != null) {
-            mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(visibility);
+            mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
+                    visibility & ~PUBLIC_STATUS_BAR_VISIBILITY_MASK);
         }
     }
 
diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/java/com/android/server/StatusBarManagerService.java
index cdbf237..1a2f867 100644
--- a/services/java/com/android/server/StatusBarManagerService.java
+++ b/services/java/com/android/server/StatusBarManagerService.java
@@ -67,6 +67,7 @@
 
     // for disabling the status bar
     ArrayList<DisableRecord> mDisableRecords = new ArrayList<DisableRecord>();
+    IBinder mSysUiVisToken = new Binder();
     int mDisabled = 0;
 
     Object mLock = new Object();
@@ -141,25 +142,29 @@
     public void disable(int what, IBinder token, String pkg) {
         enforceStatusBar();
 
+        synchronized (mLock) {
+            disableLocked(what, token, pkg);
+        }
+    }
+
+    private void disableLocked(int what, IBinder token, String pkg) {
         // It's important that the the callback and the call to mBar get done
         // in the same order when multiple threads are calling this function
         // so they are paired correctly.  The messages on the handler will be
         // handled in the order they were enqueued, but will be outside the lock.
-        synchronized (mDisableRecords) {
-            manageDisableListLocked(what, token, pkg);
-            final int net = gatherDisableActionsLocked();
-            if (net != mDisabled) {
-                mDisabled = net;
-                mHandler.post(new Runnable() {
-                        public void run() {
-                            mNotificationCallbacks.onSetDisabled(net);
-                        }
-                    });
-                if (mBar != null) {
-                    try {
-                        mBar.disable(net);
-                    } catch (RemoteException ex) {
+        manageDisableListLocked(what, token, pkg);
+        final int net = gatherDisableActionsLocked();
+        if (net != mDisabled) {
+            mDisabled = net;
+            mHandler.post(new Runnable() {
+                    public void run() {
+                        mNotificationCallbacks.onSetDisabled(net);
                     }
+                });
+            if (mBar != null) {
+                try {
+                    mBar.disable(net);
+                } catch (RemoteException ex) {
                 }
             }
         }
@@ -294,6 +299,8 @@
         synchronized (mLock) {
             final boolean lightsOn = (vis & View.STATUS_BAR_HIDDEN) == 0;
             updateLightsOnLocked(lightsOn);
+            disableLocked(vis & StatusBarManager.DISABLE_MASK, mSysUiVisToken,
+                    "WindowManager.LayoutParams");
         }
     }
 
@@ -452,37 +459,35 @@
             Slog.d(TAG, "manageDisableList what=0x" + Integer.toHexString(what) + " pkg=" + pkg);
         }
         // update the list
-        synchronized (mDisableRecords) {
-            final int N = mDisableRecords.size();
-            DisableRecord tok = null;
-            int i;
-            for (i=0; i<N; i++) {
-                DisableRecord t = mDisableRecords.get(i);
-                if (t.token == token) {
-                    tok = t;
-                    break;
-                }
+        final int N = mDisableRecords.size();
+        DisableRecord tok = null;
+        int i;
+        for (i=0; i<N; i++) {
+            DisableRecord t = mDisableRecords.get(i);
+            if (t.token == token) {
+                tok = t;
+                break;
             }
-            if (what == 0 || !token.isBinderAlive()) {
-                if (tok != null) {
-                    mDisableRecords.remove(i);
-                    tok.token.unlinkToDeath(tok, 0);
-                }
-            } else {
-                if (tok == null) {
-                    tok = new DisableRecord();
-                    try {
-                        token.linkToDeath(tok, 0);
-                    }
-                    catch (RemoteException ex) {
-                        return; // give up
-                    }
-                    mDisableRecords.add(tok);
-                }
-                tok.what = what;
-                tok.token = token;
-                tok.pkg = pkg;
+        }
+        if (what == 0 || !token.isBinderAlive()) {
+            if (tok != null) {
+                mDisableRecords.remove(i);
+                tok.token.unlinkToDeath(tok, 0);
             }
+        } else {
+            if (tok == null) {
+                tok = new DisableRecord();
+                try {
+                    token.linkToDeath(tok, 0);
+                }
+                catch (RemoteException ex) {
+                    return; // give up
+                }
+                mDisableRecords.add(tok);
+            }
+            tok.what = what;
+            tok.token = token;
+            tok.pkg = pkg;
         }
     }
 
@@ -523,7 +528,7 @@
             }
         }
 
-        synchronized (mDisableRecords) {
+        synchronized (mLock) {
             final int N = mDisableRecords.size();
             pw.println("  mDisableRecords.size=" + N
                     + " mDisabled=0x" + Integer.toHexString(mDisabled));
diff --git a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
index 5fd946e..13665e1 100644
--- a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
+++ b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
@@ -70,6 +70,12 @@
     }
 
     private Test[] mTests = new Test[] {
+        new Test("DISABLE_NAVIGATION") {
+            public void run() {
+                View v = findViewById(android.R.id.list);
+                v.setSystemUiVisibility(View.STATUS_BAR_DISABLE_NAVIGATION);
+            }
+        },
         new Test("STATUS_BAR_HIDDEN") {
             public void run() {
                 View v = findViewById(android.R.id.list);
@@ -77,7 +83,7 @@
                 v.setOnSystemUiVisibilityChangeListener(mOnSystemUiVisibilityChangeListener);
             }
         },
-        new Test("not STATUS_BAR_HIDDEN") {
+        new Test("no setSystemUiVisibility") {
             public void run() {
                 View v = findViewById(android.R.id.list);
                 v.setSystemUiVisibility(View.STATUS_BAR_VISIBLE);