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:
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 + "}";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */);
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user