diff options
12 files changed, 118 insertions, 23 deletions
diff --git a/core/java/android/window/RemoteTransition.java b/core/java/android/window/RemoteTransition.java index b243b656b8cd..4bd15f27a91a 100644 --- a/core/java/android/window/RemoteTransition.java +++ b/core/java/android/window/RemoteTransition.java @@ -18,6 +18,7 @@ package android.window; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.IApplicationThread; import android.os.IBinder; import android.os.Parcelable; @@ -34,6 +35,14 @@ public class RemoteTransition implements Parcelable { /** The actual remote-transition interface used to run the transition animation. */ private @NonNull IRemoteTransition mRemoteTransition; + /** The application thread that will be running the remote transition. */ + private @Nullable IApplicationThread mAppThread; + + /** Constructs with no app thread (animation runs in shell). */ + public RemoteTransition(@NonNull IRemoteTransition remoteTransition) { + this(remoteTransition, null /* appThread */); + } + /** Get the IBinder associated with the underlying IRemoteTransition. */ public @Nullable IBinder asBinder() { return mRemoteTransition.asBinder(); @@ -59,13 +68,17 @@ public class RemoteTransition implements Parcelable { * * @param remoteTransition * The actual remote-transition interface used to run the transition animation. + * @param appThread + * The application thread that will be running the remote transition. */ @DataClass.Generated.Member public RemoteTransition( - @NonNull IRemoteTransition remoteTransition) { + @NonNull IRemoteTransition remoteTransition, + @Nullable IApplicationThread appThread) { this.mRemoteTransition = remoteTransition; com.android.internal.util.AnnotationValidations.validate( NonNull.class, null, mRemoteTransition); + this.mAppThread = appThread; // onConstructed(); // You can define this method to get a callback } @@ -79,6 +92,14 @@ public class RemoteTransition implements Parcelable { } /** + * The application thread that will be running the remote transition. + */ + @DataClass.Generated.Member + public @Nullable IApplicationThread getAppThread() { + return mAppThread; + } + + /** * The actual remote-transition interface used to run the transition animation. */ @DataClass.Generated.Member @@ -89,6 +110,15 @@ public class RemoteTransition implements Parcelable { return this; } + /** + * The application thread that will be running the remote transition. + */ + @DataClass.Generated.Member + public @NonNull RemoteTransition setAppThread(@NonNull IApplicationThread value) { + mAppThread = value; + return this; + } + @Override @DataClass.Generated.Member public String toString() { @@ -96,7 +126,8 @@ public class RemoteTransition implements Parcelable { // String fieldNameToString() { ... } return "RemoteTransition { " + - "remoteTransition = " + mRemoteTransition + + "remoteTransition = " + mRemoteTransition + ", " + + "appThread = " + mAppThread + " }"; } @@ -106,7 +137,11 @@ public class RemoteTransition implements Parcelable { // You can override field parcelling by defining methods like: // void parcelFieldName(Parcel dest, int flags) { ... } + byte flg = 0; + if (mAppThread != null) flg |= 0x2; + dest.writeByte(flg); dest.writeStrongInterface(mRemoteTransition); + if (mAppThread != null) dest.writeStrongInterface(mAppThread); } @Override @@ -120,11 +155,14 @@ public class RemoteTransition implements Parcelable { // You can override field unparcelling by defining methods like: // static FieldType unparcelFieldName(Parcel in) { ... } + byte flg = in.readByte(); IRemoteTransition remoteTransition = IRemoteTransition.Stub.asInterface(in.readStrongBinder()); + IApplicationThread appThread = (flg & 0x2) == 0 ? null : IApplicationThread.Stub.asInterface(in.readStrongBinder()); this.mRemoteTransition = remoteTransition; com.android.internal.util.AnnotationValidations.validate( NonNull.class, null, mRemoteTransition); + this.mAppThread = appThread; // onConstructed(); // You can define this method to get a callback } @@ -144,10 +182,10 @@ public class RemoteTransition implements Parcelable { }; @DataClass.Generated( - time = 1630613039043L, + time = 1630690027011L, codegenVersion = "1.0.23", sourceFile = "frameworks/base/core/java/android/window/RemoteTransition.java", - inputSignatures = "private @android.annotation.NonNull android.window.IRemoteTransition mRemoteTransition\npublic @android.annotation.Nullable android.os.IBinder asBinder()\nclass RemoteTransition extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genSetters=true, genAidl=true)") + inputSignatures = "private @android.annotation.NonNull android.window.IRemoteTransition mRemoteTransition\nprivate @android.annotation.Nullable android.app.IApplicationThread mAppThread\npublic @android.annotation.Nullable android.os.IBinder asBinder()\nclass RemoteTransition extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genSetters=true, genAidl=true)") @Deprecated private void __metadata() {} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index 7be199c75816..4fa1eadb0bc2 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -340,8 +340,13 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, } augmentedNonApps[augmentedNonApps.length - 1] = getDividerBarLegacyTarget(); try { - ActivityTaskManager.getService().setRunningRemoteTransitionDelegate( - adapter.getCallingApplication()); + try { + ActivityTaskManager.getService().setRunningRemoteTransitionDelegate( + adapter.getCallingApplication()); + } catch (SecurityException e) { + Slog.e(TAG, "Unable to boost animation thread. This should only happen" + + " during unit tests"); + } adapter.getRunner().onAnimationStart(transit, apps, wallpapers, nonApps, finishedCallback); } catch (RemoteException e) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java index 3be896e4aca3..3e2a0e635a75 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java @@ -18,9 +18,11 @@ package com.android.wm.shell.transition; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.ActivityTaskManager; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; +import android.util.Slog; import android.view.SurfaceControl; import android.window.IRemoteTransition; import android.window.IRemoteTransitionFinishedCallback; @@ -89,6 +91,13 @@ public class OneShotRemoteHandler implements Transitions.TransitionHandler { if (mRemote.asBinder() != null) { mRemote.asBinder().linkToDeath(remoteDied, 0 /* flags */); } + try { + ActivityTaskManager.getService().setRunningRemoteTransitionDelegate( + mRemote.getAppThread()); + } catch (SecurityException e) { + Slog.e(Transitions.TAG, "Unable to boost animation thread. This should only happen" + + " during unit tests"); + } mRemote.getRemoteTransition().startAnimation(transition, info, startTransaction, cb); } catch (RemoteException e) { Log.e(Transitions.TAG, "Error running remote transition.", e); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java index c798ace18b5f..ece9f47e8788 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java @@ -18,6 +18,7 @@ package com.android.wm.shell.transition; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.ActivityTaskManager; import android.os.IBinder; import android.os.RemoteException; import android.util.ArrayMap; @@ -130,6 +131,13 @@ public class RemoteTransitionHandler implements Transitions.TransitionHandler { }; try { handleDeath(remote.asBinder(), finishCallback); + try { + ActivityTaskManager.getService().setRunningRemoteTransitionDelegate( + remote.getAppThread()); + } catch (SecurityException e) { + Log.e(Transitions.TAG, "Unable to boost animation thread. This should only happen" + + " during unit tests"); + } remote.getRemoteTransition().startAnimation(transition, info, startTransaction, cb); } catch (RemoteException e) { Log.e(Transitions.TAG, "Error running remote transition.", e); diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java index dcc4ea119376..7729a7532f8f 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java @@ -26,6 +26,7 @@ import static android.view.WindowManager.TransitionOldType; import static android.window.TransitionInfo.FLAG_IS_WALLPAPER; import android.annotation.SuppressLint; +import android.app.IApplicationThread; import android.os.IBinder; import android.os.RemoteException; import android.util.ArrayMap; @@ -51,10 +52,10 @@ public class RemoteAnimationAdapterCompat { private final RemoteTransitionCompat mRemoteTransition; public RemoteAnimationAdapterCompat(RemoteAnimationRunnerCompat runner, long duration, - long statusBarTransitionDelay) { + long statusBarTransitionDelay, IApplicationThread appThread) { mWrapped = new RemoteAnimationAdapter(wrapRemoteAnimationRunner(runner), duration, statusBarTransitionDelay); - mRemoteTransition = buildRemoteTransition(runner); + mRemoteTransition = buildRemoteTransition(runner, appThread); } RemoteAnimationAdapter getWrapped() { @@ -62,9 +63,10 @@ public class RemoteAnimationAdapterCompat { } /** Helper to just build a remote transition. Use this if the legacy adapter isn't needed. */ - public static RemoteTransitionCompat buildRemoteTransition(RemoteAnimationRunnerCompat runner) { + public static RemoteTransitionCompat buildRemoteTransition(RemoteAnimationRunnerCompat runner, + IApplicationThread appThread) { return new RemoteTransitionCompat( - new RemoteTransition(wrapRemoteTransition(runner))); + new RemoteTransition(wrapRemoteTransition(runner), appThread)); } public RemoteTransitionCompat getRemoteTransition() { diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java index 9ec95a3c992d..99b6aed497cc 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java @@ -30,6 +30,7 @@ import android.annotation.Nullable; import android.annotation.SuppressLint; import android.app.ActivityManager; import android.app.ActivityTaskManager; +import android.app.IApplicationThread; import android.content.ComponentName; import android.graphics.Rect; import android.os.IBinder; @@ -72,7 +73,7 @@ public class RemoteTransitionCompat implements Parcelable { } public RemoteTransitionCompat(@NonNull RemoteTransitionRunner runner, - @NonNull Executor executor) { + @NonNull Executor executor, @Nullable IApplicationThread appThread) { IRemoteTransition remote = new IRemoteTransition.Stub() { @Override public void startAnimation(IBinder transition, TransitionInfo info, @@ -103,12 +104,12 @@ public class RemoteTransitionCompat implements Parcelable { finishAdapter)); } }; - mTransition = new RemoteTransition(remote); + mTransition = new RemoteTransition(remote, appThread); } /** Constructor specifically for recents animation */ public RemoteTransitionCompat(RecentsAnimationListener recents, - RecentsAnimationControllerCompat controller) { + RecentsAnimationControllerCompat controller, IApplicationThread appThread) { IRemoteTransition remote = new IRemoteTransition.Stub() { final RecentsControllerWrap mRecentsSession = new RecentsControllerWrap(); IBinder mToken = null; @@ -168,7 +169,7 @@ public class RemoteTransitionCompat implements Parcelable { } } }; - mTransition = new RemoteTransition(remote); + mTransition = new RemoteTransition(remote, appThread); } /** Adds a filter check that restricts this remote transition to home open transitions. */ diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java index 01a0f271e5b9..6cf419122063 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java @@ -238,7 +238,7 @@ public class KeyguardService extends Service { TransitionFilter f = new TransitionFilter(); f.mFlags = TRANSIT_FLAG_KEYGUARD_GOING_AWAY; shellTransitions.registerRemote(f, - new RemoteTransition(wrap(mExitAnimationRunner))); + new RemoteTransition(wrap(mExitAnimationRunner), getIApplicationThread())); } if (sEnableRemoteKeyguardOccludeAnimation) { Slog.d(TAG, "KeyguardService registerRemote: TRANSIT_KEYGUARD_(UN)OCCLUDE"); @@ -257,7 +257,8 @@ public class KeyguardService extends Service { f.mRequirements[1].mMustBeIndependent = false; f.mRequirements[1].mFlags = FLAG_OCCLUDES_KEYGUARD; f.mRequirements[1].mModes = new int[]{TRANSIT_CLOSE, TRANSIT_TO_BACK}; - shellTransitions.registerRemote(f, new RemoteTransition(mOccludeAnimation)); + shellTransitions.registerRemote(f, + new RemoteTransition(mOccludeAnimation, getIApplicationThread())); // Now register for un-occlude. f = new TransitionFilter(); @@ -277,7 +278,8 @@ public class KeyguardService extends Service { f.mRequirements[0].mMustBeIndependent = false; f.mRequirements[0].mFlags = FLAG_OCCLUDES_KEYGUARD; f.mRequirements[0].mModes = new int[]{TRANSIT_OPEN, TRANSIT_TO_FRONT}; - shellTransitions.registerRemote(f, new RemoteTransition(mUnoccludeAnimation)); + shellTransitions.registerRemote(f, + new RemoteTransition(mUnoccludeAnimation, getIApplicationThread())); } } else { RemoteAnimationDefinition definition = new RemoteAnimationDefinition(); diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java index a21e4f2fee0d..e05457010df8 100644 --- a/services/core/java/com/android/server/wm/TransitionController.java +++ b/services/core/java/com/android/server/wm/TransitionController.java @@ -27,6 +27,7 @@ import static android.view.WindowManager.TRANSIT_OPEN; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; +import android.app.IApplicationThread; import android.os.IBinder; import android.os.IRemoteCallback; import android.os.RemoteException; @@ -68,6 +69,7 @@ class TransitionController { private ITransitionPlayer mTransitionPlayer; final TransitionMetricsReporter mTransitionMetricsReporter = new TransitionMetricsReporter(); + private IApplicationThread mTransitionPlayerThread; final ActivityTaskManagerService mAtm; final TaskSnapshotController mTaskSnapshotController; @@ -136,7 +138,8 @@ class TransitionController { return mCollectingTransition; } - void registerTransitionPlayer(@Nullable ITransitionPlayer player) { + void registerTransitionPlayer(@Nullable ITransitionPlayer player, + @Nullable IApplicationThread appThread) { try { // Note: asBinder() can be null if player is same process (likely in a test). if (mTransitionPlayer != null) { @@ -149,6 +152,7 @@ class TransitionController { player.asBinder().linkToDeath(mTransitionPlayerDeath, 0); } mTransitionPlayer = player; + mTransitionPlayerThread = appThread; } catch (RemoteException e) { throw new RuntimeException("Unable to set transition player"); } @@ -362,6 +366,9 @@ class TransitionController { } ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Finish Transition: %s", record); mPlayingTransitions.remove(record); + if (mPlayingTransitions.isEmpty()) { + setAnimationRunning(false /* running */); + } record.finishTransition(); mRunningLock.doNotifyLocked(); } @@ -371,9 +378,22 @@ class TransitionController { throw new IllegalStateException("Trying to move non-collecting transition to playing"); } mCollectingTransition = null; + if (mPlayingTransitions.isEmpty()) { + setAnimationRunning(true /* running */); + } mPlayingTransitions.add(transition); } + private void setAnimationRunning(boolean running) { + if (mTransitionPlayerThread == null) return; + final WindowProcessController wpc = mAtm.getProcessController(mTransitionPlayerThread); + if (wpc == null) { + Slog.w(TAG, "Unable to find process for player thread=" + mTransitionPlayerThread); + return; + } + wpc.setRunningRemoteAnimation(running); + } + void abort(Transition transition) { if (transition != mCollectingTransition) { throw new IllegalStateException("Too late to abort."); diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index 6e706e9df003..51547c74f7c0 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -45,6 +45,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityOptions; +import android.app.IApplicationThread; import android.app.WindowConfiguration; import android.content.ActivityNotFoundException; import android.content.Intent; @@ -1031,10 +1032,18 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub @Override public void registerTransitionPlayer(ITransitionPlayer player) { enforceTaskPermission("registerTransitionPlayer()"); + final int callerPid = Binder.getCallingPid(); + final int callerUid = Binder.getCallingUid(); final long ident = Binder.clearCallingIdentity(); try { synchronized (mGlobalLock) { - mTransitionController.registerTransitionPlayer(player); + final WindowProcessController wpc = + mService.getProcessController(callerPid, callerUid); + IApplicationThread appThread = null; + if (wpc != null) { + appThread = wpc.getThread(); + } + mTransitionController.registerTransitionPlayer(player, appThread); } } finally { Binder.restoreCallingIdentity(ident); diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java index 4e77fa73fd09..d9a166a62673 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java @@ -473,7 +473,7 @@ public class TransitionTests extends WindowTestsBase { final TaskSnapshotController snapshotController = mock(TaskSnapshotController.class); final TransitionController controller = new TransitionController(mAtm, snapshotController); final ITransitionPlayer player = new ITransitionPlayer.Default(); - controller.registerTransitionPlayer(player); + controller.registerTransitionPlayer(player, null /* appThread */); ITaskOrganizer mockOrg = mock(ITaskOrganizer.class); final Transition openTransition = controller.createTransition(TRANSIT_OPEN); @@ -539,7 +539,7 @@ public class TransitionTests extends WindowTestsBase { final TaskSnapshotController snapshotController = mock(TaskSnapshotController.class); final TransitionController controller = new TransitionController(mAtm, snapshotController); final ITransitionPlayer player = new ITransitionPlayer.Default(); - controller.registerTransitionPlayer(player); + controller.registerTransitionPlayer(player, null /* appThread */); ITaskOrganizer mockOrg = mock(ITaskOrganizer.class); final Transition openTransition = controller.createTransition(TRANSIT_OPEN); diff --git a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java index 3f0c13c83816..f366f57bae08 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java @@ -316,7 +316,8 @@ public class WallpaperControllerTests extends WindowTestsBase { final IBinder mockBinder = mock(IBinder.class); final ITransitionPlayer mockPlayer = mock(ITransitionPlayer.class); doReturn(mockBinder).when(mockPlayer).asBinder(); - mWm.mAtmService.getTransitionController().registerTransitionPlayer(mockPlayer); + mWm.mAtmService.getTransitionController().registerTransitionPlayer(mockPlayer, + null /* appThread */); Transition transit = mWm.mAtmService.getTransitionController().createTransition(TRANSIT_OPEN); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java index 81b00eae0021..115f8a3fecf4 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java @@ -802,7 +802,7 @@ class WindowTestsBase extends SystemServiceTestsBase { TestTransitionPlayer registerTestTransitionPlayer() { final TestTransitionPlayer testPlayer = new TestTransitionPlayer( mAtm.getTransitionController(), mAtm.mWindowOrganizerController); - testPlayer.mController.registerTransitionPlayer(testPlayer); + testPlayer.mController.registerTransitionPlayer(testPlayer, null /* appThread */); return testPlayer; } |