diff options
22 files changed, 197 insertions, 142 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 294a363bc52f..55df824b1243 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -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; } /** diff --git a/core/java/android/app/ActivityClient.java b/core/java/android/app/ActivityClient.java index 64d795c013c9..d465b220f854 100644 --- a/core/java/android/app/ActivityClient.java +++ b/core/java/android/app/ActivityClient.java @@ -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); diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 69482bc8615b..2fe1711bdbd4 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -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"); diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java index ac50676ff46b..0e1c827145d2 100644 --- a/core/java/android/app/ClientTransactionHandler.java +++ b/core/java/android/app/ClientTransactionHandler.java @@ -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, diff --git a/core/java/android/app/IActivityClientController.aidl b/core/java/android/app/IActivityClientController.aidl index e1e0a8a534a8..b9a203c3f0ba 100644 --- a/core/java/android/app/IActivityClientController.aidl +++ b/core/java/android/app/IActivityClientController.aidl @@ -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); diff --git a/core/java/android/app/LocalActivityManager.java b/core/java/android/app/LocalActivityManager.java index 2e7c9f11ac66..74e61250f109 100644 --- a/core/java/android/app/LocalActivityManager.java +++ b/core/java/android/app/LocalActivityManager.java @@ -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) { diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java index 3758cb49e2d0..73a9ceccecee 100644 --- a/core/java/android/app/servertransaction/LaunchActivityItem.java +++ b/core/java/android/app/servertransaction/LaunchActivityItem.java @@ -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; diff --git a/core/java/android/app/servertransaction/StartActivityItem.java b/core/java/android/app/servertransaction/StartActivityItem.java index 483f9de58a1c..15f65f6d9d26 100644 --- a/core/java/android/app/servertransaction/StartActivityItem.java +++ b/core/java/android/app/servertransaction/StartActivityItem.java @@ -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 + "}"; } } diff --git a/core/java/android/app/servertransaction/TransactionExecutor.java b/core/java/android/app/servertransaction/TransactionExecutor.java index 3dcf2cb5f13e..25ff8a78a0c8 100644 --- a/core/java/android/app/servertransaction/TransactionExecutor.java +++ b/core/java/android/app/servertransaction/TransactionExecutor.java @@ -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 */, diff --git a/core/java/android/app/servertransaction/TransactionExecutorHelper.java b/core/java/android/app/servertransaction/TransactionExecutorHelper.java index 56bf59b52f74..92f7dee0b0ad 100644 --- a/core/java/android/app/servertransaction/TransactionExecutorHelper.java +++ b/core/java/android/app/servertransaction/TransactionExecutorHelper.java @@ -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(); diff --git a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java index b2b34d64b12c..50b52eb2a0ea 100644 --- a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java @@ -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; @@ -247,6 +249,22 @@ public class ObjectPoolTests { } @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); StopActivityItem item = StopActivityItem.obtain(4); diff --git a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java index 7e9933c8d9df..02e75dd76a07 100644 --- a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java +++ b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java @@ -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); } } } diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java index e1c7146908d6..5705dd530c16 100644 --- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java @@ -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 diff --git a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java index a74f580b65e6..d2b20b4298d9 100644 --- a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java +++ b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java @@ -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 */); } diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java index a61e08aa1c81..e333f3814a61 100644 --- a/services/core/java/com/android/server/wm/ActivityClientController.java +++ b/services/core/java/com/android/server/wm/ActivityClientController.java @@ -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; @@ -557,23 +556,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(); try { diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index ef845c843c5f..16538962d910 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -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 abortAndClearOptionsAnimation() { + if (mPendingOptions != null) { + mPendingOptions.abort(); + } + clearOptionsAnimation(); } - void clearOptionsLocked(boolean withAbort) { - if (withAbort && pendingOptions != null) { - pendingOptions.abort(); - } - pendingOptions = null; + void clearOptionsAnimation() { + mPendingOptions = null; + mPendingRemoteAnimation = null; } - ActivityOptions takeOptionsLocked(boolean fromClient) { + 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; } diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java index f9e85cdd8d8a..2dd8c597450e 100644 --- a/services/core/java/com/android/server/wm/ActivityStartController.java +++ b/services/core/java/com/android/server/wm/ActivityStartController.java @@ -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()); diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index e30cd05c79a0..5289f8604f36 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -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; } diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java index 16f415fd9781..9d291b12c2c9 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java @@ -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); diff --git a/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java b/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java index 17cb8905f260..fc347bc609d1 100644 --- a/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java +++ b/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java @@ -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; } } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 2290c23be513..81cbd61d62d7 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -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())); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index b50e50b89683..39e3bffd3349 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -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()); + + final AppTransition appTransition = activity.mDisplayContent.mAppTransition; + spyOn(appTransition); + activity.applyOptionsAnimation(); - activity.updateOptionsLocked(ActivityOptions.makeBasic()); - assertNotNull(activity.takeOptionsLocked(false /* fromClient */)); - assertNull(activity.pendingOptions); + verify(appTransition).overridePendingAppTransitionRemote(any()); } @Test |