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

Commit dd15c42d authored by Riddle Hsu's avatar Riddle Hsu Committed by Android (Google) Code Review
Browse files

Merge "Optimize attaching process for starting activity" into main

parents 020580d7 b8028fae
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
@@ -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);
    }

+27 −1
Original line number Diff line number Diff line
@@ -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 */);
                            }
                        }
                    }
                }
            }
        }

+32 −70
Original line number Diff line number Diff line
@@ -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 {
        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 {
            return mAttachApplicationHelper.process(app);
        } finally {
            mAttachApplicationHelper.reset();
                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;
        }
    }
}
+19 −0
Original line number Diff line number Diff line
@@ -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.