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

Commit 5527a50a authored by Wale Ogunwale's avatar Wale Ogunwale
Browse files

Fixed issue with relaunching activity in the stopped state

- Cycle activity back to the stopped state if relaunched while the
activity is in the stopped state.
- Also, process Activity.recreate() request locally. After the
activity life cycler changes/clean-up we no longer need to request
the relaunch from the server since it is much easier now to cycle
the activity back to its previous state without help from the server
side.

Change-Id: Ie63420361a50d3dee2cbbcc2bbd34f3099c93996
Fixes: 64610483
Test: atest CtsActivityManagerDeviceTestCases:ActivityLifecycleTests
parent ecd5ebbf
Loading
Loading
Loading
Loading
+1 −7
Original line number Diff line number Diff line
@@ -5553,13 +5553,7 @@ public class Activity extends ContextThemeWrapper
        if (mParent != null) {
            throw new IllegalStateException("Can only be called on top-level activity");
        }
        if (Looper.myLooper() != mMainThread.getLooper()) {
            throw new IllegalStateException("Must be called from main thread");
        }
        try {
            ActivityManager.getService().requestActivityRelaunch(mToken);
        } catch (RemoteException e) {
        }
        mMainThread.handleRelaunchActivityLocally(mToken);
    }

    /**
+57 −22
Original line number Diff line number Diff line
@@ -4292,19 +4292,15 @@ public final class ActivityThread extends ClientTransactionHandler {
            View.mDebugViewAttributes = debugViewAttributes;

            // request all activities to relaunch for the changes to take place
            requestRelaunchAllActivities();
            relaunchAllActivities();
        }
    }

    private void requestRelaunchAllActivities() {
    private void relaunchAllActivities() {
        for (Map.Entry<IBinder, ActivityClientRecord> entry : mActivities.entrySet()) {
            final Activity activity = entry.getValue().activity;
            if (!activity.mFinished) {
                try {
                    ActivityManager.getService().requestActivityRelaunch(entry.getKey());
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
                handleRelaunchActivityLocally(entry.getKey());
            }
        }
    }
@@ -4679,42 +4675,81 @@ public final class ActivityThread extends ClientTransactionHandler {
            throw e.rethrowFromSystemServer();
        }

        handleRelaunchActivityInner(r, configChanges, tmp.pendingResults, tmp.pendingIntents,
                pendingActions, tmp.startsNotResumed, tmp.overrideConfig, "handleRelaunchActivity");

        if (pendingActions != null) {
            // Only report a successful relaunch to WindowManager.
            pendingActions.setReportRelaunchToWindowManager(true);
        }
    }

    /** Performs the activity relaunch locally vs. requesting from system-server. */
    void handleRelaunchActivityLocally(IBinder token) {
        if (Looper.myLooper() != getLooper()) {
            throw new IllegalStateException("Must be called from main thread");
        }

        final ActivityClientRecord r = mActivities.get(token);
        if (r == null) {
            return;
        }

        final int prevState = r.getLifecycleState();

        if (prevState < ON_RESUME) {
            Log.w(TAG, "Activity needs to be already resumed in other to be relaunched.");
            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.
        if (prevState != r.getLifecycleState()) {
            mTransactionExecutor.cycleToPath(r, prevState);
        }
    }

    private void handleRelaunchActivityInner(ActivityClientRecord r, int configChanges,
            List<ResultInfo> pendingResults, List<ReferrerIntent> pendingIntents,
            PendingTransactionActions pendingActions, boolean startsNotResumed,
            Configuration overrideConfig, String reason) {
        // Need to ensure state is saved.
        if (!r.paused) {
            performPauseActivity(r, false, "handleRelaunchActivity",
                    null /* pendingActions */);
            performPauseActivity(r, false, reason, null /* pendingActions */);
        }
        if (!r.stopped) {
            callActivityOnStop(r, true /* saveState */, "handleRelaunchActivity");
            callActivityOnStop(r, true /* saveState */, reason);
        }

        handleDestroyActivity(r.token, false, configChanges, true, "handleRelaunchActivity");
        handleDestroyActivity(r.token, false, configChanges, true, reason);

        r.activity = null;
        r.window = null;
        r.hideForNow = false;
        r.nextIdle = null;
        // Merge any pending results and pending intents; don't just replace them
        if (tmp.pendingResults != null) {
        if (pendingResults != null) {
            if (r.pendingResults == null) {
                r.pendingResults = tmp.pendingResults;
                r.pendingResults = pendingResults;
            } else {
                r.pendingResults.addAll(tmp.pendingResults);
                r.pendingResults.addAll(pendingResults);
            }
        }
        if (tmp.pendingIntents != null) {
        if (pendingIntents != null) {
            if (r.pendingIntents == null) {
                r.pendingIntents = tmp.pendingIntents;
                r.pendingIntents = pendingIntents;
            } else {
                r.pendingIntents.addAll(tmp.pendingIntents);
                r.pendingIntents.addAll(pendingIntents);
            }
        }
        r.startsNotResumed = tmp.startsNotResumed;
        r.overrideConfig = tmp.overrideConfig;
        r.startsNotResumed = startsNotResumed;
        r.overrideConfig = overrideConfig;

        handleLaunchActivity(r, pendingActions);
        // Only report a successful relaunch to WindowManager.
        pendingActions.setReportRelaunchToWindowManager(true);
    }

    @Override
@@ -5117,7 +5152,7 @@ public final class ActivityThread extends ClientTransactionHandler {
        newConfig.assetsSeq = (mConfiguration != null ? mConfiguration.assetsSeq : 0) + 1;
        handleConfigurationChanged(newConfig, null);

        requestRelaunchAllActivities();
        relaunchAllActivities();
    }

    static void freeTextLayoutCachesIfNeeded(int configDiff) {
+0 −1
Original line number Diff line number Diff line
@@ -630,7 +630,6 @@ interface IActivityManager {
    void setHasTopUi(boolean hasTopUi);

    // Start of O transactions
    void requestActivityRelaunch(in IBinder token);
    /**
     * Updates override configuration applied to specific display.
     * @param values Update values for display configuration. If null is passed it will request the
+0 −18
Original line number Diff line number Diff line
@@ -5451,24 +5451,6 @@ public class ActivityManagerService extends IActivityManager.Stub
        }
    }
    @Override
    public final void requestActivityRelaunch(IBinder token) {
        synchronized(this) {
            ActivityRecord r = ActivityRecord.isInStackLocked(token);
            if (r == null) {
                return;
            }
            final long origId = Binder.clearCallingIdentity();
            try {
                r.forceNewConfig = true;
                r.ensureActivityConfigurationLocked(0 /* globalChanges */,
                        true /* preserveWindow */);
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
        }
    }
    /**
     * This is the internal entry point for handling Activity.finish().
     *