Merge "Fix issue #5755172: Soft menu key disappears when menu is open" into ics-mr1
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index d0841dd..a99ac03 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -743,6 +743,9 @@
     public void setFlags(int flags, int mask) {
         final WindowManager.LayoutParams attrs = getAttributes();
         attrs.flags = (attrs.flags&~mask) | (flags&mask);
+        if ((mask&WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY) != 0) {
+            attrs.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY;
+        }
         mForcedWindowFlags |= mask;
         if (mCallback != null) {
             mCallback.onWindowAttributesChanged(attrs);
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index e74fec6..c0eb65b 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -824,6 +824,16 @@
         public static final int PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS = 0x00000004;
 
         /**
+         * This is set for a window that has explicitly specified its
+         * FLAG_NEEDS_MENU_KEY, so we know the value on this window is the
+         * appropriate one to use.  If this is not set, we should look at
+         * windows behind it to determine the appropriate value.
+         *
+         * @hide
+         */
+        public static final int PRIVATE_FLAG_SET_NEEDS_MENU_KEY = 0x00000008;
+
+        /**
          * Control flags that are private to the platform.
          * @hide
          */
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 2e19bf6..924cb53 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -238,6 +238,14 @@
         public WindowManager.LayoutParams getAttrs();
 
         /**
+         * Return whether this window needs the menu key shown.  Must be called
+         * with window lock held, because it may need to traverse down through
+         * window list to determine the result.
+         * @param bottom The bottom-most window to consider when determining this.
+         */
+        public boolean getNeedsMenuLw(WindowState bottom);
+
+        /**
          * Retrieve the current system UI visibility flags associated with
          * this window.
          */
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
index 0499cfa..ff8d5ac 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
@@ -138,6 +138,7 @@
                 lp.privateFlags |=
                         WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
             }
+            lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY;
             lp.setTitle("Keyguard");
             mWindowLayoutParams = lp;
 
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 535f039..f1fe43b7 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -2582,6 +2582,8 @@
 
         if (targetPreHoneycomb || (targetPreIcs && targetHcNeedsOptions && noActionBar)) {
             addFlags(WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY);
+        } else {
+            clearFlags(WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY);
         }
         
         if (mAlwaysReadCloseOnTouchAttr || getContext().getApplicationInfo().targetSdkVersion
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 7510e04..0b223c1 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -3707,8 +3707,7 @@
                 & ~mResettingSystemUiFlags
                 & ~mForceClearedSystemUiFlags;
         int diff = visibility ^ mLastSystemUiFlags;
-        final boolean needsMenu = (mFocusedWindow.getAttrs().flags
-                & WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY) != 0;
+        final boolean needsMenu = mFocusedWindow.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
         if (diff == 0 && mLastFocusNeedsMenu == needsMenu
                 && mFocusedApp == mFocusedWindow.getAppToken()) {
             return 0;
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index aa7bf2d..75bda41 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -562,6 +562,33 @@
         return mAttrs;
     }
 
+    public boolean getNeedsMenuLw(WindowManagerPolicy.WindowState bottom) {
+        int index = -1;
+        WindowState ws = this;
+        while (true) {
+            if ((ws.mAttrs.privateFlags
+                    & WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY) != 0) {
+                return (ws.mAttrs.flags & WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY) != 0;
+            }
+            // If we reached the bottom of the range of windows we are considering,
+            // assume no menu is needed.
+            if (ws == bottom) {
+                return false;
+            }
+            // The current window hasn't specified whether menu key is needed;
+            // look behind it.
+            // First, we may need to determine the starting position.
+            if (index < 0) {
+                index = mService.mWindows.indexOf(ws);
+            }
+            index--;
+            if (index < 0) {
+                return false;
+            }
+            ws = mService.mWindows.get(index);
+        }
+    }
+
     public int getSystemUiVisibility() {
         return mSystemUiVisibility;
     }