Boost remote-transition animator processes during animation
This basically ties applicationthread binder token to remote
transitions. Shell is first boosted (to run the shell transition
logic) and if it then delegates to a remotetransition, it will
then request that process also be boosted.
Bug: 183993977
Test: add logging in WPC.setRunningRemoteAnimation and verify calls
during transitions
Change-Id: I94babc327e935ea81271942287a83b948dd11f8b
This commit is contained in:
@@ -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
|
||||
}
|
||||
@@ -78,6 +91,14 @@ public class RemoteTransition implements Parcelable {
|
||||
return mRemoteTransition;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@@ -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() {}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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.");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user