Merge "Skip execution of transactions on a destroyed activity"
This commit is contained in:
committed by
Android (Google) Code Review
commit
f97fa4d77b
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user