Loading core/java/android/view/IPinnedStackController.aidl +13 −0 Original line number Diff line number Diff line Loading @@ -45,4 +45,17 @@ interface IPinnedStackController { * {@param animationDuration} suggests the animation duration transitioning to PiP window. */ void startAnimation(in Rect destinationBounds, in Rect sourceRectHint, int animationDuration); /** * Notifies the controller to reset on bounds animation, if there is any. * This could happen when screen rotation is happening and we need to notify the WM to reset * any running bounds animation on the pinned stack. * {@param bounds} here is the final destination bounds. */ void resetBoundsAnimation(in Rect bounds); /** * Reports the current default and movement bounds to controller. */ void reportBounds(in Rect defaultBounds, in Rect movementBounds); } packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java +3 −1 Original line number Diff line number Diff line Loading @@ -20,11 +20,13 @@ import android.content.Context; import android.content.res.Configuration; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.wm.DisplayWindowController; import java.io.PrintWriter; public interface BasePipManager { void initialize(Context context, BroadcastDispatcher broadcastDispatcher); void initialize(Context context, BroadcastDispatcher broadcastDispatcher, DisplayWindowController displayWindowController); void showPictureInPictureMenu(); default void expandPip() {} default void hidePipMenu(Runnable onStartCallback, Runnable onEndCallback) {} Loading packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java +84 −3 Original line number Diff line number Diff line Loading @@ -16,8 +16,14 @@ package com.android.systemui.pip; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.util.TypedValue.COMPLEX_UNIT_DIP; import static android.view.Surface.ROTATION_0; import static android.view.Surface.ROTATION_180; import android.app.ActivityManager; import android.app.ActivityTaskManager; import android.content.ComponentName; import android.content.Context; import android.content.res.Resources; Loading @@ -32,10 +38,9 @@ import android.view.DisplayInfo; import android.view.Gravity; import android.view.IPinnedStackController; import android.view.IWindowManager; import android.view.WindowContainerTransaction; import android.view.WindowManagerGlobal; import com.android.internal.policy.PipSnapAlgorithm; import java.io.PrintWriter; /** Loading Loading @@ -154,6 +159,7 @@ public class PipBoundsHandler { */ public void onMinimizedStateChanged(boolean minimized) { mIsMinimized = minimized; mSnapAlgorithm.setMinimized(minimized); } /** Loading Loading @@ -199,6 +205,7 @@ public class PipBoundsHandler { mReentrySnapFraction = INVALID_SNAP_FRACTION; mReentrySize = null; mLastPipComponentName = null; mLastDestinationBounds.setEmpty(); } public Rect getLastDestinationBounds() { Loading Loading @@ -235,8 +242,9 @@ public class PipBoundsHandler { */ public void onPrepareAnimation(Rect sourceRectHint, float aspectRatio, Rect bounds) { final Rect destinationBounds; final Rect defaultBounds = getDefaultBounds(mReentrySnapFraction, mReentrySize); if (bounds == null) { destinationBounds = getDefaultBounds(mReentrySnapFraction, mReentrySize); destinationBounds = new Rect(defaultBounds); } else { destinationBounds = new Rect(bounds); } Loading @@ -253,11 +261,84 @@ public class PipBoundsHandler { mPinnedStackController.startAnimation(destinationBounds, sourceRectHint, -1 /* animationDuration */); mLastDestinationBounds.set(destinationBounds); mPinnedStackController.reportBounds(defaultBounds, getMovementBounds(defaultBounds)); } catch (RemoteException e) { Log.e(TAG, "Failed to start PiP animation from SysUI", e); } } /** * Updates the display info, calculating and returning the new stack and movement bounds in the * new orientation of the device if necessary. * * @return {@code true} if internal {@link DisplayInfo} is rotated, {@code false} otherwise. */ public boolean onDisplayRotationChanged(Rect outBounds, int displayId, int fromRotation, int toRotation, WindowContainerTransaction t) { // Bail early if the event is not sent to current {@link #mDisplayInfo} if ((displayId != mDisplayInfo.displayId) || (fromRotation == toRotation)) { return false; } // Bail early if the pinned stack is staled. final ActivityManager.StackInfo pinnedStackInfo; try { pinnedStackInfo = ActivityTaskManager.getService() .getStackInfo(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED); if (pinnedStackInfo == null) return false; } catch (RemoteException e) { Log.e(TAG, "Failed to get StackInfo for pinned stack", e); return false; } // Calculate the snap fraction of the current stack along the old movement bounds final Rect postChangeStackBounds = new Rect(mLastDestinationBounds); final float snapFraction = getSnapFraction(postChangeStackBounds); // Populate the new {@link #mDisplayInfo}. // The {@link DisplayInfo} queried from DisplayManager would be the one before rotation, // therefore, the width/height may require a swap first. // Moving forward, we should get the new dimensions after rotation from DisplayLayout. mDisplayInfo.rotation = toRotation; updateDisplayInfoIfNeeded(); // Calculate the stack bounds in the new orientation based on same fraction along the // rotated movement bounds. final Rect postChangeMovementBounds = getMovementBounds(postChangeStackBounds, false /* adjustForIme */); mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds, snapFraction); if (mIsMinimized) { applyMinimizedOffset(postChangeStackBounds, postChangeMovementBounds); } try { outBounds.set(postChangeStackBounds); mLastDestinationBounds.set(outBounds); mPinnedStackController.resetBoundsAnimation(outBounds); mPinnedStackController.reportBounds(outBounds, getMovementBounds(outBounds)); t.setBounds(pinnedStackInfo.stackToken, outBounds); } catch (RemoteException e) { Log.e(TAG, "Failed to resize PiP on display rotation", e); } return true; } private void updateDisplayInfoIfNeeded() { final boolean updateNeeded; if ((mDisplayInfo.rotation == ROTATION_0) || (mDisplayInfo.rotation == ROTATION_180)) { updateNeeded = (mDisplayInfo.logicalWidth > mDisplayInfo.logicalHeight); } else { updateNeeded = (mDisplayInfo.logicalWidth < mDisplayInfo.logicalHeight); } if (updateNeeded) { final int newLogicalHeight = mDisplayInfo.logicalWidth; mDisplayInfo.logicalWidth = mDisplayInfo.logicalHeight; mDisplayInfo.logicalHeight = newLogicalHeight; } } /** * @return whether the given {@param aspectRatio} is valid. */ Loading core/java/com/android/internal/policy/PipSnapAlgorithm.java→packages/SystemUI/src/com/android/systemui/pip/PipSnapAlgorithm.java +1 −1 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ * limitations under the License. */ package com.android.internal.policy; package com.android.systemui.pip; import android.content.Context; import android.content.res.Configuration; Loading packages/SystemUI/src/com/android/systemui/pip/PipUI.java +6 −3 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.os.UserManager; import com.android.systemui.SystemUI; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.wm.DisplayWindowController; import java.io.FileDescriptor; import java.io.PrintWriter; Loading @@ -44,15 +45,17 @@ public class PipUI extends SystemUI implements CommandQueue.Callbacks { private final CommandQueue mCommandQueue; private BasePipManager mPipManager; private final BroadcastDispatcher mBroadcastDispatcher; private final DisplayWindowController mDisplayWindowController; private boolean mSupportsPip; @Inject public PipUI(Context context, CommandQueue commandQueue, BroadcastDispatcher broadcastDispatcher) { BroadcastDispatcher broadcastDispatcher, DisplayWindowController displayWindowController) { super(context); mBroadcastDispatcher = broadcastDispatcher; mCommandQueue = commandQueue; mDisplayWindowController = displayWindowController; } @Override Loading @@ -72,7 +75,7 @@ public class PipUI extends SystemUI implements CommandQueue.Callbacks { mPipManager = pm.hasSystemFeature(FEATURE_LEANBACK_ONLY) ? com.android.systemui.pip.tv.PipManager.getInstance() : com.android.systemui.pip.phone.PipManager.getInstance(); mPipManager.initialize(mContext, mBroadcastDispatcher); mPipManager.initialize(mContext, mBroadcastDispatcher, mDisplayWindowController); mCommandQueue.addCallback(this); } Loading Loading
core/java/android/view/IPinnedStackController.aidl +13 −0 Original line number Diff line number Diff line Loading @@ -45,4 +45,17 @@ interface IPinnedStackController { * {@param animationDuration} suggests the animation duration transitioning to PiP window. */ void startAnimation(in Rect destinationBounds, in Rect sourceRectHint, int animationDuration); /** * Notifies the controller to reset on bounds animation, if there is any. * This could happen when screen rotation is happening and we need to notify the WM to reset * any running bounds animation on the pinned stack. * {@param bounds} here is the final destination bounds. */ void resetBoundsAnimation(in Rect bounds); /** * Reports the current default and movement bounds to controller. */ void reportBounds(in Rect defaultBounds, in Rect movementBounds); }
packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java +3 −1 Original line number Diff line number Diff line Loading @@ -20,11 +20,13 @@ import android.content.Context; import android.content.res.Configuration; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.wm.DisplayWindowController; import java.io.PrintWriter; public interface BasePipManager { void initialize(Context context, BroadcastDispatcher broadcastDispatcher); void initialize(Context context, BroadcastDispatcher broadcastDispatcher, DisplayWindowController displayWindowController); void showPictureInPictureMenu(); default void expandPip() {} default void hidePipMenu(Runnable onStartCallback, Runnable onEndCallback) {} Loading
packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java +84 −3 Original line number Diff line number Diff line Loading @@ -16,8 +16,14 @@ package com.android.systemui.pip; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.util.TypedValue.COMPLEX_UNIT_DIP; import static android.view.Surface.ROTATION_0; import static android.view.Surface.ROTATION_180; import android.app.ActivityManager; import android.app.ActivityTaskManager; import android.content.ComponentName; import android.content.Context; import android.content.res.Resources; Loading @@ -32,10 +38,9 @@ import android.view.DisplayInfo; import android.view.Gravity; import android.view.IPinnedStackController; import android.view.IWindowManager; import android.view.WindowContainerTransaction; import android.view.WindowManagerGlobal; import com.android.internal.policy.PipSnapAlgorithm; import java.io.PrintWriter; /** Loading Loading @@ -154,6 +159,7 @@ public class PipBoundsHandler { */ public void onMinimizedStateChanged(boolean minimized) { mIsMinimized = minimized; mSnapAlgorithm.setMinimized(minimized); } /** Loading Loading @@ -199,6 +205,7 @@ public class PipBoundsHandler { mReentrySnapFraction = INVALID_SNAP_FRACTION; mReentrySize = null; mLastPipComponentName = null; mLastDestinationBounds.setEmpty(); } public Rect getLastDestinationBounds() { Loading Loading @@ -235,8 +242,9 @@ public class PipBoundsHandler { */ public void onPrepareAnimation(Rect sourceRectHint, float aspectRatio, Rect bounds) { final Rect destinationBounds; final Rect defaultBounds = getDefaultBounds(mReentrySnapFraction, mReentrySize); if (bounds == null) { destinationBounds = getDefaultBounds(mReentrySnapFraction, mReentrySize); destinationBounds = new Rect(defaultBounds); } else { destinationBounds = new Rect(bounds); } Loading @@ -253,11 +261,84 @@ public class PipBoundsHandler { mPinnedStackController.startAnimation(destinationBounds, sourceRectHint, -1 /* animationDuration */); mLastDestinationBounds.set(destinationBounds); mPinnedStackController.reportBounds(defaultBounds, getMovementBounds(defaultBounds)); } catch (RemoteException e) { Log.e(TAG, "Failed to start PiP animation from SysUI", e); } } /** * Updates the display info, calculating and returning the new stack and movement bounds in the * new orientation of the device if necessary. * * @return {@code true} if internal {@link DisplayInfo} is rotated, {@code false} otherwise. */ public boolean onDisplayRotationChanged(Rect outBounds, int displayId, int fromRotation, int toRotation, WindowContainerTransaction t) { // Bail early if the event is not sent to current {@link #mDisplayInfo} if ((displayId != mDisplayInfo.displayId) || (fromRotation == toRotation)) { return false; } // Bail early if the pinned stack is staled. final ActivityManager.StackInfo pinnedStackInfo; try { pinnedStackInfo = ActivityTaskManager.getService() .getStackInfo(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED); if (pinnedStackInfo == null) return false; } catch (RemoteException e) { Log.e(TAG, "Failed to get StackInfo for pinned stack", e); return false; } // Calculate the snap fraction of the current stack along the old movement bounds final Rect postChangeStackBounds = new Rect(mLastDestinationBounds); final float snapFraction = getSnapFraction(postChangeStackBounds); // Populate the new {@link #mDisplayInfo}. // The {@link DisplayInfo} queried from DisplayManager would be the one before rotation, // therefore, the width/height may require a swap first. // Moving forward, we should get the new dimensions after rotation from DisplayLayout. mDisplayInfo.rotation = toRotation; updateDisplayInfoIfNeeded(); // Calculate the stack bounds in the new orientation based on same fraction along the // rotated movement bounds. final Rect postChangeMovementBounds = getMovementBounds(postChangeStackBounds, false /* adjustForIme */); mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds, snapFraction); if (mIsMinimized) { applyMinimizedOffset(postChangeStackBounds, postChangeMovementBounds); } try { outBounds.set(postChangeStackBounds); mLastDestinationBounds.set(outBounds); mPinnedStackController.resetBoundsAnimation(outBounds); mPinnedStackController.reportBounds(outBounds, getMovementBounds(outBounds)); t.setBounds(pinnedStackInfo.stackToken, outBounds); } catch (RemoteException e) { Log.e(TAG, "Failed to resize PiP on display rotation", e); } return true; } private void updateDisplayInfoIfNeeded() { final boolean updateNeeded; if ((mDisplayInfo.rotation == ROTATION_0) || (mDisplayInfo.rotation == ROTATION_180)) { updateNeeded = (mDisplayInfo.logicalWidth > mDisplayInfo.logicalHeight); } else { updateNeeded = (mDisplayInfo.logicalWidth < mDisplayInfo.logicalHeight); } if (updateNeeded) { final int newLogicalHeight = mDisplayInfo.logicalWidth; mDisplayInfo.logicalWidth = mDisplayInfo.logicalHeight; mDisplayInfo.logicalHeight = newLogicalHeight; } } /** * @return whether the given {@param aspectRatio} is valid. */ Loading
core/java/com/android/internal/policy/PipSnapAlgorithm.java→packages/SystemUI/src/com/android/systemui/pip/PipSnapAlgorithm.java +1 −1 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ * limitations under the License. */ package com.android.internal.policy; package com.android.systemui.pip; import android.content.Context; import android.content.res.Configuration; Loading
packages/SystemUI/src/com/android/systemui/pip/PipUI.java +6 −3 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.os.UserManager; import com.android.systemui.SystemUI; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.wm.DisplayWindowController; import java.io.FileDescriptor; import java.io.PrintWriter; Loading @@ -44,15 +45,17 @@ public class PipUI extends SystemUI implements CommandQueue.Callbacks { private final CommandQueue mCommandQueue; private BasePipManager mPipManager; private final BroadcastDispatcher mBroadcastDispatcher; private final DisplayWindowController mDisplayWindowController; private boolean mSupportsPip; @Inject public PipUI(Context context, CommandQueue commandQueue, BroadcastDispatcher broadcastDispatcher) { BroadcastDispatcher broadcastDispatcher, DisplayWindowController displayWindowController) { super(context); mBroadcastDispatcher = broadcastDispatcher; mCommandQueue = commandQueue; mDisplayWindowController = displayWindowController; } @Override Loading @@ -72,7 +75,7 @@ public class PipUI extends SystemUI implements CommandQueue.Callbacks { mPipManager = pm.hasSystemFeature(FEATURE_LEANBACK_ONLY) ? com.android.systemui.pip.tv.PipManager.getInstance() : com.android.systemui.pip.phone.PipManager.getInstance(); mPipManager.initialize(mContext, mBroadcastDispatcher); mPipManager.initialize(mContext, mBroadcastDispatcher, mDisplayWindowController); mCommandQueue.addCallback(this); } Loading