Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f97fa4d7 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Skip execution of transactions on a destroyed activity"

parents 401ea164 d3062cbf
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -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) {
+5 −0
Original line number Diff line number Diff line
@@ -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);
+25 −0
Original line number Diff line number Diff line
@@ -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

+5 −0
Original line number Diff line number Diff line
@@ -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) {
+20 −1
Original line number Diff line number Diff line
@@ -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;
        }
Loading