Merge "Switch activity relaunch to lifecycler"
This commit is contained in:
committed by
Android (Google) Code Review
commit
cacd69515f
@@ -46,7 +46,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
|
||||
|
||||
@@ -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<ResultInfo> pendingResults, List<ReferrerIntent> 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<ResultInfo> pendingResults, List<ReferrerIntent> 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<mRelaunchingActivities.size(); i++) {
|
||||
@@ -4616,57 +4579,31 @@ public final class ActivityThread extends ClientTransactionHandler {
|
||||
r.pendingIntents = pendingNewIntents;
|
||||
}
|
||||
}
|
||||
|
||||
// For each relaunch request, activity manager expects an answer
|
||||
if (!r.onlyLocalRequest && fromServer) {
|
||||
try {
|
||||
ActivityManager.getService().activityRelaunched(token);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (target == null) {
|
||||
if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: target is null, fromServer:"
|
||||
+ fromServer);
|
||||
if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: target is null");
|
||||
target = new ActivityClientRecord();
|
||||
target.token = token;
|
||||
target.pendingResults = pendingResults;
|
||||
target.pendingIntents = pendingNewIntents;
|
||||
target.mPreserveWindow = preserveWindow;
|
||||
if (!fromServer) {
|
||||
final ActivityClientRecord existing = mActivities.get(token);
|
||||
if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: " + existing);
|
||||
if (existing != null) {
|
||||
if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: paused= "
|
||||
+ existing.paused);;
|
||||
target.startsNotResumed = existing.paused;
|
||||
target.overrideConfig = existing.overrideConfig;
|
||||
}
|
||||
target.onlyLocalRequest = true;
|
||||
}
|
||||
mRelaunchingActivities.add(target);
|
||||
sendMessage(H.RELAUNCH_ACTIVITY, target);
|
||||
}
|
||||
|
||||
if (fromServer) {
|
||||
target.startsNotResumed = notResumed;
|
||||
target.onlyLocalRequest = false;
|
||||
}
|
||||
if (config != null) {
|
||||
target.createdConfig = config;
|
||||
}
|
||||
if (overrideConfig != null) {
|
||||
target.overrideConfig = overrideConfig;
|
||||
scheduleRelaunch = true;
|
||||
}
|
||||
target.createdConfig = config.getGlobalConfiguration();
|
||||
target.overrideConfig = config.getOverrideConfiguration();
|
||||
target.pendingConfigChanges |= configChanges;
|
||||
}
|
||||
|
||||
return scheduleRelaunch ? target : null;
|
||||
}
|
||||
|
||||
private void handleRelaunchActivity(ActivityClientRecord tmp) {
|
||||
@Override
|
||||
public void handleRelaunchActivity(ActivityClientRecord tmp,
|
||||
PendingTransactionActions pendingActions) {
|
||||
// If we are getting ready to gc after going to the background, well
|
||||
// we are back active so skip it.
|
||||
unscheduleGcIdler();
|
||||
@@ -4735,18 +4672,10 @@ public final class ActivityThread extends ClientTransactionHandler {
|
||||
ActivityClientRecord r = mActivities.get(tmp.token);
|
||||
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handling relaunch of " + r);
|
||||
if (r == null) {
|
||||
if (!tmp.onlyLocalRequest) {
|
||||
try {
|
||||
ActivityManager.getService().activityRelaunched(tmp.token);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
r.activity.mConfigChangeFlags |= configChanges;
|
||||
r.onlyLocalRequest = tmp.onlyLocalRequest;
|
||||
r.mPreserveWindow = tmp.mPreserveWindow;
|
||||
|
||||
r.activity.mChangingConfigurations = true;
|
||||
@@ -4763,9 +4692,9 @@ public final class ActivityThread extends ClientTransactionHandler {
|
||||
// preserved by the server, so we want to notify it that we are preparing to replace
|
||||
// everything
|
||||
try {
|
||||
if (r.mPreserveWindow || r.onlyLocalRequest) {
|
||||
if (r.mPreserveWindow) {
|
||||
WindowManagerGlobal.getWindowSession().prepareToReplaceWindows(
|
||||
r.token, !r.onlyLocalRequest);
|
||||
r.token, true /* childrenOnly */);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
@@ -4804,24 +4733,22 @@ public final class ActivityThread extends ClientTransactionHandler {
|
||||
r.startsNotResumed = tmp.startsNotResumed;
|
||||
r.overrideConfig = tmp.overrideConfig;
|
||||
|
||||
// TODO(lifecycler): Move relaunch to lifecycler.
|
||||
PendingTransactionActions pendingActions = new PendingTransactionActions();
|
||||
handleLaunchActivity(r, pendingActions);
|
||||
handleStartActivity(r, pendingActions);
|
||||
handleResumeActivity(r.token, false /* clearHide */, r.isForward, "relaunch");
|
||||
if (r.startsNotResumed) {
|
||||
performPauseActivity(r, false /* finished */, "relaunch", pendingActions);
|
||||
}
|
||||
// Only report a successful relaunch to WindowManager.
|
||||
pendingActions.setReportRelaunchToWindowManager(true);
|
||||
}
|
||||
|
||||
if (!tmp.onlyLocalRequest) {
|
||||
try {
|
||||
ActivityManager.getService().activityRelaunched(r.token);
|
||||
if (r.window != null) {
|
||||
r.window.reportActivityRelaunched();
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
@Override
|
||||
public void reportRelaunch(IBinder token, PendingTransactionActions pendingActions) {
|
||||
try {
|
||||
ActivityManager.getService().activityRelaunched(token);
|
||||
final ActivityClientRecord r = mActivities.get(token);
|
||||
if (pendingActions.shouldReportRelaunchToWindowManager() && r != null
|
||||
&& r.window != null) {
|
||||
r.window.reportActivityRelaunched();
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.content.pm.ApplicationInfo;
|
||||
import android.content.res.CompatibilityInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.IBinder;
|
||||
import android.util.MergedConfiguration;
|
||||
|
||||
import com.android.internal.content.ReferrerIntent;
|
||||
|
||||
@@ -123,6 +124,39 @@ public abstract class ClientTransactionHandler {
|
||||
*/
|
||||
public abstract ActivityThread.ActivityClientRecord getActivityClient(IBinder token);
|
||||
|
||||
/**
|
||||
* Prepare activity relaunch to update internal bookkeeping. This is used to track multiple
|
||||
* relaunch and config update requests.
|
||||
* @param token Activity token.
|
||||
* @param pendingResults Activity results to be delivered.
|
||||
* @param pendingNewIntents New intent messages to be delivered.
|
||||
* @param configChanges Mask of configuration changes that have occurred.
|
||||
* @param config New configuration applied to the activity.
|
||||
* @param preserveWindow Whether the activity should try to reuse the window it created,
|
||||
* including the decor view after the relaunch.
|
||||
* @return An initialized instance of {@link ActivityThread.ActivityClientRecord} to use during
|
||||
* relaunch, or {@code null} if relaunch cancelled.
|
||||
*/
|
||||
public abstract ActivityThread.ActivityClientRecord prepareRelaunchActivity(IBinder token,
|
||||
List<ResultInfo> pendingResults, List<ReferrerIntent> 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.
|
||||
|
||||
@@ -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<ResultInfo> pendingResults,
|
||||
in List<ReferrerIntent> 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);
|
||||
|
||||
@@ -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<ResultInfo> mPendingResults;
|
||||
private List<ReferrerIntent> 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<ResultInfo> pendingResults,
|
||||
List<ReferrerIntent> 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<ActivityRelaunchItem> CREATOR =
|
||||
new Creator<ActivityRelaunchItem>() {
|
||||
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 + "}";
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<ResultInfo> resultInfoList() {
|
||||
String resultWho1 = "resultWho1";
|
||||
int requestCode1 = 7;
|
||||
|
||||
@@ -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<ResultInfo> list,
|
||||
List<ReferrerIntent> list1, int i, boolean b, Configuration configuration,
|
||||
Configuration configuration1, boolean b1) throws RemoteException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scheduleSleeping(IBinder iBinder, boolean b) throws RemoteException {
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -1509,6 +1509,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.
|
||||
|
||||
Reference in New Issue
Block a user