diff options
4 files changed, 85 insertions, 74 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 42373aa85053..bf094ed57545 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -4479,6 +4479,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A getDisplayContent().mOpeningApps.remove(this); getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this); mWmService.mSnapshotController.onAppRemoved(this); + mAtmService.mStartingProcessActivities.remove(this); mTaskSupervisor.getActivityMetricsLogger().notifyActivityRemoved(this); mTaskSupervisor.mStoppingActivities.remove(this); @@ -6221,6 +6222,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } boolean shouldBeVisible() { + return shouldBeVisible(false /* ignoringKeyguard */); + } + + boolean shouldBeVisible(boolean ignoringKeyguard) { final Task task = getTask(); if (task == null) { return false; @@ -6228,7 +6233,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A final boolean behindOccludedContainer = !task.shouldBeVisible(null /* starting */) || task.getOccludingActivityAbove(this) != null; - return shouldBeVisible(behindOccludedContainer, false /* ignoringKeyguard */); + return shouldBeVisible(behindOccludedContainer, ignoringKeyguard); } void makeVisibleIfNeeded(ActivityRecord starting, boolean reportToClient) { @@ -10510,8 +10515,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (!getTurnScreenOnFlag()) { return false; } - final Task rootTask = getRootTask(); - return mCurrentLaunchCanTurnScreenOn && rootTask != null + return mCurrentLaunchCanTurnScreenOn && mTaskSupervisor.getKeyguardController().checkKeyguardVisibility(this); } diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index a0f615b1ea58..d984fb14f523 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -390,6 +390,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { final VisibleActivityProcessTracker mVisibleActivityProcessTracker; + /** The starting activities which are waiting for their processes to attach. */ + final ArrayList<ActivityRecord> mStartingProcessActivities = new ArrayList<>(); + /* Global service lock used by the package the owns this service. */ final WindowManagerGlobalLock mGlobalLock = new WindowManagerGlobalLock(); /** @@ -4331,6 +4334,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { if (mDemoteTopAppReasons != 0) { pw.println(" mDemoteTopAppReasons=" + mDemoteTopAppReasons); } + if (!mStartingProcessActivities.isEmpty()) { + pw.println(" mStartingProcessActivities=" + mStartingProcessActivities); + } } if (!printedAnything) { @@ -5178,6 +5184,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop, String hostingType) { + if (!mStartingProcessActivities.contains(activity)) { + mStartingProcessActivities.add(activity); + } else if (mProcessNames.get( + activity.processName, activity.info.applicationInfo.uid) != null) { + // The process is already starting. Wait for it to attach. + return; + } try { if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) { Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "dispatchingStartProcess:" @@ -6174,7 +6187,20 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @Override public void onProcessRemoved(String name, int uid) { synchronized (mGlobalLockWithoutBoost) { - mProcessNames.remove(name, uid); + final WindowProcessController proc = mProcessNames.remove(name, uid); + if (proc != null && !mStartingProcessActivities.isEmpty()) { + for (int i = mStartingProcessActivities.size() - 1; i >= 0; i--) { + final ActivityRecord r = mStartingProcessActivities.get(i); + if (uid == r.info.applicationInfo.uid && name.equals(r.processName)) { + Slog.w(TAG, proc + " is removed with pending start " + r); + mStartingProcessActivities.remove(i); + // If visible, finish it to avoid getting stuck on screen. + if (r.isVisibleRequested()) { + r.finishIfPossible("starting-proc-removed", false /* oomAdj */); + } + } + } + } } } diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index e9a877e6013d..1e88fe444ea9 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -72,7 +72,6 @@ import static com.android.server.wm.RootWindowContainerProto.KEYGUARD_CONTROLLER import static com.android.server.wm.RootWindowContainerProto.WINDOW_CONTAINER; import static com.android.server.wm.Task.REPARENT_LEAVE_ROOT_TASK_IN_PLACE; import static com.android.server.wm.Task.REPARENT_MOVE_ROOT_TASK_TO_FRONT; -import static com.android.server.wm.TaskFragment.TASK_FRAGMENT_VISIBILITY_INVISIBLE; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; @@ -270,8 +269,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> private int mTmpTaskLayerRank; private final RankTaskLayersRunnable mRankTaskLayersRunnable = new RankTaskLayersRunnable(); - private final AttachApplicationHelper mAttachApplicationHelper = new AttachApplicationHelper(); - private String mDestroyAllActivitiesReason; private final Runnable mDestroyAllActivitiesRunnable = new Runnable() { @Override @@ -1838,11 +1835,39 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } boolean attachApplication(WindowProcessController app) throws RemoteException { - try { - return mAttachApplicationHelper.process(app); - } finally { - mAttachApplicationHelper.reset(); + final ArrayList<ActivityRecord> activities = mService.mStartingProcessActivities; + RemoteException remoteException = null; + boolean hasActivityStarted = false; + for (int i = activities.size() - 1; i >= 0; i--) { + final ActivityRecord r = activities.get(i); + if (app.mUid != r.info.applicationInfo.uid || !app.mName.equals(r.processName)) { + // The attaching process does not match the starting activity. + continue; + } + // Consume the pending record. + activities.remove(i); + final TaskFragment tf = r.getTaskFragment(); + if (tf == null || r.finishing || r.app != null + // Ignore keyguard because the app may use show-when-locked when creating. + || !r.shouldBeVisible(true /* ignoringKeyguard */) + || !r.showToCurrentUser()) { + continue; + } + try { + final boolean canResume = r.isFocusable() && r == tf.topRunningActivity(); + if (mTaskSupervisor.realStartActivityLocked(r, app, canResume, + true /* checkConfig */)) { + hasActivityStarted = true; + } + } catch (RemoteException e) { + Slog.w(TAG, "Exception in new process when starting " + r, e); + remoteException = e; + } + } + if (remoteException != null) { + throw remoteException; } + return hasActivityStarted; } /** @@ -3748,67 +3773,4 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } } } - - private class AttachApplicationHelper implements Consumer<Task>, Predicate<ActivityRecord> { - private boolean mHasActivityStarted; - private RemoteException mRemoteException; - private WindowProcessController mApp; - private ActivityRecord mTop; - - void reset() { - mHasActivityStarted = false; - mRemoteException = null; - mApp = null; - mTop = null; - } - - boolean process(WindowProcessController app) throws RemoteException { - mApp = app; - for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) { - getChildAt(displayNdx).forAllRootTasks(this); - if (mRemoteException != null) { - throw mRemoteException; - } - } - if (!mHasActivityStarted) { - ensureActivitiesVisible(); - } - return mHasActivityStarted; - } - - @Override - public void accept(Task rootTask) { - if (mRemoteException != null) { - return; - } - if (rootTask.getVisibility(null /* starting */) - == TASK_FRAGMENT_VISIBILITY_INVISIBLE) { - return; - } - mTop = rootTask.topRunningActivity(); - rootTask.forAllActivities(this); - } - - @Override - public boolean test(ActivityRecord r) { - if (r.finishing || !r.showToCurrentUser() || !r.visibleIgnoringKeyguard - || r.app != null || mApp.mUid != r.info.applicationInfo.uid - || !mApp.mName.equals(r.processName)) { - return false; - } - - try { - if (mTaskSupervisor.realStartActivityLocked(r, mApp, - mTop == r && r.getTask().canBeResumed(r) /* andResume */, - true /* checkConfig */)) { - mHasActivityStarted = true; - } - } catch (RemoteException e) { - Slog.w(TAG, "Exception in new application when starting activity " + mTop, e); - mRemoteException = e; - return true; - } - return false; - } - } } diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java index 649f5207e88f..dcf3dadcf5a3 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java @@ -74,6 +74,7 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Rect; import android.os.PowerManager; +import android.os.RemoteException; import android.os.UserHandle; import android.platform.test.annotations.Presubmit; import android.util.Pair; @@ -237,6 +238,24 @@ public class RootWindowContainerTests extends WindowTestsBase { assertFalse(wpc.hasActivities()); } + @Test + public void testAttachApplication() { + final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build(); + activity.detachFromProcess(); + mAtm.startProcessAsync(activity, false /* knownToBeDead */, + true /* isTop */, "test" /* hostingType */); + final WindowProcessController proc = mSystemServicesTestRule.addProcess( + activity.packageName, activity.processName, + 6789 /* pid */, activity.info.applicationInfo.uid); + try { + mRootWindowContainer.attachApplication(proc); + verify(mSupervisor).realStartActivityLocked(eq(activity), eq(proc), anyBoolean(), + anyBoolean()); + } catch (RemoteException e) { + e.rethrowAsRuntimeException(); + } + } + /** * This test ensures that we do not try to restore a task based off an invalid task id. We * should expect {@code null} to be returned in this case. |