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

Commit 17e38420 authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Ensure to update top process state when launching activity

- Combine addPackage, clearWaitingToKill and updateProcessInfo
  into onStartActivity that reduces the amount of messages and
  acquiring lock.
- Invoke onStartActivity after setting activity state to ensure
  oom adjustment uses the latest state (currently the order is
  ensured by lock contention but it is too implicit).
- Make the message of onStartActivity always enqueue at front so
  the process can gain the top state earlier.

Test: AppLaunchTest
Bug: 123043091
Change-Id: Id8d00273a5dc88526c3c158c49423c15fb99a0d5
parent 4f1adafc
Loading
Loading
Loading
Loading
+11 −19
Original line number Diff line number Diff line
@@ -878,13 +878,6 @@ class ProcessRecord implements WindowProcessListener {
        return null;
    }

    @Override
    public void addPackage(String pkg, long versionCode) {
        synchronized (mService) {
            addPackage(pkg, versionCode, mService.mProcessStats);
        }
    }

    /*
     *  Return true if package has been added false if not
     */
@@ -1302,15 +1295,13 @@ class ProcessRecord implements WindowProcessListener {
    }

    @Override
    public void updateProcessInfo(boolean updateServiceConnectionActivities, boolean updateLru,
            boolean activityChange, boolean updateOomAdj) {
    public void updateProcessInfo(boolean updateServiceConnectionActivities, boolean activityChange,
            boolean updateOomAdj) {
        synchronized (mService) {
            if (updateServiceConnectionActivities) {
                mService.mServices.updateServiceConnectionActivitiesLocked(this);
            }
            if (updateLru) {
                mService.mProcessList.updateLruProcessLocked(this, activityChange, null);
            }
            mService.mProcessList.updateLruProcessLocked(this, activityChange, null /* client */);
            if (updateOomAdj) {
                mService.updateOomAdjLocked();
            }
@@ -1332,19 +1323,20 @@ class ProcessRecord implements WindowProcessListener {
    }

    @Override
    public void clearWaitingToKill() {
    public void onStartActivity(int topProcessState, boolean setProfileProc, String packageName,
            long versionCode) {
        synchronized (mService) {
            waitingToKill = null;
        }
    }

    @Override
    public void onStartActivity(int topProcessState, boolean setProfileProc) {
        synchronized (mService) {
            if (setProfileProc) {
                mService.mProfileData.setProfileProc(this);
            }
            if (packageName != null) {
                addPackage(packageName, versionCode, mService.mProcessStats);
            }

            // Update oom adj first, we don't want the additional states are involved in this round.
            updateProcessInfo(false /* updateServiceConnectionActivities */,
                    true /* activityChange */, true /* updateOomAdj */);
            hasShownUi = true;
            setPendingUiClean(true);
            forceProcessStateUpTo(topProcessState);
+4 −3
Original line number Diff line number Diff line
@@ -2753,7 +2753,7 @@ class ActivityStack extends ConfigurationContainer {
            // happens to be sitting towards the end.
            if (next.attachedToProcess()) {
                next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
                        true /* updateLru */, true /* activityChange */, false /* updateOomAdj */);
                        true /* activityChange */, false /* updateOomAdj */);
            }
            if (lastResumed != null) {
                lastResumed.setWillCloseOrEnterPip(true);
@@ -2903,7 +2903,7 @@ class ActivityStack extends ConfigurationContainer {
            next.setState(RESUMED, "resumeTopActivityInnerLocked");

            next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
                    true /* updateLru */, true /* activityChange */, true /* updateOomAdj */);
                    true /* activityChange */, true /* updateOomAdj */);
            updateLRUListLocked(next);

            // Have the window manager re-evaluate the orientation of
@@ -4600,7 +4600,8 @@ class ActivityStack extends ConfigurationContainer {
                    // Update any services we are bound to that might care about whether
                    // their client may have activities.
                    // No longer have activities, so update LRU list and oom adj.
                    r.app.updateProcessInfo(true, true, false, true);
                    r.app.updateProcessInfo(true /* updateServiceConnectionActivities */,
                            false /* activityChange */, true /* updateOomAdj */);
                }
            }

+4 −11
Original line number Diff line number Diff line
@@ -769,14 +769,12 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
                                + " old=" + r.app + " new=" + proc);
            }

            proc.clearWaitingToKill();
            r.launchCount++;
            r.lastLaunchTime = SystemClock.uptimeMillis();

            if (DEBUG_ALL) Slog.v(TAG, "Launching: " + r);

            proc.addActivityIfNeeded(r);
            proc.updateProcessInfo(false, true, true, true);

            final LockTaskController lockTaskController = mService.getLockTaskController();
            if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE
@@ -814,7 +812,6 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
                r.forceNewConfig = false;
                mService.getAppWarningsLocked().onStartActivity(r);
                r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
                ProfilerInfo profilerInfo = proc.onStartActivity(mService.mTopProcessState);

                // Because we could be starting an Activity in the system process this may not go
                // across a Binder interface which would create a new Configuration. Consequently
@@ -840,7 +837,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
                        mergedConfiguration.getOverrideConfiguration(), r.compat,
                        r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
                        r.icicle, r.persistentState, results, newIntents,
                        dc.isNextTransitionForward(), profilerInfo));
                        dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded()));

                // Set desired final state.
                final ActivityLifecycleItem lifecycleItem;
@@ -910,6 +907,9 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
                    "Moving to PAUSED: " + r + " (starting in paused state)");
            r.setState(PAUSED, "realStartActivityLocked");
        }
        // Perform OOM scoring after the activity state is set, so the process can be updated with
        // the latest state.
        proc.onStartActivity(mService.mTopProcessState, r.info);

        // Launch the new version setup screen if needed.  We do this -after-
        // launching the initial activity (that is, home), so that it can have
@@ -960,13 +960,6 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
        boolean knownToBeDead = false;
        if (wpc != null && wpc.hasThread()) {
            try {
                if ((r.info.flags & ActivityInfo.FLAG_MULTIPROCESS) == 0
                        || !"android".equals(r.info.packageName)) {
                    // Don't add this if it is a platform component that is marked to run in
                    // multiple processes, because this is actually part of the framework so doesn't
                    // make sense to track as a separate apk in the process.
                    wpc.addPackage(r.info.packageName, r.info.applicationInfo.longVersionCode);
                }
                realStartActivityLocked(r, wpc, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
+36 −45
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import android.app.IApplicationThread;
import android.app.ProfilerInfo;
import android.app.servertransaction.ConfigurationChangeItem;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
import android.os.Message;
@@ -771,13 +772,12 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
                WindowProcessListener::clearProfilerIfNeeded, mListener));
    }

    void updateProcessInfo(boolean updateServiceConnectionActivities, boolean updateLru,
            boolean activityChange, boolean updateOomAdj) {
    void updateProcessInfo(boolean updateServiceConnectionActivities, boolean activityChange,
            boolean updateOomAdj) {
        if (mListener == null) return;
        // Posting on handler so WM lock isn't held when we call into AM.
        final Message m = PooledLambda.obtainMessage(WindowProcessListener::updateProcessInfo,
                mListener, updateServiceConnectionActivities, updateLru, activityChange,
                updateOomAdj);
                mListener, updateServiceConnectionActivities, activityChange, updateOomAdj);
        mAtm.mH.sendMessage(m);
    }

@@ -801,53 +801,44 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
        return mListener == null ? false : mListener.isRemoved();
    }

    void clearWaitingToKill() {
        if (mListener == null) return;
        // Posting on handler so WM lock isn't held when we call into AM.
        final Message m = PooledLambda.obtainMessage(
                WindowProcessListener::clearWaitingToKill, mListener);
        mAtm.mH.sendMessage(m);
    private boolean shouldSetProfileProc() {
        return mAtm.mProfileApp != null && mAtm.mProfileApp.equals(mName)
                && (mAtm.mProfileProc == null || mAtm.mProfileProc == this);
    }

    void addPackage(String pkg, long versionCode) {
        if (mListener == null) return;
        // Posting on handler so WM lock isn't held when we call into AM.
        final Message m = PooledLambda.obtainMessage(
                WindowProcessListener::addPackage, mListener, pkg, versionCode);
        mAtm.mH.sendMessage(m);
    ProfilerInfo createProfilerInfoIfNeeded() {
        final ProfilerInfo currentProfilerInfo = mAtm.mProfilerInfo;
        if (currentProfilerInfo == null || currentProfilerInfo.profileFile == null
                || !shouldSetProfileProc()) {
            return null;
        }

    ProfilerInfo onStartActivity(int topProcessState) {
        ProfilerInfo profilerInfo = null;
        boolean setProfileProc = false;
        if (mAtm.mProfileApp != null
                && mAtm.mProfileApp.equals(mName)) {
            if (mAtm.mProfileProc == null || mAtm.mProfileProc == this) {
                setProfileProc = true;
                final ProfilerInfo profilerInfoSvc = mAtm.mProfilerInfo;
                if (profilerInfoSvc != null && profilerInfoSvc.profileFile != null) {
                    if (profilerInfoSvc.profileFd != null) {
        if (currentProfilerInfo.profileFd != null) {
            try {
                            profilerInfoSvc.profileFd = profilerInfoSvc.profileFd.dup();
                currentProfilerInfo.profileFd = currentProfilerInfo.profileFd.dup();
            } catch (IOException e) {
                            profilerInfoSvc.closeFd();
                        }
                    }

                    profilerInfo = new ProfilerInfo(profilerInfoSvc);
                currentProfilerInfo.closeFd();
            }
        }
        return new ProfilerInfo(currentProfilerInfo);
    }


        if (mListener != null) {
            // Posting on handler so WM lock isn't held when we call into AM.
    void onStartActivity(int topProcessState, ActivityInfo info) {
        if (mListener == null) return;
        String packageName = null;
        if ((info.flags & ActivityInfo.FLAG_MULTIPROCESS) == 0
                || !"android".equals(info.packageName)) {
            // Don't add this if it is a platform component that is marked to run in multiple
            // processes, because this is actually part of the framework so doesn't make sense
            // to track as a separate apk in the process.
            packageName = info.packageName;
        }
        // Posting the message at the front of queue so WM lock isn't held when we call into AM,
        // and the process state of starting activity can be updated quicker which will give it a
        // higher scheduling group.
        final Message m = PooledLambda.obtainMessage(WindowProcessListener::onStartActivity,
                    mListener, topProcessState, setProfileProc);
            mAtm.mH.sendMessage(m);
        }

        return profilerInfo;
                mListener, topProcessState, shouldSetProfileProc(), packageName,
                info.applicationInfo.longVersionCode);
        mAtm.mH.sendMessageAtFrontOfQueue(m);
    }

    public void appDied() {
+4 −9
Original line number Diff line number Diff line
@@ -41,8 +41,8 @@ public interface WindowProcessListener {
    void setPendingUiCleanAndForceProcessStateUpTo(int newState);

    /** Update the process information. */
    void updateProcessInfo(boolean updateServiceConnectionActivities, boolean updateLru,
            boolean activityChange, boolean updateOomAdj);
    void updateProcessInfo(boolean updateServiceConnectionActivities, boolean activityChange,
            boolean updateOomAdj);

    /**
     * Returns true if the process is removed and we should completely clean up the related records
@@ -53,14 +53,9 @@ public interface WindowProcessListener {
    /** Returns the total time (in milliseconds) spent executing in both user and system code. */
    long getCpuTime();

    /** Clears the waiting to kill reason for this process. */
    void clearWaitingToKill();

    /** Adds the package to the process. */
    void addPackage(String pkg, long versionCode);

    /** Called when we are in the process on starting an activity. */
    void onStartActivity(int topProcessState, boolean setProfileProc);
    void onStartActivity(int topProcessState, boolean setProfileProc, String packageName,
            long versionCode);

    /** App died :(...oh well */
    void appDied();