Merge "PIP: Send KEYCODE_WINDOW to app first if PIP isn't exist" into nyc-dev
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index eb895ff..2fc1187 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3071,6 +3071,13 @@
     /**
      * @hide
      *
+     * Whether the TV's picture-in-picture is visible or not.
+     */
+    public static final int TV_PICTURE_IN_PICTURE_VISIBLE = 0x00010000;
+
+    /**
+     * @hide
+     *
      * Makes navigation bar transparent (but not the status bar).
      */
     public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index e3abb5d..e598113 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -24,6 +24,7 @@
 import android.annotation.Nullable;
 import android.annotation.StyleRes;
 import android.annotation.SystemApi;
+import android.app.ActivityManagerNative;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
@@ -1256,6 +1257,18 @@
     }
 
     /**
+     * Puts the activity in picture-in-picture mode.
+     * @see android.R.attr#supportsPictureInPicture
+     * @hide
+     */
+    protected void enterPictureInPictureMode() {
+        try {
+            ActivityManagerNative.getDefault().enterPictureInPictureMode(mAppToken);
+        } catch (IllegalArgumentException|RemoteException e) {
+        }
+    }
+
+    /**
      * Convenience for
      * {@link #setContentView(View, android.view.ViewGroup.LayoutParams)}
      * to set the screen content from a layout resource.  The resource will be
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 151c530..1619843 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -2002,6 +2002,13 @@
                 }
                 return true;
             }
+
+            case KeyEvent.KEYCODE_WINDOW: {
+                if (!event.isCanceled()) {
+                    enterPictureInPictureMode();
+                }
+                return true;
+            }
         }
 
         return false;
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 5cbe1ce..7706ff7 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -105,14 +105,9 @@
     void onCameraLaunchGestureDetected(int source);
 
     /**
-     * Request picture-in-picture.
-     *
-     * <p>
-     * This is called when an user presses picture-in-picture key or equivalent.
-     * TV device may start picture-in-picture from foreground activity if there's none.
-     * Picture-in-picture overlay menu will be shown instead otherwise.
+     * Shows the TV's picture-in-picture menu if an activity is in picture-in-picture mode.
      */
-    void requestTvPictureInPicture();
+    void showTvPictureInPictureMenu();
 
     void addQsTile(in ComponentName tile);
     void remQsTile(in ComponentName tile);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 1bc2ebc..7b23c80 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -68,7 +68,7 @@
     private static final int MSG_START_ASSIST                  = 23 << MSG_SHIFT;
     private static final int MSG_CAMERA_LAUNCH_GESTURE         = 24 << MSG_SHIFT;
     private static final int MSG_TOGGLE_KEYBOARD_SHORTCUTS     = 25 << MSG_SHIFT;
-    private static final int MSG_REQUEST_TV_PICTURE_IN_PICTURE = 26 << MSG_SHIFT;
+    private static final int MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU = 26 << MSG_SHIFT;
     private static final int MSG_ADD_QS_TILE                   = 27 << MSG_SHIFT;
     private static final int MSG_REMOVE_QS_TILE                = 28 << MSG_SHIFT;
     private static final int MSG_CLICK_QS_TILE                 = 29 << MSG_SHIFT;
@@ -124,7 +124,7 @@
         void showAssistDisclosure();
         void startAssist(Bundle args);
         void onCameraLaunchGestureDetected(int source);
-        void requestTvPictureInPicture();
+        void showTvPictureInPictureMenu();
 
         void addQsTile(ComponentName tile);
         void remQsTile(ComponentName tile);
@@ -274,10 +274,10 @@
     }
 
     @Override
-    public void requestTvPictureInPicture() {
+    public void showTvPictureInPictureMenu() {
         synchronized (mLock) {
-            mHandler.removeMessages(MSG_REQUEST_TV_PICTURE_IN_PICTURE);
-            mHandler.obtainMessage(MSG_REQUEST_TV_PICTURE_IN_PICTURE).sendToTarget();
+            mHandler.removeMessages(MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU);
+            mHandler.obtainMessage(MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU).sendToTarget();
         }
     }
 
@@ -488,8 +488,8 @@
                 case MSG_CAMERA_LAUNCH_GESTURE:
                     mCallbacks.onCameraLaunchGestureDetected(msg.arg1);
                     break;
-                case MSG_REQUEST_TV_PICTURE_IN_PICTURE:
-                    mCallbacks.requestTvPictureInPicture();
+                case MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU:
+                    mCallbacks.showTvPictureInPictureMenu();
                     break;
                 case MSG_ADD_QS_TILE:
                     mCallbacks.addQsTile((ComponentName) msg.obj);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 436dc9d..23e3561 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -4503,7 +4503,7 @@
     }
 
     @Override
-    public void requestTvPictureInPicture() {
+    public void showTvPictureInPictureMenu() {
         // no-op.
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index f9202c4..27726af 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -189,8 +189,8 @@
     }
 
     @Override
-    public void requestTvPictureInPicture() {
-        PipManager.getInstance().requestTvPictureInPicture();
+    public void showTvPictureInPictureMenu() {
+        PipManager.getInstance().showTvPictureInPictureMenu();
     }
 
     @Override
@@ -224,8 +224,22 @@
         putComponent(TvStatusBar.class, this);
     }
 
+    /**
+     * Updates the visibility of the picture-in-picture.
+     */
+    public void updatePipVisibility(boolean visible) {
+        if (visible) {
+            mSystemUiVisibility |= View.TV_PICTURE_IN_PICTURE_VISIBLE;
+        } else {
+            mSystemUiVisibility &= ~View.TV_PICTURE_IN_PICTURE_VISIBLE;
+        }
+        notifyUiVisibilityChanged(mSystemUiVisibility);
+    }
+
+    /**
+     * Updates the visibility of the Recents
+     */
     public void updateRecentsVisibility(boolean visible) {
-        // Update the recents visibility flag
         if (visible) {
             mSystemUiVisibility |= View.RECENT_APPS_VISIBLE;
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
index d7efca7..9842634 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
@@ -41,8 +41,10 @@
 
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
-import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.SystemUIApplication;
 import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
+import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.statusbar.tv.TvStatusBar;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -225,26 +227,14 @@
     }
 
     /**
-     * Request PIP.
-     * It could either start PIP if there's none, and show PIP menu otherwise.
+     * Shows the picture-in-picture menu if an activity is in picture-in-picture mode.
      */
-    public void requestTvPictureInPicture() {
-        if (DEBUG) Log.d(TAG, "requestTvPictureInPicture()");
-        if (!isPipShown()) {
-            startPip();
-        } else if (mState == STATE_PIP_OVERLAY) {
+    public void showTvPictureInPictureMenu() {
+        if (mState == STATE_PIP_OVERLAY) {
             resizePinnedStack(STATE_PIP_MENU);
         }
     }
 
-    private void startPip() {
-        try {
-            mActivityManager.moveTopActivityToPinnedStack(FULLSCREEN_WORKSPACE_STACK_ID, mPipBounds);
-        } catch (RemoteException|IllegalArgumentException e) {
-            Log.e(TAG, "moveTopActivityToPinnedStack failed", e);
-        }
-    }
-
     /**
      * Closes PIP (PIPed activity and PIP system UI).
      */
@@ -268,6 +258,7 @@
             mListeners.get(i).onPipActivityClosed();
         }
         mHandler.removeCallbacks(mClosePipRunnable);
+        updatePipVisibility(false);
     }
 
     /**
@@ -622,6 +613,7 @@
             for (int i = mListeners.size() - 1; i >= 0; i--) {
                 mListeners.get(i).onPipEntered();
             }
+            updatePipVisibility(true);
         }
 
         @Override
@@ -706,4 +698,11 @@
     public PipRecentsOverlayManager getPipRecentsOverlayManager() {
         return mPipRecentsOverlayManager;
     }
+
+    private void updatePipVisibility(boolean visible) {
+        TvStatusBar statusBar = ((SystemUIApplication) mContext).getComponent(TvStatusBar.class);
+        if (statusBar != null) {
+            statusBar.updatePipVisibility(visible);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index e159179..df74ed1 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -404,8 +404,9 @@
     volatile boolean mEndCallKeyHandled;
     volatile boolean mCameraGestureTriggeredDuringGoingToSleep;
     volatile boolean mGoingToSleep;
+    volatile boolean mRecentsVisible;
+    volatile boolean mTvPictureInPictureVisible;
 
-    boolean mRecentsVisible;
     int mRecentAppsHeldModifiers;
     boolean mLanguageSwitchKeyPressed;
 
@@ -712,7 +713,7 @@
     private static final int MSG_POWER_LONG_PRESS = 14;
     private static final int MSG_UPDATE_DREAMING_SLEEP_TOKEN = 15;
     private static final int MSG_REQUEST_TRANSIENT_BARS = 16;
-    private static final int MSG_REQUEST_TV_PICTURE_IN_PICTURE = 17;
+    private static final int MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU = 17;
     private static final int MSG_BACK_LONG_PRESS = 18;
 
     private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0;
@@ -775,8 +776,8 @@
                         requestTransientBars(targetBar);
                     }
                     break;
-                case MSG_REQUEST_TV_PICTURE_IN_PICTURE:
-                    requestTvPictureInPictureInternal();
+                case MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU:
+                    showTvPictureInPictureMenuInternal();
                     break;
                 case MSG_BACK_LONG_PRESS:
                     backLongPress();
@@ -1457,22 +1458,18 @@
         }
     }
 
-    private void requestTvPictureInPicture(KeyEvent event) {
-        if (DEBUG_INPUT) Log.d(TAG, "requestTvPictureInPicture event=" + event);
-        mHandler.removeMessages(MSG_REQUEST_TV_PICTURE_IN_PICTURE);
-        Message msg = mHandler.obtainMessage(MSG_REQUEST_TV_PICTURE_IN_PICTURE);
+    private void showTvPictureInPictureMenu(KeyEvent event) {
+        if (DEBUG_INPUT) Log.d(TAG, "showTvPictureInPictureMenu event=" + event);
+        mHandler.removeMessages(MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU);
+        Message msg = mHandler.obtainMessage(MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU);
         msg.setAsynchronous(true);
         msg.sendToTarget();
     }
 
-    private void requestTvPictureInPictureInternal() {
-        try {
-            StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
-            if (statusbar != null) {
-                statusbar.requestTvPictureInPicture();
-            }
-        } catch (IllegalArgumentException e) {
-            Slog.e(TAG, "Cannot handle picture-in-picture key", e);
+    private void showTvPictureInPictureMenuInternal() {
+        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
+        if (statusbar != null) {
+            statusbar.showTvPictureInPictureMenu();
         }
     }
 
@@ -3787,6 +3784,7 @@
         mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
         mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
         mRecentsVisible = (visibility & View.RECENT_APPS_VISIBLE) > 0;
+        mTvPictureInPictureVisible = (visibility & View.TV_PICTURE_IN_PICTURE_VISIBLE) > 0;
 
         // Reset any bits in mForceClearingStatusBarVisibility that
         // are now clear.
@@ -5674,10 +5672,16 @@
             }
             case KeyEvent.KEYCODE_WINDOW: {
                 if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) {
-                    if (!down) {
-                        requestTvPictureInPicture(event);
+                    if (mTvPictureInPictureVisible) {
+                        // Consumes the key only if picture-in-picture is visible
+                        // to show picture-in-picture control menu.
+                        // This gives a chance to the foreground activity
+                        // to customize PIP key behavior.
+                        if (!down) {
+                            showTvPictureInPictureMenu(event);
+                        }
+                        result &= ~ACTION_PASS_TO_USER;
                     }
-                    result &= ~ACTION_PASS_TO_USER;
                 }
                 break;
             }
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index 52b2439..fb0dd2a 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -41,14 +41,9 @@
     void toggleKeyboardShortcutsMenu(int deviceId);
 
     /**
-     * Request picture-in-picture.
-     *
-     * <p>
-     * This is called when an user presses picture-in-picture key or equivalent.
-     * TV device may start picture-in-picture from foreground activity if there's none.
-     * Picture-in-picture overlay menu will be shown instead otherwise.
+     * Show TV picture-in-picture menu.
      */
-    void requestTvPictureInPicture();
+    void showTvPictureInPictureMenu();
 
     void setWindowState(int window, int state);
 
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index c630d4a..baa7f1e 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -295,10 +295,10 @@
         }
 
         @Override
-        public void requestTvPictureInPicture() {
+        public void showTvPictureInPictureMenu() {
             if (mBar != null) {
                 try {
-                    mBar.requestTvPictureInPicture();
+                    mBar.showTvPictureInPictureMenu();
                 } catch (RemoteException ex) {}
             }
         }