Merge "Only handle Context submenus as dialogs when parent is a dialog"
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index e405564..f6b8e91 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -17,11 +17,13 @@
 package com.android.internal.policy;
 
 import com.android.internal.R;
+import com.android.internal.policy.PhoneWindow.PhoneWindowMenuCallback;
 import com.android.internal.view.FloatingActionMode;
 import com.android.internal.view.RootViewSurfaceTaker;
 import com.android.internal.view.StandaloneActionMode;
 import com.android.internal.view.menu.ContextMenuBuilder;
 import com.android.internal.view.menu.MenuHelper;
+import com.android.internal.view.menu.MenuPresenter;
 import com.android.internal.widget.ActionBarContextView;
 import com.android.internal.widget.BackgroundFallback;
 import com.android.internal.widget.DecorCaptionView;
@@ -684,9 +686,10 @@
         }
 
         // Reuse the context menu builder.
+        final PhoneWindowMenuCallback callback = mWindow.mContextMenuCallback;
         if (mWindow.mContextMenu == null) {
             mWindow.mContextMenu = new ContextMenuBuilder(getContext());
-            mWindow.mContextMenu.setCallback(mWindow.mContextMenuCallback);
+            mWindow.mContextMenu.setCallback(callback);
         } else {
             mWindow.mContextMenu.clearAll();
         }
@@ -698,9 +701,11 @@
             helper = mWindow.mContextMenu.showDialog(originalView, originalView.getWindowToken());
         }
 
-        if (helper != null) {
-            helper.setPresenterCallback(mWindow.mContextMenuCallback);
-        }
+        // If it's a dialog, the callback needs to handle showing sub-menus.
+        // Either way, the callback is required for propagating selection to
+        // Context.onContextMenuItemSelected().
+        callback.setShowDialogForSubmenu(!isPopup);
+        helper.setPresenterCallback(callback);
 
         mWindow.mContextMenuHelper = helper;
         return helper != null;
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 86bd782..1e9035b 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -127,7 +127,7 @@
      * Simple callback used by the context menu and its submenus. The options
      * menu submenus do not use this (their behavior is more complex).
      */
-    final DialogMenuCallback mContextMenuCallback = new DialogMenuCallback(FEATURE_CONTEXT_MENU);
+    final PhoneWindowMenuCallback mContextMenuCallback = new PhoneWindowMenuCallback(this);
 
     final TypedValue mMinWidthMajor = new TypedValue();
     final TypedValue mMinWidthMinor = new TypedValue();
@@ -3592,27 +3592,34 @@
      * <li> Calls back to the callback's onMenuItemSelected when an item is
      * selected.
      */
-    private final class DialogMenuCallback implements MenuBuilder.Callback, MenuPresenter.Callback {
-        private int mFeatureId;
+    public static final class PhoneWindowMenuCallback
+            implements MenuBuilder.Callback, MenuPresenter.Callback {
+        private static final int FEATURE_ID = FEATURE_CONTEXT_MENU;
+
+        private final PhoneWindow mWindow;
+
         private MenuDialogHelper mSubMenuHelper;
 
-        public DialogMenuCallback(int featureId) {
-            mFeatureId = featureId;
+        private boolean mShowDialogForSubmenu;
+
+        public PhoneWindowMenuCallback(PhoneWindow window) {
+            mWindow = window;
         }
 
+        @Override
         public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
             if (menu.getRootMenu() != menu) {
                 onCloseSubMenu(menu);
             }
 
             if (allMenusAreClosing) {
-                Callback callback = getCallback();
-                if (callback != null && !isDestroyed()) {
-                    callback.onPanelClosed(mFeatureId, menu);
+                final Callback callback = mWindow.getCallback();
+                if (callback != null && !mWindow.isDestroyed()) {
+                    callback.onPanelClosed(FEATURE_ID, menu);
                 }
 
-                if (menu == mContextMenu) {
-                    dismissContextMenu();
+                if (menu == mWindow.mContextMenu) {
+                    mWindow.dismissContextMenu();
                 }
 
                 // Dismiss the submenu, if it is showing
@@ -3623,33 +3630,45 @@
             }
         }
 
-        public void onCloseSubMenu(MenuBuilder menu) {
-            Callback callback = getCallback();
-            if (callback != null && !isDestroyed()) {
-                callback.onPanelClosed(mFeatureId, menu.getRootMenu());
+        private void onCloseSubMenu(MenuBuilder menu) {
+            final Callback callback = mWindow.getCallback();
+            if (callback != null && !mWindow.isDestroyed()) {
+                callback.onPanelClosed(FEATURE_ID, menu.getRootMenu());
             }
         }
 
+        @Override
         public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
-            Callback callback = getCallback();
-            return (callback != null && !isDestroyed())
-                    && callback.onMenuItemSelected(mFeatureId, item);
+            final Callback callback = mWindow.getCallback();
+            return callback != null && !mWindow.isDestroyed()
+                    && callback.onMenuItemSelected(FEATURE_ID, item);
         }
 
+        @Override
         public void onMenuModeChange(MenuBuilder menu) {
         }
 
+        @Override
         public boolean onOpenSubMenu(MenuBuilder subMenu) {
-            if (subMenu == null) return false;
+            if (subMenu == null) {
+                return false;
+            }
 
             // Set a simple callback for the submenu
             subMenu.setCallback(this);
 
-            // The window manager will give us a valid window token
-            mSubMenuHelper = new MenuDialogHelper(subMenu);
-            mSubMenuHelper.show(null);
+            if (mShowDialogForSubmenu) {
+                // The window manager will give us a valid window token
+                mSubMenuHelper = new MenuDialogHelper(subMenu);
+                mSubMenuHelper.show(null);
+                return true;
+            }
 
-            return true;
+            return false;
+        }
+
+        public void setShowDialogForSubmenu(boolean enabled) {
+            mShowDialogForSubmenu = enabled;
         }
     }
 
diff --git a/core/java/com/android/internal/view/menu/StandardMenuPopup.java b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
index 6a5f6d8..c2adc42 100644
--- a/core/java/com/android/internal/view/menu/StandardMenuPopup.java
+++ b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
@@ -242,13 +242,13 @@
     @Override
     public boolean onSubMenuSelected(SubMenuBuilder subMenu) {
         if (subMenu.hasVisibleItems()) {
-            MenuPopupHelper subPopup = new MenuPopupHelper(
-                    mContext, subMenu, mShownAnchorView, mOverflowOnly, mPopupStyleAttr,
-                    mPopupStyleRes);
+            final MenuPopupHelper subPopup = new MenuPopupHelper(mContext, subMenu,
+                    mShownAnchorView, mOverflowOnly, mPopupStyleAttr, mPopupStyleRes);
             subPopup.setPresenterCallback(mPresenterCallback);
             subPopup.setForceShowIcon(mAdapter.getForceShowIcon());
 
-            if (subPopup.tryShow()) {
+            // Show the new sub-menu popup at the same location as this popup.
+            if (subPopup.tryShow(mXOffset, mYOffset)) {
                 if (mPresenterCallback != null) {
                     mPresenterCallback.onOpenSubMenu(subMenu);
                 }