Merge "Skip execution of transactions on a destroyed activity"

This commit is contained in:
TreeHugger Robot
2018-07-13 03:38:16 +00:00
committed by Android (Google) Code Review
6 changed files with 104 additions and 1 deletions

View File

@@ -35,6 +35,7 @@ import android.app.servertransaction.ActivityLifecycleItem.LifecycleState;
import android.app.servertransaction.ActivityRelaunchItem;
import android.app.servertransaction.ActivityResultItem;
import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.ClientTransactionItem;
import android.app.servertransaction.PendingTransactionActions;
import android.app.servertransaction.PendingTransactionActions.StopInfo;
import android.app.servertransaction.TransactionExecutor;
@@ -176,6 +177,7 @@ import java.net.InetAddress;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -257,6 +259,8 @@ public final class ActivityThread extends ClientTransactionHandler {
final H mH = new H();
final Executor mExecutor = new HandlerExecutor(mH);
final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();
final Map<IBinder, ClientTransactionItem> mActivitiesToBeDestroyed =
Collections.synchronizedMap(new ArrayMap<IBinder, ClientTransactionItem>());
// List of new activities (via ActivityRecord.nextIdle) that should
// be reported when next we idle.
ActivityClientRecord mNewActivities = null;
@@ -4473,6 +4477,11 @@ public final class ActivityThread extends ClientTransactionHandler {
return component == null ? "[Unknown]" : component.toShortString();
}
@Override
public Map<IBinder, ClientTransactionItem> getActivitiesToBeDestroyed() {
return mActivitiesToBeDestroyed;
}
@Override
public void handleDestroyActivity(IBinder token, boolean finishing, int configChanges,
boolean getNonConfigInstance, String reason) {

View File

@@ -16,6 +16,7 @@
package android.app;
import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.ClientTransactionItem;
import android.app.servertransaction.PendingTransactionActions;
import android.app.servertransaction.TransactionExecutor;
import android.content.Intent;
@@ -29,6 +30,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.ReferrerIntent;
import java.util.List;
import java.util.Map;
/**
* Defines operations that a {@link android.app.servertransaction.ClientTransaction} or its items
@@ -78,6 +80,9 @@ public abstract class ClientTransactionHandler {
// Execute phase related logic and handlers. Methods here execute actual lifecycle transactions
// and deliver callbacks.
/** Get activity and its corresponding transaction item which are going to destroy. */
public abstract Map<IBinder, ClientTransactionItem> getActivitiesToBeDestroyed();
/** Destroy the activity. */
public abstract void handleDestroyActivity(IBinder token, boolean finishing, int configChanges,
boolean getNonConfigInstance, String reason);

View File

@@ -164,6 +164,31 @@ public class ClientTransaction implements Parcelable, ObjectPoolItem {
ObjectPool.recycle(this);
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(64);
sb.append("ClientTransaction{");
if (mActivityToken != null) {
sb.append(" a:").append(Integer.toHexString(System.identityHashCode(mActivityToken)));
}
if (mActivityCallbacks != null && !mActivityCallbacks.isEmpty()) {
sb.append(" c:");
final int size = mActivityCallbacks.size();
for (int i = 0; i < size; i++) {
sb.append(mActivityCallbacks.get(i).getClass().getSimpleName());
if (i < size - 1) {
sb.append(",");
}
}
}
if (mLifecycleStateRequest != null) {
sb.append(" s:");
sb.append(mLifecycleStateRequest.getClass().getSimpleName());
}
sb.append(" }");
return sb.toString();
}
// Parcelable implementation

View File

@@ -32,6 +32,11 @@ public class DestroyActivityItem extends ActivityLifecycleItem {
private boolean mFinished;
private int mConfigChanges;
@Override
public void preExecute(ClientTransactionHandler client, IBinder token) {
client.getActivitiesToBeDestroyed().put(token, this);
}
@Override
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {

View File

@@ -35,6 +35,7 @@ import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
import java.util.List;
import java.util.Map;
/**
* Class that manages transaction execution in the correct order.
@@ -63,6 +64,24 @@ public class TransactionExecutor {
*/
public void execute(ClientTransaction transaction) {
final IBinder token = transaction.getActivityToken();
if (token != null) {
final Map<IBinder, ClientTransactionItem> activitiesToBeDestroyed =
mTransactionHandler.getActivitiesToBeDestroyed();
final ClientTransactionItem destroyItem = activitiesToBeDestroyed.get(token);
if (destroyItem != null) {
if (transaction.getLifecycleStateRequest() == destroyItem) {
// It is going to execute the transaction that will destroy activity with the
// token, so the corresponding to-be-destroyed record can be removed.
activitiesToBeDestroyed.remove(token);
}
if (mTransactionHandler.getActivityClient(token) == null) {
// The activity has not been created but has been requested to destroy, so all
// transactions for the token are just like being cancelled.
Slog.w(TAG, "Skip pre-destroyed " + transaction);
return;
}
}
}
log("Start resolving transaction for client: " + mTransactionHandler + ", token: " + token);
executeCallbacks(transaction);
@@ -76,7 +95,7 @@ public class TransactionExecutor {
@VisibleForTesting
public void executeCallbacks(ClientTransaction transaction) {
final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
if (callbacks == null) {
if (callbacks == null || callbacks.isEmpty()) {
// No callbacks to execute, return early.
return;
}