Merge "Use transaction for local activity relaunch" into pi-dev

This commit is contained in:
Andrii Kulian
2018-03-27 17:24:42 +00:00
committed by Android (Google) Code Review
3 changed files with 69 additions and 11 deletions

View File

@@ -30,12 +30,15 @@ import android.annotation.Nullable;
import android.app.assist.AssistContent; import android.app.assist.AssistContent;
import android.app.assist.AssistStructure; import android.app.assist.AssistStructure;
import android.app.backup.BackupAgent; import android.app.backup.BackupAgent;
import android.app.servertransaction.ActivityLifecycleItem;
import android.app.servertransaction.ActivityLifecycleItem.LifecycleState; import android.app.servertransaction.ActivityLifecycleItem.LifecycleState;
import android.app.servertransaction.ActivityRelaunchItem;
import android.app.servertransaction.ActivityResultItem; import android.app.servertransaction.ActivityResultItem;
import android.app.servertransaction.ClientTransaction; import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.PendingTransactionActions; import android.app.servertransaction.PendingTransactionActions;
import android.app.servertransaction.PendingTransactionActions.StopInfo; import android.app.servertransaction.PendingTransactionActions.StopInfo;
import android.app.servertransaction.TransactionExecutor; import android.app.servertransaction.TransactionExecutor;
import android.app.servertransaction.TransactionExecutorHelper;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks2; import android.content.ComponentCallbacks2;
import android.content.ComponentName; import android.content.ComponentName;
@@ -520,6 +523,10 @@ public final class ActivityThread extends ClientTransactionHandler {
return activityInfo.persistableMode == ActivityInfo.PERSIST_ACROSS_REBOOTS; return activityInfo.persistableMode == ActivityInfo.PERSIST_ACROSS_REBOOTS;
} }
public boolean isVisibleFromServer() {
return activity != null && activity.mVisibleFromServer;
}
public String toString() { public String toString() {
ComponentName componentName = intent != null ? intent.getComponent() : null; ComponentName componentName = intent != null ? intent.getComponent() : null;
return "ActivityRecord{" return "ActivityRecord{"
@@ -1797,6 +1804,7 @@ public final class ActivityThread extends ClientTransactionHandler {
// message is handled. // message is handled.
transaction.recycle(); transaction.recycle();
} }
// TODO(lifecycler): Recycle locally scheduled transactions.
break; break;
} }
Object obj = msg.obj; Object obj = msg.obj;
@@ -2755,6 +2763,11 @@ public final class ActivityThread extends ClientTransactionHandler {
} }
} }
@Override
TransactionExecutor getTransactionExecutor() {
return mTransactionExecutor;
}
void sendMessage(int what, Object obj) { void sendMessage(int what, Object obj) {
sendMessage(what, obj, 0, 0, false); sendMessage(what, obj, 0, 0, false);
} }
@@ -4723,15 +4736,22 @@ public final class ActivityThread extends ClientTransactionHandler {
return; return;
} }
// TODO(b/73747058): Investigate converting this to use transaction to relaunch.
handleRelaunchActivityInner(r, 0 /* configChanges */, null /* pendingResults */,
null /* pendingIntents */, null /* pendingActions */, prevState != ON_RESUME,
r.overrideConfig, "handleRelaunchActivityLocally");
// Restore back to the previous state before relaunch if needed. // Initialize a relaunch request.
if (prevState != r.getLifecycleState()) { final MergedConfiguration mergedConfiguration = new MergedConfiguration(
mTransactionExecutor.cycleToPath(r, prevState); r.createdConfig != null ? r.createdConfig : mConfiguration,
} r.overrideConfig);
final ActivityRelaunchItem activityRelaunchItem = ActivityRelaunchItem.obtain(
null /* pendingResults */, null /* pendingIntents */, 0 /* configChanges */,
mergedConfiguration, r.mPreserveWindow);
// Make sure to match the existing lifecycle state in the end of the transaction.
final ActivityLifecycleItem lifecycleRequest =
TransactionExecutorHelper.getLifecycleRequestForCurrentState(r);
// Schedule the transaction.
final ClientTransaction transaction = ClientTransaction.obtain(this.mAppThread, r.token);
transaction.addCallback(activityRelaunchItem);
transaction.setLifecycleStateRequest(lifecycleRequest);
executeTransaction(transaction);
} }
private void handleRelaunchActivityInner(ActivityClientRecord r, int configChanges, private void handleRelaunchActivityInner(ActivityClientRecord r, int configChanges,

View File

@@ -17,6 +17,7 @@ package android.app;
import android.app.servertransaction.ClientTransaction; import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.PendingTransactionActions; import android.app.servertransaction.PendingTransactionActions;
import android.app.servertransaction.TransactionExecutor;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.res.CompatibilityInfo; import android.content.res.CompatibilityInfo;
import android.content.res.Configuration; import android.content.res.Configuration;
@@ -43,6 +44,22 @@ public abstract class ClientTransactionHandler {
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction); sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
} }
/**
* Execute transaction immediately without scheduling it. This is used for local requests, so
* it will also recycle the transaction.
*/
void executeTransaction(ClientTransaction transaction) {
transaction.preExecute(this);
getTransactionExecutor().execute(transaction);
transaction.recycle();
}
/**
* Get the {@link TransactionExecutor} that will be performing lifecycle transitions and
* callbacks for activities.
*/
abstract TransactionExecutor getTransactionExecutor();
abstract void sendMessage(int what, Object obj); abstract void sendMessage(int what, Object obj);

View File

@@ -26,7 +26,7 @@ import static android.app.servertransaction.ActivityLifecycleItem.ON_STOP;
import static android.app.servertransaction.ActivityLifecycleItem.PRE_ON_CREATE; import static android.app.servertransaction.ActivityLifecycleItem.PRE_ON_CREATE;
import static android.app.servertransaction.ActivityLifecycleItem.UNDEFINED; import static android.app.servertransaction.ActivityLifecycleItem.UNDEFINED;
import android.app.ActivityThread; import android.app.ActivityThread.ActivityClientRecord;
import android.util.IntArray; import android.util.IntArray;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
@@ -124,7 +124,7 @@ public class TransactionExecutorHelper {
* {@link ActivityLifecycleItem#UNDEFINED} if there is not path. * {@link ActivityLifecycleItem#UNDEFINED} if there is not path.
*/ */
@VisibleForTesting @VisibleForTesting
public int getClosestPreExecutionState(ActivityThread.ActivityClientRecord r, public int getClosestPreExecutionState(ActivityClientRecord r,
int postExecutionState) { int postExecutionState) {
switch (postExecutionState) { switch (postExecutionState) {
case UNDEFINED: case UNDEFINED:
@@ -147,7 +147,7 @@ public class TransactionExecutorHelper {
* were provided or there is not path. * were provided or there is not path.
*/ */
@VisibleForTesting @VisibleForTesting
public int getClosestOfStates(ActivityThread.ActivityClientRecord r, int[] finalStates) { public int getClosestOfStates(ActivityClientRecord r, int[] finalStates) {
if (finalStates == null || finalStates.length == 0) { if (finalStates == null || finalStates.length == 0) {
return UNDEFINED; return UNDEFINED;
} }
@@ -168,6 +168,27 @@ public class TransactionExecutorHelper {
return closestState; return closestState;
} }
/** Get the lifecycle state request to match the current state in the end of a transaction. */
public static ActivityLifecycleItem getLifecycleRequestForCurrentState(ActivityClientRecord r) {
final int prevState = r.getLifecycleState();
final ActivityLifecycleItem lifecycleItem;
switch (prevState) {
// TODO(lifecycler): Extend to support all possible states.
case ON_PAUSE:
lifecycleItem = PauseActivityItem.obtain();
break;
case ON_STOP:
lifecycleItem = StopActivityItem.obtain(r.isVisibleFromServer(),
0 /* configChanges */);
break;
default:
lifecycleItem = ResumeActivityItem.obtain(false /* isForward */);
break;
}
return lifecycleItem;
}
/** /**
* Check if there is a destruction involved in the path. We want to avoid a lifecycle sequence * Check if there is a destruction involved in the path. We want to avoid a lifecycle sequence
* that involves destruction and recreation if there is another path. * that involves destruction and recreation if there is another path.