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

Commit fa825638 authored by Kweku Adams's avatar Kweku Adams
Browse files

Adding automatic heap dumping for system server.

This adds a request to ActivityManager to track the system server's pss heap
and make sure it doesn't go above a predefined limit. If it does, the dump is
generated and a notification is posted.

Bug: 77490269
Test: flash device and test with 100MB and 150MB limits
Change-Id: Ie886cc36860e8557fbd037b3bfd4975d12806a4b
parent 319e7cb6
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -4037,7 +4037,7 @@ public class ActivityManager {
     * continues running even if the process is killed and restarted.  To remove the watch,
     * use {@link #clearWatchHeapLimit()}.
     *
     * <p>This API only work if the calling process has been marked as
     * <p>This API only works if the calling process has been marked as
     * {@link ApplicationInfo#FLAG_DEBUGGABLE} or this is running on a debuggable
     * (userdebug or eng) build.</p>
     *
+3 −0
Original line number Diff line number Diff line
@@ -3983,6 +3983,9 @@
    <!-- Whether or not to enable automatic heap dumps for the system server on debuggable builds. -->
    <bool name="config_debugEnableAutomaticSystemServerHeapDumps">false</bool>

    <!-- Trigger a heap dump if the system server pss usage exceeds this threshold. 400 MB -->
    <integer name="config_debugSystemServerPssThresholdBytes">419430400</integer>

    <!-- See DropBoxManagerService.
         The minimum period in milliseconds between broadcasts for entries with low priority
         dropbox tags. -->
+1 −0
Original line number Diff line number Diff line
@@ -3225,6 +3225,7 @@
  <java-symbol type="bool" name="config_batterymeterDualTone" />

  <java-symbol type="bool" name="config_debugEnableAutomaticSystemServerHeapDumps" />
  <java-symbol type="integer" name="config_debugSystemServerPssThresholdBytes" />

  <!-- Accessibility Shortcut -->
  <java-symbol type="string" name="accessibility_shortcut_warning_dialog_title" />
+53 −2
Original line number Diff line number Diff line
@@ -20,8 +20,10 @@ import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_POWER_QUICK

import android.app.ActivityThread;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig.OnPropertyChangedListener;
@@ -38,6 +40,7 @@ import java.io.PrintWriter;
 * Settings constants that can modify the activity manager's behavior.
 */
final class ActivityManagerConstants extends ContentObserver {
    private static final String TAG = "ActivityManagerConstants";

    // Key names stored in the settings value.
    private static final String KEY_BACKGROUND_SETTLE_TIME = "background_settle_time";
@@ -272,6 +275,16 @@ final class ActivityManagerConstants extends ContentObserver {
    // memory trimming.
    public int CUR_TRIM_CACHED_PROCESSES;

    private static final long MIN_AUTOMATIC_HEAP_DUMP_PSS_THRESHOLD_BYTES = 100 * 1024; // 100 KB

    private final boolean mSystemServerAutomaticHeapDumpEnabled;

    /** Package to report to when the memory usage exceeds the limit. */
    private final String mSystemServerAutomaticHeapDumpPackageName;

    /** Byte limit for dump heap monitoring. */
    private long mSystemServerAutomaticHeapDumpPssThresholdBytes;

    private static final Uri ACTIVITY_MANAGER_CONSTANTS_URI = Settings.Global.getUriFor(
                Settings.Global.ACTIVITY_MANAGER_CONSTANTS);

@@ -286,6 +299,9 @@ final class ActivityManagerConstants extends ContentObserver {
                Settings.Global.getUriFor(
                        Settings.Global.BACKGROUND_ACTIVITY_STARTS_PACKAGE_NAMES_WHITELIST);

    private static final Uri ENABLE_AUTOMATIC_SYSTEM_SERVER_HEAP_DUMPS_URI =
            Settings.Global.getUriFor(Settings.Global.ENABLE_AUTOMATIC_SYSTEM_SERVER_HEAP_DUMPS);

    private final OnPropertyChangedListener mOnDeviceConfigChangedListener =
            new OnPropertyChangedListener() {
                @Override
@@ -296,9 +312,17 @@ final class ActivityManagerConstants extends ContentObserver {
                }
            };

    public ActivityManagerConstants(ActivityManagerService service, Handler handler) {
    ActivityManagerConstants(Context context, ActivityManagerService service, Handler handler) {
        super(handler);
        mService = service;
        mSystemServerAutomaticHeapDumpEnabled = Build.IS_DEBUGGABLE
                && context.getResources().getBoolean(
                com.android.internal.R.bool.config_debugEnableAutomaticSystemServerHeapDumps);
        mSystemServerAutomaticHeapDumpPackageName = context.getPackageName();
        mSystemServerAutomaticHeapDumpPssThresholdBytes = Math.max(
                MIN_AUTOMATIC_HEAP_DUMP_PSS_THRESHOLD_BYTES,
                context.getResources().getInteger(
                        com.android.internal.R.integer.config_debugSystemServerPssThresholdBytes));
    }

    public void start(ContentResolver resolver) {
@@ -308,10 +332,17 @@ final class ActivityManagerConstants extends ContentObserver {
        mResolver.registerContentObserver(BACKGROUND_ACTIVITY_STARTS_ENABLED_URI, false, this);
        mResolver.registerContentObserver(BACKGROUND_ACTIVITY_STARTS_PACKAGE_NAMES_WHITELIST_URI,
                false, this);
        if (mSystemServerAutomaticHeapDumpEnabled) {
            mResolver.registerContentObserver(ENABLE_AUTOMATIC_SYSTEM_SERVER_HEAP_DUMPS_URI,
                    false, this);
        }
        updateConstants();
        updateActivityStartsLoggingEnabled();
        updateBackgroundActivityStartsEnabled();
        updateBackgroundActivityStartsPackageNamesWhitelist();
        if (mSystemServerAutomaticHeapDumpEnabled) {
            updateEnableAutomaticSystemServerHeapDumps();
        }
        DeviceConfig.addOnPropertyChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                ActivityThread.currentApplication().getMainExecutor(),
                mOnDeviceConfigChangedListener);
@@ -343,6 +374,8 @@ final class ActivityManagerConstants extends ContentObserver {
            updateBackgroundActivityStartsEnabled();
        } else if (BACKGROUND_ACTIVITY_STARTS_PACKAGE_NAMES_WHITELIST_URI.equals(uri)) {
            updateBackgroundActivityStartsPackageNamesWhitelist();
        } else if (ENABLE_AUTOMATIC_SYSTEM_SERVER_HEAP_DUMPS_URI.equals(uri)) {
            updateEnableAutomaticSystemServerHeapDumps();
        }
    }

@@ -450,6 +483,24 @@ final class ActivityManagerConstants extends ContentObserver {
        mPackageNamesWhitelistedForBgActivityStarts = newSet;
    }

    private void updateEnableAutomaticSystemServerHeapDumps() {
        if (!mSystemServerAutomaticHeapDumpEnabled) {
            Slog.wtf(TAG,
                    "updateEnableAutomaticSystemServerHeapDumps called when leak detection "
                            + "disabled");
            return;
        }
        // Monitoring is on by default, so if the setting hasn't been set by the user,
        // monitoring should be on.
        final boolean enabled = Settings.Global.getInt(mResolver,
                Settings.Global.ENABLE_AUTOMATIC_SYSTEM_SERVER_HEAP_DUMPS, 1) == 1;

        // Setting the threshold to 0 stops the checking.
        final long threshold = enabled ? mSystemServerAutomaticHeapDumpPssThresholdBytes : 0;
        mService.setDumpHeapDebugLimit(null, 0, threshold,
                mSystemServerAutomaticHeapDumpPackageName);
    }

    private void updateMaxCachedProcesses() {
        String maxCachedProcessesFlag = DeviceConfig.getProperty(
                DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_MAX_CACHED_PROCESSES);
@@ -460,7 +511,7 @@ final class ActivityManagerConstants extends ContentObserver {
                    : mOverrideMaxCachedProcesses;
        } catch (NumberFormatException e) {
            // Bad flag value from Phenotype, revert to default.
            Slog.e("ActivityManagerConstants",
            Slog.e(TAG,
                    "Unable to parse flag for max_cached_processes: " + maxCachedProcessesFlag, e);
            CUR_MAX_CACHED_PROCESSES = DEFAULT_MAX_CACHED_PROCESSES;
        }
+3 −2
Original line number Diff line number Diff line
@@ -2288,7 +2288,8 @@ public class ActivityManagerService extends IActivityManager.Stub
        mBatteryStatsService = null;
        mHandler = hasHandlerThread ? new MainHandler(handlerThread.getLooper()) : null;
        mHandlerThread = handlerThread;
        mConstants = hasHandlerThread ? new ActivityManagerConstants(this, mHandler) : null;
        mConstants = hasHandlerThread
                ? new ActivityManagerConstants(mContext, this, mHandler) : null;
        final ActiveUids activeUids = new ActiveUids(this, false /* postChangesToAtm */);
        mProcessList.init(this, activeUids);
        mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids);
@@ -2336,7 +2337,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        mProcStartHandlerThread.start();
        mProcStartHandler = new Handler(mProcStartHandlerThread.getLooper());
        mConstants = new ActivityManagerConstants(this, mHandler);
        mConstants = new ActivityManagerConstants(mContext, this, mHandler);
        final ActiveUids activeUids = new ActiveUids(this, true /* postChangesToAtm */);
        mProcessList.init(this, activeUids);
        mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids);