Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java +3 −3 Original line number Diff line number Diff line Loading @@ -427,10 +427,10 @@ public class PipAnimationController { new PipContentOverlay.PipSnapshotOverlay(snapshot, sourceRectHint)); } void setAppIconContentOverlay(Context context, Rect bounds, ActivityInfo activityInfo, int appIconSizePx) { void setAppIconContentOverlay(Context context, Rect appBounds, Rect destinationBounds, ActivityInfo activityInfo, int appIconSizePx) { reattachContentOverlay( new PipContentOverlay.PipAppIconOverlay(context, bounds, new PipContentOverlay.PipAppIconOverlay(context, appBounds, destinationBounds, new IconProvider(context).getIcon(activityInfo), appIconSizePx)); } Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipContentOverlay.java +31 −10 Original line number Diff line number Diff line Loading @@ -180,20 +180,34 @@ public abstract class PipContentOverlay { private final Context mContext; private final int mAppIconSizePx; private final Rect mAppBounds; private final int mOverlayHalfSize; private final Matrix mTmpTransform = new Matrix(); private final float[] mTmpFloat9 = new float[9]; private Bitmap mBitmap; public PipAppIconOverlay(Context context, Rect appBounds, public PipAppIconOverlay(Context context, Rect appBounds, Rect destinationBounds, Drawable appIcon, int appIconSizePx) { mContext = context; final int maxAppIconSizePx = (int) TypedValue.applyDimension(COMPLEX_UNIT_DIP, MAX_APP_ICON_SIZE_DP, context.getResources().getDisplayMetrics()); mAppIconSizePx = Math.min(maxAppIconSizePx, appIconSizePx); mAppBounds = new Rect(appBounds); mBitmap = Bitmap.createBitmap(appBounds.width(), appBounds.height(), Bitmap.Config.ARGB_8888); final int appWidth = appBounds.width(); final int appHeight = appBounds.height(); // In order to have the overlay always cover the pip window during the transition, the // overlay will be drawn with the max size of the start and end bounds in different // rotation. final int overlaySize = Math.max(Math.max(appWidth, appHeight), Math.max(destinationBounds.width(), destinationBounds.height())) + 1; mOverlayHalfSize = overlaySize >> 1; // When the activity is in the secondary split, make sure the scaling center is not // offset. mAppBounds = new Rect(0, 0, appWidth, appHeight); mBitmap = Bitmap.createBitmap(overlaySize, overlaySize, Bitmap.Config.ARGB_8888); prepareAppIconOverlay(appIcon); mLeash = new SurfaceControl.Builder(new SurfaceSession()) .setCallsite(TAG) Loading @@ -215,12 +229,19 @@ public abstract class PipContentOverlay { public void onAnimationUpdate(SurfaceControl.Transaction atomicTx, Rect currentBounds, float fraction) { mTmpTransform.reset(); // In order for the overlay to always cover the pip window, the overlay may have a // size larger than the pip window. Make sure that app icon is at the center. final int appBoundsCenterX = mAppBounds.centerX(); final int appBoundsCenterY = mAppBounds.centerY(); mTmpTransform.setTranslate( appBoundsCenterX - mOverlayHalfSize, appBoundsCenterY - mOverlayHalfSize); // Scale back the bitmap with the pivot point at center. mTmpTransform.postScale( (float) mAppBounds.width() / currentBounds.width(), (float) mAppBounds.height() / currentBounds.height(), mAppBounds.centerX(), mAppBounds.centerY()); appBoundsCenterX, appBoundsCenterY); atomicTx.setMatrix(mLeash, mTmpTransform, mTmpFloat9) .setAlpha(mLeash, fraction < 0.5f ? 0 : (fraction - 0.5f) * 2); } Loading Loading @@ -253,10 +274,10 @@ public abstract class PipContentOverlay { ta.recycle(); } final Rect appIconBounds = new Rect( mAppBounds.centerX() - mAppIconSizePx / 2, mAppBounds.centerY() - mAppIconSizePx / 2, mAppBounds.centerX() + mAppIconSizePx / 2, mAppBounds.centerY() + mAppIconSizePx / 2); mOverlayHalfSize - mAppIconSizePx / 2, mOverlayHalfSize - mAppIconSizePx / 2, mOverlayHalfSize + mAppIconSizePx / 2, mOverlayHalfSize + mAppIconSizePx / 2); appIcon.setBounds(appIconBounds); appIcon.draw(canvas); mBitmap = mBitmap.copy(Bitmap.Config.HARDWARE, false /* mutable */); Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +2 −2 Original line number Diff line number Diff line Loading @@ -1718,7 +1718,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, sourceHintRect = computeRotatedBounds(rotationDelta, direction, destinationBounds, sourceHintRect); } Rect baseBounds = direction == TRANSITION_DIRECTION_SNAP_AFTER_RESIZE final Rect baseBounds = direction == TRANSITION_DIRECTION_SNAP_AFTER_RESIZE ? mPipBoundsState.getBounds() : currentBounds; final boolean existingAnimatorRunning = mPipAnimationController.getCurrentAnimator() != null && mPipAnimationController.getCurrentAnimator().isRunning(); Loading @@ -1741,7 +1741,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, final boolean hasTopActivityInfo = mTaskInfo.topActivityInfo != null; if (hasTopActivityInfo) { animator.setAppIconContentOverlay( mContext, currentBounds, mTaskInfo.topActivityInfo, mContext, currentBounds, destinationBounds, mTaskInfo.topActivityInfo, mPipBoundsState.getLauncherState().getAppIconSizePx()); } else { ProtoLog.w(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java +1 −1 Original line number Diff line number Diff line Loading @@ -916,7 +916,7 @@ public class PipTransition extends PipTransitionController { final boolean hasTopActivityInfo = taskInfo.topActivityInfo != null; if (hasTopActivityInfo) { animator.setAppIconContentOverlay( mContext, currentBounds, taskInfo.topActivityInfo, mContext, currentBounds, destinationBounds, taskInfo.topActivityInfo, mPipBoundsState.getLauncherState().getAppIconSizePx()); } else { ProtoLog.w(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, Loading services/core/java/com/android/server/wm/RootWindowContainer.java +7 −2 Original line number Diff line number Diff line Loading @@ -2095,6 +2095,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } final TaskFragment organizedTf = r.getOrganizedTaskFragment(); final TaskFragment taskFragment = r.getTaskFragment(); final boolean singleActivity = task.getNonFinishingActivityCount() == 1; if (singleActivity) { rootTask = task; Loading Loading @@ -2137,7 +2138,11 @@ class RootWindowContainer extends WindowContainer<DisplayContent> .setIntent(r.intent) .setDeferTaskAppear(true) .setHasBeenVisible(true) .setWindowingMode(task.getRequestedOverrideWindowingMode()) // In case the activity is in system split screen, or Activity Embedding // split, we need to animate the PIP Task from the original TaskFragment // bounds, so also setting the windowing mode, otherwise the bounds may // be reset to fullscreen. .setWindowingMode(taskFragment.getWindowingMode()) .build(); // Establish bi-directional link between the original and pinned task. r.setLastParentBeforePip(launchIntoPipHostActivity); Loading @@ -2150,7 +2155,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // current bounds. // Use Task#setBoundsUnchecked to skip checking windowing mode as the windowing mode // will be updated later after this is collected in transition. rootTask.setBoundsUnchecked(r.getTaskFragment().getBounds()); rootTask.setBoundsUnchecked(taskFragment.getBounds()); // Move the last recents animation transaction from original task to the new one. if (task.mLastRecentsAnimationTransaction != null) { Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java +3 −3 Original line number Diff line number Diff line Loading @@ -427,10 +427,10 @@ public class PipAnimationController { new PipContentOverlay.PipSnapshotOverlay(snapshot, sourceRectHint)); } void setAppIconContentOverlay(Context context, Rect bounds, ActivityInfo activityInfo, int appIconSizePx) { void setAppIconContentOverlay(Context context, Rect appBounds, Rect destinationBounds, ActivityInfo activityInfo, int appIconSizePx) { reattachContentOverlay( new PipContentOverlay.PipAppIconOverlay(context, bounds, new PipContentOverlay.PipAppIconOverlay(context, appBounds, destinationBounds, new IconProvider(context).getIcon(activityInfo), appIconSizePx)); } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipContentOverlay.java +31 −10 Original line number Diff line number Diff line Loading @@ -180,20 +180,34 @@ public abstract class PipContentOverlay { private final Context mContext; private final int mAppIconSizePx; private final Rect mAppBounds; private final int mOverlayHalfSize; private final Matrix mTmpTransform = new Matrix(); private final float[] mTmpFloat9 = new float[9]; private Bitmap mBitmap; public PipAppIconOverlay(Context context, Rect appBounds, public PipAppIconOverlay(Context context, Rect appBounds, Rect destinationBounds, Drawable appIcon, int appIconSizePx) { mContext = context; final int maxAppIconSizePx = (int) TypedValue.applyDimension(COMPLEX_UNIT_DIP, MAX_APP_ICON_SIZE_DP, context.getResources().getDisplayMetrics()); mAppIconSizePx = Math.min(maxAppIconSizePx, appIconSizePx); mAppBounds = new Rect(appBounds); mBitmap = Bitmap.createBitmap(appBounds.width(), appBounds.height(), Bitmap.Config.ARGB_8888); final int appWidth = appBounds.width(); final int appHeight = appBounds.height(); // In order to have the overlay always cover the pip window during the transition, the // overlay will be drawn with the max size of the start and end bounds in different // rotation. final int overlaySize = Math.max(Math.max(appWidth, appHeight), Math.max(destinationBounds.width(), destinationBounds.height())) + 1; mOverlayHalfSize = overlaySize >> 1; // When the activity is in the secondary split, make sure the scaling center is not // offset. mAppBounds = new Rect(0, 0, appWidth, appHeight); mBitmap = Bitmap.createBitmap(overlaySize, overlaySize, Bitmap.Config.ARGB_8888); prepareAppIconOverlay(appIcon); mLeash = new SurfaceControl.Builder(new SurfaceSession()) .setCallsite(TAG) Loading @@ -215,12 +229,19 @@ public abstract class PipContentOverlay { public void onAnimationUpdate(SurfaceControl.Transaction atomicTx, Rect currentBounds, float fraction) { mTmpTransform.reset(); // In order for the overlay to always cover the pip window, the overlay may have a // size larger than the pip window. Make sure that app icon is at the center. final int appBoundsCenterX = mAppBounds.centerX(); final int appBoundsCenterY = mAppBounds.centerY(); mTmpTransform.setTranslate( appBoundsCenterX - mOverlayHalfSize, appBoundsCenterY - mOverlayHalfSize); // Scale back the bitmap with the pivot point at center. mTmpTransform.postScale( (float) mAppBounds.width() / currentBounds.width(), (float) mAppBounds.height() / currentBounds.height(), mAppBounds.centerX(), mAppBounds.centerY()); appBoundsCenterX, appBoundsCenterY); atomicTx.setMatrix(mLeash, mTmpTransform, mTmpFloat9) .setAlpha(mLeash, fraction < 0.5f ? 0 : (fraction - 0.5f) * 2); } Loading Loading @@ -253,10 +274,10 @@ public abstract class PipContentOverlay { ta.recycle(); } final Rect appIconBounds = new Rect( mAppBounds.centerX() - mAppIconSizePx / 2, mAppBounds.centerY() - mAppIconSizePx / 2, mAppBounds.centerX() + mAppIconSizePx / 2, mAppBounds.centerY() + mAppIconSizePx / 2); mOverlayHalfSize - mAppIconSizePx / 2, mOverlayHalfSize - mAppIconSizePx / 2, mOverlayHalfSize + mAppIconSizePx / 2, mOverlayHalfSize + mAppIconSizePx / 2); appIcon.setBounds(appIconBounds); appIcon.draw(canvas); mBitmap = mBitmap.copy(Bitmap.Config.HARDWARE, false /* mutable */); Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +2 −2 Original line number Diff line number Diff line Loading @@ -1718,7 +1718,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, sourceHintRect = computeRotatedBounds(rotationDelta, direction, destinationBounds, sourceHintRect); } Rect baseBounds = direction == TRANSITION_DIRECTION_SNAP_AFTER_RESIZE final Rect baseBounds = direction == TRANSITION_DIRECTION_SNAP_AFTER_RESIZE ? mPipBoundsState.getBounds() : currentBounds; final boolean existingAnimatorRunning = mPipAnimationController.getCurrentAnimator() != null && mPipAnimationController.getCurrentAnimator().isRunning(); Loading @@ -1741,7 +1741,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, final boolean hasTopActivityInfo = mTaskInfo.topActivityInfo != null; if (hasTopActivityInfo) { animator.setAppIconContentOverlay( mContext, currentBounds, mTaskInfo.topActivityInfo, mContext, currentBounds, destinationBounds, mTaskInfo.topActivityInfo, mPipBoundsState.getLauncherState().getAppIconSizePx()); } else { ProtoLog.w(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java +1 −1 Original line number Diff line number Diff line Loading @@ -916,7 +916,7 @@ public class PipTransition extends PipTransitionController { final boolean hasTopActivityInfo = taskInfo.topActivityInfo != null; if (hasTopActivityInfo) { animator.setAppIconContentOverlay( mContext, currentBounds, taskInfo.topActivityInfo, mContext, currentBounds, destinationBounds, taskInfo.topActivityInfo, mPipBoundsState.getLauncherState().getAppIconSizePx()); } else { ProtoLog.w(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, Loading
services/core/java/com/android/server/wm/RootWindowContainer.java +7 −2 Original line number Diff line number Diff line Loading @@ -2095,6 +2095,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } final TaskFragment organizedTf = r.getOrganizedTaskFragment(); final TaskFragment taskFragment = r.getTaskFragment(); final boolean singleActivity = task.getNonFinishingActivityCount() == 1; if (singleActivity) { rootTask = task; Loading Loading @@ -2137,7 +2138,11 @@ class RootWindowContainer extends WindowContainer<DisplayContent> .setIntent(r.intent) .setDeferTaskAppear(true) .setHasBeenVisible(true) .setWindowingMode(task.getRequestedOverrideWindowingMode()) // In case the activity is in system split screen, or Activity Embedding // split, we need to animate the PIP Task from the original TaskFragment // bounds, so also setting the windowing mode, otherwise the bounds may // be reset to fullscreen. .setWindowingMode(taskFragment.getWindowingMode()) .build(); // Establish bi-directional link between the original and pinned task. r.setLastParentBeforePip(launchIntoPipHostActivity); Loading @@ -2150,7 +2155,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // current bounds. // Use Task#setBoundsUnchecked to skip checking windowing mode as the windowing mode // will be updated later after this is collected in transition. rootTask.setBoundsUnchecked(r.getTaskFragment().getBounds()); rootTask.setBoundsUnchecked(taskFragment.getBounds()); // Move the last recents animation transaction from original task to the new one. if (task.mLastRecentsAnimationTransaction != null) { Loading