resolved conflicts for merge of faf083ef to master

Change-Id: I316a1b4356f6dba6c3880ccb02dbb2fa00d21a85
diff --git a/api/current.xml b/api/current.xml
index 5c18afc..50a4fcf 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -217827,6 +217827,19 @@
 <parameter name="selected" type="boolean">
 </parameter>
 </method>
+<method name="dispatchSystemUiVisibilityChanged"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visibility" type="int">
+</parameter>
+</method>
 <method name="dispatchTouchEvent"
  return="boolean"
  abstract="false"
@@ -218880,6 +218893,19 @@
  visibility="protected"
 >
 </method>
+<method name="getSystemUiVisibility"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visibility" type="int">
+</parameter>
+</method>
 <method name="getTag"
  return="java.lang.Object"
  abstract="false"
@@ -221143,6 +221169,19 @@
 <parameter name="l" type="android.view.View.OnLongClickListener">
 </parameter>
 </method>
+<method name="setOnSystemUiVisibilityChangeListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="l" type="android.view.View.OnSystemUiVisibilityChangeListener">
+</parameter>
+</method>
 <method name="setOnTouchListener"
  return="void"
  abstract="false"
@@ -221396,6 +221435,19 @@
 <parameter name="soundEffectsEnabled" type="boolean">
 </parameter>
 </method>
+<method name="setSystemUiVisibility"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visibility" type="int">
+</parameter>
+</method>
 <method name="setTag"
  return="void"
  abstract="false"
@@ -222403,6 +222455,28 @@
  visibility="public"
 >
 </field>
+<field name="STATUS_BAR_HIDDEN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_BAR_VISIBLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="VIEW_LOG_TAG"
  type="java.lang.String"
  transient="false"
@@ -222821,6 +222895,27 @@
 </parameter>
 </method>
 </interface>
+<interface name="View.OnSystemUiVisibilityChangeListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onSystemUiVisibilityChange"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visibility" type="int">
+</parameter>
+</method>
+</interface>
 <interface name="View.OnTouchListener"
  abstract="true"
  static="true"
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 85a8c1a..0e482d6 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -70,4 +70,9 @@
      * Drag/drop events
      */
      void dispatchDragEvent(in DragEvent event);
+
+    /**
+     * System chrome visibility changes
+     */
+     void dispatchSystemUiVisibilityChanged(int visibility);
 }
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 8bdc1f8..51653df 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -187,4 +187,9 @@
 	 * Create a screenshot of the applications currently displayed.
 	 */
 	Bitmap screenshotApplications(IBinder appToken, int maxWidth, int maxHeight);
+
+    /**
+     * Called by the status bar to notify Views of changes to System UI visiblity.
+     */
+    void statusBarVisibilityChanged(int visibility);
 }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 8bcd0a3..27a71c5 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -48,6 +48,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.util.AttributeSet;
@@ -1697,6 +1698,20 @@
     public static final int OVER_SCROLL_NEVER = 2;
 
     /**
+     * View has requested the status bar to be visible (the default).
+     *
+     * @see setSystemUiVisibility
+     */
+    public static final int STATUS_BAR_VISIBLE = 0;
+
+    /**
+     * View has requested the status bar to be visible (the default).
+     *
+     * @see setSystemUiVisibility
+     */
+    public static final int STATUS_BAR_HIDDEN = 0x00000001;
+
+    /**
      * 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},
@@ -1735,6 +1750,12 @@
     int mPrivateFlags;
 
     /**
+     * This view's request for the visibility of the status bar.
+     * @hide
+     */
+    int mSystemUiVisibility;
+
+    /**
      * Count of how many windows this view has been attached to.
      */
     int mWindowAttachCount;
@@ -2037,6 +2058,8 @@
 
     private OnDragListener mOnDragListener;
 
+    private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
+
     /**
      * The application environment this view lives in.
      * This field should be made private, so it is hidden from the SDK.
@@ -4716,17 +4739,22 @@
     }
 
     void performCollectViewAttributes(int visibility) {
-        //noinspection PointlessBitwiseExpression
-        if (((visibility | mViewFlags) & (VISIBILITY_MASK | KEEP_SCREEN_ON))
-                == (VISIBLE | KEEP_SCREEN_ON)) {
-            mAttachInfo.mKeepScreenOn = true;
+        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
+            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
+                mAttachInfo.mKeepScreenOn = true;
+            }
+            mAttachInfo.mSystemUiVisibility |= mSystemUiVisibility;
+            if (mOnSystemUiVisibilityChangeListener != null) {
+                mAttachInfo.mHasSystemUiListeners = true;
+            }
         }
     }
 
     void needGlobalAttributesUpdate(boolean force) {
-        AttachInfo ai = mAttachInfo;
+        final AttachInfo ai = mAttachInfo;
         if (ai != null) {
-            if (ai.mKeepScreenOn || force) {
+            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
+                    || ai.mHasSystemUiListeners) {
                 ai.mRecomputeGlobalAttributes = true;
             }
         }
@@ -5342,7 +5370,7 @@
         }
 
         if ((changed & KEEP_SCREEN_ON) != 0) {
-            if (mParent != null) {
+            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
                 mParent.recomputeViewAttributes(this);
             }
         }
@@ -10659,6 +10687,40 @@
     }
 
     /**
+     * Request that the visibility of the status bar be changed.
+     */
+    public void setSystemUiVisibility(int visibility) {
+        if (visibility != mSystemUiVisibility) {
+            mSystemUiVisibility = visibility;
+            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
+                mParent.recomputeViewAttributes(this);
+            }
+        }
+    }
+
+    /**
+     * Returns the status bar visibility that this view has requested.
+     */
+    public int getSystemUiVisibility(int visibility) {
+        return mSystemUiVisibility;
+    }
+
+    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
+        mOnSystemUiVisibilityChangeListener = l;
+        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
+            mParent.recomputeViewAttributes(this);
+        }
+    }
+
+    /**
+     */
+    public void dispatchSystemUiVisibilityChanged(int visibility) {
+        if (mOnSystemUiVisibilityChangeListener != null) {
+            mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(visibility);
+        }
+    }
+
+    /**
      * !!! TODO: real docs
      *
      * The base class implementation makes the shadow the same size and appearance
@@ -11348,6 +11410,22 @@
         void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
     }
 
+    /**
+     * Interface definition for a callback to be invoked when the status bar changes
+     * visibility.
+     *
+     * @see #setOnSystemUiVisibilityChangeListener
+     */
+    public interface OnSystemUiVisibilityChangeListener {
+        /**
+         * Called when the status bar changes visibility because of a call to
+         * {@link #setSystemUiVisibility}.
+         *
+         * @param visibility {@link #STATUS_BAR_VISIBLE} or {@link #STATUS_BAR_HIDDEN}.
+         */
+        public void onSystemUiVisibilityChange(int visibility);
+    }
+
     private final class UnsetPressedState implements Runnable {
         public void run() {
             setPressed(false);
@@ -11566,6 +11644,17 @@
         boolean mKeepScreenOn;
 
         /**
+         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
+         */
+        int mSystemUiVisibility;
+
+        /**
+         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
+         * attached.
+         */
+        boolean mHasSystemUiListeners;
+
+        /**
          * Set if the visibility of any views has changed.
          */
         boolean mViewVisibilityChanged;
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index a3508d1..19f1f7a 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -860,8 +860,10 @@
      * {@inheritDoc}
      */
     public void recomputeViewAttributes(View child) {
-        ViewParent parent = mParent;
-        if (parent != null) parent.recomputeViewAttributes(this);
+        if (mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
+            ViewParent parent = mParent;
+            if (parent != null) parent.recomputeViewAttributes(this);
+        }
     }
 
     @Override
@@ -1070,6 +1072,18 @@
         return child.mCanAcceptDrop;
     }
 
+    @Override
+    public void dispatchSystemUiVisibilityChanged(int visible) {
+        super.dispatchSystemUiVisibilityChanged(visible);
+
+        final int count = mChildrenCount;
+        final View[] children = mChildren;
+        for (int i=0; i <count; i++) {
+            final View child = children[i];
+            child.dispatchSystemUiVisibilityChanged(visible);
+        }
+    }
+
     /**
      * {@inheritDoc}
      */
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index e73f0dd..6bc5e8a 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -723,6 +723,7 @@
             attachInfo.mWindowVisibility = viewVisibility;
             attachInfo.mRecomputeGlobalAttributes = false;
             attachInfo.mKeepScreenOn = false;
+            attachInfo.mSystemUiVisibility = 0;
             viewVisibilityChanged = false;
             mLastConfiguration.setTo(host.getResources().getConfiguration());
             host.dispatchAttachedToWindow(attachInfo, 0);
@@ -896,14 +897,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);
             }
         }
 
@@ -985,6 +989,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:" +
@@ -1900,7 +1906,8 @@
     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_GENERIC_MOTION = 1017;
+    public final static int DISPATCH_SYSTEM_UI_VISIBILITY = 1017;
+    public final static int DISPATCH_GENERIC_MOTION = 1018;
 
     @Override
     public void handleMessage(Message msg) {
@@ -2066,6 +2073,9 @@
             event.mLocalState = mLocalDragState;    // only present when this app called startDrag()
             handleDragEvent(event);
         } break;
+        case DISPATCH_SYSTEM_UI_VISIBILITY: {
+            handleDispatchSystemUiVisibilityChanged(msg.arg1);
+        } break;
         }
     }
     
@@ -2931,6 +2941,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;
@@ -3249,6 +3264,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.
@@ -3467,6 +3486,14 @@
                 viewRoot.dispatchDragEvent(event);
             }
         }
+
+        @Override
+        public void dispatchSystemUiVisibilityChanged(int visibility) {
+            final ViewRoot viewRoot = mViewRoot.get();
+            if (viewRoot != null) {
+                viewRoot.dispatchSystemUiVisibilityChanged(visibility);
+            }
+        }
     }
 
     /**
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index c985358..d3d8b08 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -950,7 +950,22 @@
          * will be used.
          */
         public int screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-        
+
+        /**
+         * Control the visibility of the status bar.
+         * @hide
+         */
+        public int systemUiVisibility;
+
+        /**
+         * Get callbacks about the system ui visibility changing.
+         * 
+         * TODO: Maybe there should be a bitfield of optional callbacks that we need.
+         *
+         * @hide
+         */
+        public boolean hasSystemUiListeners;
+
         public LayoutParams() {
             super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
             type = TYPE_APPLICATION;
@@ -1030,6 +1045,8 @@
             out.writeString(packageName);
             TextUtils.writeToParcel(mTitle, out, parcelableFlags);
             out.writeInt(screenOrientation);
+            out.writeInt(systemUiVisibility);
+            out.writeInt(hasSystemUiListeners ? 1 : 0);
         }
         
         public static final Parcelable.Creator<LayoutParams> CREATOR
@@ -1065,6 +1082,8 @@
             packageName = in.readString();
             mTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
             screenOrientation = in.readInt();
+            systemUiVisibility = in.readInt();
+            hasSystemUiListeners = in.readInt() != 0;
         }
     
         @SuppressWarnings({"PointlessBitwiseExpression"})
@@ -1082,6 +1101,10 @@
         public static final int SCREEN_BRIGHTNESS_CHANGED = 1<<11;
         /** {@hide} */
         public static final int BUTTON_BRIGHTNESS_CHANGED = 1<<12;
+        /** {@hide} */
+        public static final int SYSTEM_UI_VISIBILITY_CHANGED = 1<<13;
+        /** {@hide} */
+        public static final int SYSTEM_UI_LISTENER_CHANGED = 1<<14;
     
         // internal buffer to backup/restore parameters under compatibility mode.
         private int[] mCompatibilityParamsBackup = null;
@@ -1181,6 +1204,16 @@
                 changes |= SCREEN_ORIENTATION_CHANGED;
             }
 
+            if (systemUiVisibility != o.systemUiVisibility) {
+                systemUiVisibility = o.systemUiVisibility;
+                changes |= SYSTEM_UI_VISIBILITY_CHANGED;
+            }
+
+            if (hasSystemUiListeners != o.hasSystemUiListeners) {
+                hasSystemUiListeners = o.hasSystemUiListeners;
+                changes |= SYSTEM_UI_LISTENER_CHANGED;
+            }
+
             return changes;
         }
     
@@ -1253,6 +1286,14 @@
             if ((flags & FLAG_COMPATIBLE_WINDOW) != 0) {
                 sb.append(" compatible=true");
             }
+            if (systemUiVisibility != 0) {
+                sb.append(" sysui=0x");
+                sb.append(Integer.toHexString(systemUiVisibility));
+            }
+            if (hasSystemUiListeners) {
+                sb.append(" sysuil=");
+                sb.append(hasSystemUiListeners);
+            }
             sb.append('}');
             return sb.toString();
         }
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index e8d67da..ad06902 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -695,6 +695,12 @@
      * immediately.
      */
     public boolean allowAppAnimationsLw();
+
+
+    /**
+     * A new window has been focused.
+     */
+    public void focusChanged(WindowState lastFocus, WindowState newFocus);
     
     /**
      * Called after the screen turns off.
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index f86b72d..d83a534 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -45,5 +45,5 @@
             int uid, int initialPid, String message);
     void onClearAllNotifications();
     void onNotificationClear(String pkg, String tag, int id);
-    void setLightsOn(boolean on);
+    void setSystemUiVisibility(int vis);
 }
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index d5213db..c41b2cb 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -73,6 +73,9 @@
     public void dispatchDragEvent(DragEvent event) {
     }
 
+    public void dispatchSystemUiVisibilityChanged(int visibility) {
+    }
+
     public void dispatchWallpaperCommand(String action, int x, int y,
             int z, Bundle extras, boolean sync) {
         if (sync) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index a3a58ed..c2f74f0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -564,17 +564,28 @@
                     if (DEBUG) Slog.d(TAG, "hiding shadows (lights on)");
                     mBarContents.setVisibility(View.VISIBLE);
                     mShadow.setVisibility(View.GONE);
+                    notifyLightsChanged(true);
                     break;
                 case MSG_HIDE_CHROME:
                     if (DEBUG) Slog.d(TAG, "showing shadows (lights out)");
                     animateCollapse();
                     mBarContents.setVisibility(View.GONE);
                     mShadow.setVisibility(View.VISIBLE);
+                    notifyLightsChanged(false);
                     break;
             }
         }
     }
 
+    private void notifyLightsChanged(boolean shown) {
+        try {
+            Slog.d(TAG, "lights " + (shown?"on":"out"));
+            mWindowManager.statusBarVisibilityChanged(
+                    shown ? View.STATUS_BAR_VISIBLE : View.STATUS_BAR_HIDDEN);
+        } catch (RemoteException ex) {
+        }
+    }
+
     public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
         if (DEBUG) Slog.d(TAG, "addIcon(" + slot + ") -> " + icon);
     }
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 0d0e89c..67e0e67 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -34,6 +34,7 @@
 import android.database.ContentObserver;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
+import android.os.Binder;
 import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
@@ -270,7 +271,10 @@
     int mPointerLocationMode = 0;
     PointerLocationView mPointerLocationView = null;
     InputChannel mPointerLocationInputChannel;
-    
+
+    // The last window we were told about in focusChanged.
+    WindowState mFocusedWindow;
+
     private final InputHandler mPointerLocationInputHandler = new BaseInputHandler() {
         @Override
         public void handleMotion(MotionEvent event, InputQueue.FinishedCallback finishedCallback) {
@@ -1953,7 +1957,9 @@
                 mKeyguardMediator.setHidden(false);
             }
         }
-        
+
+        updateSystemUiVisibility();
+
         // update since mAllowLockscreenWhenOn might have changed
         updateLockScreenTimeout();
         return changes;
@@ -1993,6 +1999,11 @@
         return true;
     }
 
+    public void focusChanged(WindowState lastFocus, WindowState newFocus) {
+        mFocusedWindow = newFocus;
+        updateSystemUiVisibility();
+    }
+
     /** {@inheritDoc} */
     public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
         // lid changed state
@@ -2838,6 +2849,34 @@
         return mScreenOn;
     }
 
+    private void updateSystemUiVisibility() {
+        // If there is no window focused, there will be nobody to handle the events
+        // anyway, so just hang on in whatever state we're in until things settle down.
+        if (mFocusedWindow != null) {
+            final int visibility = mFocusedWindow.getAttrs().systemUiVisibility;
+            mHandler.post(new Runnable() {
+                    public void run() {
+                        if (mStatusBarService == null) {
+                            mStatusBarService = IStatusBarService.Stub.asInterface(
+                                    ServiceManager.getService("statusbar"));
+                        }
+                        if (mStatusBarService != null) {
+                            // need to assume status bar privileges to invoke lights on
+                            long origId = Binder.clearCallingIdentity();
+                            try {
+                                mStatusBarService.setSystemUiVisibility(visibility);
+                            } catch (RemoteException e) {
+                                // not much to be done
+                                mStatusBarService = null;
+                            } finally {
+                                Binder.restoreCallingIdentity(origId);
+                            }
+                        }
+                    }
+                });
+        }
+    }
+
     public void dump(String prefix, FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
                 pw.print(" mSystemRead="); pw.println(mSystemReady);
diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/java/com/android/server/StatusBarManagerService.java
index cbfa4ee..50ea3fa 100644
--- a/services/java/com/android/server/StatusBarManagerService.java
+++ b/services/java/com/android/server/StatusBarManagerService.java
@@ -32,6 +32,7 @@
 import android.os.Handler;
 import android.os.SystemClock;
 import android.util.Slog;
+import android.view.View;
 
 import com.android.internal.statusbar.IStatusBar;
 import com.android.internal.statusbar.IStatusBarService;
@@ -308,10 +309,11 @@
      * app keeps trying to turn it on.  For now they can just fight it out.  Having
      * these two separte inputs will allow us to keep that change local to here.  --joeo
      */
-    public void setLightsOn(boolean lightsOn) {
+    public void setSystemUiVisibility(int vis) {
         enforceStatusBarService();
 
         synchronized (mLock) {
+            final boolean lightsOn = (vis & View.STATUS_BAR_HIDDEN) == 0;
             updateLightsOnLocked(lightsOn);
         }
     }
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index a2abec2..eeb224c 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -8882,6 +8882,8 @@
                                 // Ignore if process has died.
                             }
                         }
+
+                        mPolicy.focusChanged(lastFocus, newFocus);
                     }
                 } break;
 
@@ -11458,6 +11460,23 @@
     }
 
     @Override
+    public void statusBarVisibilityChanged(int visibility) {
+        synchronized (mWindowMap) {
+            final int N = mWindows.size();
+            for (int i = 0; i < N; i++) {
+                WindowState ws = mWindows.get(i);
+                try {
+                    if (ws.getAttrs().hasSystemUiListeners) {
+                        ws.mClient.dispatchSystemUiVisibilityChanged(visibility);
+                    }
+                } catch (RemoteException e) {
+                    // so sorry
+                }
+            }
+        }
+    }
+
+    @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
                 != PackageManager.PERMISSION_GRANTED) {
diff --git a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
index 563f28c..5fd946e 100644
--- a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
+++ b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
@@ -27,6 +27,8 @@
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.StatusBarManager;
+import android.content.Context;
+import android.util.AttributeSet;
 import android.os.Vibrator;
 import android.os.Bundle;
 import android.os.Handler;
@@ -36,6 +38,7 @@
 import android.widget.RemoteViews;
 import android.widget.Toast;
 import android.os.PowerManager;
+import android.view.View;
 import android.view.Window;
 import android.view.WindowManager;
 
@@ -46,6 +49,13 @@
     NotificationManager mNotificationManager;
     Handler mHandler = new Handler();
 
+    View.OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener
+            = new View.OnSystemUiVisibilityChangeListener() {
+        public void onSystemUiVisibilityChange(int visibility) {
+            Log.d(TAG, "onSystemUiVisibilityChange visibility=" + visibility);
+        }
+    };
+
     @Override
     protected String tag() {
         return TAG;
@@ -60,6 +70,20 @@
     }
 
     private Test[] mTests = new Test[] {
+        new Test("STATUS_BAR_HIDDEN") {
+            public void run() {
+                View v = findViewById(android.R.id.list);
+                v.setSystemUiVisibility(View.STATUS_BAR_HIDDEN);
+                v.setOnSystemUiVisibilityChangeListener(mOnSystemUiVisibilityChangeListener);
+            }
+        },
+        new Test("not STATUS_BAR_HIDDEN") {
+            public void run() {
+                View v = findViewById(android.R.id.list);
+                v.setSystemUiVisibility(View.STATUS_BAR_VISIBLE);
+                v.setOnSystemUiVisibilityChangeListener(null);
+            }
+        },
         new Test("Double Remove") {
             public void run() {
                 Log.d(TAG, "set 0");
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
index 4a7ab58..a8da377 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
@@ -86,6 +86,10 @@
         // pass for now.
     }
 
+    public void dispatchSystemUiVisibilityChanged(int visibility) {
+        // pass for now.
+    }
+
     public IBinder asBinder() {
         // pass for now.
         return null;