OSDN Git Service

Move default pip position to right above the shelf.
authorTracy Zhou <tracyzhou@google.com>
Fri, 9 Mar 2018 05:58:36 +0000 (21:58 -0800)
committerTracy Zhou <tracyzhou@google.com>
Mon, 19 Mar 2018 17:41:08 +0000 (17:41 +0000)
This change takes care of the flow from WindowManagerService to
PinnedStackController, all the way to PipTouchHandler. It also
introduces a WindowManager hook that allows Launcher to pass in
shelf visibility and height. A separate change is made to send
signals from Launcher to SysUI. (ag/3724896)

Bug: 73961893
Change-Id: I2ff54e78bc2dc35c806b902464048b051a4d6394
Test: atest CtsActivityManagerDeviceTestCases:ActivityManagerPinnedStackTests

14 files changed:
core/java/android/app/ActivityManagerInternal.java
core/java/android/view/IPinnedStackListener.aidl
core/java/android/view/IWindowManager.aidl
core/java/com/android/internal/policy/PipSnapAlgorithm.java
core/res/res/values/config.xml
packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
services/core/java/com/android/server/am/ActivityManagerService.java
services/core/java/com/android/server/wm/PinnedStackController.java
services/core/java/com/android/server/wm/WindowManagerService.java
services/tests/servicestests/src/com/android/server/wm/PinnedStackControllerTest.java [new file with mode: 0644]

index 2752fa9..db9d923 100644 (file)
@@ -385,4 +385,10 @@ public abstract class ActivityManagerInternal {
      * Returns a list that contains the memory stats for currently running processes.
      */
     public abstract List<ProcessMemoryState> getMemoryStateForProcesses();
+
+    /**
+     * This enforces {@code func} can only be called if either the caller is Recents activity or
+     * has {@code permission}.
+     */
+    public abstract void enforceCallerIsRecentsOrHasPermission(String permission, String func);
 }
index 9382741..2da353b 100644 (file)
@@ -47,17 +47,25 @@ oneway interface IPinnedStackListener {
      * the WM has changed in the mean time but the client has not received onMovementBoundsChanged).
      */
     void onMovementBoundsChanged(in Rect insetBounds, in Rect normalBounds, in Rect animatingBounds,
-            boolean fromImeAdjustement, int displayRotation);
+            boolean fromImeAdjustment, boolean fromShelfAdjustment, int displayRotation);
 
     /**
      * Called when window manager decides to adjust the pinned stack bounds because of the IME, or
      * when the listener is first registered to allow the listener to synchronized its state with
      * the controller.  This call will always be followed by a onMovementBoundsChanged() call
-     * with fromImeAdjustement set to true.
+     * with fromImeAdjustement set to {@code true}.
      */
     void onImeVisibilityChanged(boolean imeVisible, int imeHeight);
 
     /**
+     * Called when window manager decides to adjust the pinned stack bounds because of the shelf, or
+     * when the listener is first registered to allow the listener to synchronized its state with
+     * the controller.  This call will always be followed by a onMovementBoundsChanged() call
+     * with fromShelfAdjustment set to {@code true}.
+     */
+    void onShelfVisibilityChanged(boolean shelfVisible, int shelfHeight);
+
+    /**
      * Called when window manager decides to adjust the minimized state, or when the listener
      * is first registered to allow the listener to synchronized its state with the controller.
      */
index d172fb5..613e6d8 100644 (file)
@@ -284,7 +284,12 @@ interface IWindowManager
      */
     oneway void setPipVisibility(boolean visible);
 
-   /**
+    /**
+     * Called by System UI to notify of changes to the visibility and height of the shelf.
+     */
+    void setShelfHeight(boolean visible, int shelfHeight);
+
+    /**
      * Called by System UI to enable or disable haptic feedback on the navigation bar buttons.
      */
     void setNavBarVirtualKeyHapticFeedbackEnabled(boolean enabled);
@@ -295,8 +300,8 @@ interface IWindowManager
     boolean hasNavigationBar();
 
     /**
-    * Get the position of the nav bar
-    */
+     * Get the position of the nav bar
+     */
     int getNavBarPosition();
 
     /**
index 749d00c..5b6b619 100644 (file)
@@ -325,14 +325,14 @@ public class PipSnapAlgorithm {
      * {@param stackBounds}.
      */
     public void getMovementBounds(Rect stackBounds, Rect insetBounds, Rect movementBoundsOut,
-            int imeHeight) {
+            int bottomOffset) {
         // Adjust the right/bottom to ensure the stack bounds never goes offscreen
         movementBoundsOut.set(insetBounds);
         movementBoundsOut.right = Math.max(insetBounds.left, insetBounds.right -
                 stackBounds.width());
         movementBoundsOut.bottom = Math.max(insetBounds.top, insetBounds.bottom -
                 stackBounds.height());
-        movementBoundsOut.bottom -= imeHeight;
+        movementBoundsOut.bottom -= bottomOffset;
     }
 
     /**
index cf13d1c..eea1a47 100644 (file)
     <item name="config_pictureInPictureAspectRatioLimitForMinSize" format="float" type="dimen">1.777778</item>
 
     <!-- The default gravity for the picture-in-picture window.
-         Currently, this maps to Gravity.TOP | Gravity.RIGHT -->
-    <integer name="config_defaultPictureInPictureGravity">0x35</integer>
+         Currently, this maps to Gravity.BOTTOM | Gravity.RIGHT -->
+    <integer name="config_defaultPictureInPictureGravity">0x55</integer>
 
     <!-- The minimum aspect ratio (width/height) that is supported for picture-in-picture.  Any
          ratio smaller than this is considered too tall and thin to be usable. Currently, this
index 2de3ae2..9355acf 100644 (file)
@@ -23,7 +23,6 @@ import android.graphics.Rect;
 import android.os.Handler;
 import android.os.RemoteException;
 import android.util.Log;
-import android.view.RemoteAnimationAdapter;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 
@@ -124,4 +123,12 @@ public class WindowManagerWrapper {
             Log.w(TAG, "Failed to enable or disable navigation bar button haptics: ", e);
         }
     }
+
+    public void setShelfHeight(boolean visible, int shelfHeight) {
+        try {
+            WindowManagerGlobal.getWindowManagerService().setShelfHeight(visible, shelfHeight);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to set shelf height");
+        }
+    }
 }
index 24d0126..2af7ae2 100644 (file)
@@ -133,6 +133,13 @@ public class PipManager implements BasePipManager {
         }
 
         @Override
+        public void onShelfVisibilityChanged(boolean shelfVisible, int shelfHeight) {
+            mHandler.post(() -> {
+               mTouchHandler.onShelfVisibilityChanged(shelfVisible, shelfHeight);
+            });
+        }
+
+        @Override
         public void onMinimizedStateChanged(boolean isMinimized) {
             mHandler.post(() -> {
                 mTouchHandler.setMinimizedState(isMinimized, true /* fromController */);
@@ -141,10 +148,11 @@ public class PipManager implements BasePipManager {
 
         @Override
         public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds,
-                Rect animatingBounds, boolean fromImeAdjustement, int displayRotation) {
+                Rect animatingBounds, boolean fromImeAdjustment, boolean fromShelfAdjustment,
+                int displayRotation) {
             mHandler.post(() -> {
                 mTouchHandler.onMovementBoundsChanged(insetBounds, normalBounds, animatingBounds,
-                        fromImeAdjustement, displayRotation);
+                        fromImeAdjustment, fromShelfAdjustment, displayRotation);
             });
         }
 
index 21a836c..31d8cbb 100644 (file)
@@ -16,8 +16,6 @@
 
 package com.android.systemui.pip.phone;
 
-import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static com.android.systemui.Interpolators.FAST_OUT_LINEAR_IN;
@@ -71,7 +69,7 @@ public class PipMotionHelper implements Handler.Callback {
     private static final int EXPAND_STACK_TO_MENU_DURATION = 250;
     private static final int EXPAND_STACK_TO_FULLSCREEN_DURATION = 300;
     private static final int MINIMIZE_STACK_MAX_DURATION = 200;
-    private static final int IME_SHIFT_DURATION = 300;
+    private static final int SHIFT_DURATION = 300;
 
     // The fraction of the stack width that the user has to drag offscreen to minimize the PiP
     private static final float MINIMIZE_OFFSCREEN_FRACTION = 0.3f;
@@ -354,11 +352,11 @@ public class PipMotionHelper implements Handler.Callback {
     }
 
     /**
-     * Animates the PiP to offset it from the IME.
+     * Animates the PiP to offset it from the IME or shelf.
      */
-    void animateToIMEOffset(Rect toBounds) {
+    void animateToOffset(Rect toBounds) {
         cancelAnimations();
-        resizeAndAnimatePipUnchecked(toBounds, IME_SHIFT_DURATION);
+        resizeAndAnimatePipUnchecked(toBounds, SHIFT_DURATION);
     }
 
     /**
index 77931e4..3ba3d0e 100644 (file)
@@ -120,6 +120,8 @@ public class PipTouchHandler {
     private boolean mIsImeShowing;
     private int mImeHeight;
     private int mImeOffset;
+    private boolean mIsShelfShowing;
+    private int mShelfHeight;
     private float mSavedSnapFraction = -1f;
     private boolean mSendingHoverAccessibilityEvents;
     private boolean mMovementWithinMinimize;
@@ -249,13 +251,20 @@ public class PipTouchHandler {
         mImeHeight = imeHeight;
     }
 
+    public void onShelfVisibilityChanged(boolean shelfVisible, int shelfHeight) {
+        mIsShelfShowing = shelfVisible;
+        mShelfHeight = shelfHeight;
+    }
+
     public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds, Rect animatingBounds,
-            boolean fromImeAdjustement, int displayRotation) {
+            boolean fromImeAdjustment, boolean fromShelfAdjustment, int displayRotation) {
+        final int bottomOffset = mIsImeShowing ? mImeHeight : 0;
+
         // Re-calculate the expanded bounds
         mNormalBounds = normalBounds;
         Rect normalMovementBounds = new Rect();
         mSnapAlgorithm.getMovementBounds(mNormalBounds, insetBounds, normalMovementBounds,
-                mIsImeShowing ? mImeHeight : 0);
+                bottomOffset);
 
         // Calculate the expanded size
         float aspectRatio = (float) normalBounds.width() / normalBounds.height();
@@ -266,40 +275,23 @@ public class PipTouchHandler {
         mExpandedBounds.set(0, 0, expandedSize.getWidth(), expandedSize.getHeight());
         Rect expandedMovementBounds = new Rect();
         mSnapAlgorithm.getMovementBounds(mExpandedBounds, insetBounds, expandedMovementBounds,
-                mIsImeShowing ? mImeHeight : 0);
+                bottomOffset);
 
-        // If this is from an IME adjustment, then we should move the PiP so that it is not occluded
-        // by the IME
-        if (fromImeAdjustement) {
+        // If this is from an IME or shelf adjustment, then we should move the PiP so that it is not
+        // occluded by the IME or shelf.
+        if (fromImeAdjustment || fromShelfAdjustment) {
             if (mTouchState.isUserInteracting()) {
                 // Defer the update of the current movement bounds until after the user finishes
                 // touching the screen
             } else {
-                final Rect bounds = new Rect(animatingBounds);
                 final Rect toMovementBounds = mMenuState == MENU_STATE_FULL
                         ? expandedMovementBounds
                         : normalMovementBounds;
-                if (mIsImeShowing) {
-                    // IME visible, apply the IME offset if the space allows for it
-                    final int imeOffset = toMovementBounds.bottom - Math.max(toMovementBounds.top,
-                            toMovementBounds.bottom - mImeOffset);
-                    if (bounds.top == mMovementBounds.bottom) {
-                        // If the PIP is currently resting on top of the IME, then adjust it with
-                        // the showing IME
-                        bounds.offsetTo(bounds.left, toMovementBounds.bottom - imeOffset);
-                    } else {
-                        bounds.offset(0, Math.min(0, toMovementBounds.bottom - imeOffset
-                                - bounds.top));
-                    }
-                } else {
-                    // IME hidden
-                    if (bounds.top >= (mMovementBounds.bottom - mImeOffset)) {
-                        // If the PIP is resting on top of the IME, then adjust it with the hiding
-                        // IME
-                        bounds.offsetTo(bounds.left, toMovementBounds.bottom);
-                    }
-                }
-                mMotionHelper.animateToIMEOffset(bounds);
+                animateToOffset(animatingBounds, toMovementBounds,
+                        fromImeAdjustment,
+                        fromImeAdjustment ? mIsImeShowing : mIsShelfShowing,
+                        // Shelf height serves as an offset, but does not change movement bounds.
+                        fromImeAdjustment ? mImeOffset : mShelfHeight);
             }
         }
 
@@ -321,6 +313,26 @@ public class PipTouchHandler {
         }
     }
 
+    private void animateToOffset(Rect animatingBounds, Rect toMovementBounds,
+            boolean fromImeAdjustment, boolean showing, int offset) {
+        final Rect bounds = new Rect(animatingBounds);
+        if (showing) {
+            // IME/shelf visible, apply the IME/shelf offset if the space allows for it
+            final int calculatedOffset = toMovementBounds.bottom - Math.max(toMovementBounds.top,
+                    toMovementBounds.bottom - offset);
+            bounds.offset(0,
+                    Math.min(0, toMovementBounds.bottom - calculatedOffset - bounds.top));
+        } else {
+            // IME/shelf hidden
+            if (bounds.top >= (mMovementBounds.bottom - offset)) {
+                bounds.offset(0, toMovementBounds.bottom - bounds.top -
+                        // Counter going back home from search where keyboard is up.
+                        (fromImeAdjustment ? mShelfHeight : 0));
+            }
+        }
+        mMotionHelper.animateToOffset(bounds);
+    }
+
     private void onRegistrationChanged(boolean isRegistered) {
         mAccessibilityManager.setPictureInPictureActionReplacingConnection(isRegistered
                 ? new PipAccessibilityInteractionConnection(mMotionHelper,
@@ -801,6 +813,8 @@ public class PipTouchHandler {
         pw.println(innerPrefix + "mIsMinimized=" + mIsMinimized);
         pw.println(innerPrefix + "mIsImeShowing=" + mIsImeShowing);
         pw.println(innerPrefix + "mImeHeight=" + mImeHeight);
+        pw.println(innerPrefix + "mIsShelfShowing=" + mIsShelfShowing);
+        pw.println(innerPrefix + "mShelfHeight=" + mShelfHeight);
         pw.println(innerPrefix + "mSavedSnapFraction=" + mSavedSnapFraction);
         pw.println(innerPrefix + "mEnableDragToEdgeDismiss=" + ENABLE_DISMISS_DRAG_TO_EDGE);
         pw.println(innerPrefix + "mEnableMinimize=" + ENABLE_MINIMIZE);
index a984680..d6f6760 100644 (file)
@@ -200,11 +200,15 @@ public class PipManager implements BasePipManager {
         }
 
         @Override
+        public void onShelfVisibilityChanged(boolean shelfVisible, int shelfHeight) {}
+
+        @Override
         public void onMinimizedStateChanged(boolean isMinimized) {}
 
         @Override
         public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds,
-                Rect animatingBounds, boolean fromImeAdjustement, int displayRotation) {
+                Rect animatingBounds, boolean fromImeAdjustment, boolean fromShelfAdjustment,
+                int displayRotation) {
             mHandler.post(() -> {
                 mDefaultPipBounds.set(normalBounds);
             });
index 063c1f1..5f605c4 100644 (file)
@@ -26259,10 +26259,12 @@ public class ActivityManagerService extends IActivityManager.Stub
             return mUserController.mMaxRunningUsers;
         }
 
+        @Override
         public boolean isCallerRecents(int callingUid) {
             return getRecentTasks().isCallerRecents(callingUid);
         }
 
+        @Override
         public boolean isRecentsComponentHomeActivity(int userId) {
             return getRecentTasks().isRecentsComponentHomeActivity(userId);
         }
@@ -26301,6 +26303,11 @@ public class ActivityManagerService extends IActivityManager.Stub
             }
             return processMemoryStates;
         }
+
+        @Override
+        public void enforceCallerIsRecentsOrHasPermission(String permission, String func) {
+            ActivityManagerService.this.enforceCallerIsRecentsOrHasPermission(permission, func);
+        }
     }
 
     /**
index 6966f1b..2293fb2 100644 (file)
@@ -88,6 +88,8 @@ class PinnedStackController {
     private boolean mIsMinimized;
     private boolean mIsImeShowing;
     private int mImeHeight;
+    private boolean mIsShelfShowing;
+    private int mShelfHeight;
 
     // The set of actions and aspect-ratio for the that are currently allowed on the PiP activity
     private ArrayList<RemoteAction> mActions = new ArrayList<>();
@@ -213,9 +215,11 @@ class PinnedStackController {
             listener.onListenerRegistered(mCallbacks);
             mPinnedStackListener = listener;
             notifyImeVisibilityChanged(mIsImeShowing, mImeHeight);
+            notifyShelfVisibilityChanged(mIsShelfShowing, mShelfHeight);
             // The movement bounds notification needs to be sent before the minimized state, since
             // SystemUI may use the bounds to retore the minimized position
-            notifyMovementBoundsChanged(false /* fromImeAdjustment */);
+            notifyMovementBoundsChanged(false /* fromImeAdjustment */,
+                    false /* fromShelfAdjustment */);
             notifyActionsChanged(mActions);
             notifyMinimizeChanged(mIsMinimized);
         } catch (RemoteException e) {
@@ -297,7 +301,9 @@ class PinnedStackController {
                 mSnapAlgorithm.applySnapFraction(defaultBounds, movementBounds, snapFraction);
             } else {
                 Gravity.apply(mDefaultStackGravity, size.getWidth(), size.getHeight(), insetBounds,
-                        0, mIsImeShowing ? mImeHeight : 0, defaultBounds);
+                        0, Math.max(mIsImeShowing ? mImeHeight : 0,
+                                mIsShelfShowing ? mShelfHeight : 0),
+                        defaultBounds);
             }
             return defaultBounds;
         }
@@ -310,7 +316,7 @@ class PinnedStackController {
      */
     synchronized void onDisplayInfoChanged() {
         mDisplayInfo.copyFrom(mDisplayContent.getDisplayInfo());
-        notifyMovementBoundsChanged(false /* fromImeAdjustment */);
+        notifyMovementBoundsChanged(false /* fromImeAdjustment */, false /* fromShelfAdjustment */);
     }
 
     /**
@@ -342,14 +348,15 @@ class PinnedStackController {
             // Calculate the stack bounds in the new orientation to the same same fraction along the
             // rotated movement bounds.
             final Rect postChangeMovementBounds = getMovementBounds(postChangeStackBounds,
-                    false /* adjustForIme */);
+                    false /* adjustForIme */, false /* adjustForShelf */);
             mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds,
                     snapFraction);
             if (mIsMinimized) {
                 applyMinimizedOffset(postChangeStackBounds, postChangeMovementBounds);
             }
 
-            notifyMovementBoundsChanged(false /* fromImeAdjustment */);
+            notifyMovementBoundsChanged(false /* fromImeAdjustment */,
+                    false /* fromShelfAdjustment */);
 
             outBounds.set(postChangeStackBounds);
             return true;
@@ -373,7 +380,22 @@ class PinnedStackController {
         mIsImeShowing = imeShowing;
         mImeHeight = imeHeight;
         notifyImeVisibilityChanged(imeShowing, imeHeight);
-        notifyMovementBoundsChanged(true /* fromImeAdjustment */);
+        notifyMovementBoundsChanged(true /* fromImeAdjustment */, false /* fromShelfAdjustment */);
+    }
+
+    /**
+     * Sets the shelf state and height.
+     */
+    void setAdjustedForShelf(boolean adjustedForShelf, int shelfHeight) {
+        final boolean shelfShowing = adjustedForShelf && shelfHeight > 0;
+        if (shelfShowing == mIsShelfShowing && shelfHeight == mShelfHeight) {
+            return;
+        }
+
+        mIsShelfShowing = shelfShowing;
+        mShelfHeight = shelfHeight;
+        notifyShelfVisibilityChanged(shelfShowing, shelfHeight);
+        notifyMovementBoundsChanged(false /* fromImeAdjustment */, true /* fromShelfAdjustment */);
     }
 
     /**
@@ -382,7 +404,8 @@ class PinnedStackController {
     void setAspectRatio(float aspectRatio) {
         if (Float.compare(mAspectRatio, aspectRatio) != 0) {
             mAspectRatio = aspectRatio;
-            notifyMovementBoundsChanged(false /* fromImeAdjustment */);
+            notifyMovementBoundsChanged(false /* fromImeAdjustment */,
+                    false /* fromShelfAdjustment */);
         }
     }
 
@@ -417,6 +440,16 @@ class PinnedStackController {
         }
     }
 
+    private void notifyShelfVisibilityChanged(boolean shelfVisible, int shelfHeight) {
+        if (mPinnedStackListener != null) {
+            try {
+                mPinnedStackListener.onShelfVisibilityChanged(shelfVisible, shelfHeight);
+            } catch (RemoteException e) {
+                Slog.e(TAG_WM, "Error delivering bounds changed event.", e);
+            }
+        }
+    }
+
     /**
      * Notifies listeners that the PIP minimized state has changed.
      */
@@ -446,7 +479,8 @@ class PinnedStackController {
     /**
      * Notifies listeners that the PIP movement bounds have changed.
      */
-    private void notifyMovementBoundsChanged(boolean fromImeAdjustement) {
+    private void notifyMovementBoundsChanged(boolean fromImeAdjustment,
+            boolean fromShelfAdjustment) {
         synchronized (mService.mWindowMap) {
             if (mPinnedStackListener == null) {
                 return;
@@ -467,7 +501,8 @@ class PinnedStackController {
                     animatingBounds.set(normalBounds);
                 }
                 mPinnedStackListener.onMovementBoundsChanged(insetBounds, normalBounds,
-                        animatingBounds, fromImeAdjustement, mDisplayInfo.rotation);
+                        animatingBounds, fromImeAdjustment, fromShelfAdjustment,
+                        mDisplayInfo.rotation);
             } catch (RemoteException e) {
                 Slog.e(TAG_WM, "Error delivering actions changed event.", e);
             }
@@ -493,7 +528,8 @@ class PinnedStackController {
      */
     private Rect getMovementBounds(Rect stackBounds) {
         synchronized (mService.mWindowMap) {
-            return getMovementBounds(stackBounds, true /* adjustForIme */);
+            return getMovementBounds(stackBounds, true /* adjustForIme */,
+                    true /* adjustForShelf */);
         }
     }
 
@@ -501,14 +537,15 @@ class PinnedStackController {
      * @return the movement bounds for the given {@param stackBounds} and the current state of the
      *         controller.
      */
-    private Rect getMovementBounds(Rect stackBounds, boolean adjustForIme) {
+    private Rect getMovementBounds(Rect stackBounds, boolean adjustForIme, boolean adjustForShelf) {
         synchronized (mService.mWindowMap) {
             final Rect movementBounds = new Rect();
             getInsetBounds(movementBounds);
 
             // Apply the movement bounds adjustments based on the current state
             mSnapAlgorithm.getMovementBounds(stackBounds, movementBounds, movementBounds,
-                    (adjustForIme && mIsImeShowing) ? mImeHeight : 0);
+                    Math.max((adjustForIme && mIsImeShowing) ? mImeHeight : 0,
+                            (adjustForShelf && mIsShelfShowing) ? mShelfHeight : 0));
             return movementBounds;
         }
     }
@@ -549,6 +586,9 @@ class PinnedStackController {
         pw.print(prefix + "  movementBounds="); getMovementBounds(mTmpRect).printShortString(pw);
         pw.println();
         pw.println(prefix + "  mIsImeShowing=" + mIsImeShowing);
+        pw.println(prefix + "  mImeHeight=" + mImeHeight);
+        pw.println(prefix + "  mIsShelfShowing=" + mIsShelfShowing);
+        pw.println(prefix + "  mShelfHeight=" + mShelfHeight);
         pw.println(prefix + "  mIsMinimized=" + mIsMinimized);
         if (mActions.isEmpty()) {
             pw.println(prefix + "  mActions=[]");
index ea84b22..9f8de58 100644 (file)
@@ -5892,6 +5892,16 @@ public class WindowManagerService extends IWindowManager.Stub
     }
 
     @Override
+    public void setShelfHeight(boolean visible, int shelfHeight) {
+        mAmInternal.enforceCallerIsRecentsOrHasPermission(android.Manifest.permission.STATUS_BAR,
+                "setShelfHeight()");
+        synchronized (mWindowMap) {
+            getDefaultDisplayContentLocked().getPinnedStackController().setAdjustedForShelf(visible,
+                    shelfHeight);
+        }
+    }
+
+    @Override
     public void statusBarVisibilityChanged(int visibility) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
                 != PackageManager.PERMISSION_GRANTED) {
diff --git a/services/tests/servicestests/src/com/android/server/wm/PinnedStackControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/PinnedStackControllerTest.java
new file mode 100644 (file)
index 0000000..96745fa
--- /dev/null
@@ -0,0 +1,63 @@
+package com.android.server.wm;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.IPinnedStackListener;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class PinnedStackControllerTest extends WindowTestsBase {
+
+    @Mock private IPinnedStackListener mIPinnedStackListener;
+    @Mock private IPinnedStackListener.Stub mIPinnedStackListenerStub;
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        MockitoAnnotations.initMocks(this);
+        when(mIPinnedStackListener.asBinder()).thenReturn(mIPinnedStackListenerStub);
+    }
+
+    @Test
+    public void setShelfHeight_shelfVisibilityChangedTriggered() throws RemoteException {
+        sWm.mSupportsPictureInPicture = true;
+        sWm.registerPinnedStackListener(DEFAULT_DISPLAY, mIPinnedStackListener);
+
+        verify(mIPinnedStackListener).onImeVisibilityChanged(false, 0);
+        verify(mIPinnedStackListener).onShelfVisibilityChanged(false, 0);
+        verify(mIPinnedStackListener).onMovementBoundsChanged(any(), any(), any(), eq(false),
+                eq(false), anyInt());
+        verify(mIPinnedStackListener).onActionsChanged(any());
+        verify(mIPinnedStackListener).onMinimizedStateChanged(anyBoolean());
+
+        reset(mIPinnedStackListener);
+
+        final int SHELF_HEIGHT = 300;
+
+        sWm.setShelfHeight(true, SHELF_HEIGHT);
+        verify(mIPinnedStackListener).onShelfVisibilityChanged(true, SHELF_HEIGHT);
+        verify(mIPinnedStackListener).onMovementBoundsChanged(any(), any(), any(), eq(false),
+                eq(true), anyInt());
+        verify(mIPinnedStackListener, never()).onImeVisibilityChanged(anyBoolean(), anyInt());
+    }
+}