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

Commit c2c19c9a authored by Christopher Tate's avatar Christopher Tate
Browse files

Defer PSS collection while an activity is starting

Make sure not to process any requested PSS collections for a brief time
after an activity start is initiated, to reduce resource contention
during the launch.

Device config atom to configure:

  ActivityManager/activity_start_pss_defer

Milliseconds; defaults to zero (PSS deferral policy disabled)

Bug: 133433769
Test: manual
Change-Id: Icf5cf2e3dde0bd5fd3ab9c4a85adfb1f3382057f
parent 15f4e21d
Loading
Loading
Loading
Loading
+130 −1
Original line number Diff line number Diff line
@@ -272,6 +272,7 @@ import android.os.storage.IStorageManager;
import android.os.storage.StorageManager;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.provider.DeviceConfig.Properties;
import android.server.ServerProtoEnums;
import android.sysprop.VoldProperties;
import android.text.TextUtils;
@@ -356,6 +357,7 @@ import com.android.server.uri.UriGrantsManagerInternal;
import com.android.server.utils.PriorityDump;
import com.android.server.utils.TimingsTraceAndSlog;
import com.android.server.vr.VrManagerInternal;
import com.android.server.wm.ActivityMetricsLaunchObserver;
import com.android.server.wm.ActivityServiceConnectionsHolder;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.ActivityTaskManagerService;
@@ -392,6 +394,7 @@ import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.BiFunction;
@@ -861,6 +864,51 @@ public class ActivityManagerService extends IActivityManager.Stub
     */
    final ArrayList<ProcessRecord> mPendingPssProcesses = new ArrayList<ProcessRecord>();
    /**
     * Depth of overlapping activity-start PSS deferral notes
     */
    private final AtomicInteger mActivityStartingNesting = new AtomicInteger(0);
    private final ActivityMetricsLaunchObserver mActivityLaunchObserver =
            new ActivityMetricsLaunchObserver() {
        @Override
        public void onActivityLaunched(byte[] activity, int temperature) {
            // This is safe to force to the head of the queue because it relies only
            // on refcounting to track begin/end of deferrals, not on actual
            // message ordering.  We don't care *what* activity is being
            // launched; only that we're doing so.
            if (mPssDeferralTime > 0) {
                final Message msg = mBgHandler.obtainMessage(DEFER_PSS_MSG);
                mBgHandler.sendMessageAtFrontOfQueue(msg);
            }
        }
        // The other observer methods are unused
        @Override
        public void onIntentStarted(Intent intent) {
        }
        @Override
        public void onIntentFailed() {
        }
        @Override
        public void onActivityLaunchCancelled(byte[] abortingActivity) {
        }
        @Override
        public void onActivityLaunchFinished(byte[] finalActivity) {
        }
    };
    /**
     * How long we defer PSS gathering while activities are starting, in milliseconds.
     * This is adjustable via DeviceConfig.  If it is zero or negative, no PSS deferral
     * is done.
     */
    private volatile long mPssDeferralTime = 0;
    private static final String ACTIVITY_START_PSS_DEFER_CONFIG = "activity_start_pss_defer";
    private boolean mBinderTransactionTrackingEnabled = false;
    /**
@@ -874,6 +922,20 @@ public class ActivityManagerService extends IActivityManager.Stub
     */
    boolean mFullPssPending = false;
    /**
     * Observe DeviceConfig changes to the PSS calculation interval
     */
    private final DeviceConfig.OnPropertiesChangedListener mPssDelayConfigListener =
            new DeviceConfig.OnPropertiesChangedListener() {
                @Override
                public void onPropertiesChanged(Properties properties) {
                    mPssDeferralTime = properties.getLong(ACTIVITY_START_PSS_DEFER_CONFIG, 0);
                    if (DEBUG_PSS) {
                        Slog.d(TAG_PSS, "Activity-start PSS delay now "
                                + mPssDeferralTime + " ms");
                    }
                }
            };
    /**
     * This is for verifying the UID report flow.
@@ -1838,6 +1900,8 @@ public class ActivityManagerService extends IActivityManager.Stub
    }
    static final int COLLECT_PSS_BG_MSG = 1;
    static final int DEFER_PSS_MSG = 2;
    static final int STOP_DEFERRING_PSS_MSG = 3;
    final Handler mBgHandler = new Handler(BackgroundThread.getHandler().getLooper()) {
        @Override
@@ -1945,6 +2009,30 @@ public class ActivityManagerService extends IActivityManager.Stub
                    }
                } while (true);
            }
            case DEFER_PSS_MSG: {
                deferPssForActivityStart();
            } break;
            case STOP_DEFERRING_PSS_MSG: {
                final int nesting = mActivityStartingNesting.decrementAndGet();
                if (nesting <= 0) {
                    if (DEBUG_PSS) {
                        Slog.d(TAG_PSS, "PSS activity start deferral interval ended; now "
                                + nesting);
                    }
                    if (nesting < 0) {
                        Slog.wtf(TAG, "Activity start nesting undercount!");
                        mActivityStartingNesting.incrementAndGet();
                    }
                } else {
                    if (DEBUG_PSS) {
                        Slog.d(TAG_PSS, "Still deferring PSS, nesting=" + nesting);
                    }
                }
            }
            break;
            }
        }
    };
@@ -8832,6 +8920,12 @@ public class ActivityManagerService extends IActivityManager.Stub
                NETWORK_ACCESS_TIMEOUT_MS, NETWORK_ACCESS_TIMEOUT_DEFAULT_MS);
        mHiddenApiBlacklist.registerObserver();
        final long pssDeferralMs = DeviceConfig.getLong(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                ACTIVITY_START_PSS_DEFER_CONFIG, 0L);
        DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                ActivityThread.currentApplication().getMainExecutor(),
                mPssDelayConfigListener);
        synchronized (this) {
            mDebugApp = mOrigDebugApp = debugApp;
            mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
@@ -8848,6 +8942,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                    com.android.internal.R.bool.config_multiuserDelayUserDataLocking);
            mWaitForNetworkTimeoutMs = waitForNetworkTimeoutMs;
            mPssDeferralTime = pssDeferralMs;
        }
    }
@@ -8921,6 +9016,10 @@ public class ActivityManagerService extends IActivityManager.Stub
        mAtmInternal.updateTopComponentForFactoryTest();
        t.traceEnd();
        t.traceBegin("registerActivityLaunchObserver");
        mAtmInternal.getLaunchObserverRegistry().registerLaunchObserver(mActivityLaunchObserver);
        t.traceEnd();
        t.traceBegin("watchDeviceProvisioning");
        watchDeviceProvisioning(mContext);
        t.traceEnd();
@@ -16177,7 +16276,13 @@ public class ActivityManagerService extends IActivityManager.Stub
            return false;
        }
        if (mPendingPssProcesses.size() == 0) {
            mBgHandler.sendEmptyMessage(COLLECT_PSS_BG_MSG);
            final long deferral = (mPssDeferralTime > 0 && mActivityStartingNesting.get() > 0)
                    ? mPssDeferralTime : 0;
            if (DEBUG_PSS && deferral > 0) {
                Slog.d(TAG_PSS, "requestPssLocked() deferring PSS request by "
                        + deferral + " ms");
            }
            mBgHandler.sendEmptyMessageDelayed(COLLECT_PSS_BG_MSG, deferral);
        }
        if (DEBUG_PSS) Slog.d(TAG_PSS, "Requesting pss of: " + proc);
        proc.pssProcState = procState;
@@ -16186,6 +16291,30 @@ public class ActivityManagerService extends IActivityManager.Stub
        return true;
    }
    /**
     * Re-defer a posted PSS collection pass, if one exists.  Assumes deferral is
     * currently active policy when called.
     */
    private void deferPssIfNeededLocked() {
        if (mPendingPssProcesses.size() > 0) {
            mBgHandler.removeMessages(COLLECT_PSS_BG_MSG);
            mBgHandler.sendEmptyMessageDelayed(COLLECT_PSS_BG_MSG, mPssDeferralTime);
        }
    }
    private void deferPssForActivityStart() {
        synchronized (ActivityManagerService.this) {
            if (mPssDeferralTime > 0) {
                if (DEBUG_PSS) {
                    Slog.d(TAG_PSS, "Deferring PSS collection for activity start");
                }
                deferPssIfNeededLocked();
                mActivityStartingNesting.getAndIncrement();
                mBgHandler.sendEmptyMessageDelayed(STOP_DEFERRING_PSS_MSG, mPssDeferralTime);
            }
        }
    }
    /**
     * Schedule PSS collection of all processes.
     */