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

Commit 09f22a63 authored by Chris Li's avatar Chris Li
Browse files

Refactor for pending dispatched ClientTransaction cleanup

Bug: 323801078
Test: refactor only
Flag: com.android.window.flags.cleanup_dispatch_pending_transactions_remote_exception
Change-Id: If5cc8d1c4ab3923c82bc37730169f9e9fac5f0bf
parent 2abdbbd3
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -1113,11 +1113,11 @@ class ActivityClientController extends IActivityClientController.Stub {
                    false /* fromClient */);
        }

        try {
        final EnterPipRequestedItem item = new EnterPipRequestedItem(r.token);
            mService.getLifecycleManager().scheduleTransactionItem(r.app.getThread(), item);
            return true;
        } catch (Exception e) {
        try {
            return mService.getLifecycleManager().scheduleTransactionItem(r.app.getThread(), item);
        } catch (RemoteException e) {
            // TODO(b/323801078): remove Exception when cleanup
            Slog.w(TAG, "Failed to send enter pip requested item: "
                    + r.intent.getComponent(), e);
            return false;
@@ -1129,10 +1129,11 @@ class ActivityClientController extends IActivityClientController.Stub {
     */
    void onPictureInPictureUiStateChanged(@NonNull ActivityRecord r,
            PictureInPictureUiState pipState) {
        try {
        final PipStateTransactionItem item = new PipStateTransactionItem(r.token, pipState);
        try {
            mService.getLifecycleManager().scheduleTransactionItem(r.app.getThread(), item);
        } catch (Exception e) {
        } catch (RemoteException e) {
            // TODO(b/323801078): remove Exception when cleanup
            Slog.w(TAG, "Failed to send pip state transaction item: "
                    + r.intent.getComponent(), e);
        }
+127 −87
Original line number Diff line number Diff line
@@ -253,6 +253,7 @@ import android.annotation.Size;
import android.app.Activity;
import android.app.ActivityManager.TaskDescription;
import android.app.ActivityOptions;
import android.app.IApplicationThread;
import android.app.IScreenCaptureObserver;
import android.app.PendingIntent;
import android.app.PictureInPictureParams;
@@ -1371,15 +1372,16 @@ final class ActivityRecord extends WindowToken {
                    this, displayId);
            return;
        }
        try {
        ProtoLog.v(WM_DEBUG_SWITCH, "Reporting activity moved to "
                        + "display, activityRecord=%s, displayId=%d, config=%s", this, displayId,
                config);

        final MoveToDisplayItem item =
                new MoveToDisplayItem(token, displayId, config, activityWindowInfo);
        try {
            mAtmService.getLifecycleManager().scheduleTransactionItem(app.getThread(), item);
        } catch (RemoteException e) {
            // TODO(b/323801078): remove Exception when cleanup
            // If process died, whatever.
        }
    }
@@ -1391,14 +1393,15 @@ final class ActivityRecord extends WindowToken {
                    + "update - client not running, activityRecord=%s", this);
            return;
        }
        try {
        ProtoLog.v(WM_DEBUG_CONFIGURATION, "Sending new config to %s, "
                + "config: %s", this, config);

        final ActivityConfigurationChangeItem item =
                new ActivityConfigurationChangeItem(token, config, activityWindowInfo);
        try {
            mAtmService.getLifecycleManager().scheduleTransactionItem(app.getThread(), item);
        } catch (RemoteException e) {
            // TODO(b/323801078): remove Exception when cleanup
            // If process died, whatever.
        }
    }
@@ -1413,19 +1416,18 @@ final class ActivityRecord extends WindowToken {
        if (onTop) {
            app.addToPendingTop();
        }
        try {
        ProtoLog.v(WM_DEBUG_STATES, "Sending position change to %s, onTop: %b",
                this, onTop);

            final TopResumedActivityChangeItem item =
                    new TopResumedActivityChangeItem(token, onTop);
            mAtmService.getLifecycleManager().scheduleTransactionItem(app.getThread(), item);
        final TopResumedActivityChangeItem item = new TopResumedActivityChangeItem(token, onTop);
        try {
            return mAtmService.getLifecycleManager().scheduleTransactionItem(app.getThread(), item);
        } catch (RemoteException e) {
            // TODO(b/323801078): remove Exception when cleanup
            // If process died, whatever.
            Slog.w(TAG, "Failed to send top-resumed=" + onTop + " to " + this, e);
            return false;
        }
        return true;
    }

    void updateMultiWindowMode() {
@@ -2620,14 +2622,21 @@ final class ActivityRecord extends WindowToken {
            removeStartingWindow();
            return;
        }
        try {
        mTransferringSplashScreenState = TRANSFER_SPLASH_SCREEN_ATTACH_TO_CLIENT;
        final TransferSplashScreenViewStateItem item =
                new TransferSplashScreenViewStateItem(token, parcelable, windowAnimationLeash);
            mAtmService.getLifecycleManager().scheduleTransactionItem(app.getThread(), item);
            scheduleTransferSplashScreenTimeout();
        } catch (Exception e) {
        boolean isSuccessful;
        try {
            isSuccessful = mAtmService.getLifecycleManager().scheduleTransactionItem(
                    app.getThread(), item);
        } catch (RemoteException e) {
            // TODO(b/323801078): remove Exception when cleanup
            Slog.w(TAG, "onCopySplashScreenComplete fail: " + this);
            isSuccessful = false;
        }
        if (isSuccessful) {
            scheduleTransferSplashScreenTimeout();
        } else {
            mStartingWindow.cancelAnimation();
            parcelable.clearIfNeeded();
            mTransferringSplashScreenState = TRANSFER_SPLASH_SCREEN_FINISH;
@@ -3971,11 +3980,23 @@ final class ActivityRecord extends WindowToken {

            boolean skipDestroy = false;

            try {
            if (DEBUG_SWITCH) Slog.i(TAG_SWITCH, "Destroying: " + this);
            boolean isSuccessful;
            final IApplicationThread client = app.getThread();
            if (client == null) {
                Slog.w(TAG_WM, "Failed to schedule DestroyActivityItem because client is inactive");
                isSuccessful = false;
            } else {
                final DestroyActivityItem item = new DestroyActivityItem(token, finishing);
                mAtmService.getLifecycleManager().scheduleTransactionItem(app.getThread(), item);
            } catch (Exception e) {
                try {
                    isSuccessful = mAtmService.getLifecycleManager().scheduleTransactionItem(
                            client, item);
                } catch (RemoteException e) {
                    // TODO(b/323801078): remove Exception when cleanup
                    isSuccessful = false;
                }
            }
            if (!isSuccessful) {
                // We can just ignore exceptions here...  if the process has crashed, our death
                // notification will clean things up.
                if (finishing) {
@@ -4898,13 +4919,17 @@ final class ActivityRecord extends WindowToken {
        }

        if (isState(RESUMED) && attachedToProcess()) {
            try {
            final ArrayList<ResultInfo> list = new ArrayList<>();
            list.add(new ResultInfo(resultWho, requestCode, resultCode, data, callerToken));
            final ActivityResultItem item = new ActivityResultItem(token, list);
                mAtmService.getLifecycleManager().scheduleTransactionItem(app.getThread(), item);
            try {
                final boolean isSuccessful = mAtmService.getLifecycleManager()
                        .scheduleTransactionItem(app.getThread(), item);
                if (isSuccessful) {
                    return;
            } catch (Exception e) {
                }
            } catch (RemoteException e) {
                // TODO(b/323801078): remove Exception when cleanup
                Slog.w(TAG, "Exception thrown sending result to " + this, e);
            }
        }
@@ -4931,6 +4956,7 @@ final class ActivityRecord extends WindowToken {
                            app.getThread(), activityResultItem);
                }
            } catch (RemoteException e) {
                // TODO(b/323801078): remove Exception when cleanup
                Slog.w(TAG, "Exception thrown sending result to " + this, e);
            }
            // We return here to ensure that result for media projection setup is not stored as a
@@ -5003,7 +5029,6 @@ final class ActivityRecord extends WindowToken {
        }
        final ReferrerIntent rintent = new ReferrerIntent(intent, getFilteredReferrer(referrer),
                callerToken);
        boolean unsent = true;
        final boolean isTopActivityWhileSleeping = isSleeping() && isTopRunningActivity();

        // We want to immediately deliver the intent to the activity if:
@@ -5012,26 +5037,27 @@ final class ActivityRecord extends WindowToken {
        // - The device is sleeping and it is the top activity behind the lock screen (b/6700897).
        if ((mState == RESUMED || mState == PAUSED || isTopActivityWhileSleeping)
                && attachedToProcess()) {
            try {
                ArrayList<ReferrerIntent> ar = new ArrayList<>(1);
            final ArrayList<ReferrerIntent> ar = new ArrayList<>(1);
            ar.add(rintent);
            // Making sure the client state is RESUMED after transaction completed and doing
            // so only if activity is currently RESUMED. Otherwise, client may have extra
            // life-cycle calls to RESUMED (and PAUSED later).
                final NewIntentItem item =
                        new NewIntentItem(token, ar, mState == RESUMED /* resume */);
                mAtmService.getLifecycleManager().scheduleTransactionItem(app.getThread(), item);
                unsent = false;
            final NewIntentItem item = new NewIntentItem(token, ar, mState == RESUMED /* resume */);
            try {
                final boolean isSuccessful = mAtmService.getLifecycleManager()
                        .scheduleTransactionItem(app.getThread(), item);
                if (isSuccessful) {
                    return;
                }
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
            } catch (NullPointerException e) {
                // TODO(b/323801078): remove Exception when cleanup
                Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
            }
        }
        if (unsent) {

        // Didn't send.
        addNewIntentLocked(rintent);
    }
    }

    void updateOptionsLocked(ActivityOptions options) {
        if (options != null) {
@@ -6060,11 +6086,12 @@ final class ActivityRecord extends WindowToken {
            setState(PAUSING, "makeActiveIfNeeded");
            EventLogTags.writeWmPauseActivity(mUserId, System.identityHashCode(this),
                    shortComponentName, "userLeaving=false", "make-active");
            try {
            final PauseActivityItem item = new PauseActivityItem(token, finishing,
                    false /* userLeaving */, false /* dontReport */, mAutoEnteringPip);
            try {
                mAtmService.getLifecycleManager().scheduleTransactionItem(app.getThread(), item);
            } catch (Exception e) {
            } catch (RemoteException e) {
                // TODO(b/323801078): remove Exception when cleanup
                Slog.w(TAG, "Exception thrown sending pause: " + intent.getComponent(), e);
            }
        } else if (shouldStartActivity()) {
@@ -6073,10 +6100,11 @@ final class ActivityRecord extends WindowToken {
            }
            setState(STARTED, "makeActiveIfNeeded");

            final StartActivityItem item = new StartActivityItem(token, takeSceneTransitionInfo());
            try {
                mAtmService.getLifecycleManager().scheduleTransactionItem(app.getThread(),
                        new StartActivityItem(token, takeSceneTransitionInfo()));
            } catch (Exception e) {
                mAtmService.getLifecycleManager().scheduleTransactionItem(app.getThread(), item);
            } catch (RemoteException e) {
                // TODO(b/323801078): remove Exception when cleanup
                Slog.w(TAG, "Exception thrown sending start: " + intent.getComponent(), e);
            }
            // The activity may be waiting for stop, but that is no longer appropriate if we are
@@ -6360,7 +6388,6 @@ final class ActivityRecord extends WindowToken {
            return;
        }
        resumeKeyDispatchingLocked();
        try {
        ProtoLog.v(WM_DEBUG_STATES, "Moving to STOPPING: %s (stop requested)", this);

        setState(STOPPING, "stopIfPossible");
@@ -6369,14 +6396,21 @@ final class ActivityRecord extends WindowToken {
        }
        EventLogTags.writeWmStopActivity(
                mUserId, System.identityHashCode(this), shortComponentName);
            mAtmService.getLifecycleManager().scheduleTransactionItem(app.getThread(),
                    new StopActivityItem(token));

            mAtmService.mH.postDelayed(mStopTimeoutRunnable, STOP_TIMEOUT);
        } catch (Exception e) {
        final StopActivityItem item = new StopActivityItem(token);
        boolean isSuccessful;
        try {
            isSuccessful = mAtmService.getLifecycleManager().scheduleTransactionItem(
                    app.getThread(), item);
        } catch (RemoteException e) {
            // TODO(b/323801078): remove Exception when cleanup
            // Maybe just ignore exceptions here...  if the process has crashed, our death
            // notification will clean things up.
            Slog.w(TAG, "Exception thrown during pause", e);
            isSuccessful = false;
        }
        if (isSuccessful) {
            mAtmService.mH.postDelayed(mStopTimeoutRunnable, STOP_TIMEOUT);
        } else {
            // Just in case, assume it to be stopped.
            mAppStopped = true;
            mStoppedTime = SystemClock.uptimeMillis();
@@ -8982,7 +9016,6 @@ final class ActivityRecord extends WindowToken {
                    task.mTaskId, shortComponentName, Integer.toHexString(configChangeFlags));
        }

        try {
        ProtoLog.i(WM_DEBUG_STATES, "Moving to %s Relaunching %s callers=%s" ,
                (andResume ? "RESUMED" : "PAUSED"), this, Debug.getCallers(6));
        final ClientTransactionItem callbackItem = new ActivityRelaunchItem(token,
@@ -8997,14 +9030,20 @@ final class ActivityRecord extends WindowToken {
        } else {
            lifecycleItem = new PauseActivityItem(token);
        }
            mAtmService.getLifecycleManager().scheduleTransactionItems(
        boolean isSuccessful;
        try {
            isSuccessful = mAtmService.getLifecycleManager().scheduleTransactionItems(
                    app.getThread(), callbackItem, lifecycleItem);
        } catch (RemoteException e) {
            // TODO(b/323801078): remove Exception when cleanup
            Slog.w(TAG, "Failed to relaunch " + this + ": " + e);
            isSuccessful = false;
        }
        if (isSuccessful) {
            startRelaunching();
            // Note: don't need to call pauseIfSleepingLocked() here, because the caller will only
            // request resume if this activity is currently resumed, which implies we aren't
            // sleeping.
        } catch (RemoteException e) {
            Slog.w(TAG, "Failed to relaunch " + this + ": " + e);
        }

        if (andResume) {
@@ -9084,10 +9123,11 @@ final class ActivityRecord extends WindowToken {
    private void scheduleStopForRestartProcess() {
        // The process will be killed until the activity reports stopped with saved state (see
        // {@link ActivityTaskManagerService.activityStopped}).
        final StopActivityItem item = new StopActivityItem(token);
        try {
            mAtmService.getLifecycleManager().scheduleTransactionItem(app.getThread(),
                    new StopActivityItem(token));
            mAtmService.getLifecycleManager().scheduleTransactionItem(app.getThread(), item);
        } catch (RemoteException e) {
            // TODO(b/323801078): remove Exception when cleanup
            Slog.w(TAG, "Exception thrown during restart " + this, e);
        }
        mTaskSupervisor.scheduleRestartTimeout(this);
+9 −4
Original line number Diff line number Diff line
@@ -88,17 +88,22 @@ class ActivityRefresher {
                new RefreshCallbackItem(activity.token, cycleThroughStop ? ON_STOP : ON_PAUSE);
        final ResumeActivityItem resumeActivityItem = new ResumeActivityItem(
                activity.token, /* isForward */ false, /* shouldSendCompatFakeFocus */ false);
        boolean isSuccessful;
        try {
            activity.mAtmService.getLifecycleManager().scheduleTransactionItems(
            isSuccessful = activity.mAtmService.getLifecycleManager().scheduleTransactionItems(
                    activity.app.getThread(), refreshCallbackItem, resumeActivityItem);
        } catch (RemoteException e) {
            isSuccessful = false;
        }
        if (isSuccessful) {
            mHandler.postDelayed(() -> {
                synchronized (mWmService.mGlobalLock) {
                    onActivityRefreshed(activity);
                }
            }, REFRESH_CALLBACK_TIMEOUT_MS);
        } catch (RemoteException e) {
            activity.mAppCompatController.getCameraOverrides()
                    .setIsRefreshRequested(false);
        } else {
            activity.mAppCompatController.getCameraOverrides().setIsRefreshRequested(false);

        }
    }

+102 −59
Original line number Diff line number Diff line
@@ -88,6 +88,7 @@ import android.graphics.Insets;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.ArraySet;
import android.util.DisplayMetrics;
@@ -1754,7 +1755,6 @@ class TaskFragment extends WindowContainer<WindowContainer> {
                }
            }

            try {
            final IApplicationThread appThread = next.app.getThread();
            // Deliver all pending results.
            final ArrayList<ResultInfo> a = next.results;
@@ -1765,14 +1765,38 @@ class TaskFragment extends WindowContainer<WindowContainer> {
                        Slog.v(TAG_RESULTS, "Delivering results to " + next + ": " + a);
                    }
                    final ActivityResultItem item = new ActivityResultItem(next.token, a);
                        mAtmService.getLifecycleManager().scheduleTransactionItem(appThread, item);
                    boolean isSuccessful;
                    try {
                        isSuccessful = mAtmService.getLifecycleManager().scheduleTransactionItem(
                                appThread, item);
                    } catch (RemoteException e) {
                        // TODO(b/323801078): remove Exception when cleanup
                        isSuccessful = false;
                    }
                    if (!isSuccessful) {
                        onResumeTopActivityRemoteFailure(lastState, next, lastResumedActivity,
                                lastFocusedRootTask);
                        return true;
                    }
                }
            }

            if (next.newIntents != null) {
                final NewIntentItem item =
                        new NewIntentItem(next.token, next.newIntents, true /* resume */);
                    mAtmService.getLifecycleManager().scheduleTransactionItem(appThread, item);
                boolean isSuccessful;
                try {
                    isSuccessful = mAtmService.getLifecycleManager().scheduleTransactionItem(
                            appThread, item);
                } catch (RemoteException e) {
                    // TODO(b/323801078): remove Exception when cleanup
                    isSuccessful = false;
                }
                if (!isSuccessful) {
                    onResumeTopActivityRemoteFailure(lastState, next, lastResumedActivity,
                            lastFocusedRootTask);
                    return true;
                }
            }

            // Well the app will no longer be stopped.
@@ -1789,32 +1813,22 @@ class TaskFragment extends WindowContainer<WindowContainer> {
            final ResumeActivityItem resumeActivityItem = new ResumeActivityItem(
                    next.token, topProcessState, dc.isNextTransitionForward(),
                    next.shouldSendCompatFakeFocus());
                mAtmService.getLifecycleManager().scheduleTransactionItem(
            boolean isSuccessful;
            try {
                isSuccessful = mAtmService.getLifecycleManager().scheduleTransactionItem(
                        appThread, resumeActivityItem);

                ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Resumed %s", next);
            } catch (Exception e) {
                // Whoops, need to restart this activity!
                ProtoLog.v(WM_DEBUG_STATES, "Resume failed; resetting state to %s: "
                        + "%s", lastState, next);
                next.setState(lastState, "resumeTopActivityInnerLocked");

                // lastResumedActivity being non-null implies there is a lastStack present.
                if (lastResumedActivity != null) {
                    lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked");
                }

                Slog.i(TAG, "Restarting because process died: " + next);
                if (!next.hasBeenLaunched) {
                    next.hasBeenLaunched = true;
                } else if (SHOW_APP_STARTING_PREVIEW && lastFocusedRootTask != null
                        && lastFocusedRootTask.isTopRootTaskInDisplayArea()) {
                    next.showStartingWindow(false /* taskSwitch */);
            } catch (RemoteException e) {
                // TODO(b/323801078): remove Exception when cleanup
                isSuccessful = false;
            }
                mTaskSupervisor.startSpecificActivity(next, true, false);
            if (!isSuccessful) {
                onResumeTopActivityRemoteFailure(lastState, next, lastResumedActivity,
                        lastFocusedRootTask);
                return true;
            }

            ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Resumed %s", next);

            next.completeResumeLocked();
        } else {
            // Whoops, need to restart this activity!
@@ -1833,6 +1847,29 @@ class TaskFragment extends WindowContainer<WindowContainer> {
        return true;
    }

    /** Likely app process has been killed. Needs to restart this activity. */
    private void onResumeTopActivityRemoteFailure(@NonNull ActivityRecord.State lastState,
            @NonNull ActivityRecord next, @Nullable ActivityRecord lastResumedActivity,
            @Nullable Task lastFocusedRootTask) {
        ProtoLog.v(WM_DEBUG_STATES, "Resume failed; resetting state to %s: "
                + "%s", lastState, next);
        next.setState(lastState, "resumeTopActivityInnerLocked");

        // lastResumedActivity being non-null implies there is a lastStack present.
        if (lastResumedActivity != null) {
            lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked");
        }

        Slog.i(TAG, "Restarting because process died: " + next);
        if (!next.hasBeenLaunched) {
            next.hasBeenLaunched = true;
        } else if (SHOW_APP_STARTING_PREVIEW && lastFocusedRootTask != null
                && lastFocusedRootTask.isTopRootTaskInDisplayArea()) {
            next.showStartingWindow(false /* taskSwitch */);
        }
        mTaskSupervisor.startSpecificActivity(next, true, false);
    }

    boolean shouldSleepOrShutDownActivities() {
        return shouldSleepActivities() || mAtmService.mShuttingDown;
    }
@@ -2037,17 +2074,23 @@ class TaskFragment extends WindowContainer<WindowContainer> {
    void schedulePauseActivity(ActivityRecord prev, boolean userLeaving,
            boolean pauseImmediately, boolean autoEnteringPip, String reason) {
        ProtoLog.v(WM_DEBUG_STATES, "Enqueueing pending pause: %s", prev);
        try {
        prev.mPauseSchedulePendingForPip = false;
        EventLogTags.writeWmPauseActivity(prev.mUserId, System.identityHashCode(prev),
                prev.shortComponentName, "userLeaving=" + userLeaving, reason);

        final PauseActivityItem item = new PauseActivityItem(prev.token, prev.finishing,
                userLeaving, pauseImmediately, autoEnteringPip);
            mAtmService.getLifecycleManager().scheduleTransactionItem(prev.app.getThread(), item);
        } catch (Exception e) {
        boolean isSuccessful;
        try {
            isSuccessful = mAtmService.getLifecycleManager().scheduleTransactionItem(
                    prev.app.getThread(), item);
        } catch (RemoteException e) {
            // TODO(b/323801078): remove Exception when cleanup
            // Ignore exception, if process died other code will cleanup.
            Slog.w(TAG, "Exception thrown during pause", e);
            isSuccessful = false;
        }
        if (!isSuccessful) {
            mPausingActivity = null;
            mLastPausedActivity = null;
            mTaskSupervisor.mNoHistoryActivities.remove(prev);