Loading core/java/android/app/WaitResult.java +11 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ import android.content.ComponentName; import android.os.Parcel; import android.os.Parcelable; import java.io.PrintWriter; /** * Information returned after waiting for an activity start. * Loading Loading @@ -69,4 +71,13 @@ public class WaitResult implements Parcelable { thisTime = source.readLong(); totalTime = source.readLong(); } public void dump(PrintWriter pw, String prefix) { pw.println(prefix + "WaitResult:"); pw.println(prefix + " result=" + result); pw.println(prefix + " timeout=" + timeout); pw.println(prefix + " who=" + who); pw.println(prefix + " thisTime=" + thisTime); pw.println(prefix + " totalTime=" + totalTime); } } No newline at end of file services/core/java/com/android/server/am/ActivityRecord.java +7 −5 Original line number Diff line number Diff line Loading @@ -505,7 +505,8 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo else TimeUtils.formatDuration(startTime, now, pw); pw.println(); } final boolean waitingVisible = mStackSupervisor.mWaitingVisibleActivities.contains(this); final boolean waitingVisible = mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(this); if (lastVisibleTime != 0 || waitingVisible || nowVisible) { pw.print(prefix); pw.print("waitingVisible="); pw.print(waitingVisible); pw.print(" nowVisible="); pw.print(nowVisible); Loading Loading @@ -1912,13 +1913,14 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo // If this activity was already idle, then we now need to make sure we perform // the full stop of any activities that are waiting to do so. This is because // we won't do that while they are still waiting for this one to become visible. final int size = mStackSupervisor.mWaitingVisibleActivities.size(); final int size = mStackSupervisor.mActivitiesWaitingForVisibleActivity.size(); if (size > 0) { for (int i = 0; i < size; i++) { ActivityRecord r = mStackSupervisor.mWaitingVisibleActivities.get(i); final ActivityRecord r = mStackSupervisor.mActivitiesWaitingForVisibleActivity.get(i); if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "Was waiting for visible: " + r); } mStackSupervisor.mWaitingVisibleActivities.clear(); mStackSupervisor.mActivitiesWaitingForVisibleActivity.clear(); mStackSupervisor.scheduleIdleLocked(); } } Loading Loading @@ -1959,7 +1961,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo // First find the real culprit... if this activity is waiting for // another activity to start or has stopped, then the key dispatching // timeout should not be caused by this. if (mStackSupervisor.mWaitingVisibleActivities.contains(this) || stopped) { if (mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(this) || stopped) { final ActivityStack stack = mStackSupervisor.getFocusedStack(); // Try to use the one which is closest to top. ActivityRecord r = stack.mResumedActivity; Loading services/core/java/com/android/server/am/ActivityStack.java +14 −17 Original line number Diff line number Diff line Loading @@ -116,7 +116,6 @@ import android.util.Slog; import android.util.SparseArray; import android.view.Display; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IVoiceInteractor; import com.android.internal.os.BatteryStatsImpl; import com.android.server.Watchdog; Loading Loading @@ -1349,7 +1348,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } else if (prev.app != null) { if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueue pending stop if needed: " + prev + " wasStopping=" + wasStopping + " visible=" + prev.visible); if (mStackSupervisor.mWaitingVisibleActivities.remove(prev)) { if (mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(prev)) { if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause, no longer waiting: " + prev); } Loading Loading @@ -2262,7 +2261,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mStackSupervisor.mStoppingActivities.remove(next); mStackSupervisor.mGoingToSleepActivities.remove(next); next.sleeping = false; mStackSupervisor.mWaitingVisibleActivities.remove(next); mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(next); if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next); Loading Loading @@ -2324,9 +2323,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } if (prev != null && prev != next) { if (!mStackSupervisor.mWaitingVisibleActivities.contains(prev) if (!mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev) && next != null && !next.nowVisible) { mStackSupervisor.mWaitingVisibleActivities.add(prev); mStackSupervisor.mActivitiesWaitingForVisibleActivity.add(prev); if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming top, waiting visible to hide: " + prev); } else { Loading @@ -2342,13 +2341,13 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai prev.setVisibility(false); if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Not waiting for visible to hide: " + prev + ", waitingVisible=" + mStackSupervisor.mWaitingVisibleActivities.contains(prev) + mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev) + ", nowVisible=" + next.nowVisible); } else { if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Previous already visible but still waiting to hide: " + prev + ", waitingVisible=" + mStackSupervisor.mWaitingVisibleActivities.contains(prev) + mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev) + ", nowVisible=" + next.nowVisible); } } Loading Loading @@ -3617,8 +3616,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mWindowManager.prepareAppTransition(transit, false); r.setVisibility(false); mWindowManager.executeAppTransition(); if (!mStackSupervisor.mWaitingVisibleActivities.contains(r)) { mStackSupervisor.mWaitingVisibleActivities.add(r); if (!mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(r)) { mStackSupervisor.mActivitiesWaitingForVisibleActivity.add(r); } } Loading Loading @@ -3650,7 +3649,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // make sure the record is cleaned out of other places. mStackSupervisor.mStoppingActivities.remove(r); mStackSupervisor.mGoingToSleepActivities.remove(r); mStackSupervisor.mWaitingVisibleActivities.remove(r); mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(r); if (mResumedActivity == r) { mResumedActivity = null; } Loading Loading @@ -3870,11 +3869,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai r.app = null; } // Make sure this record is no longer in the pending finishes list. // This could happen, for example, if we are trimming activities // down to the max limit while they are still waiting to finish. mStackSupervisor.mFinishingActivities.remove(r); mStackSupervisor.mWaitingVisibleActivities.remove(r); // Inform supervisor the activity has been removed. mStackSupervisor.cleanupActivity(r); // Remove any pending results. if (r.finishing && r.pendingResults != null) { Loading Loading @@ -4253,8 +4250,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai "mStoppingActivities"); removeHistoryRecordsForAppLocked(mStackSupervisor.mGoingToSleepActivities, app, "mGoingToSleepActivities"); removeHistoryRecordsForAppLocked(mStackSupervisor.mWaitingVisibleActivities, app, "mWaitingVisibleActivities"); removeHistoryRecordsForAppLocked(mStackSupervisor.mActivitiesWaitingForVisibleActivity, app, "mActivitiesWaitingForVisibleActivity"); removeHistoryRecordsForAppLocked(mStackSupervisor.mFinishingActivities, app, "mFinishingActivities"); Loading services/core/java/com/android/server/am/ActivityStackSupervisor.java +81 −22 Original line number Diff line number Diff line Loading @@ -153,6 +153,7 @@ import android.provider.MediaStore; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.service.voice.IVoiceInteractionSession; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.EventLog; Loading @@ -164,7 +165,6 @@ import android.view.Display; import android.view.InputEvent; import android.view.Surface; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.content.ReferrerIntent; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; Loading @@ -174,7 +174,6 @@ import com.android.internal.util.ArrayUtils; import com.android.internal.widget.LockPatternUtils; import com.android.server.LocalServices; import com.android.server.am.ActivityStack.ActivityState; import com.android.server.wm.StackWindowController; import com.android.server.wm.WindowManagerService; import java.io.FileDescriptor; Loading Loading @@ -346,10 +345,12 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D /** List of activities that are waiting for a new activity to become visible before completing * whatever operation they are supposed to do. */ final ArrayList<ActivityRecord> mWaitingVisibleActivities = new ArrayList<>(); // TODO: Remove mActivitiesWaitingForVisibleActivity list and just remove activity from // mStoppingActivities when something else comes up. final ArrayList<ActivityRecord> mActivitiesWaitingForVisibleActivity = new ArrayList<>(); /** List of processes waiting to find out about the next visible activity. */ final ArrayList<WaitResult> mWaitingActivityVisible = new ArrayList<>(); /** List of processes waiting to find out when a specific activity becomes visible. */ private final ArrayList<WaitInfo> mWaitingForActivityVisible = new ArrayList<>(); /** List of processes waiting to find out about the next launched activity. */ final ArrayList<WaitResult> mWaitingActivityLaunched = new ArrayList<>(); Loading Loading @@ -1003,7 +1004,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D final ActivityStack stack = stacks.get(stackNdx); final ActivityRecord r = stack.mResumedActivity; if (r != null) { if (!r.nowVisible || mWaitingVisibleActivities.contains(r)) { if (!r.nowVisible || mActivitiesWaitingForVisibleActivity.contains(r)) { return false; } foundResumed = true; Loading Loading @@ -1083,22 +1084,41 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } } void waitActivityVisible(ComponentName name, WaitResult result) { final WaitInfo waitInfo = new WaitInfo(name, result); mWaitingForActivityVisible.add(waitInfo); } void cleanupActivity(ActivityRecord r) { // Make sure this record is no longer in the pending finishes list. // This could happen, for example, if we are trimming activities // down to the max limit while they are still waiting to finish. mFinishingActivities.remove(r); mActivitiesWaitingForVisibleActivity.remove(r); for (int i = mWaitingForActivityVisible.size() - 1; i >= 0; --i) { if (mWaitingForActivityVisible.get(i).matches(r)) { mWaitingForActivityVisible.remove(i); } } } void reportActivityVisibleLocked(ActivityRecord r) { sendWaitingVisibleReportLocked(r); } void sendWaitingVisibleReportLocked(ActivityRecord r) { boolean changed = false; for (int i = mWaitingActivityVisible.size()-1; i >= 0; i--) { WaitResult w = mWaitingActivityVisible.get(i); if (w.who == null) { for (int i = mWaitingForActivityVisible.size() - 1; i >= 0; --i) { final WaitInfo w = mWaitingForActivityVisible.get(i); if (w.matches(r)) { final WaitResult result = w.getResult(); changed = true; w.timeout = false; if (r != null) { w.who = new ComponentName(r.info.packageName, r.info.name); } w.totalTime = SystemClock.uptimeMillis() - w.thisTime; w.thisTime = w.totalTime; result.timeout = false; result.who = w.getComponent(); result.totalTime = SystemClock.uptimeMillis() - result.thisTime; result.thisTime = result.totalTime; mWaitingForActivityVisible.remove(w); } } if (changed) { Loading Loading @@ -3421,13 +3441,11 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D final boolean nowVisible = allResumedActivitiesVisible(); for (int activityNdx = mStoppingActivities.size() - 1; activityNdx >= 0; --activityNdx) { ActivityRecord s = mStoppingActivities.get(activityNdx); // TODO: Remove mWaitingVisibleActivities list and just remove activity from // mStoppingActivities when something else comes up. boolean waitingVisible = mWaitingVisibleActivities.contains(s); boolean waitingVisible = mActivitiesWaitingForVisibleActivity.contains(s); if (DEBUG_STATES) Slog.v(TAG, "Stopping " + s + ": nowVisible=" + nowVisible + " waitingVisible=" + waitingVisible + " finishing=" + s.finishing); if (waitingVisible && nowVisible) { mWaitingVisibleActivities.remove(s); mActivitiesWaitingForVisibleActivity.remove(s); waitingVisible = false; if (s.finishing) { // If this activity is finishing, it is sitting on top of Loading Loading @@ -3520,6 +3538,13 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D pw.print(":"); pw.println(Arrays.toString(packages.valueAt(i))); } } if (!mWaitingForActivityVisible.isEmpty()) { pw.print(prefix); pw.println("mWaitingForActivityVisible="); for (int i = 0; i < mWaitingForActivityVisible.size(); ++i) { pw.print(prefix); pw.print(prefix); mWaitingForActivityVisible.get(i).dump(pw, prefix); } } pw.println(" mLockTaskModeTasks" + mLockTaskModeTasks); mKeyguardController.dump(pw, prefix); } Loading Loading @@ -3642,9 +3667,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D false, dumpPackage, true, " Activities waiting to finish:", null); printed |= dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll, false, dumpPackage, true, " Activities waiting to stop:", null); printed |= dumpHistoryList(fd, pw, mWaitingVisibleActivities, " ", "Wait", false, !dumpAll, false, dumpPackage, true, " Activities waiting for another to become visible:", null); printed |= dumpHistoryList(fd, pw, mActivitiesWaitingForVisibleActivity, " ", "Wait", false, !dumpAll, false, dumpPackage, true, " Activities waiting for another to become visible:", null); printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll, false, dumpPackage, true, " Activities waiting to sleep:", null); printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll, Loading Loading @@ -4995,4 +5020,38 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } return topActivityTokens; } /** * Internal container to store a match qualifier alongside a WaitResult. */ static class WaitInfo { private final ComponentName mTargetComponent; private final WaitResult mResult; public WaitInfo(ComponentName targetComponent, WaitResult result) { this.mTargetComponent = targetComponent; this.mResult = result; } public boolean matches(ActivityRecord record) { return mTargetComponent == null || (TextUtils.equals(mTargetComponent.getPackageName(), record.info.packageName) && TextUtils.equals(mTargetComponent.getClassName(), record.info.name)); } public WaitResult getResult() { return mResult; } public ComponentName getComponent() { return mTargetComponent; } public void dump(PrintWriter pw, String prefix) { pw.println(prefix + "WaitInfo:"); pw.println(prefix + " mTargetComponent=" + mTargetComponent); pw.println(prefix + " mResult="); mResult.dump(pw, prefix); } } } services/core/java/com/android/server/am/ActivityStarter.java +30 −27 Original line number Diff line number Diff line Loading @@ -118,14 +118,11 @@ import android.os.UserManager; import android.service.voice.IVoiceInteractionSession; import android.util.EventLog; import android.util.Slog; import android.view.Display; import com.android.internal.app.HeavyWeightSwitcherActivity; import com.android.internal.app.IVoiceInteractor; import com.android.server.LocalServices; import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch; import com.android.server.pm.InstantAppResolver; import com.android.server.vr.VrManagerInternal; import com.android.server.wm.WindowManagerService; import java.util.ArrayList; Loading @@ -152,7 +149,6 @@ class ActivityStarter { // Share state variable among methods when starting an activity. private ActivityRecord mStartActivity; private ActivityRecord mReusedActivity; private Intent mIntent; private int mCallingUid; private ActivityOptions mOptions; Loading Loading @@ -520,7 +516,7 @@ class ActivityStarter { doPendingActivityLaunchesLocked(false); return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true, options, inTask); options, inTask, outActivity); } /** Loading Loading @@ -821,15 +817,19 @@ class ActivityStarter { } } if (res == START_TASK_TO_FRONT) { ActivityRecord r = stack.topRunningActivityLocked(); final ActivityRecord r = outRecord[0]; // ActivityRecord may represent a different activity, but it should not be in // the resumed state. if (r.nowVisible && r.state == RESUMED) { outResult.timeout = false; outResult.who = new ComponentName(r.info.packageName, r.info.name); outResult.who = r.realActivity; outResult.totalTime = 0; outResult.thisTime = 0; } else { outResult.thisTime = SystemClock.uptimeMillis(); mSupervisor.mWaitingActivityVisible.add(outResult); mSupervisor.waitActivityVisible(r.realActivity, outResult); // Note: the timeout variable is not currently not ever set. do { try { mService.wait(); Loading @@ -840,9 +840,7 @@ class ActivityStarter { } } final ActivityRecord launchedActivity = mReusedActivity != null ? mReusedActivity : outRecord[0]; mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, launchedActivity); mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, outRecord[0]); return res; } } Loading Loading @@ -954,12 +952,13 @@ class ActivityStarter { private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) { int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask, ActivityRecord[] outActivity) { int result = START_CANCELED; try { mService.mWindowManager.deferSurfaceLayout(); result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags, doResume, options, inTask); startFlags, doResume, options, inTask, outActivity); } finally { // If we are not able to proceed, disassociate the activity from the task. Leaving an // activity in an incomplete state can lead to issues, such as performing operations Loading @@ -979,7 +978,8 @@ class ActivityStarter { // Note: This method should only be called from {@link startActivity}. private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) { int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask, ActivityRecord[] outActivity) { setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession, voiceInteractor); Loading @@ -990,16 +990,16 @@ class ActivityStarter { mIntent.setFlags(mLaunchFlags); mReusedActivity = getReusableIntentActivity(); ActivityRecord reusedActivity = getReusableIntentActivity(); final int preferredLaunchStackId = (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID; if (mReusedActivity != null) { if (reusedActivity != null) { // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but // still needs to be a lock task mode violation since the task gets cleared out and // the device would otherwise leave the locked task. if (mSupervisor.isLockTaskModeViolation(mReusedActivity.getTask(), if (mSupervisor.isLockTaskModeViolation(reusedActivity.getTask(), (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) { mSupervisor.showLockTaskToast(); Loading @@ -1008,12 +1008,12 @@ class ActivityStarter { } if (mStartActivity.getTask() == null) { mStartActivity.setTask(mReusedActivity.getTask()); mStartActivity.setTask(reusedActivity.getTask()); } if (mReusedActivity.getTask().intent == null) { if (reusedActivity.getTask().intent == null) { // This task was started because of movement of the activity based on affinity... // Now that we are actually launching it, we can assign the base intent. mReusedActivity.getTask().setIntent(mStartActivity); reusedActivity.getTask().setIntent(mStartActivity); } // This code path leads to delivering a new intent, we want to make sure we schedule it Loading @@ -1022,7 +1022,7 @@ class ActivityStarter { if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0 || isDocumentLaunchesIntoExisting(mLaunchFlags) || mLaunchSingleInstance || mLaunchSingleTask) { final TaskRecord task = mReusedActivity.getTask(); final TaskRecord task = reusedActivity.getTask(); // In this situation we want to remove all activities from the task up to the one // being started. In most cases this means we are resetting the task to its initial Loading @@ -1030,12 +1030,12 @@ class ActivityStarter { final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity, mLaunchFlags); // The above code can remove {@code mReusedActivity} from the task, leading to the // The above code can remove {@code reusedActivity} from the task, leading to the // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The // task reference is needed in the call below to // {@link setTargetStackAndMoveToFrontIfNeeded}. if (mReusedActivity.getTask() == null) { mReusedActivity.setTask(task); if (reusedActivity.getTask() == null) { reusedActivity.setTask(task); } if (top != null) { Loading @@ -1052,7 +1052,10 @@ class ActivityStarter { sendPowerHintForLaunchStartIfNeeded(false /* forceSend */); mReusedActivity = setTargetStackAndMoveToFrontIfNeeded(mReusedActivity); reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity); if (outActivity.length > 0) { outActivity[0] = reusedActivity; } if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) { // We don't need to start a new activity, and the client said not to do anything Loading @@ -1061,7 +1064,7 @@ class ActivityStarter { resumeTargetStackIfNeeded(); return START_RETURN_INTENT_TO_CALLER; } setTaskFromIntentActivity(mReusedActivity); setTaskFromIntentActivity(reusedActivity); if (!mAddingToTask && mReuseTask == null) { // We didn't do anything... but it was needed (a.k.a., client don't use that Loading Loading @@ -1963,7 +1966,7 @@ class ActivityStarter { final boolean resume = doResume && mPendingActivityLaunches.isEmpty(); try { startActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null); null, null /*outRecords*/); } catch (Exception e) { Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e); pal.sendErrorResult(e.getMessage()); Loading Loading
core/java/android/app/WaitResult.java +11 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ import android.content.ComponentName; import android.os.Parcel; import android.os.Parcelable; import java.io.PrintWriter; /** * Information returned after waiting for an activity start. * Loading Loading @@ -69,4 +71,13 @@ public class WaitResult implements Parcelable { thisTime = source.readLong(); totalTime = source.readLong(); } public void dump(PrintWriter pw, String prefix) { pw.println(prefix + "WaitResult:"); pw.println(prefix + " result=" + result); pw.println(prefix + " timeout=" + timeout); pw.println(prefix + " who=" + who); pw.println(prefix + " thisTime=" + thisTime); pw.println(prefix + " totalTime=" + totalTime); } } No newline at end of file
services/core/java/com/android/server/am/ActivityRecord.java +7 −5 Original line number Diff line number Diff line Loading @@ -505,7 +505,8 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo else TimeUtils.formatDuration(startTime, now, pw); pw.println(); } final boolean waitingVisible = mStackSupervisor.mWaitingVisibleActivities.contains(this); final boolean waitingVisible = mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(this); if (lastVisibleTime != 0 || waitingVisible || nowVisible) { pw.print(prefix); pw.print("waitingVisible="); pw.print(waitingVisible); pw.print(" nowVisible="); pw.print(nowVisible); Loading Loading @@ -1912,13 +1913,14 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo // If this activity was already idle, then we now need to make sure we perform // the full stop of any activities that are waiting to do so. This is because // we won't do that while they are still waiting for this one to become visible. final int size = mStackSupervisor.mWaitingVisibleActivities.size(); final int size = mStackSupervisor.mActivitiesWaitingForVisibleActivity.size(); if (size > 0) { for (int i = 0; i < size; i++) { ActivityRecord r = mStackSupervisor.mWaitingVisibleActivities.get(i); final ActivityRecord r = mStackSupervisor.mActivitiesWaitingForVisibleActivity.get(i); if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "Was waiting for visible: " + r); } mStackSupervisor.mWaitingVisibleActivities.clear(); mStackSupervisor.mActivitiesWaitingForVisibleActivity.clear(); mStackSupervisor.scheduleIdleLocked(); } } Loading Loading @@ -1959,7 +1961,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo // First find the real culprit... if this activity is waiting for // another activity to start or has stopped, then the key dispatching // timeout should not be caused by this. if (mStackSupervisor.mWaitingVisibleActivities.contains(this) || stopped) { if (mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(this) || stopped) { final ActivityStack stack = mStackSupervisor.getFocusedStack(); // Try to use the one which is closest to top. ActivityRecord r = stack.mResumedActivity; Loading
services/core/java/com/android/server/am/ActivityStack.java +14 −17 Original line number Diff line number Diff line Loading @@ -116,7 +116,6 @@ import android.util.Slog; import android.util.SparseArray; import android.view.Display; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IVoiceInteractor; import com.android.internal.os.BatteryStatsImpl; import com.android.server.Watchdog; Loading Loading @@ -1349,7 +1348,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } else if (prev.app != null) { if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueue pending stop if needed: " + prev + " wasStopping=" + wasStopping + " visible=" + prev.visible); if (mStackSupervisor.mWaitingVisibleActivities.remove(prev)) { if (mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(prev)) { if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause, no longer waiting: " + prev); } Loading Loading @@ -2262,7 +2261,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mStackSupervisor.mStoppingActivities.remove(next); mStackSupervisor.mGoingToSleepActivities.remove(next); next.sleeping = false; mStackSupervisor.mWaitingVisibleActivities.remove(next); mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(next); if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next); Loading Loading @@ -2324,9 +2323,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } if (prev != null && prev != next) { if (!mStackSupervisor.mWaitingVisibleActivities.contains(prev) if (!mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev) && next != null && !next.nowVisible) { mStackSupervisor.mWaitingVisibleActivities.add(prev); mStackSupervisor.mActivitiesWaitingForVisibleActivity.add(prev); if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming top, waiting visible to hide: " + prev); } else { Loading @@ -2342,13 +2341,13 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai prev.setVisibility(false); if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Not waiting for visible to hide: " + prev + ", waitingVisible=" + mStackSupervisor.mWaitingVisibleActivities.contains(prev) + mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev) + ", nowVisible=" + next.nowVisible); } else { if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Previous already visible but still waiting to hide: " + prev + ", waitingVisible=" + mStackSupervisor.mWaitingVisibleActivities.contains(prev) + mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev) + ", nowVisible=" + next.nowVisible); } } Loading Loading @@ -3617,8 +3616,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mWindowManager.prepareAppTransition(transit, false); r.setVisibility(false); mWindowManager.executeAppTransition(); if (!mStackSupervisor.mWaitingVisibleActivities.contains(r)) { mStackSupervisor.mWaitingVisibleActivities.add(r); if (!mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(r)) { mStackSupervisor.mActivitiesWaitingForVisibleActivity.add(r); } } Loading Loading @@ -3650,7 +3649,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // make sure the record is cleaned out of other places. mStackSupervisor.mStoppingActivities.remove(r); mStackSupervisor.mGoingToSleepActivities.remove(r); mStackSupervisor.mWaitingVisibleActivities.remove(r); mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(r); if (mResumedActivity == r) { mResumedActivity = null; } Loading Loading @@ -3870,11 +3869,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai r.app = null; } // Make sure this record is no longer in the pending finishes list. // This could happen, for example, if we are trimming activities // down to the max limit while they are still waiting to finish. mStackSupervisor.mFinishingActivities.remove(r); mStackSupervisor.mWaitingVisibleActivities.remove(r); // Inform supervisor the activity has been removed. mStackSupervisor.cleanupActivity(r); // Remove any pending results. if (r.finishing && r.pendingResults != null) { Loading Loading @@ -4253,8 +4250,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai "mStoppingActivities"); removeHistoryRecordsForAppLocked(mStackSupervisor.mGoingToSleepActivities, app, "mGoingToSleepActivities"); removeHistoryRecordsForAppLocked(mStackSupervisor.mWaitingVisibleActivities, app, "mWaitingVisibleActivities"); removeHistoryRecordsForAppLocked(mStackSupervisor.mActivitiesWaitingForVisibleActivity, app, "mActivitiesWaitingForVisibleActivity"); removeHistoryRecordsForAppLocked(mStackSupervisor.mFinishingActivities, app, "mFinishingActivities"); Loading
services/core/java/com/android/server/am/ActivityStackSupervisor.java +81 −22 Original line number Diff line number Diff line Loading @@ -153,6 +153,7 @@ import android.provider.MediaStore; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.service.voice.IVoiceInteractionSession; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.EventLog; Loading @@ -164,7 +165,6 @@ import android.view.Display; import android.view.InputEvent; import android.view.Surface; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.content.ReferrerIntent; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; Loading @@ -174,7 +174,6 @@ import com.android.internal.util.ArrayUtils; import com.android.internal.widget.LockPatternUtils; import com.android.server.LocalServices; import com.android.server.am.ActivityStack.ActivityState; import com.android.server.wm.StackWindowController; import com.android.server.wm.WindowManagerService; import java.io.FileDescriptor; Loading Loading @@ -346,10 +345,12 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D /** List of activities that are waiting for a new activity to become visible before completing * whatever operation they are supposed to do. */ final ArrayList<ActivityRecord> mWaitingVisibleActivities = new ArrayList<>(); // TODO: Remove mActivitiesWaitingForVisibleActivity list and just remove activity from // mStoppingActivities when something else comes up. final ArrayList<ActivityRecord> mActivitiesWaitingForVisibleActivity = new ArrayList<>(); /** List of processes waiting to find out about the next visible activity. */ final ArrayList<WaitResult> mWaitingActivityVisible = new ArrayList<>(); /** List of processes waiting to find out when a specific activity becomes visible. */ private final ArrayList<WaitInfo> mWaitingForActivityVisible = new ArrayList<>(); /** List of processes waiting to find out about the next launched activity. */ final ArrayList<WaitResult> mWaitingActivityLaunched = new ArrayList<>(); Loading Loading @@ -1003,7 +1004,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D final ActivityStack stack = stacks.get(stackNdx); final ActivityRecord r = stack.mResumedActivity; if (r != null) { if (!r.nowVisible || mWaitingVisibleActivities.contains(r)) { if (!r.nowVisible || mActivitiesWaitingForVisibleActivity.contains(r)) { return false; } foundResumed = true; Loading Loading @@ -1083,22 +1084,41 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } } void waitActivityVisible(ComponentName name, WaitResult result) { final WaitInfo waitInfo = new WaitInfo(name, result); mWaitingForActivityVisible.add(waitInfo); } void cleanupActivity(ActivityRecord r) { // Make sure this record is no longer in the pending finishes list. // This could happen, for example, if we are trimming activities // down to the max limit while they are still waiting to finish. mFinishingActivities.remove(r); mActivitiesWaitingForVisibleActivity.remove(r); for (int i = mWaitingForActivityVisible.size() - 1; i >= 0; --i) { if (mWaitingForActivityVisible.get(i).matches(r)) { mWaitingForActivityVisible.remove(i); } } } void reportActivityVisibleLocked(ActivityRecord r) { sendWaitingVisibleReportLocked(r); } void sendWaitingVisibleReportLocked(ActivityRecord r) { boolean changed = false; for (int i = mWaitingActivityVisible.size()-1; i >= 0; i--) { WaitResult w = mWaitingActivityVisible.get(i); if (w.who == null) { for (int i = mWaitingForActivityVisible.size() - 1; i >= 0; --i) { final WaitInfo w = mWaitingForActivityVisible.get(i); if (w.matches(r)) { final WaitResult result = w.getResult(); changed = true; w.timeout = false; if (r != null) { w.who = new ComponentName(r.info.packageName, r.info.name); } w.totalTime = SystemClock.uptimeMillis() - w.thisTime; w.thisTime = w.totalTime; result.timeout = false; result.who = w.getComponent(); result.totalTime = SystemClock.uptimeMillis() - result.thisTime; result.thisTime = result.totalTime; mWaitingForActivityVisible.remove(w); } } if (changed) { Loading Loading @@ -3421,13 +3441,11 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D final boolean nowVisible = allResumedActivitiesVisible(); for (int activityNdx = mStoppingActivities.size() - 1; activityNdx >= 0; --activityNdx) { ActivityRecord s = mStoppingActivities.get(activityNdx); // TODO: Remove mWaitingVisibleActivities list and just remove activity from // mStoppingActivities when something else comes up. boolean waitingVisible = mWaitingVisibleActivities.contains(s); boolean waitingVisible = mActivitiesWaitingForVisibleActivity.contains(s); if (DEBUG_STATES) Slog.v(TAG, "Stopping " + s + ": nowVisible=" + nowVisible + " waitingVisible=" + waitingVisible + " finishing=" + s.finishing); if (waitingVisible && nowVisible) { mWaitingVisibleActivities.remove(s); mActivitiesWaitingForVisibleActivity.remove(s); waitingVisible = false; if (s.finishing) { // If this activity is finishing, it is sitting on top of Loading Loading @@ -3520,6 +3538,13 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D pw.print(":"); pw.println(Arrays.toString(packages.valueAt(i))); } } if (!mWaitingForActivityVisible.isEmpty()) { pw.print(prefix); pw.println("mWaitingForActivityVisible="); for (int i = 0; i < mWaitingForActivityVisible.size(); ++i) { pw.print(prefix); pw.print(prefix); mWaitingForActivityVisible.get(i).dump(pw, prefix); } } pw.println(" mLockTaskModeTasks" + mLockTaskModeTasks); mKeyguardController.dump(pw, prefix); } Loading Loading @@ -3642,9 +3667,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D false, dumpPackage, true, " Activities waiting to finish:", null); printed |= dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll, false, dumpPackage, true, " Activities waiting to stop:", null); printed |= dumpHistoryList(fd, pw, mWaitingVisibleActivities, " ", "Wait", false, !dumpAll, false, dumpPackage, true, " Activities waiting for another to become visible:", null); printed |= dumpHistoryList(fd, pw, mActivitiesWaitingForVisibleActivity, " ", "Wait", false, !dumpAll, false, dumpPackage, true, " Activities waiting for another to become visible:", null); printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll, false, dumpPackage, true, " Activities waiting to sleep:", null); printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll, Loading Loading @@ -4995,4 +5020,38 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } return topActivityTokens; } /** * Internal container to store a match qualifier alongside a WaitResult. */ static class WaitInfo { private final ComponentName mTargetComponent; private final WaitResult mResult; public WaitInfo(ComponentName targetComponent, WaitResult result) { this.mTargetComponent = targetComponent; this.mResult = result; } public boolean matches(ActivityRecord record) { return mTargetComponent == null || (TextUtils.equals(mTargetComponent.getPackageName(), record.info.packageName) && TextUtils.equals(mTargetComponent.getClassName(), record.info.name)); } public WaitResult getResult() { return mResult; } public ComponentName getComponent() { return mTargetComponent; } public void dump(PrintWriter pw, String prefix) { pw.println(prefix + "WaitInfo:"); pw.println(prefix + " mTargetComponent=" + mTargetComponent); pw.println(prefix + " mResult="); mResult.dump(pw, prefix); } } }
services/core/java/com/android/server/am/ActivityStarter.java +30 −27 Original line number Diff line number Diff line Loading @@ -118,14 +118,11 @@ import android.os.UserManager; import android.service.voice.IVoiceInteractionSession; import android.util.EventLog; import android.util.Slog; import android.view.Display; import com.android.internal.app.HeavyWeightSwitcherActivity; import com.android.internal.app.IVoiceInteractor; import com.android.server.LocalServices; import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch; import com.android.server.pm.InstantAppResolver; import com.android.server.vr.VrManagerInternal; import com.android.server.wm.WindowManagerService; import java.util.ArrayList; Loading @@ -152,7 +149,6 @@ class ActivityStarter { // Share state variable among methods when starting an activity. private ActivityRecord mStartActivity; private ActivityRecord mReusedActivity; private Intent mIntent; private int mCallingUid; private ActivityOptions mOptions; Loading Loading @@ -520,7 +516,7 @@ class ActivityStarter { doPendingActivityLaunchesLocked(false); return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true, options, inTask); options, inTask, outActivity); } /** Loading Loading @@ -821,15 +817,19 @@ class ActivityStarter { } } if (res == START_TASK_TO_FRONT) { ActivityRecord r = stack.topRunningActivityLocked(); final ActivityRecord r = outRecord[0]; // ActivityRecord may represent a different activity, but it should not be in // the resumed state. if (r.nowVisible && r.state == RESUMED) { outResult.timeout = false; outResult.who = new ComponentName(r.info.packageName, r.info.name); outResult.who = r.realActivity; outResult.totalTime = 0; outResult.thisTime = 0; } else { outResult.thisTime = SystemClock.uptimeMillis(); mSupervisor.mWaitingActivityVisible.add(outResult); mSupervisor.waitActivityVisible(r.realActivity, outResult); // Note: the timeout variable is not currently not ever set. do { try { mService.wait(); Loading @@ -840,9 +840,7 @@ class ActivityStarter { } } final ActivityRecord launchedActivity = mReusedActivity != null ? mReusedActivity : outRecord[0]; mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, launchedActivity); mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, outRecord[0]); return res; } } Loading Loading @@ -954,12 +952,13 @@ class ActivityStarter { private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) { int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask, ActivityRecord[] outActivity) { int result = START_CANCELED; try { mService.mWindowManager.deferSurfaceLayout(); result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags, doResume, options, inTask); startFlags, doResume, options, inTask, outActivity); } finally { // If we are not able to proceed, disassociate the activity from the task. Leaving an // activity in an incomplete state can lead to issues, such as performing operations Loading @@ -979,7 +978,8 @@ class ActivityStarter { // Note: This method should only be called from {@link startActivity}. private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) { int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask, ActivityRecord[] outActivity) { setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession, voiceInteractor); Loading @@ -990,16 +990,16 @@ class ActivityStarter { mIntent.setFlags(mLaunchFlags); mReusedActivity = getReusableIntentActivity(); ActivityRecord reusedActivity = getReusableIntentActivity(); final int preferredLaunchStackId = (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID; if (mReusedActivity != null) { if (reusedActivity != null) { // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but // still needs to be a lock task mode violation since the task gets cleared out and // the device would otherwise leave the locked task. if (mSupervisor.isLockTaskModeViolation(mReusedActivity.getTask(), if (mSupervisor.isLockTaskModeViolation(reusedActivity.getTask(), (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) { mSupervisor.showLockTaskToast(); Loading @@ -1008,12 +1008,12 @@ class ActivityStarter { } if (mStartActivity.getTask() == null) { mStartActivity.setTask(mReusedActivity.getTask()); mStartActivity.setTask(reusedActivity.getTask()); } if (mReusedActivity.getTask().intent == null) { if (reusedActivity.getTask().intent == null) { // This task was started because of movement of the activity based on affinity... // Now that we are actually launching it, we can assign the base intent. mReusedActivity.getTask().setIntent(mStartActivity); reusedActivity.getTask().setIntent(mStartActivity); } // This code path leads to delivering a new intent, we want to make sure we schedule it Loading @@ -1022,7 +1022,7 @@ class ActivityStarter { if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0 || isDocumentLaunchesIntoExisting(mLaunchFlags) || mLaunchSingleInstance || mLaunchSingleTask) { final TaskRecord task = mReusedActivity.getTask(); final TaskRecord task = reusedActivity.getTask(); // In this situation we want to remove all activities from the task up to the one // being started. In most cases this means we are resetting the task to its initial Loading @@ -1030,12 +1030,12 @@ class ActivityStarter { final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity, mLaunchFlags); // The above code can remove {@code mReusedActivity} from the task, leading to the // The above code can remove {@code reusedActivity} from the task, leading to the // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The // task reference is needed in the call below to // {@link setTargetStackAndMoveToFrontIfNeeded}. if (mReusedActivity.getTask() == null) { mReusedActivity.setTask(task); if (reusedActivity.getTask() == null) { reusedActivity.setTask(task); } if (top != null) { Loading @@ -1052,7 +1052,10 @@ class ActivityStarter { sendPowerHintForLaunchStartIfNeeded(false /* forceSend */); mReusedActivity = setTargetStackAndMoveToFrontIfNeeded(mReusedActivity); reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity); if (outActivity.length > 0) { outActivity[0] = reusedActivity; } if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) { // We don't need to start a new activity, and the client said not to do anything Loading @@ -1061,7 +1064,7 @@ class ActivityStarter { resumeTargetStackIfNeeded(); return START_RETURN_INTENT_TO_CALLER; } setTaskFromIntentActivity(mReusedActivity); setTaskFromIntentActivity(reusedActivity); if (!mAddingToTask && mReuseTask == null) { // We didn't do anything... but it was needed (a.k.a., client don't use that Loading Loading @@ -1963,7 +1966,7 @@ class ActivityStarter { final boolean resume = doResume && mPendingActivityLaunches.isEmpty(); try { startActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null); null, null /*outRecords*/); } catch (Exception e) { Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e); pal.sendErrorResult(e.getMessage()); Loading