From b372da6ef81cd56f681f95d042692922b72b5751 Mon Sep 17 00:00:00 2001 From: Andrii Kulian Date: Thu, 18 Jan 2018 10:46:24 -0800 Subject: [PATCH] Switch activity relaunch to lifecycler This is needed to be able to relaunch an activity and eventually bring it to stopped state while it is not visible. Before this relaunch request put activity in resumed state in the end. With lifecycler both relaunch and request to move to stopped state can be done in a single transaction to client. Also fixed extra relaunch request to activity which was sent before it was even started. It happened because we were waiting for another activity to pause before actually scheduling the launch, and in activity-paused callback we were ensuring config first. This led to configuration update for not-yet launched activity and relaunch message was sent first. Bug: 64610483 Test: android.app.servertransaction tests Change-Id: Ib89c20cd0fdff209319d4819023c3cdd641a72c7 --- config/hiddenapi-light-greylist.txt | 1 - core/java/android/app/ActivityThread.java | 143 ++++---------- .../android/app/ClientTransactionHandler.java | 34 ++++ core/java/android/app/IApplicationThread.aidl | 3 - .../ActivityRelaunchItem.java | 176 ++++++++++++++++++ .../PendingTransactionActions.java | 19 ++ .../servertransaction/ObjectPoolTests.java | 20 ++ .../app/servertransaction/TestUtils.java | 10 + .../TransactionParcelTests.java | 25 ++- .../com/android/server/am/ActivityRecord.java | 35 +++- .../server/am/ActivityStackSupervisor.java | 2 + 11 files changed, 343 insertions(+), 125 deletions(-) create mode 100644 core/java/android/app/servertransaction/ActivityRelaunchItem.java diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt index 54e971fc5ee94..6198406fe96fc 100644 --- a/config/hiddenapi-light-greylist.txt +++ b/config/hiddenapi-light-greylist.txt @@ -43,7 +43,6 @@ Landroid/app/ActivityThread$H;->BIND_SERVICE:I Landroid/app/ActivityThread$H;->CREATE_SERVICE:I Landroid/app/ActivityThread$H;->EXIT_APPLICATION:I Landroid/app/ActivityThread$H;->RECEIVER:I -Landroid/app/ActivityThread$H;->RELAUNCH_ACTIVITY:I Landroid/app/ActivityThread$H;->REMOVE_PROVIDER:I Landroid/app/ActivityThread$H;->SERVICE_ARGS:I Landroid/app/ActivityThread$H;->STOP_SERVICE:I diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 3d088ff9e5c39..bdf09b8d8fcdb 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -113,6 +113,7 @@ import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Log; import android.util.LogPrinter; +import android.util.MergedConfiguration; import android.util.Pair; import android.util.PrintWriterPrinter; import android.util.Slog; @@ -204,7 +205,7 @@ public final class ActivityThread extends ClientTransactionHandler { private static final boolean DEBUG_SERVICE = false; public static final boolean DEBUG_MEMORY_TRIM = false; private static final boolean DEBUG_PROVIDER = false; - private static final boolean DEBUG_ORDER = false; + public static final boolean DEBUG_ORDER = false; private static final long MIN_TIME_BETWEEN_GCS = 5*1000; private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003; private static final int LOG_AM_ON_PAUSE_CALLED = 30021; @@ -398,7 +399,6 @@ public final class ActivityThread extends ClientTransactionHandler { boolean startsNotResumed; public final boolean isForward; int pendingConfigChanges; - boolean onlyLocalRequest; Window mPendingRemoveWindow; WindowManager mPendingRemoveWindowManager; @@ -520,7 +520,6 @@ public final class ActivityThread extends ClientTransactionHandler { sb.append(", startsNotResumed=").append(startsNotResumed); sb.append(", isForward=").append(isForward); sb.append(", pendingConfigChanges=").append(pendingConfigChanges); - sb.append(", onlyLocalRequest=").append(onlyLocalRequest); sb.append(", preserveWindow=").append(mPreserveWindow); if (activity != null) { sb.append(", Activity{"); @@ -765,15 +764,6 @@ public final class ActivityThread extends ClientTransactionHandler { sendMessage(H.SLEEPING, token, sleeping ? 1 : 0); } - @Override - public final void scheduleRelaunchActivity(IBinder token, - List pendingResults, List pendingNewIntents, - int configChanges, boolean notResumed, Configuration config, - Configuration overrideConfig, boolean preserveWindow) { - requestRelaunchActivity(token, pendingResults, pendingNewIntents, - configChanges, notResumed, config, overrideConfig, true, preserveWindow); - } - public final void scheduleReceiver(Intent intent, ActivityInfo info, CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras, boolean sync, int sendingUser, int processState) { @@ -1531,7 +1521,6 @@ public final class ActivityThread extends ClientTransactionHandler { public static final int UNBIND_SERVICE = 122; public static final int DUMP_SERVICE = 123; public static final int LOW_MEMORY = 124; - public static final int RELAUNCH_ACTIVITY = 126; public static final int PROFILER_CONTROL = 127; public static final int CREATE_BACKUP_AGENT = 128; public static final int DESTROY_BACKUP_AGENT = 129; @@ -1577,7 +1566,6 @@ public final class ActivityThread extends ClientTransactionHandler { case UNBIND_SERVICE: return "UNBIND_SERVICE"; case DUMP_SERVICE: return "DUMP_SERVICE"; case LOW_MEMORY: return "LOW_MEMORY"; - case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY"; case PROFILER_CONTROL: return "PROFILER_CONTROL"; case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT"; case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT"; @@ -1611,12 +1599,6 @@ public final class ActivityThread extends ClientTransactionHandler { public void handleMessage(Message msg) { if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what)); switch (msg.what) { - case RELAUNCH_ACTIVITY: { - Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart"); - ActivityClientRecord r = (ActivityClientRecord)msg.obj; - handleRelaunchActivity(r); - Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); - } break; case BIND_APPLICATION: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication"); AppBindData data = (AppBindData)msg.obj; @@ -3726,20 +3708,6 @@ public final class ActivityThread extends ClientTransactionHandler { } r.activity.performResume(r.startsNotResumed); - synchronized (mResourcesManager) { - // If there is a pending local relaunch that was requested when the activity was - // paused, it will put the activity into paused state when it finally happens. - // Since the activity resumed before being relaunched, we don't want that to - // happen, so we need to clear the request to relaunch paused. - for (int i = mRelaunchingActivities.size() - 1; i >= 0; i--) { - final ActivityClientRecord relaunching = mRelaunchingActivities.get(i); - if (relaunching.token == r.token - && relaunching.onlyLocalRequest && relaunching.startsNotResumed) { - relaunching.startsNotResumed = false; - } - } - } - EventLog.writeEvent(LOG_AM_ON_RESUME_CALLED, UserHandle.myUserId(), r.activity.getComponentName().getClassName(), reason); @@ -3888,14 +3856,12 @@ public final class ActivityThread extends ClientTransactionHandler { } } - if (!r.onlyLocalRequest) { - r.nextIdle = mNewActivities; - mNewActivities = r; - if (localLOGV) Slog.v( - TAG, "Scheduling idle handler for " + r); - Looper.myQueue().addIdleHandler(new Idler()); + r.nextIdle = mNewActivities; + mNewActivities = r; + if (localLOGV) { + Slog.v(TAG, "Scheduling idle handler for " + r); } - r.onlyLocalRequest = false; + Looper.myQueue().addIdleHandler(new Idler()); } else { // If an exception was thrown when trying to resume, then // just end this activity. @@ -4586,15 +4552,12 @@ public final class ActivityThread extends ClientTransactionHandler { mSomeActivitiesChanged = true; } - /** - * @param preserveWindow Whether the activity should try to reuse the window it created, - * including the decor view after the relaunch. - */ - public final void requestRelaunchActivity(IBinder token, + @Override + public ActivityClientRecord prepareRelaunchActivity(IBinder token, List pendingResults, List pendingNewIntents, - int configChanges, boolean notResumed, Configuration config, - Configuration overrideConfig, boolean fromServer, boolean preserveWindow) { + int configChanges, MergedConfiguration config, boolean preserveWindow) { ActivityClientRecord target = null; + boolean scheduleRelaunch = false; synchronized (mResourcesManager) { for (int i=0; i pendingResults, List pendingNewIntents, + int configChanges, MergedConfiguration config, boolean preserveWindow); + + /** + * Perform activity relaunch. + * @param r Activity client record prepared for relaunch. + * @param pendingActions Pending actions to be used on later stages of activity transaction. + * */ + public abstract void handleRelaunchActivity(ActivityThread.ActivityClientRecord r, + PendingTransactionActions pendingActions); + + /** + * Report that relaunch request was handled. + * @param token Target activity token. + * @param pendingActions Pending actions initialized on earlier stages of activity transaction. + * Used to check if we should report relaunch to WM. + * */ + public abstract void reportRelaunch(IBinder token, PendingTransactionActions pendingActions); + /** * Debugging output. * @param pw {@link PrintWriter} to write logs to. diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl index 9e99a78ccfbda..ae9b83ec01222 100644 --- a/core/java/android/app/IApplicationThread.aidl +++ b/core/java/android/app/IApplicationThread.aidl @@ -83,9 +83,6 @@ oneway interface IApplicationThread { int resultCode, in String data, in Bundle extras, boolean ordered, boolean sticky, int sendingUser, int processState); void scheduleLowMemory(); - void scheduleRelaunchActivity(IBinder token, in List pendingResults, - in List pendingNewIntents, int configChanges, boolean notResumed, - in Configuration config, in Configuration overrideConfig, boolean preserveWindow); void scheduleSleeping(IBinder token, boolean sleeping); void profilerControl(boolean start, in ProfilerInfo profilerInfo, int profileType); void setSchedulingGroup(int group); diff --git a/core/java/android/app/servertransaction/ActivityRelaunchItem.java b/core/java/android/app/servertransaction/ActivityRelaunchItem.java new file mode 100644 index 0000000000000..d8a7463cb0869 --- /dev/null +++ b/core/java/android/app/servertransaction/ActivityRelaunchItem.java @@ -0,0 +1,176 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app.servertransaction; + +import static android.app.ActivityThread.DEBUG_ORDER; + +import android.app.ActivityThread; +import android.app.ClientTransactionHandler; +import android.app.ResultInfo; +import android.os.IBinder; +import android.os.Parcel; +import android.os.Trace; +import android.util.MergedConfiguration; +import android.util.Slog; + +import com.android.internal.content.ReferrerIntent; + +import java.util.List; +import java.util.Objects; + +/** + * Activity relaunch callback. + * @hide + */ +public class ActivityRelaunchItem extends ClientTransactionItem { + + private static final String TAG = "ActivityRelaunchItem"; + + private List mPendingResults; + private List mPendingNewIntents; + private int mConfigChanges; + private MergedConfiguration mConfig; + private boolean mPreserveWindow; + + /** + * A record that was properly configured for relaunch. Execution will be cancelled if not + * initialized after {@link #preExecute(ClientTransactionHandler, IBinder)}. + */ + private ActivityThread.ActivityClientRecord mActivityClientRecord; + + @Override + public void preExecute(ClientTransactionHandler client, IBinder token) { + mActivityClientRecord = client.prepareRelaunchActivity(token, mPendingResults, + mPendingNewIntents, mConfigChanges, mConfig, mPreserveWindow); + } + + @Override + public void execute(ClientTransactionHandler client, IBinder token, + PendingTransactionActions pendingActions) { + if (mActivityClientRecord == null) { + if (DEBUG_ORDER) Slog.d(TAG, "Activity relaunch cancelled"); + return; + } + Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart"); + client.handleRelaunchActivity(mActivityClientRecord, pendingActions); + Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); + } + + @Override + public void postExecute(ClientTransactionHandler client, IBinder token, + PendingTransactionActions pendingActions) { + client.reportRelaunch(token, pendingActions); + } + + // ObjectPoolItem implementation + + private ActivityRelaunchItem() {} + + /** Obtain an instance initialized with provided params. */ + public static ActivityRelaunchItem obtain(List pendingResults, + List pendingNewIntents, int configChanges, MergedConfiguration config, + boolean preserveWindow) { + ActivityRelaunchItem instance = ObjectPool.obtain(ActivityRelaunchItem.class); + if (instance == null) { + instance = new ActivityRelaunchItem(); + } + instance.mPendingResults = pendingResults; + instance.mPendingNewIntents = pendingNewIntents; + instance.mConfigChanges = configChanges; + instance.mConfig = config; + instance.mPreserveWindow = preserveWindow; + + return instance; + } + + @Override + public void recycle() { + mPendingResults = null; + mPendingNewIntents = null; + mConfigChanges = 0; + mConfig = null; + mPreserveWindow = false; + mActivityClientRecord = null; + ObjectPool.recycle(this); + } + + + // Parcelable implementation + + /** Write to Parcel. */ + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeTypedList(mPendingResults, flags); + dest.writeTypedList(mPendingNewIntents, flags); + dest.writeInt(mConfigChanges); + dest.writeTypedObject(mConfig, flags); + dest.writeBoolean(mPreserveWindow); + } + + /** Read from Parcel. */ + private ActivityRelaunchItem(Parcel in) { + mPendingResults = in.createTypedArrayList(ResultInfo.CREATOR); + mPendingNewIntents = in.createTypedArrayList(ReferrerIntent.CREATOR); + mConfigChanges = in.readInt(); + mConfig = in.readTypedObject(MergedConfiguration.CREATOR); + mPreserveWindow = in.readBoolean(); + } + + public static final Creator CREATOR = + new Creator() { + public ActivityRelaunchItem createFromParcel(Parcel in) { + return new ActivityRelaunchItem(in); + } + + public ActivityRelaunchItem[] newArray(int size) { + return new ActivityRelaunchItem[size]; + } + }; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final ActivityRelaunchItem other = (ActivityRelaunchItem) o; + return Objects.equals(mPendingResults, other.mPendingResults) + && Objects.equals(mPendingNewIntents, other.mPendingNewIntents) + && mConfigChanges == other.mConfigChanges && Objects.equals(mConfig, other.mConfig) + && mPreserveWindow == other.mPreserveWindow; + } + + @Override + public int hashCode() { + int result = 17; + result = 31 * result + Objects.hashCode(mPendingResults); + result = 31 * result + Objects.hashCode(mPendingNewIntents); + result = 31 * result + mConfigChanges; + result = 31 * result + Objects.hashCode(mConfig); + result = 31 * result + (mPreserveWindow ? 1 : 0); + return result; + } + + @Override + public String toString() { + return "ActivityRelaunchItem{pendingResults=" + mPendingResults + + ",pendingNewIntents=" + mPendingNewIntents + ",configChanges=" + mConfigChanges + + ",config=" + mConfig + ",preserveWindow" + mPreserveWindow + "}"; + } +} diff --git a/core/java/android/app/servertransaction/PendingTransactionActions.java b/core/java/android/app/servertransaction/PendingTransactionActions.java index 073d28cfa27f5..af7b7a21a5829 100644 --- a/core/java/android/app/servertransaction/PendingTransactionActions.java +++ b/core/java/android/app/servertransaction/PendingTransactionActions.java @@ -44,6 +44,7 @@ public class PendingTransactionActions { private boolean mCallOnPostCreate; private Bundle mOldState; private StopInfo mStopInfo; + private boolean mReportRelaunchToWM; public PendingTransactionActions() { clear(); @@ -91,6 +92,24 @@ public class PendingTransactionActions { mStopInfo = stopInfo; } + /** + * Check if we should report an activity relaunch to WindowManager. We report back for every + * relaunch request to ActivityManager, but only for those that were actually finished to we + * report to WindowManager. + */ + public boolean shouldReportRelaunchToWindowManager() { + return mReportRelaunchToWM; + } + + /** + * Set if we should report an activity relaunch to WindowManager. We report back for every + * relaunch request to ActivityManager, but only for those that were actually finished we report + * to WindowManager. + */ + public void setReportRelaunchToWindowManager(boolean reportToWm) { + mReportRelaunchToWM = reportToWm; + } + /** Reports to server about activity stop. */ public static class StopInfo implements Runnable { private static final String TAG = "ActivityStopInfo"; diff --git a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java index aefc47e955127..fb0f5344f6430 100644 --- a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java @@ -17,6 +17,7 @@ package android.app.servertransaction; import static android.app.servertransaction.TestUtils.config; +import static android.app.servertransaction.TestUtils.mergedConfig; import static android.app.servertransaction.TestUtils.referrerIntentList; import static android.app.servertransaction.TestUtils.resultInfoList; @@ -150,6 +151,25 @@ public class ObjectPoolTests { assertFalse(item2.equals(emptyItem)); } + @Test + public void testRecycleActivityRelaunchItem() { + ActivityRelaunchItem emptyItem = ActivityRelaunchItem.obtain(null, null, 0, null, false); + Configuration overrideConfig = new Configuration(); + overrideConfig.assetsSeq = 5; + ActivityRelaunchItem item = ActivityRelaunchItem.obtain(resultInfoList(), + referrerIntentList(), 42, mergedConfig(), true); + assertNotSame(item, emptyItem); + assertFalse(item.equals(emptyItem)); + + item.recycle(); + assertEquals(item, emptyItem); + + ActivityRelaunchItem item2 = ActivityRelaunchItem.obtain(resultInfoList(), + referrerIntentList(), 42, mergedConfig(), true); + assertSame(item, item2); + assertFalse(item2.equals(emptyItem)); + } + @Test public void testRecycleMoveToDisplayItem() { MoveToDisplayItem emptyItem = MoveToDisplayItem.obtain(0, null); diff --git a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java index e92351609256d..d125fe790ebac 100644 --- a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java +++ b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java @@ -21,6 +21,7 @@ import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import android.app.ResultInfo; import android.content.Intent; import android.content.res.Configuration; +import android.util.MergedConfiguration; import com.android.internal.content.ReferrerIntent; @@ -38,6 +39,15 @@ class TestUtils { return config; } + static MergedConfiguration mergedConfig() { + Configuration config = config(); + Configuration overrideConfig = new Configuration(); + overrideConfig.densityDpi = 30; + overrideConfig.screenWidthDp = 40; + overrideConfig.smallestScreenWidthDp = 15; + return new MergedConfiguration(config, overrideConfig); + } + static List resultInfoList() { String resultWho1 = "resultWho1"; int requestCode1 = 7; diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java index 77aaa2d7f9eaa..0906435db912f 100644 --- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java @@ -17,6 +17,7 @@ package android.app.servertransaction; import static android.app.servertransaction.TestUtils.config; +import static android.app.servertransaction.TestUtils.mergedConfig; import static android.app.servertransaction.TestUtils.referrerIntentList; import static android.app.servertransaction.TestUtils.resultInfoList; @@ -27,7 +28,6 @@ import android.app.IApplicationThread; import android.app.IInstrumentationWatcher; import android.app.IUiAutomationConnection; import android.app.ProfilerInfo; -import android.app.ResultInfo; import android.content.ComponentName; import android.content.IIntentReceiver; import android.content.Intent; @@ -53,7 +53,6 @@ import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import com.android.internal.app.IVoiceInteractor; -import com.android.internal.content.ReferrerIntent; import org.junit.Before; import org.junit.Test; @@ -242,6 +241,22 @@ public class TransactionParcelTests { assertTrue(item.equals(result)); } + @Test + public void testRelaunch() { + // Write to parcel + Configuration overrideConfig = new Configuration(); + overrideConfig.assetsSeq = 5; + ActivityRelaunchItem item = ActivityRelaunchItem.obtain(resultInfoList(), + referrerIntentList(), 35, mergedConfig(), true); + writeAndPrepareForReading(item); + + // Read from parcel and assert + ActivityRelaunchItem result = ActivityRelaunchItem.CREATOR.createFromParcel(mParcel); + + assertEquals(item.hashCode(), result.hashCode()); + assertTrue(item.equals(result)); + } + @Test public void testPause() { // Write to parcel @@ -434,12 +449,6 @@ public class TransactionParcelTests { public void scheduleLowMemory() throws RemoteException { } - @Override - public void scheduleRelaunchActivity(IBinder iBinder, List list, - List list1, int i, boolean b, Configuration configuration, - Configuration configuration1, boolean b1) throws RemoteException { - } - @Override public void scheduleSleeping(IBinder iBinder, boolean b) throws RemoteException { } diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index cae0d2bc5dd9b..4bb18e2b0f010 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -133,11 +133,16 @@ import android.app.ActivityOptions; import android.app.PendingIntent; import android.app.PictureInPictureParams; import android.app.ResultInfo; +import android.app.servertransaction.ActivityLifecycleItem; +import android.app.servertransaction.ActivityRelaunchItem; +import android.app.servertransaction.ClientTransaction; +import android.app.servertransaction.ClientTransactionItem; import android.app.servertransaction.MoveToDisplayItem; import android.app.servertransaction.MultiWindowModeChangeItem; import android.app.servertransaction.NewIntentItem; import android.app.servertransaction.PauseActivityItem; import android.app.servertransaction.PipModeChangeItem; +import android.app.servertransaction.ResumeActivityItem; import android.app.servertransaction.WindowVisibilityItem; import android.app.servertransaction.ActivityConfigurationChangeItem; import android.content.ComponentName; @@ -2370,6 +2375,15 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo setLastReportedConfiguration(service.getGlobalConfiguration(), newMergedOverrideConfig); + if (state == INITIALIZING) { + // No need to relaunch or schedule new config for activity that hasn't been launched + // yet. We do, however, return after applying the config to activity record, so that + // it will use it for launch transaction. + if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, + "Skipping config check for initializing activity: " + this); + return true; + } + if (changes == 0 && !forceNewConfig) { if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Configuration no differences in " + this); @@ -2559,12 +2573,23 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo + " callers=" + Debug.getCallers(6)); forceNewConfig = false; mStackSupervisor.activityRelaunchingLocked(this); - app.thread.scheduleRelaunchActivity(appToken, pendingResults, pendingNewIntents, - configChangeFlags, !andResume, - new Configuration(service.getGlobalConfiguration()), - new Configuration(getMergedOverrideConfiguration()), preserveWindow); + final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(pendingResults, + pendingNewIntents, configChangeFlags, + new MergedConfiguration(service.getGlobalConfiguration(), + getMergedOverrideConfiguration()), + preserveWindow); + final ActivityLifecycleItem lifecycleItem; + if (andResume) { + lifecycleItem = ResumeActivityItem.obtain(service.isNextTransitionForward()); + } else { + lifecycleItem = PauseActivityItem.obtain(); + } + final ClientTransaction transaction = ClientTransaction.obtain(app.thread, appToken); + transaction.addCallback(callbackItem); + transaction.setLifecycleStateRequest(lifecycleItem); + service.mLifecycleManager.scheduleTransaction(transaction); // Note: don't need to call pauseIfSleepingLocked() here, because the caller will only - // pass in 'andResume' if this activity is currently resumed, which implies we aren't + // request resume if this activity is currently resumed, which implies we aren't // sleeping. } catch (RemoteException e) { if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH, "Relaunch failed", e); diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index a0f31cd213b7a..47e977b90dace 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -1508,6 +1508,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D Slog.w(TAG, "Activity " + r + " being launched, but already in LRU list"); } + // TODO(lifecycler): Resume or pause requests are done as part of launch transaction, + // so updating the state should be done accordingly. if (andResume && readyToResume()) { // As part of the process of launching, ActivityThread also performs // a resume.