Send ActivityOptions to client

This removes getActivityOptions from server side. So 2 binder
transactions from Activity#performCreate and performStart can
be eliminated.

The remote animation in ActivityOptions is also separated to
another field of ActivityRecord, so when consuming the options,
the remote animation won't be affected.

Bug: 65202329
Bug: 132432864
Bug: 175409544
Test: WmTests:ActivityRecordTests#testTakeOptions
      ObjectPoolTests#testRecycleStartActivityItem
      CtsTransitionTestCases:ActivityTransitionTest
      CtsUsageStatsTestCases:ActivityTransitionTest

Change-Id: I600a9a478a3e596e58b0a8120cfa8b9f32598b47
This commit is contained in:
Riddle Hsu
2020-12-17 17:05:46 +08:00
parent fc01550355
commit e4b3ff67a6
22 changed files with 198 additions and 143 deletions

View File

@@ -890,6 +890,9 @@ public class Activity extends ContextThemeWrapper
@UnsupportedAppUsage
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
/** The options for scene transition. */
ActivityOptions mPendingOptions;
private static final class ManagedCursor {
ManagedCursor(Cursor cursor) {
mCursor = cursor;
@@ -7258,7 +7261,7 @@ public class Activity extends ContextThemeWrapper
}
/**
* Retrieve the ActivityOptions passed in from the launching activity or passed back
* Takes the ActivityOptions passed in from the launching activity or passed back
* from an activity launched by this activity in its call to {@link
* #convertToTranslucent(TranslucentConversionListener, ActivityOptions)}
*
@@ -7267,7 +7270,10 @@ public class Activity extends ContextThemeWrapper
*/
@UnsupportedAppUsage
ActivityOptions getActivityOptions() {
return ActivityOptions.fromBundle(ActivityClient.getInstance().getActivityOptions(mToken));
final ActivityOptions options = mPendingOptions;
// The option only applies once.
mPendingOptions = null;
return options;
}
/**

View File

@@ -237,14 +237,6 @@ public class ActivityClient {
}
}
Bundle getActivityOptions(IBinder token) {
try {
return getActivityClientController().getActivityOptions(token);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
public void setRequestedOrientation(IBinder token, int requestedOrientation) {
try {
getActivityClientController().setRequestedOrientation(token, requestedOrientation);

View File

@@ -567,6 +567,9 @@ public final class ActivityThread extends ClientTransactionHandler {
@UnsupportedAppUsage
boolean mPreserveWindow;
/** The options for scene transition. */
ActivityOptions mActivityOptions;
/**
* If non-null, the activity is launching with a specified rotation, the adjustments should
* be consumed before activity creation.
@@ -587,8 +590,8 @@ public final class ActivityThread extends ClientTransactionHandler {
ActivityInfo info, Configuration overrideConfig, CompatibilityInfo compatInfo,
String referrer, IVoiceInteractor voiceInteractor, Bundle state,
PersistableBundle persistentState, List<ResultInfo> pendingResults,
List<ReferrerIntent> pendingNewIntents, boolean isForward,
ProfilerInfo profilerInfo, ClientTransactionHandler client,
List<ReferrerIntent> pendingNewIntents, ActivityOptions activityOptions,
boolean isForward, ProfilerInfo profilerInfo, ClientTransactionHandler client,
IBinder assistToken, FixedRotationAdjustments fixedRotationAdjustments) {
this.token = token;
this.assistToken = assistToken;
@@ -607,6 +610,7 @@ public final class ActivityThread extends ClientTransactionHandler {
this.overrideConfig = overrideConfig;
this.packageInfo = client.getPackageInfoNoCheck(activityInfo.applicationInfo,
compatInfo);
mActivityOptions = activityOptions;
mPendingFixedRotationAdjustments = fixedRotationAdjustments;
init();
}
@@ -3469,6 +3473,10 @@ public final class ActivityThread extends ClientTransactionHandler {
activity.setTheme(theme);
}
if (r.mActivityOptions != null) {
activity.mPendingOptions = r.mActivityOptions;
r.mActivityOptions = null;
}
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
@@ -3509,7 +3517,7 @@ public final class ActivityThread extends ClientTransactionHandler {
@Override
public void handleStartActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions) {
PendingTransactionActions pendingActions, ActivityOptions activityOptions) {
final Activity activity = r.activity;
if (!r.stopped) {
throw new IllegalStateException("Can't start activity that is not stopped.");
@@ -3520,6 +3528,9 @@ public final class ActivityThread extends ClientTransactionHandler {
}
unscheduleGcIdler();
if (activityOptions != null) {
activity.mPendingOptions = activityOptions;
}
// Start
activity.performStart("handleStartActivity");

View File

@@ -164,7 +164,7 @@ public abstract class ClientTransactionHandler {
/** Perform activity start. */
public abstract void handleStartActivity(@NonNull ActivityClientRecord r,
PendingTransactionActions pendingActions);
PendingTransactionActions pendingActions, ActivityOptions activityOptions);
/** Get package info. */
public abstract LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,

View File

@@ -60,7 +60,6 @@ interface IActivityClientController {
String getCallingPackage(in IBinder token);
int getLaunchedFromUid(in IBinder token);
String getLaunchedFromPackage(in IBinder token);
Bundle getActivityOptions(in IBinder token);
void setRequestedOrientation(in IBinder token, int requestedOrientation);
int getRequestedOrientation(in IBinder token);

View File

@@ -178,7 +178,8 @@ public class LocalActivityManager {
pendingActions = null;
}
mActivityThread.handleStartActivity(clientRecord, pendingActions);
mActivityThread.handleStartActivity(clientRecord, pendingActions,
null /* activityOptions */);
r.curState = STARTED;
if (desiredState == RESUMED) {

View File

@@ -21,6 +21,7 @@ import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityClient;
import android.app.ActivityOptions;
import android.app.ActivityThread.ActivityClientRecord;
import android.app.ClientTransactionHandler;
import android.app.IActivityClientController;
@@ -66,6 +67,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
private PersistableBundle mPersistentState;
private List<ResultInfo> mPendingResults;
private List<ReferrerIntent> mPendingNewIntents;
private ActivityOptions mActivityOptions;
private boolean mIsForward;
private ProfilerInfo mProfilerInfo;
private IBinder mAssistToken;
@@ -92,8 +94,8 @@ public class LaunchActivityItem extends ClientTransactionItem {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
mPendingResults, mPendingNewIntents, mIsForward,
mProfilerInfo, client, mAssistToken, mFixedRotationAdjustments);
mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,
client, mAssistToken, mFixedRotationAdjustments);
client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
@@ -114,8 +116,9 @@ public class LaunchActivityItem extends ClientTransactionItem {
Configuration curConfig, Configuration overrideConfig, CompatibilityInfo compatInfo,
String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state,
PersistableBundle persistentState, List<ResultInfo> pendingResults,
List<ReferrerIntent> pendingNewIntents, boolean isForward, ProfilerInfo profilerInfo,
IBinder assistToken, IActivityClientController activityClientController,
List<ReferrerIntent> pendingNewIntents, ActivityOptions activityOptions,
boolean isForward, ProfilerInfo profilerInfo, IBinder assistToken,
IActivityClientController activityClientController,
FixedRotationAdjustments fixedRotationAdjustments) {
LaunchActivityItem instance = ObjectPool.obtain(LaunchActivityItem.class);
if (instance == null) {
@@ -123,8 +126,8 @@ public class LaunchActivityItem extends ClientTransactionItem {
}
setValues(instance, intent, ident, info, curConfig, overrideConfig, compatInfo, referrer,
voiceInteractor, procState, state, persistentState, pendingResults,
pendingNewIntents, isForward, profilerInfo, assistToken, activityClientController,
fixedRotationAdjustments);
pendingNewIntents, activityOptions, isForward, profilerInfo, assistToken,
activityClientController, fixedRotationAdjustments);
return instance;
}
@@ -132,7 +135,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
@Override
public void recycle() {
setValues(this, null, 0, null, null, null, null, null, null, 0, null, null, null, null,
false, null, null, null, null);
null, false, null, null, null, null);
ObjectPool.recycle(this);
}
@@ -155,6 +158,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
dest.writePersistableBundle(mPersistentState);
dest.writeTypedList(mPendingResults, flags);
dest.writeTypedList(mPendingNewIntents, flags);
dest.writeBundle(mActivityOptions != null ? mActivityOptions.toBundle() : null);
dest.writeBoolean(mIsForward);
dest.writeTypedObject(mProfilerInfo, flags);
dest.writeStrongBinder(mAssistToken);
@@ -172,7 +176,8 @@ public class LaunchActivityItem extends ClientTransactionItem {
in.readBundle(getClass().getClassLoader()),
in.readPersistableBundle(getClass().getClassLoader()),
in.createTypedArrayList(ResultInfo.CREATOR),
in.createTypedArrayList(ReferrerIntent.CREATOR), in.readBoolean(),
in.createTypedArrayList(ReferrerIntent.CREATOR),
ActivityOptions.fromBundle(in.readBundle()), in.readBoolean(),
in.readTypedObject(ProfilerInfo.CREATOR),
in.readStrongBinder(),
IActivityClientController.Stub.asInterface(in.readStrongBinder()),
@@ -210,6 +215,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
&& areBundlesEqualRoughly(mPersistentState, other.mPersistentState)
&& Objects.equals(mPendingResults, other.mPendingResults)
&& Objects.equals(mPendingNewIntents, other.mPendingNewIntents)
&& (mActivityOptions == null) == (other.mActivityOptions == null)
&& mIsForward == other.mIsForward
&& Objects.equals(mProfilerInfo, other.mProfilerInfo)
&& Objects.equals(mAssistToken, other.mAssistToken)
@@ -230,6 +236,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
result = 31 * result + getRoughBundleHashCode(mPersistentState);
result = 31 * result + Objects.hashCode(mPendingResults);
result = 31 * result + Objects.hashCode(mPendingNewIntents);
result = 31 * result + (mActivityOptions != null ? 1 : 0);
result = 31 * result + (mIsForward ? 1 : 0);
result = 31 * result + Objects.hashCode(mProfilerInfo);
result = 31 * result + Objects.hashCode(mAssistToken);
@@ -268,9 +275,9 @@ public class LaunchActivityItem extends ClientTransactionItem {
+ ",curConfig=" + mCurConfig + ",overrideConfig=" + mOverrideConfig
+ ",referrer=" + mReferrer + ",procState=" + mProcState + ",state=" + mState
+ ",persistentState=" + mPersistentState + ",pendingResults=" + mPendingResults
+ ",pendingNewIntents=" + mPendingNewIntents + ",profilerInfo=" + mProfilerInfo
+ ",assistToken=" + mAssistToken + ",rotationAdj=" + mFixedRotationAdjustments
+ "}";
+ ",pendingNewIntents=" + mPendingNewIntents + ",options=" + mActivityOptions
+ ",profilerInfo=" + mProfilerInfo + ",assistToken=" + mAssistToken
+ ",rotationAdj=" + mFixedRotationAdjustments + "}";
}
// Using the same method to set and clear values to make sure we don't forget anything
@@ -279,8 +286,8 @@ public class LaunchActivityItem extends ClientTransactionItem {
CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
int procState, Bundle state, PersistableBundle persistentState,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
boolean isForward, ProfilerInfo profilerInfo, IBinder assistToken,
IActivityClientController activityClientController,
ActivityOptions activityOptions, boolean isForward, ProfilerInfo profilerInfo,
IBinder assistToken, IActivityClientController activityClientController,
FixedRotationAdjustments fixedRotationAdjustments) {
instance.mIntent = intent;
instance.mIdent = ident;
@@ -295,6 +302,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
instance.mPersistentState = persistentState;
instance.mPendingResults = pendingResults;
instance.mPendingNewIntents = pendingNewIntents;
instance.mActivityOptions = activityOptions;
instance.mIsForward = isForward;
instance.mProfilerInfo = profilerInfo;
instance.mAssistToken = assistToken;

View File

@@ -20,6 +20,7 @@ import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityOptions;
import android.app.ActivityThread.ActivityClientRecord;
import android.app.ClientTransactionHandler;
import android.os.Parcel;
@@ -33,11 +34,13 @@ public class StartActivityItem extends ActivityLifecycleItem {
private static final String TAG = "StartActivityItem";
private ActivityOptions mActivityOptions;
@Override
public void execute(ClientTransactionHandler client, ActivityClientRecord r,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "startActivityItem");
client.handleStartActivity(r, pendingActions);
client.handleStartActivity(r, pendingActions, mActivityOptions);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
@@ -52,11 +55,12 @@ public class StartActivityItem extends ActivityLifecycleItem {
private StartActivityItem() {}
/** Obtain an instance initialized with provided params. */
public static StartActivityItem obtain() {
public static StartActivityItem obtain(ActivityOptions activityOptions) {
StartActivityItem instance = ObjectPool.obtain(StartActivityItem.class);
if (instance == null) {
instance = new StartActivityItem();
}
instance.mActivityOptions = activityOptions;
return instance;
}
@@ -64,6 +68,7 @@ public class StartActivityItem extends ActivityLifecycleItem {
@Override
public void recycle() {
super.recycle();
mActivityOptions = null;
ObjectPool.recycle(this);
}
@@ -73,12 +78,12 @@ public class StartActivityItem extends ActivityLifecycleItem {
/** Write to Parcel. */
@Override
public void writeToParcel(Parcel dest, int flags) {
// Empty
dest.writeBundle(mActivityOptions != null ? mActivityOptions.toBundle() : null);
}
/** Read from Parcel. */
private StartActivityItem(Parcel in) {
// Empty
mActivityOptions = ActivityOptions.fromBundle(in.readBundle());
}
public static final @NonNull Creator<StartActivityItem> CREATOR =
@@ -100,17 +105,20 @@ public class StartActivityItem extends ActivityLifecycleItem {
if (o == null || getClass() != o.getClass()) {
return false;
}
return true;
final StartActivityItem other = (StartActivityItem) o;
return (mActivityOptions == null) == (other.mActivityOptions == null);
}
@Override
public int hashCode() {
return 17;
int result = 17;
result = 31 * result + (mActivityOptions != null ? 1 : 0);
return result;
}
@Override
public String toString() {
return "StartActivityItem{}";
return "StartActivityItem{options=" + mActivityOptions + "}";
}
}

View File

@@ -218,7 +218,8 @@ public class TransactionExecutor {
null /* customIntent */);
break;
case ON_START:
mTransactionHandler.handleStartActivity(r, mPendingActions);
mTransactionHandler.handleStartActivity(r, mPendingActions,
null /* activityOptions */);
break;
case ON_RESUME:
mTransactionHandler.handleResumeActivity(r, false /* finalStateRequest */,

View File

@@ -186,7 +186,7 @@ public class TransactionExecutorHelper {
switch (prevState) {
// TODO(lifecycler): Extend to support all possible states.
case ON_START:
lifecycleItem = StartActivityItem.obtain();
lifecycleItem = StartActivityItem.obtain(null /* activityOptions */);
break;
case ON_PAUSE:
lifecycleItem = PauseActivityItem.obtain();

View File

@@ -23,9 +23,11 @@ import static android.app.servertransaction.TestUtils.resultInfoList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import android.app.ActivityOptions;
import android.app.servertransaction.TestUtils.LaunchActivityItemBuilder;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -246,6 +248,22 @@ public class ObjectPoolTests {
assertFalse(item2.equals(emptyItem));
}
@Test
public void testRecycleStartActivityItem() {
StartActivityItem emptyItem = StartActivityItem.obtain(null /* activityOptions */);
StartActivityItem item = StartActivityItem.obtain(ActivityOptions.makeBasic());
assertNotSame(item, emptyItem);
assertNotEquals(item, emptyItem);
item.recycle();
assertEquals(item, emptyItem);
StartActivityItem item2 = StartActivityItem.obtain(
ActivityOptions.makeBasic().setLaunchDisplayId(10));
assertSame(item, item2);
assertNotEquals(item2, emptyItem);
}
@Test
public void testRecycleStopItem() {
StopActivityItem emptyItem = StopActivityItem.obtain(0);

View File

@@ -18,6 +18,7 @@ package android.app.servertransaction;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import android.app.ActivityOptions;
import android.app.ProfilerInfo;
import android.app.ResultInfo;
import android.content.Intent;
@@ -104,6 +105,7 @@ class TestUtils {
private PersistableBundle mPersistentState;
private List<ResultInfo> mPendingResults;
private List<ReferrerIntent> mPendingNewIntents;
private ActivityOptions mActivityOptions;
private boolean mIsForward;
private ProfilerInfo mProfilerInfo;
private IBinder mAssistToken;
@@ -174,6 +176,11 @@ class TestUtils {
return this;
}
LaunchActivityItemBuilder setActivityOptions(ActivityOptions activityOptions) {
mActivityOptions = activityOptions;
return this;
}
LaunchActivityItemBuilder setIsForward(boolean isForward) {
mIsForward = isForward;
return this;
@@ -198,8 +205,8 @@ class TestUtils {
return LaunchActivityItem.obtain(mIntent, mIdent, mInfo,
mCurConfig, mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor,
mProcState, mState, mPersistentState, mPendingResults, mPendingNewIntents,
mIsForward, mProfilerInfo, mAssistToken, null /* activityClientController */,
mFixedRotationAdjustments);
mActivityOptions, mIsForward, mProfilerInfo, mAssistToken,
null /* activityClientController */, mFixedRotationAdjustments);
}
}
}

View File

@@ -24,6 +24,7 @@ import static android.app.servertransaction.TestUtils.resultInfoList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import android.app.ActivityOptions;
import android.app.ContentProviderHolder;
import android.app.IApplicationThread;
import android.app.IInstrumentationWatcher;
@@ -200,9 +201,10 @@ public class TransactionParcelTests {
.setIntent(intent).setIdent(ident).setInfo(activityInfo).setCurConfig(config())
.setOverrideConfig(overrideConfig).setCompatInfo(compat).setReferrer(referrer)
.setProcState(procState).setState(bundle).setPersistentState(persistableBundle)
.setPendingResults(resultInfoList()).setPendingNewIntents(referrerIntentList())
.setIsForward(true).setAssistToken(new Binder())
.setFixedRotationAdjustments(fixedRotationAdjustments).build();
.setPendingResults(resultInfoList()).setActivityOptions(ActivityOptions.makeBasic())
.setPendingNewIntents(referrerIntentList()).setIsForward(true)
.setAssistToken(new Binder()).setFixedRotationAdjustments(fixedRotationAdjustments)
.build();
writeAndPrepareForReading(item);
@@ -273,7 +275,7 @@ public class TransactionParcelTests {
@Test
public void testStart() {
// Write to parcel
StartActivityItem item = StartActivityItem.obtain();
StartActivityItem item = StartActivityItem.obtain(ActivityOptions.makeBasic());
writeAndPrepareForReading(item);
// Read from parcel and assert

View File

@@ -242,7 +242,7 @@ public class ActivityThreadClientTest {
}
private void startActivity(ActivityClientRecord r) {
mThread.handleStartActivity(r, null /* pendingActions */);
mThread.handleStartActivity(r, null /* pendingActions */, null /* activityOptions */);
}
private void resumeActivity(ActivityClientRecord r) {
@@ -295,8 +295,9 @@ public class ActivityThreadClientTest {
0 /* ident */, info, new Configuration(),
CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null /* referrer */,
null /* voiceInteractor */, null /* state */, null /* persistentState */,
null /* pendingResults */, null /* pendingNewIntents */, true /* isForward */,
null /* profilerInfo */, mThread /* client */, null /* asssitToken */,
null /* pendingResults */, null /* pendingNewIntents */,
null /* activityOptions */, true /* isForward */, null /* profilerInfo */,
mThread /* client */, null /* asssitToken */,
null /* fixedRotationAdjustments */);
}

View File

@@ -42,7 +42,6 @@ import static com.android.server.wm.Task.ActivityState.DESTROYING;
import android.annotation.NonNull;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
import android.app.IActivityClientController;
import android.app.PictureInPictureParams;
@@ -556,23 +555,6 @@ class ActivityClientController extends IActivityClientController.Stub {
}
}
@Override
public Bundle getActivityOptions(IBinder token) {
final long origId = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
if (r == null) {
return null;
}
final ActivityOptions activityOptions = r.takeOptionsLocked(true /* fromClient */);
return activityOptions != null ? activityOptions.toBundle() : null;
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
@Override
public void setRequestedOrientation(IBinder token, int requestedOrientation) {
final long origId = Binder.clearCallingIdentity();

View File

@@ -284,6 +284,7 @@ import android.view.DisplayInfo;
import android.view.IAppTransitionAnimationSpecsFuture;
import android.view.IApplicationToken;
import android.view.InputApplicationHandle;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationDefinition;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
@@ -462,7 +463,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act
ArrayList<ReferrerIntent> newIntents; // any pending new intents for single-top mode
Intent mLastNewIntent; // the last new intent we delivered to client
ActivityOptions pendingOptions; // most recently given options
/** The most recently given options. */
private ActivityOptions mPendingOptions;
/** Non-null if {@link #mPendingOptions} specifies the remote animation. */
private RemoteAnimationAdapter mPendingRemoteAnimation;
ActivityOptions returningOptions; // options that are coming back via convertToTranslucent
AppTimeTracker appTimeTracker; // set if we are tracking the time in this app/task/activity
ActivityServiceConnectionsHolder mServiceConnectionsHolder; // Service connections.
@@ -882,8 +886,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
}
}
if (pendingOptions != null) {
pw.print(prefix); pw.print("pendingOptions="); pw.println(pendingOptions);
if (mPendingOptions != null) {
pw.print(prefix); pw.print("pendingOptions="); pw.println(mPendingOptions);
}
if (mPendingRemoteAnimation != null) {
pw.print(prefix);
pw.print("pendingRemoteAnimationCallingPid=");
pw.println(mPendingRemoteAnimation.getCallingPid());
}
if (appTimeTracker != null) {
appTimeTracker.dumpWithHeader(pw, prefix, false);
@@ -1633,8 +1642,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
lockTaskLaunchMode = getLockTaskLaunchMode(aInfo, options);
if (options != null) {
pendingOptions = options;
final PendingIntent usageReport = pendingOptions.getUsageTimeReport();
setOptions(options);
final PendingIntent usageReport = options.getUsageTimeReport();
if (usageReport != null) {
appTimeTracker = new AppTimeTracker(usageReport);
}
@@ -2206,7 +2215,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (task != null && !finishing) {
task = null;
}
clearOptionsLocked();
abortAndClearOptionsAnimation();
}
}
@@ -2993,7 +3002,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
finishing = true;
if (stopped) {
clearOptionsLocked();
abortAndClearOptionsAnimation();
}
mAtmService.getTransitionController().requestTransitionIfNeeded(TRANSIT_CLOSE, this);
}
@@ -3861,33 +3870,47 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
void updateOptionsLocked(ActivityOptions options) {
if (options != null) {
if (DEBUG_TRANSITION) Slog.i(TAG, "Update options for " + this);
if (pendingOptions != null) {
pendingOptions.abort();
if (mPendingOptions != null) {
mPendingOptions.abort();
}
pendingOptions = options;
setOptions(options);
}
}
void applyOptionsLocked() {
if (pendingOptions != null
&& pendingOptions.getAnimationType() != ANIM_SCENE_TRANSITION) {
if (DEBUG_TRANSITION) Slog.i(TAG, "Applying options for " + this);
applyOptionsLocked(pendingOptions, intent);
if (task == null) {
clearOptionsLocked(false /* withAbort */);
} else {
// This will clear the options for all the ActivityRecords for this Task.
task.forAllActivities((r) -> {
r.clearOptionsLocked(false /* withAbort */);
});
private void setOptions(@NonNull ActivityOptions options) {
mPendingOptions = options;
if (options.getAnimationType() == ANIM_REMOTE_ANIMATION) {
mPendingRemoteAnimation = options.getRemoteAnimationAdapter();
}
}
void applyOptionsAnimation() {
if (DEBUG_TRANSITION) Slog.i(TAG, "Applying options for " + this);
if (mPendingRemoteAnimation != null) {
mDisplayContent.mAppTransition.overridePendingAppTransitionRemote(
mPendingRemoteAnimation);
} else {
if (mPendingOptions == null
|| mPendingOptions.getAnimationType() == ANIM_SCENE_TRANSITION) {
// Scene transition will run on the client side.
return;
}
applyOptionsAnimation(mPendingOptions, intent);
}
if (task == null) {
clearOptionsAnimation();
} else {
// This will clear the options for all the ActivityRecords for this Task.
task.forAllActivities((r) -> {
r.clearOptionsAnimation();
});
}
}
/**
* Apply override app transition base on options & animation type.
*/
void applyOptionsLocked(ActivityOptions pendingOptions, Intent intent) {
private void applyOptionsAnimation(ActivityOptions pendingOptions, Intent intent) {
final int animationType = pendingOptions.getAnimationType();
final DisplayContent displayContent = getDisplayContent();
switch (animationType) {
@@ -3969,10 +3992,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
displayContent.mAppTransition
.overridePendingAppTransitionStartCrossProfileApps();
break;
case ANIM_REMOTE_ANIMATION:
displayContent.mAppTransition.overridePendingAppTransitionRemote(
pendingOptions.getRemoteAnimationAdapter());
break;
case ANIM_NONE:
case ANIM_UNDEFINED:
break;
@@ -4033,35 +4052,32 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
}
void clearOptionsLocked() {
clearOptionsLocked(true /* withAbort */);
}
void clearOptionsLocked(boolean withAbort) {
if (withAbort && pendingOptions != null) {
pendingOptions.abort();
void abortAndClearOptionsAnimation() {
if (mPendingOptions != null) {
mPendingOptions.abort();
}
pendingOptions = null;
clearOptionsAnimation();
}
ActivityOptions takeOptionsLocked(boolean fromClient) {
void clearOptionsAnimation() {
mPendingOptions = null;
mPendingRemoteAnimation = null;
}
ActivityOptions getOptions() {
return mPendingOptions;
}
ActivityOptions takeOptions() {
if (DEBUG_TRANSITION) Slog.i(TAG, "Taking options for " + this + " callers="
+ Debug.getCallers(6));
ActivityOptions opts = pendingOptions;
// If we are trying to take activity options from the client, do not null it out if it's a
// remote animation as the client doesn't need it ever. This is a workaround when client is
// faster to take the options than we are to resume the next activity.
// TODO (b/132432864): Fix the root cause of these transition preparing/applying options
// timing somehow
if (!fromClient || opts == null || opts.getRemoteAnimationAdapter() == null) {
pendingOptions = null;
}
final ActivityOptions opts = mPendingOptions;
mPendingOptions = null;
return opts;
}
boolean allowMoveToFront() {
return pendingOptions == null || !pendingOptions.getAvoidMoveToFront();
return mPendingOptions == null || !mPendingOptions.getAvoidMoveToFront();
}
void removeUriPermissionsLocked() {
@@ -4883,7 +4899,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
try {
mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
StartActivityItem.obtain());
StartActivityItem.obtain(takeOptions()));
} catch (Exception e) {
Slog.w(TAG, "Exception thrown sending start: " + intent.getComponent(), e);
}
@@ -5204,7 +5220,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
notifyAppStopped();
if (finishing) {
clearOptionsLocked();
abortAndClearOptionsAnimation();
} else {
if (deferRelaunchUntilPaused) {
destroyImmediately("stop-config");
@@ -5838,8 +5854,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// We don't show starting window for overlay activities.
return;
}
if (pendingOptions != null
&& pendingOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {
if (mPendingOptions != null
&& mPendingOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {
// Don't show starting window when using shared element transition.
return;
}

View File

@@ -528,7 +528,7 @@ public class ActivityStartController {
"pendingActivityLaunch");
try {
starter.startResolvedActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags,
resume, pal.r.pendingOptions, null, pal.intentGrants);
resume, pal.r.getOptions(), null, pal.intentGrants);
} catch (Exception e) {
Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
pal.sendErrorResult(e.getMessage());

View File

@@ -1258,7 +1258,7 @@ class ActivityStarter {
}
// We pretend to the caller that it was really started to make it backward compatible, but
// they will just get a cancel result.
ActivityOptions.abort(r.pendingOptions);
ActivityOptions.abort(r.getOptions());
return true;
}

View File

@@ -868,8 +868,8 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
r.getSavedState(), r.getPersistentSavedState(), results, newIntents,
dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),
r.assistToken, activityClientController,
r.takeOptions(), dc.isNextTransitionForward(),
proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,
r.createFixedRotationAdjustmentsIfNeeded()));
// Set desired final state.
@@ -2566,9 +2566,10 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
try {
mService.moveTaskToFrontLocked(null /* appThread */, null /* callingPackage */,
task.mTaskId, 0, options);
// Apply options to prevent pendingOptions be taken by client to make sure
// the override pending app transition will be applied immediately.
targetActivity.applyOptionsLocked();
// Apply options to prevent pendingOptions be taken when scheduling activity
// lifecycle transaction to make sure the override pending app transition will
// be applied immediately.
targetActivity.applyOptionsAnimation();
} finally {
mActivityMetricsLogger.notifyActivityLaunched(launchingState,
START_TASK_TO_FRONT, targetActivity, activityOptions);

View File

@@ -267,8 +267,9 @@ class ResetTargetTaskHelper {
private boolean takeOption(ActivityRecord p, boolean noOptions) {
mCanMoveOptions = false;
if (noOptions && mTopOptions == null) {
mTopOptions = p.takeOptionsLocked(false /* fromClient */);
mTopOptions = p.getOptions();
if (mTopOptions != null) {
p.clearOptionsAnimation();
noOptions = false;
}
}

View File

@@ -1926,8 +1926,9 @@ class Task extends WindowContainer<WindowContainer> {
if (r == boundaryActivity) return true;
if (!r.finishing) {
final ActivityOptions opts = r.takeOptionsLocked(false /* fromClient */);
final ActivityOptions opts = r.getOptions();
if (opts != null) {
r.clearOptionsAnimation();
// TODO: Why is this updating the boundary activity vs. the current activity???
boundaryActivity.updateOptionsLocked(opts);
}
@@ -6247,9 +6248,9 @@ class Task extends WindowContainer<WindowContainer> {
}
if (anim) {
next.applyOptionsLocked();
next.applyOptionsAnimation();
} else {
next.clearOptionsLocked();
next.abortAndClearOptionsAnimation();
}
mTaskSupervisor.mNoAnimActivities.clear();
@@ -6356,7 +6357,7 @@ class Task extends WindowContainer<WindowContainer> {
mAtmService.getAppWarningsLocked().onResumeActivity(next);
next.app.setPendingUiCleanAndForceProcessStateUpTo(mAtmService.mTopProcessState);
next.clearOptionsLocked();
next.abortAndClearOptionsAnimation();
transaction.setLifecycleStateRequest(
ResumeActivityItem.obtain(next.app.getReportedProcState(),
dc.isNextTransitionForward()));

View File

@@ -254,26 +254,26 @@ public class ActivityRecordTests extends WindowTestsBase {
// Set and apply options for ActivityRecord. Pending options should be cleared
activity.updateOptionsLocked(activityOptions);
activity.applyOptionsLocked();
assertNull(activity.pendingOptions);
activity.applyOptionsAnimation();
assertNull(activity.getOptions());
// Set options for two ActivityRecords in same Task. Apply one ActivityRecord options.
// Pending options should be cleared for both ActivityRecords
ActivityRecord activity2 = new ActivityBuilder(mAtm).setTask(activity.getTask()).build();
activity2.updateOptionsLocked(activityOptions);
activity.updateOptionsLocked(activityOptions);
activity.applyOptionsLocked();
assertNull(activity.pendingOptions);
assertNull(activity2.pendingOptions);
activity.applyOptionsAnimation();
assertNull(activity.getOptions());
assertNull(activity2.getOptions());
// Set options for two ActivityRecords in separate Tasks. Apply one ActivityRecord options.
// Pending options should be cleared for only ActivityRecord that was applied
activity2 = new ActivityBuilder(mAtm).setCreateTask(true).build();
activity2.updateOptionsLocked(activityOptions);
activity.updateOptionsLocked(activityOptions);
activity.applyOptionsLocked();
assertNull(activity.pendingOptions);
assertNotNull(activity2.pendingOptions);
activity.applyOptionsAnimation();
assertNull(activity.getOptions());
assertNotNull(activity2.getOptions());
}
@Test
@@ -653,21 +653,21 @@ public class ActivityRecordTests extends WindowTestsBase {
public void onAnimationStart(RemoteAnimationTarget[] apps,
RemoteAnimationTarget[] wallpapers,
IRemoteAnimationFinishedCallback finishedCallback) {
}
@Override
public void onAnimationCancelled() {
}
}, 0, 0));
activity.updateOptionsLocked(opts);
assertNotNull(activity.takeOptionsLocked(true /* fromClient */));
assertNotNull(activity.pendingOptions);
assertNotNull(activity.takeOptions());
assertNull(activity.getOptions());
activity.updateOptionsLocked(ActivityOptions.makeBasic());
assertNotNull(activity.takeOptionsLocked(false /* fromClient */));
assertNull(activity.pendingOptions);
final AppTransition appTransition = activity.mDisplayContent.mAppTransition;
spyOn(appTransition);
activity.applyOptionsAnimation();
verify(appTransition).overridePendingAppTransitionRemote(any());
}
@Test