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

Commit 0181fbc4 authored by Dianne Hackborn's avatar Dianne Hackborn Committed by Android Git Automerger
Browse files

am f6a7e1f7: Merge "Don\'t wait for current activity to pause before resuming next."

* commit 'f6a7e1f7':
  Don't wait for current activity to pause before resuming next.
parents 49786bbd f6a7e1f7
Loading
Loading
Loading
Loading
+17 −11
Original line number Diff line number Diff line
@@ -138,6 +138,7 @@ import java.io.StringWriter;
import java.lang.IllegalStateException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
@@ -3520,13 +3521,7 @@ public final class ActivityManagerService extends ActivityManagerNative
        }
        // Just in case...
        if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
            if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
            mMainStack.mPausingActivity = null;
        }
        if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
            mMainStack.mLastPausedActivity = null;
        }
        mMainStack.appDiedLocked(app);
        // Remove this application's activities from active lists.
        mMainStack.removeHistoryRecordsForAppLocked(app);
@@ -7231,7 +7226,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                mMainStack.stopIfSleepingLocked();
                final long endTime = System.currentTimeMillis() + timeout;
                while (mMainStack.mResumedActivity != null
                        || mMainStack.mPausingActivity != null) {
                        || mMainStack.mPausingActivities.size() > 0) {
                    long delay = endTime - System.currentTimeMillis();
                    if (delay <= 0) {
                        Slog.w(TAG, "Activity manager shutdown timed out");
@@ -9025,8 +9020,13 @@ public final class ActivityManagerService extends ActivityManagerNative
        }
        pw.println(" ");
        if (mMainStack.mPausingActivity != null) {
            pw.println("  mPausingActivity: " + mMainStack.mPausingActivity);
        if (mMainStack.mPausingActivities.size() > 0) {
            pw.println("  mPausingActivities: " + Arrays.toString(
                    mMainStack.mPausingActivities.toArray()));
        }
        if (mMainStack.mInputPausedActivities.size() > 0) {
            pw.println("  mInputPausedActivities: " + Arrays.toString(
                    mMainStack.mInputPausedActivities.toArray()));
        }
        pw.println("  mResumedActivity: " + mMainStack.mResumedActivity);
        pw.println("  mFocusedActivity: " + mFocusedActivity);
@@ -14759,7 +14759,13 @@ public final class ActivityManagerService extends ActivityManagerNative
    private final ActivityRecord resumedAppLocked() {
        ActivityRecord resumedActivity = mMainStack.mResumedActivity;
        if (resumedActivity == null || resumedActivity.app == null) {
            resumedActivity = mMainStack.mPausingActivity;
            for (int i=mMainStack.mPausingActivities.size()-1; i>=0; i--) {
                ActivityRecord r = mMainStack.mPausingActivities.get(i);
                if (r.app != null) {
                    resumedActivity = r;
                    break;
                }
            }
            if (resumedActivity == null || resumedActivity.app == null) {
                resumedActivity = mMainStack.topRunningActivityLocked(null);
            }
+4 −1
Original line number Diff line number Diff line
@@ -602,6 +602,7 @@ final class ActivityRecord {
    
    public void windowsDrawn() {
        synchronized(service) {
            stack.reportActivityDrawnLocked(this);
            if (launchTime != 0) {
                final long curTime = SystemClock.uptimeMillis();
                final long thisTime = curTime - launchTime;
@@ -690,7 +691,9 @@ final class ActivityRecord {
            // Hmmm, who might we be waiting for?
            r = stack.mResumedActivity;
            if (r == null) {
                r = stack.mPausingActivity;
                if (stack.mPausingActivities.size() > 0) {
                    r = stack.mPausingActivities.get(stack.mPausingActivities.size()-1);
                }
            }
            // Both of those null?  Fall back to 'this' again
            if (r == null) {
+118 −76
Original line number Diff line number Diff line
@@ -227,7 +227,13 @@ final class ActivityStack {
     * When we are in the process of pausing an activity, before starting the
     * next one, this variable holds the activity that is currently being paused.
     */
    ActivityRecord mPausingActivity = null;
    final ArrayList<ActivityRecord> mPausingActivities = new ArrayList<ActivityRecord>();

    /**
     * These activities currently have their input paused, as they want for
     * the next top activity to have its windows visible.
     */
    final ArrayList<ActivityRecord> mInputPausedActivities = new ArrayList<ActivityRecord>();

    /**
     * This is the last activity that we put into the paused state.  This is
@@ -807,9 +813,9 @@ final class ActivityStack {
                startPausingLocked(false, true);
                return;
            }
            if (mPausingActivity != null) {
            if (mPausingActivities.size() > 0) {
                // Still waiting for something to pause; can't sleep yet.
                if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still waiting to pause " + mPausingActivity);
                if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still waiting to pause " + mPausingActivities);
                return;
            }

@@ -872,11 +878,6 @@ final class ActivityStack {
    }

    private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
        if (mPausingActivity != null) {
            RuntimeException e = new RuntimeException();
            Slog.e(TAG, "Trying to pause when pause is already pending for "
                  + mPausingActivity, e);
        }
        ActivityRecord prev = mResumedActivity;
        if (prev == null) {
            RuntimeException e = new RuntimeException();
@@ -884,19 +885,25 @@ final class ActivityStack {
            resumeTopActivityLocked(null);
            return;
        }
        if (mPausingActivities.contains(prev)) {
            RuntimeException e = new RuntimeException();
            Slog.e(TAG, "Trying to pause when pause when already pausing " + prev, e);
        }
        if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSING: " + prev);
        else if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
        mResumedActivity = null;
        mPausingActivity = prev;
        mPausingActivities.add(prev);
        mLastPausedActivity = prev;
        prev.state = ActivityState.PAUSING;
        prev.task.touchActiveTime();
        prev.updateThumbnail(screenshotActivities(prev), null);

        mService.updateCpuStats();
        ActivityRecord pausing;
        
        if (prev.app != null && prev.app.thread != null) {
            if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
            pausing = prev;
            try {
                EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
                        System.identityHashCode(prev),
@@ -909,12 +916,14 @@ final class ActivityStack {
            } catch (Exception e) {
                // Ignore exception, if process died other code will cleanup.
                Slog.w(TAG, "Exception thrown during pause", e);
                mPausingActivity = null;
                mPausingActivities.remove(prev);
                mLastPausedActivity = null;
                pausing = null;
            }
        } else {
            mPausingActivity = null;
            mPausingActivities.remove(prev);
            mLastPausedActivity = null;
            pausing = null;
        }

        // If we are not going to sleep, we want to ensure the device is
@@ -928,18 +937,28 @@ final class ActivityStack {
            }
        }


        if (mPausingActivity != null) {
        if (pausing != null) {
            // Have the window manager pause its key dispatching until the new
            // activity has started.  If we're pausing the activity just because
            // the screen is being turned off and the UI is sleeping, don't interrupt
            // key dispatch; the same activity will pick it up again on wakeup.
            if (!uiSleeping) {
                prev.pauseKeyDispatchingLocked();
                pausing.pauseKeyDispatchingLocked();
                mInputPausedActivities.add(prev);
            } else {
                if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
            }

            if (pausing.configDestroy) {
                // The previous is being paused because the configuration
                // is changing, which means it is actually stopping...
                // To juggle the fact that we are also starting a new
                // instance right now, we need to first completely stop
                // the current instance before starting the new one.
                if (DEBUG_PAUSE) Slog.v(TAG, "Destroying at pause: " + prev);
                destroyActivityLocked(pausing, true, false, "pause-config");
            }

            // Schedule a pause timeout in case the app doesn't respond.
            // We don't give it much time because this directly impacts the
            // responsiveness seen by the user.
@@ -951,7 +970,10 @@ final class ActivityStack {
            // This activity failed to schedule the
            // pause, so just treat it as being paused now.
            if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
            resumeTopActivityLocked(null);
        }

        if (!mService.isSleeping()) {
            resumeTopActivityLocked(pausing);
        }
    }
    
@@ -966,16 +988,17 @@ final class ActivityStack {
            if (index >= 0) {
                r = mHistory.get(index);
                mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
                if (mPausingActivity == r) {
                if (mPausingActivities.contains(r)) {
                    if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSED: " + r
                            + (timeout ? " (due to timeout)" : " (pause complete)"));
                    r.state = ActivityState.PAUSED;
                    completePauseLocked();
                    completePauseLocked(r);
                } else {
                    ActivityRecord old = mPausingActivities.size() > 0
                            ? mPausingActivities.get(0) : null;
                    EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
                            System.identityHashCode(r), r.shortComponentName, 
                            mPausingActivity != null
                                ? mPausingActivity.shortComponentName : "(none)");
                            old != null ? old.shortComponentName : "(none)");
                }
            }
        }
@@ -1001,8 +1024,14 @@ final class ActivityStack {
                ProcessRecord fgApp = null;
                if (mResumedActivity != null) {
                    fgApp = mResumedActivity.app;
                } else if (mPausingActivity != null) {
                    fgApp = mPausingActivity.app;
                } else {
                    for (int i=mPausingActivities.size()-1; i>=0; i--) {
                        ActivityRecord pausing = mPausingActivities.get(i);
                        if (pausing.app == r.app) {
                            fgApp = pausing.app;
                            break;
                        }
                    }
                }
                if (r.app != null && fgApp != null && r.app != fgApp
                        && r.lastVisibleTime > mService.mPreviousProcessVisibleTime
@@ -1014,11 +1043,9 @@ final class ActivityStack {
        }
    }

    private final void completePauseLocked() {
        ActivityRecord prev = mPausingActivity;
    private final void completePauseLocked(ActivityRecord prev) {
        if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
        
        if (prev != null) {
        if (prev.finishing) {
            if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
            prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
@@ -1054,19 +1081,12 @@ final class ActivityStack {
            if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
            prev = null;
        }
            mPausingActivity = null;
        }
        mPausingActivities.remove(prev);

        if (!mService.isSleeping()) {
            resumeTopActivityLocked(prev);
        } else {
        if (mService.isSleeping()) {
            checkReadyForSleepLocked();
        }

        if (prev != null) {
            prev.resumeKeyDispatchingLocked();
        }

        if (prev.app != null && prev.cpuTimeAtResume > 0
                && mService.mBatteryStatsService.isOnBattery()) {
            long diff = 0;
@@ -1122,7 +1142,9 @@ final class ActivityStack {
        if (mMainStack) {
            mService.setFocusedActivityLocked(next);
        }
        if (mInputPausedActivities.remove(next)) {
            next.resumeKeyDispatchingLocked();
        }
        ensureActivitiesVisibleLocked(null, 0);
        mService.mWindowManager.executeAppTransition();
        mNoAnimActivities.clear();
@@ -1352,13 +1374,6 @@ final class ActivityStack {

        if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);

        // If we are currently pausing an activity, then don't do anything
        // until that is done.
        if (mPausingActivity != null) {
            if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: pausing=" + mPausingActivity);
            return false;
        }

        // Okay we are now going to start a switch, to 'next'.  We may first
        // have to pause the current activity, but this is an important point
        // where we have decided to go to 'next' so keep track of that.
@@ -2440,7 +2455,7 @@ final class ActivityStack {
        
        err = startActivityUncheckedLocked(r, sourceRecord,
                grantedUriPermissions, grantedMode, onlyIfNeeded, true);
        if (mDismissKeyguardOnNextActivity && mPausingActivity == null) {
        if (mDismissKeyguardOnNextActivity && mPausingActivities.size() == 0) {
            // Someone asked to have the keyguard dismissed on the next
            // activity start, but we are not actually doing an activity
            // switch...  just dismiss the keyguard now, because we
@@ -3112,6 +3127,17 @@ final class ActivityStack {
        mService.notifyAll();
    }

    void reportActivityDrawnLocked(ActivityRecord r) {
        if (mResumedActivity == r) {
            // Once the resumed activity has been drawn, we can stop
            // pausing input on all other activities.
            for (int i=mInputPausedActivities.size()-1; i>=0; i--) {
                mInputPausedActivities.get(i).resumeKeyDispatchingLocked();
            }
            mInputPausedActivities.clear();
        }
    }

    void reportActivityVisibleLocked(ActivityRecord r) {
        for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
            WaitResult w = mWaitingActivityVisible.get(i);
@@ -3170,7 +3196,9 @@ final class ActivityStack {
                    mService.setFocusedActivityLocked(topRunningActivityLocked(null));
                }
            }
            if (mInputPausedActivities.remove(r)) {
                r.resumeKeyDispatchingLocked();
            }
            try {
                r.stopped = false;
                if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r
@@ -3496,7 +3524,7 @@ final class ActivityStack {
            // Tell window manager to prepare for this one to be removed.
            mService.mWindowManager.setAppVisibility(r.appToken, false);
                
            if (mPausingActivity == null) {
            if (!mPausingActivities.contains(r)) {
                if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
                if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
                startPausingLocked(false, false);
@@ -3580,6 +3608,20 @@ final class ActivityStack {
        return r;
    }

    final void appDiedLocked(ProcessRecord app) {
        for (int i=mPausingActivities.size()-1; i>=0; i--) {
            ActivityRecord r = mPausingActivities.get(i);
            if (r.app == app) {
                if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " + r);
                mPausingActivities.remove(i);
                mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
            }
        }
        if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
            mLastPausedActivity = null;
        }
    }

    /**
     * Perform the common clean-up of an activity record.  This is called both
     * as part of destroyActivityLocked() (when destroying the client-side