diff --git a/prebuilts/libs/WindowManager-Shell-14.jar b/prebuilts/libs/WindowManager-Shell-14.jar index a1258b3f25..1ef4dacdfb 100644 Binary files a/prebuilts/libs/WindowManager-Shell-14.jar and b/prebuilts/libs/WindowManager-Shell-14.jar differ diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index 0f8eed17ba..c13aaef402 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -1561,9 +1561,10 @@ public abstract class AbsSwipeUpHandler, Q extends ? mRecentsAnimationTargets .findTask(mGestureState.getTopRunningTaskId()) : null; + var taskInfo = mGestureState.getRunningTask().mAllCachedTasks.get(0); final ArrayList cookies = Utilities.ATLEAST_S && runningTaskTarget != null - && runningTaskTarget.taskInfo != null - ? runningTaskTarget.taskInfo.launchCookies + && taskInfo != null + ? taskInfo.launchCookies : new ArrayList<>(); boolean isTranslucent = runningTaskTarget != null && runningTaskTarget.isTranslucent; boolean hasValidLeash = runningTaskTarget != null @@ -1573,8 +1574,8 @@ public abstract class AbsSwipeUpHandler, Q extends && hasValidLeash && Utilities.ATLEAST_T && runningTaskTarget.allowEnterPip - && runningTaskTarget.taskInfo.pictureInPictureParams != null - && runningTaskTarget.taskInfo.pictureInPictureParams.isAutoEnterEnabled(); + && taskInfo.pictureInPictureParams != null + && taskInfo.pictureInPictureParams.isAutoEnterEnabled(); HomeAnimationFactory homeAnimFactory = createHomeAnimationFactory(cookies, duration, isTranslucent, appCanEnterPip, runningTaskTarget); @@ -1597,6 +1598,8 @@ public abstract class AbsSwipeUpHandler, Q extends mRecentsAnimationController.screenshotTask(taskId)); }); + if (mSwipePipToHomeAnimator == null) return; + // let SystemUi reparent the overlay leash as soon as possible SystemUiProxy.INSTANCE.get(mContext).stopSwipePipToHome( mSwipePipToHomeAnimator.getTaskId(), @@ -1715,7 +1718,7 @@ public abstract class AbsSwipeUpHandler, Q extends private SwipePipToHomeAnimator createWindowAnimationToPip(HomeAnimationFactory homeAnimFactory, RemoteAnimationTarget runningTaskTarget, float startProgress) { // Directly animate the app to PiP (picture-in-picture) mode - final ActivityManager.RunningTaskInfo taskInfo = runningTaskTarget.taskInfo; + final ActivityManager.RunningTaskInfo taskInfo = mGestureState.getRunningTask().mAllCachedTasks.get(0); final RecentsOrientedState orientationState = mRemoteTargetHandles[0].getTaskViewSimulator() .getOrientationState(); final int windowRotation = calculateWindowRotation(runningTaskTarget, orientationState); @@ -1731,11 +1734,13 @@ public abstract class AbsSwipeUpHandler, Q extends windowToHomePositionMap.mapRect(startRect); final Rect hotseatKeepClearArea = getKeepClearAreaForHotseat(); + if (taskInfo == null) return null; final Rect destinationBounds = SystemUiProxy.INSTANCE.get(mContext) .startSwipePipToHome(taskInfo.topActivity, taskInfo.topActivityInfo, - runningTaskTarget.taskInfo.pictureInPictureParams, + taskInfo.pictureInPictureParams, homeRotation, + mDp.hotseatBarSizePx, hotseatKeepClearArea); if (destinationBounds == null) { // No destination bounds returned from SystemUI, bail early. @@ -1759,7 +1764,7 @@ public abstract class AbsSwipeUpHandler, Q extends .setAppIconSizePx(mDp.iconSizePx) .setLeash(runningTaskTarget.leash) .setSourceRectHint( - runningTaskTarget.taskInfo.pictureInPictureParams.getSourceRectHint()) + taskInfo.pictureInPictureParams.getSourceRectHint()) .setAppBounds(appBounds) .setHomeToWindowPositionMap(homeToWindowPositionMap) .setStartBounds(startRect) @@ -2214,7 +2219,8 @@ public abstract class AbsSwipeUpHandler, Q extends * This should happen before {@link #finishRecentsControllerToHome(Runnable)}. */ private void maybeFinishSwipePipToHome() { - if (mIsSwipingPipToHome && mSwipePipToHomeAnimators[0] != null) { + if (mIsSwipingPipToHome && mSwipePipToHomeAnimators[0] != null && mRecentsAnimationController != null) { + mRecentsAnimationController.setFinishTaskTransaction( mSwipePipToHomeAnimator.getTaskId(), mSwipePipToHomeAnimator.getFinishTransaction(), diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java index baa336beb3..88cd3caa64 100644 --- a/quickstep/src/com/android/quickstep/SystemUiProxy.java +++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java @@ -83,6 +83,7 @@ import com.android.wm.shell.desktopmode.IDesktopMode; import com.android.wm.shell.desktopmode.IDesktopTaskListener; import com.android.wm.shell.draganddrop.IDragAndDrop; import com.android.wm.shell.onehanded.IOneHanded; +import com.android.wm.shell.pip.PipData; import com.android.wm.shell.pip.IPip; import com.android.wm.shell.pip.IPipAnimationListener; import com.android.wm.shell.recents.IRecentTasks; @@ -625,14 +626,19 @@ public class SystemUiProxy implements ISystemUiProxy { */ @Nullable public Rect startSwipePipToHome(ComponentName componentName, ActivityInfo activityInfo, - PictureInPictureParams pictureInPictureParams, int launcherRotation, + PictureInPictureParams pictureInPictureParams, int launcherRotation, int hotseatBarSize, Rect hotseatKeepClearArea) { if (mPip != null) { try { return mPip.startSwipePipToHome(componentName, activityInfo, - pictureInPictureParams, launcherRotation, hotseatKeepClearArea); + pictureInPictureParams, launcherRotation, new PipData(hotseatBarSize)); } catch (Throwable e) { - Log.w(TAG, "Failed call startSwipePipToHome", e); + try { + return mPip.startSwipePipToHome(componentName, activityInfo, + pictureInPictureParams, launcherRotation, new PipData(hotseatKeepClearArea)); + } catch (Throwable t) { + Log.w(TAG, "Failed call startSwipePipToHome", e); + } } } return null; diff --git a/systemUIShared/src/com/android/wm/shell/pip/IPip.aidl b/systemUIShared/src/com/android/wm/shell/pip/IPip.aidl new file mode 100644 index 0000000000..dae6ed21eb --- /dev/null +++ b/systemUIShared/src/com/android/wm/shell/pip/IPip.aidl @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.pip; + +import android.app.PictureInPictureParams; +import android.view.SurfaceControl; +import android.content.ComponentName; +import android.content.pm.ActivityInfo; +import android.graphics.Rect; +import com.android.wm.shell.pip.IPipAnimationListener; +import com.android.wm.shell.pip.PipData; + +/** + * Interface that is exposed to remote callers to manipulate the Pip feature. + */ +interface IPip { + + /** + * Notifies that Activity is about to be swiped to home with entering PiP transition and + * queries the destination bounds for PiP depends on Launcher's rotation and shelf height. + * + * @param componentName ComponentName represents the Activity + * @param activityInfo ActivityInfo tied to the Activity + * @param pictureInPictureParams PictureInPictureParams tied to the Activity + * @param launcherRotation Launcher rotation to calculate the PiP destination bounds + * @param hotseatKeepClearArea Bounds of Hotseat to avoid used to calculate PiP destination + bounds + * @return destination bounds the PiP window should land into + */ + Rect startSwipePipToHome(in ComponentName componentName, in ActivityInfo activityInfo, + in PictureInPictureParams pictureInPictureParams, + int launcherRotation, in PipData hotseatKeepClearArea) = 1; + + /** + * Notifies the swiping Activity to PiP onto home transition is finished + * + * @param taskId the Task id that the Activity and overlay are currently in. + * @param componentName ComponentName represents the Activity + * @param destinationBounds the destination bounds the PiP window lands into + * @param overlay an optional overlay to fade out after entering PiP + */ + oneway void stopSwipePipToHome(int taskId, in ComponentName componentName, + in Rect destinationBounds, in SurfaceControl overlay) = 2; + + /** + * Notifies the swiping Activity to PiP onto home transition is aborted + * + * @param taskId the Task id that the Activity and overlay are currently in. + * @param componentName ComponentName represents the Activity + */ + oneway void abortSwipePipToHome(int taskId, in ComponentName componentName) = 3; + + /** + * Sets listener to get pinned stack animation callbacks. + */ + oneway void setPipAnimationListener(IPipAnimationListener listener) = 4; + + /** + * Sets the shelf height and visibility. + */ + oneway void setShelfHeight(boolean visible, int shelfHeight) = 5; + + /** + * Sets the next pip animation type to be the alpha animation. + */ + oneway void setPipAnimationTypeToAlpha() = 6; + + /** + * Sets the height and visibility of the Launcher keep clear area. + */ + oneway void setLauncherKeepClearAreaHeight(boolean visible, int height) = 7; + + /** + * Sets the app icon size in pixel used by Launcher + */ + oneway void setLauncherAppIconSize(int iconSizePx) = 8; +} diff --git a/systemUIShared/src/com/android/wm/shell/pip/IPipAnimationListener.aidl b/systemUIShared/src/com/android/wm/shell/pip/IPipAnimationListener.aidl new file mode 100644 index 0000000000..062e3ba263 --- /dev/null +++ b/systemUIShared/src/com/android/wm/shell/pip/IPipAnimationListener.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.pip; + +/** + * Listener interface that Launcher attaches to SystemUI to get Pip animation callbacks. + */ +oneway interface IPipAnimationListener { + /** + * Notifies the listener that the Pip animation is started. + */ + void onPipAnimationStarted(); + + /** + * Notifies the listener about PiP resource dimensions changed. + * Listener can expect an immediate callback the first time they attach. + * + * @param cornerRadius the pixel value of the corner radius, zero means it's disabled. + * @param shadowRadius the pixel value of the shadow radius, zero means it's disabled. + */ + void onPipResourceDimensionsChanged(int cornerRadius, int shadowRadius); + + /** + * Notifies the listener that user leaves PiP by tapping on the expand button. + */ + void onExpandPip(); +} diff --git a/systemUIShared/src/com/android/wm/shell/pip/PipData.aidl b/systemUIShared/src/com/android/wm/shell/pip/PipData.aidl new file mode 100644 index 0000000000..82c8a94ef1 --- /dev/null +++ b/systemUIShared/src/com/android/wm/shell/pip/PipData.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2024 Lawnchair Launcher + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.pip; + +parcelable PipData; \ No newline at end of file diff --git a/systemUIShared/src/com/android/wm/shell/pip/PipData.java b/systemUIShared/src/com/android/wm/shell/pip/PipData.java new file mode 100644 index 0000000000..4487a9e429 --- /dev/null +++ b/systemUIShared/src/com/android/wm/shell/pip/PipData.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2024 Lawnchair Launcher + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.pip; + +import android.os.Parcel; +import android.os.Parcelable; +import android.graphics.Rect; + +public class PipData implements Parcelable { + private Rect rect; + private int intValue; + + public PipData(Rect rect) { + this.rect = rect; + } + + public PipData(int intValue) { + this.intValue = intValue; + } + + protected PipData(Parcel in) { + rect = in.readParcelable(Rect.class.getClassLoader()); + intValue = in.readInt(); + } + + public static final Creator CREATOR = new Creator<>() { + @Override + public PipData createFromParcel(Parcel in) { + return new PipData (in); + } + + @Override + public PipData[] newArray(int size) { + return new PipData[size]; + } + }; + + public Rect getRect() { + return rect; + } + + public int getIntValue() { + return intValue; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeParcelable(rect, flags); + dest.writeInt(intValue); + } + + @Override + public int describeContents() { + return 0; + } +} \ No newline at end of file