visibility ("lights out") API.

1. Views may setSystemUiVisibility() to recommend that
the system chrome (status bar or other UI) show or hide
itself.  (This functionality was previously available only
via the FLAG_FULLSCREEN window flag for some SystemUI
implementations.)

2. Views may register a OnSystemUiVisibilityChangedListener
on a view, and find out when the system UI actually
appears or disappears, allowing apps to coordinate the
appearance of their own UI if desired.

Bug: 3241144
Change-Id: Ia1758d94099182d49a1e3688ea2738ae4995b829
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 8a9b78b..d932141 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -718,6 +718,7 @@
             attachInfo.mWindowVisibility = viewVisibility;
             attachInfo.mRecomputeGlobalAttributes = false;
             attachInfo.mKeepScreenOn = false;
+            attachInfo.mSystemUiVisibility = 0;
             viewVisibilityChanged = false;
             mLastConfiguration.setTo(host.getResources().getConfiguration());
             host.dispatchAttachedToWindow(attachInfo, 0);
@@ -891,14 +892,17 @@
         }
 
         if (attachInfo.mRecomputeGlobalAttributes) {
-            //Log.i(TAG, "Computing screen on!");
+            //Log.i(TAG, "Computing view hierarchy attributes!");
             attachInfo.mRecomputeGlobalAttributes = false;
-            boolean oldVal = attachInfo.mKeepScreenOn;
+            boolean oldScreenOn = attachInfo.mKeepScreenOn;
+            int oldVis = attachInfo.mSystemUiVisibility;
             attachInfo.mKeepScreenOn = false;
+            attachInfo.mSystemUiVisibility = 0;
+            attachInfo.mHasSystemUiListeners = false;
             host.dispatchCollectViewAttributes(0);
-            if (attachInfo.mKeepScreenOn != oldVal) {
+            if (attachInfo.mKeepScreenOn != oldScreenOn ||
+                    attachInfo.mSystemUiVisibility != oldVis) {
                 params = lp;
-                //Log.i(TAG, "Keep screen on changed: " + attachInfo.mKeepScreenOn);
             }
         }
 
@@ -980,6 +984,8 @@
                     if (attachInfo.mKeepScreenOn) {
                         params.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
                     }
+                    params.systemUiVisibility = attachInfo.mSystemUiVisibility;
+                    params.hasSystemUiListeners = attachInfo.mHasSystemUiListeners;
                 }
                 if (DEBUG_LAYOUT) {
                     Log.i(TAG, "host=w:" + host.getMeasuredWidth() + ", h:" +
@@ -1895,6 +1901,7 @@
     public final static int CLOSE_SYSTEM_DIALOGS = 1014;
     public final static int DISPATCH_DRAG_EVENT = 1015;
     public final static int DISPATCH_DRAG_LOCATION_EVENT = 1016;
+    public final static int DISPATCH_SYSTEM_UI_VISIBILITY = 1017;
 
     @Override
     public void handleMessage(Message msg) {
@@ -2057,6 +2064,9 @@
             event.mLocalState = mLocalDragState;    // only present when this app called startDrag()
             handleDragEvent(event);
         } break;
+        case DISPATCH_SYSTEM_UI_VISIBILITY: {
+            handleDispatchSystemUiVisibilityChanged(msg.arg1);
+        } break;
         }
     }
     
@@ -2826,6 +2836,11 @@
         event.recycle();
     }
 
+    public void handleDispatchSystemUiVisibilityChanged(int visibility) {
+        if (mView == null) return;
+        mView.dispatchSystemUiVisibilityChanged(visibility);
+    }
+
     public void getLastTouchPoint(Point outLocation) {
         outLocation.x = (int) mLastTouchPoint.x;
         outLocation.y = (int) mLastTouchPoint.y;
@@ -3141,6 +3156,10 @@
         sendMessage(msg);
     }
 
+    public void dispatchSystemUiVisibilityChanged(int visibility) {
+        sendMessage(obtainMessage(DISPATCH_SYSTEM_UI_VISIBILITY, visibility, 0));
+    }
+
     /**
      * The window is getting focus so if there is anything focused/selected
      * send an {@link AccessibilityEvent} to announce that.
@@ -3359,6 +3378,14 @@
                 viewRoot.dispatchDragEvent(event);
             }
         }
+
+        @Override
+        public void dispatchSystemUiVisibilityChanged(int visibility) {
+            final ViewRoot viewRoot = mViewRoot.get();
+            if (viewRoot != null) {
+                viewRoot.dispatchSystemUiVisibilityChanged(visibility);
+            }
+        }
     }
 
     /**