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

Commit 4f632a30 authored by Andrii Kulian's avatar Andrii Kulian Committed by android-build-merger
Browse files

Merge "Don't finish activity on duplicate resume request" into pi-dev

am: 38af02e7

Change-Id: I8d7d56c9b6d7b1e987379ae26e883a8e1deb2ecf
parents 99b208a7 38af02e7
Loading
Loading
Loading
Loading
+144 −145
Original line number Diff line number Diff line
@@ -3736,12 +3736,25 @@ public final class ActivityThread extends ClientTransactionHandler {
        //Slog.i(TAG, "Running services: " + mServices);
    }

    ActivityClientRecord performResumeActivity(IBinder token, boolean finalStateRequest,
    /**
     * Resume the activity.
     * @param token Target activity token.
     * @param finalStateRequest Flag indicating if this is part of final state resolution for a
     *                          transaction.
     * @param reason Reason for performing the action.
     *
     * @return The {@link ActivityClientRecord} that was resumed, {@code null} otherwise.
     */
    @VisibleForTesting
    public ActivityClientRecord performResumeActivity(IBinder token, boolean finalStateRequest,
            String reason) {
        ActivityClientRecord r = mActivities.get(token);
        if (localLOGV) Slog.v(TAG, "Performing resume of " + r
                + " finished=" + r.activity.mFinished);
        if (r != null && !r.activity.mFinished) {
        final ActivityClientRecord r = mActivities.get(token);
        if (localLOGV) {
            Slog.v(TAG, "Performing resume of " + r + " finished=" + r.activity.mFinished);
        }
        if (r == null || r.activity.mFinished) {
            return null;
        }
        if (r.getLifecycleState() == ON_RESUME) {
            if (!finalStateRequest) {
                final RuntimeException e = new IllegalStateException(
@@ -3779,11 +3792,8 @@ public final class ActivityThread extends ClientTransactionHandler {
            r.setState(ON_RESUME);
        } catch (Exception e) {
            if (!mInstrumentation.onException(r.activity, e)) {
                    throw new RuntimeException(
                        "Unable to resume activity "
                        + r.intent.getComponent().toShortString()
                        + ": " + e.toString(), e);
                }
                throw new RuntimeException("Unable to resume activity "
                        + r.intent.getComponent().toShortString() + ": " + e.toString(), e);
            }
        }
        return r;
@@ -3816,17 +3826,20 @@ public final class ActivityThread extends ClientTransactionHandler {

        // TODO Push resumeArgs into the activity for consideration
        final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
        if (r == null) {
            // We didn't actually resume the activity, so skipping any follow-up actions.
            return;
        }

        if (r != null) {
        final Activity a = r.activity;

            if (localLOGV) Slog.v(
                TAG, "Resume " + r + " started activity: " +
                a.mStartedActivity + ", hideForNow: " + r.hideForNow
                + ", finished: " + a.mFinished);
        if (localLOGV) {
            Slog.v(TAG, "Resume " + r + " started activity: " + a.mStartedActivity
                    + ", hideForNow: " + r.hideForNow + ", finished: " + a.mFinished);
        }

            final int forwardBit = isForward ?
                    WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
        final int forwardBit = isForward
                ? WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;

        // If the window hasn't yet been added to the window manager,
        // and this guy didn't finish itself or start another activity,
@@ -3878,8 +3891,7 @@ public final class ActivityThread extends ClientTransactionHandler {
            // we started another activity, then don't yet make the
            // window visible.
        } else if (!willBeVisible) {
                if (localLOGV) Slog.v(
                    TAG, "Launch " + r + " mStartedActivity set");
            if (localLOGV) Slog.v(TAG, "Launch " + r + " mStartedActivity set");
            r.hideForNow = true;
        }

@@ -3888,16 +3900,16 @@ public final class ActivityThread extends ClientTransactionHandler {

        // The window is now visible if it has been added, we are not
        // simply finishing, and we are not starting another activity.
            if (!r.activity.mFinished && willBeVisible
                    && r.activity.mDecor != null && !r.hideForNow) {
        if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {
            if (r.newConfig != null) {
                performConfigurationChangedForActivity(r, r.newConfig);
                    if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
                            + r.activityInfo.name + " with newConfig " + r.activity.mCurrentConfig);
                if (DEBUG_CONFIGURATION) {
                    Slog.v(TAG, "Resuming activity " + r.activityInfo.name + " with newConfig "
                            + r.activity.mCurrentConfig);
                }
                r.newConfig = null;
            }
                if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
                        + isForward);
            if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward=" + isForward);
            WindowManager.LayoutParams l = r.window.getAttributes();
            if ((l.softInputMode
                    & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
@@ -3921,21 +3933,8 @@ public final class ActivityThread extends ClientTransactionHandler {

        r.nextIdle = mNewActivities;
        mNewActivities = r;
            if (localLOGV) {
                Slog.v(TAG, "Scheduling idle handler for " + r);
            }
        if (localLOGV) Slog.v(TAG, "Scheduling idle handler for " + r);
        Looper.myQueue().addIdleHandler(new Idler());
        } else {
            // If an exception was thrown when trying to resume, then
            // just end this activity.
            try {
                ActivityManager.getService()
                    .finishActivity(token, Activity.RESULT_CANCELED, null,
                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }
    }

    @Override
+3 −1
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.content.res.Configuration;
import android.os.IBinder;
import android.util.MergedConfiguration;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.ReferrerIntent;

import java.io.PrintWriter;
@@ -48,7 +49,8 @@ public abstract class ClientTransactionHandler {
     * Execute transaction immediately without scheduling it. This is used for local requests, so
     * it will also recycle the transaction.
     */
    void executeTransaction(ClientTransaction transaction) {
    @VisibleForTesting
    public void executeTransaction(ClientTransaction transaction) {
        transaction.preExecute(this);
        getTransactionExecutor().execute(transaction);
        transaction.recycle();
+18 −0
Original line number Diff line number Diff line
@@ -16,7 +16,10 @@

package android.app.activity;

import static org.junit.Assert.assertNull;

import android.app.Activity;
import android.app.ActivityThread;
import android.app.IApplicationThread;
import android.app.servertransaction.ActivityRelaunchItem;
import android.app.servertransaction.ClientTransaction;
@@ -76,6 +79,21 @@ public class ActivityThreadTest {
        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
    }

    /** Verify that repeated resume requests to activity will be ignored. */
    @Test
    public void testRepeatedResume() throws Exception {
        final Activity activity = mActivityTestRule.launchActivity(new Intent());
        final ActivityThread activityThread = activity.getActivityThread();
        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
            activityThread.executeTransaction(newResumeTransaction(activity));
            assertNull(activityThread.performResumeActivity(activity.getActivityToken(),
                    true /* finalStateRequest */, "test"));

            assertNull(activityThread.performResumeActivity(activity.getActivityToken(),
                    false /* finalStateRequest */, "test"));
        });
    }

    private static ClientTransaction newRelaunchResumeTransaction(Activity activity) {
        final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(null,
                null, 0, new MergedConfiguration(), false /* preserveWindow */);