Merge "Fix flicker when starting an activity from Recents." into sc-dev

This commit is contained in:
Issei Suzuki
2021-02-05 11:10:57 +00:00
committed by Android (Google) Code Review
9 changed files with 91 additions and 6 deletions

View File

@@ -28,6 +28,7 @@ package android {
field public static final String READ_PRIVILEGED_PHONE_STATE = "android.permission.READ_PRIVILEGED_PHONE_STATE"; field public static final String READ_PRIVILEGED_PHONE_STATE = "android.permission.READ_PRIVILEGED_PHONE_STATE";
field public static final String REMOVE_TASKS = "android.permission.REMOVE_TASKS"; field public static final String REMOVE_TASKS = "android.permission.REMOVE_TASKS";
field public static final String RESET_APP_ERRORS = "android.permission.RESET_APP_ERRORS"; field public static final String RESET_APP_ERRORS = "android.permission.RESET_APP_ERRORS";
field public static final String START_TASKS_FROM_RECENTS = "android.permission.START_TASKS_FROM_RECENTS";
field public static final String SUSPEND_APPS = "android.permission.SUSPEND_APPS"; field public static final String SUSPEND_APPS = "android.permission.SUSPEND_APPS";
field public static final String TEST_BIOMETRIC = "android.permission.TEST_BIOMETRIC"; field public static final String TEST_BIOMETRIC = "android.permission.TEST_BIOMETRIC";
field public static final String TEST_MANAGE_ROLLBACKS = "android.permission.TEST_MANAGE_ROLLBACKS"; field public static final String TEST_MANAGE_ROLLBACKS = "android.permission.TEST_MANAGE_ROLLBACKS";
@@ -119,6 +120,7 @@ package android.app {
public class ActivityOptions { public class ActivityOptions {
method @NonNull public static android.app.ActivityOptions makeCustomAnimation(@NonNull android.content.Context, int, int, @Nullable android.os.Handler, @Nullable android.app.ActivityOptions.OnAnimationStartedListener, @Nullable android.app.ActivityOptions.OnAnimationFinishedListener); method @NonNull public static android.app.ActivityOptions makeCustomAnimation(@NonNull android.content.Context, int, int, @Nullable android.os.Handler, @Nullable android.app.ActivityOptions.OnAnimationStartedListener, @Nullable android.app.ActivityOptions.OnAnimationFinishedListener);
method @NonNull @RequiresPermission(android.Manifest.permission.START_TASKS_FROM_RECENTS) public static android.app.ActivityOptions makeCustomTaskAnimation(@NonNull android.content.Context, int, int, @Nullable android.os.Handler, @Nullable android.app.ActivityOptions.OnAnimationStartedListener, @Nullable android.app.ActivityOptions.OnAnimationFinishedListener);
method public static void setExitTransitionTimeout(long); method public static void setExitTransitionTimeout(long);
method public void setLaunchActivityType(int); method public void setLaunchActivityType(int);
method public void setLaunchTaskId(int); method public void setLaunchTaskId(int);

View File

@@ -17,6 +17,7 @@
package android.app; package android.app;
import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS; import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.Display.INVALID_DISPLAY; import static android.view.Display.INVALID_DISPLAY;
@@ -310,6 +311,9 @@ public class ActivityOptions {
private static final String KEY_REMOTE_TRANSITION = private static final String KEY_REMOTE_TRANSITION =
"android:activity.remoteTransition"; "android:activity.remoteTransition";
private static final String KEY_OVERRIDE_TASK_TRANSITION =
"android:activity.overrideTaskTransition";
/** /**
* @see #setLaunchCookie * @see #setLaunchCookie
* @hide * @hide
@@ -393,6 +397,7 @@ public class ActivityOptions {
private RemoteAnimationAdapter mRemoteAnimationAdapter; private RemoteAnimationAdapter mRemoteAnimationAdapter;
private IBinder mLaunchCookie; private IBinder mLaunchCookie;
private IRemoteTransition mRemoteTransition; private IRemoteTransition mRemoteTransition;
private boolean mOverrideTaskTransition;
/** /**
* Create an ActivityOptions specifying a custom animation to run when * Create an ActivityOptions specifying a custom animation to run when
@@ -475,6 +480,40 @@ public class ActivityOptions {
return opts; return opts;
} }
/**
* Create an ActivityOptions specifying a custom animation to run when the activity in the
* different task is displayed.
*
* @param context Who is defining this. This is the application that the
* animation resources will be loaded from.
* @param enterResId A resource ID of the animation resource to use for
* the incoming activity. Use 0 for no animation.
* @param exitResId A resource ID of the animation resource to use for
* the outgoing activity. Use 0 for no animation.
* @param handler If <var>listener</var> is non-null this must be a valid
* Handler on which to dispatch the callback; otherwise it should be null.
* @param startedListener Optional OnAnimationStartedListener to find out when the
* requested animation has started running. If for some reason the animation
* is not executed, the callback will happen immediately.
* @param finishedListener Optional OnAnimationFinishedListener when the animation
* has finished running.
*
* @return Returns a new ActivityOptions object that you can use to
* supply these options as the options Bundle when starting an activity.
* @hide
*/
@RequiresPermission(START_TASKS_FROM_RECENTS)
@TestApi
public static @NonNull ActivityOptions makeCustomTaskAnimation(@NonNull Context context,
int enterResId, int exitResId, @Nullable Handler handler,
@Nullable OnAnimationStartedListener startedListener,
@Nullable OnAnimationFinishedListener finishedListener) {
ActivityOptions opts = makeCustomAnimation(context, enterResId, exitResId, handler,
startedListener, finishedListener);
opts.mOverrideTaskTransition = true;
return opts;
}
/** /**
* Creates an ActivityOptions specifying a custom animation to run in place on an existing * Creates an ActivityOptions specifying a custom animation to run in place on an existing
* activity. * activity.
@@ -1107,6 +1146,7 @@ public class ActivityOptions {
mLaunchCookie = opts.getBinder(KEY_LAUNCH_COOKIE); mLaunchCookie = opts.getBinder(KEY_LAUNCH_COOKIE);
mRemoteTransition = IRemoteTransition.Stub.asInterface(opts.getBinder( mRemoteTransition = IRemoteTransition.Stub.asInterface(opts.getBinder(
KEY_REMOTE_TRANSITION)); KEY_REMOTE_TRANSITION));
mOverrideTaskTransition = opts.getBoolean(KEY_OVERRIDE_TASK_TRANSITION);
} }
/** /**
@@ -1561,6 +1601,12 @@ public class ActivityOptions {
return mLaunchCookie; return mLaunchCookie;
} }
/** @hide */
public boolean getOverrideTaskTransition() {
return mOverrideTaskTransition;
}
/** /**
* Update the current values in this ActivityOptions from those supplied * Update the current values in this ActivityOptions from those supplied
* in <var>otherOptions</var>. Any values * in <var>otherOptions</var>. Any values
@@ -1789,6 +1835,9 @@ public class ActivityOptions {
if (mRemoteTransition != null) { if (mRemoteTransition != null) {
b.putBinder(KEY_REMOTE_TRANSITION, mRemoteTransition.asBinder()); b.putBinder(KEY_REMOTE_TRANSITION, mRemoteTransition.asBinder());
} }
if (mOverrideTaskTransition) {
b.putBoolean(KEY_OVERRIDE_TASK_TRANSITION, mOverrideTaskTransition);
}
return b; return b;
} }

View File

@@ -2539,7 +2539,7 @@
<permission android:name="android.permission.REAL_GET_TASKS" <permission android:name="android.permission.REAL_GET_TASKS"
android:protectionLevel="signature|privileged" /> android:protectionLevel="signature|privileged" />
<!-- Allows an application to start a task from a ActivityManager#RecentTaskInfo. <!-- @TestApi Allows an application to start a task from a ActivityManager#RecentTaskInfo.
@hide --> @hide -->
<permission android:name="android.permission.START_TASKS_FROM_RECENTS" <permission android:name="android.permission.START_TASKS_FROM_RECENTS"
android:protectionLevel="signature|privileged|recents" /> android:protectionLevel="signature|privileged|recents" />

View File

@@ -72,9 +72,13 @@ public abstract class ActivityOptionsCompat {
return ActivityOptions.makeRemoteTransition(remoteTransition.getTransition()); return ActivityOptions.makeRemoteTransition(remoteTransition.getTransition());
} }
/**
* Returns ActivityOptions for overriding task transition animation.
*/
public static ActivityOptions makeCustomAnimation(Context context, int enterResId, public static ActivityOptions makeCustomAnimation(Context context, int enterResId,
int exitResId, final Runnable callback, final Handler callbackHandler) { int exitResId, final Runnable callback, final Handler callbackHandler) {
return ActivityOptions.makeCustomAnimation(context, enterResId, exitResId, callbackHandler, return ActivityOptions.makeCustomTaskAnimation(context, enterResId, exitResId,
callbackHandler,
new ActivityOptions.OnAnimationStartedListener() { new ActivityOptions.OnAnimationStartedListener() {
@Override @Override
public void onAnimationStarted() { public void onAnimationStarted() {

View File

@@ -975,7 +975,8 @@ class ActivityClientController extends IActivityClientController.Stub {
final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
if (r != null && r.isState(Task.ActivityState.RESUMED, Task.ActivityState.PAUSING)) { if (r != null && r.isState(Task.ActivityState.RESUMED, Task.ActivityState.PAUSING)) {
r.mDisplayContent.mAppTransition.overridePendingAppTransition( r.mDisplayContent.mAppTransition.overridePendingAppTransition(
packageName, enterAnim, exitAnim, null, null); packageName, enterAnim, exitAnim, null, null,
r.mOverrideTaskTransition);
} }
} }
Binder.restoreCallingIdentity(origId); Binder.restoreCallingIdentity(origId);

View File

@@ -682,6 +682,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
boolean mRequestForceTransition; boolean mRequestForceTransition;
boolean mEnteringAnimation; boolean mEnteringAnimation;
boolean mOverrideTaskTransition;
boolean mAppStopped; boolean mAppStopped;
// A hint to override the window specified rotation animation, or -1 to use the window specified // A hint to override the window specified rotation animation, or -1 to use the window specified
@@ -1627,6 +1628,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (rotationAnimation >= 0) { if (rotationAnimation >= 0) {
mRotationAnimationHint = rotationAnimation; mRotationAnimationHint = rotationAnimation;
} }
mOverrideTaskTransition = options.getOverrideTaskTransition();
} }
ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService( ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
@@ -3997,7 +4000,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
pendingOptions.getCustomEnterResId(), pendingOptions.getCustomEnterResId(),
pendingOptions.getCustomExitResId(), pendingOptions.getCustomExitResId(),
pendingOptions.getAnimationStartedListener(), pendingOptions.getAnimationStartedListener(),
pendingOptions.getAnimationFinishedListener()); pendingOptions.getAnimationFinishedListener(),
pendingOptions.getOverrideTaskTransition());
break; break;
case ANIM_CLIP_REVEAL: case ANIM_CLIP_REVEAL:
displayContent.mAppTransition.overridePendingAppTransitionClipReveal( displayContent.mAppTransition.overridePendingAppTransitionClipReveal(

View File

@@ -266,6 +266,7 @@ public class AppTransition implements Dump {
private final boolean mLowRamRecentsEnabled; private final boolean mLowRamRecentsEnabled;
private final int mDefaultWindowAnimationStyleResId; private final int mDefaultWindowAnimationStyleResId;
private boolean mOverrideTaskTransition;
private RemoteAnimationController mRemoteAnimationController; private RemoteAnimationController mRemoteAnimationController;
@@ -971,7 +972,8 @@ public class AppTransition implements Dump {
@Nullable Rect surfaceInsets, @Nullable Rect stableInsets, boolean isVoiceInteraction, @Nullable Rect surfaceInsets, @Nullable Rect stableInsets, boolean isVoiceInteraction,
boolean freeform, WindowContainer container) { boolean freeform, WindowContainer container) {
if (mNextAppTransitionOverrideRequested && container.canCustomizeAppTransition()) { if (mNextAppTransitionOverrideRequested
&& (container.canCustomizeAppTransition() || mOverrideTaskTransition)) {
mNextAppTransitionType = NEXT_TRANSIT_TYPE_CUSTOM; mNextAppTransitionType = NEXT_TRANSIT_TYPE_CUSTOM;
} }
@@ -1175,7 +1177,8 @@ public class AppTransition implements Dump {
} }
void overridePendingAppTransition(String packageName, int enterAnim, int exitAnim, void overridePendingAppTransition(String packageName, int enterAnim, int exitAnim,
IRemoteCallback startedCallback, IRemoteCallback endedCallback) { IRemoteCallback startedCallback, IRemoteCallback endedCallback,
boolean overrideTaskTransaction) {
if (canOverridePendingAppTransition()) { if (canOverridePendingAppTransition()) {
clear(); clear();
mNextAppTransitionOverrideRequested = true; mNextAppTransitionOverrideRequested = true;
@@ -1185,6 +1188,7 @@ public class AppTransition implements Dump {
postAnimationCallback(); postAnimationCallback();
mNextAppTransitionCallback = startedCallback; mNextAppTransitionCallback = startedCallback;
mAnimationFinishedCallback = endedCallback; mAnimationFinishedCallback = endedCallback;
mOverrideTaskTransition = overrideTaskTransaction;
} }
} }

View File

@@ -709,6 +709,13 @@ public class AppTransitionController {
applyAnimations(closingWcs, closingApps, transit, false /* visible */, animLp, applyAnimations(closingWcs, closingApps, transit, false /* visible */, animLp,
voiceInteraction); voiceInteraction);
for (int i = 0; i < openingApps.size(); ++i) {
openingApps.valueAtUnchecked(i).mOverrideTaskTransition = false;
}
for (int i = 0; i < closingApps.size(); ++i) {
closingApps.valueAtUnchecked(i).mOverrideTaskTransition = false;
}
final AccessibilityController accessibilityController = final AccessibilityController accessibilityController =
mDisplayContent.mWmService.mAccessibilityController; mDisplayContent.mWmService.mAccessibilityController;
if (accessibilityController != null) { if (accessibilityController != null) {

View File

@@ -253,6 +253,20 @@ public class SafeActivityOptions {
throw new SecurityException(msg); throw new SecurityException(msg);
} }
// Check if the caller is allowed to override any app transition animation.
final boolean overrideTaskTransition = options.getOverrideTaskTransition();
if (aInfo != null && overrideTaskTransition) {
final int startTasksFromRecentsPerm = ActivityTaskManagerService.checkPermission(
START_TASKS_FROM_RECENTS, callingPid, callingUid);
if (startTasksFromRecentsPerm != PERMISSION_GRANTED) {
final String msg = "Permission Denial: starting " + getIntentString(intent)
+ " from " + callerApp + " (pid=" + callingPid
+ ", uid=" + callingUid + ") with overrideTaskTransition=true";
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
}
// Check permission for remote animations // Check permission for remote animations
final RemoteAnimationAdapter adapter = options.getRemoteAnimationAdapter(); final RemoteAnimationAdapter adapter = options.getRemoteAnimationAdapter();
if (adapter != null && supervisor.mService.checkPermission( if (adapter != null && supervisor.mService.checkPermission(