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

Commit 0ef403e5 authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Add some new experiment constants for activity and power manager.

Activity manager now has constants, starting with two: bg check
and process limit.

Power manager now has constants, starting with one: controlling
disabling of wake locks from cached processes.

Test: manual

Change-Id: I05db42e2104e9d31584f85251412df2d5efb34b6
parent d11b9e77
Loading
Loading
Loading
Loading
+45 −5
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ import android.os.IBinder;
import android.os.LocaleList;
import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.speech.tts.TextToSpeech;
@@ -162,13 +163,13 @@ public final class Settings {
     * In some cases, a matching Activity may not exist, so ensure you
     * safeguard against this.
     * <p>
     * Input: {@link ConnectivityManager.EXTRA_TETHER_TYPE} should be included to specify which type
     * of tethering should be checked. {@link ConnectivityManager.EXTRA_PROVISION_CALLBACK} should
     * Input: {@link ConnectivityManager#EXTRA_TETHER_TYPE} should be included to specify which type
     * of tethering should be checked. {@link ConnectivityManager#EXTRA_PROVISION_CALLBACK} should
     * contain a {@link ResultReceiver} which will be called back with a tether result code.
     * <p>
     * Output: The result of the provisioning check.
     * {@link ConnectivityManager.TETHER_ERROR_NO_ERROR} if successful,
     * {@link ConnectivityManager.TETHER_ERROR_PROVISION_FAILED} for failure.
     * {@link ConnectivityManager#TETHER_ERROR_NO_ERROR} if successful,
     * {@link ConnectivityManager#TETHER_ERROR_PROVISION_FAILED} for failure.
     *
     * @hide
     */
@@ -8741,6 +8742,26 @@ public final class Settings {
        public static final String
                BLUETOOTH_PAN_PRIORITY_PREFIX = "bluetooth_pan_priority_";

        /**
         * Activity manager specific settings.
         * This is encoded as a key=value list, separated by commas. Ex:
         *
         * "enforce_bg_check=true,max_cached_processes=24"
         *
         * The following keys are supported:
         *
         * <pre>
         * enforce_bg_check                     (boolean)
         * max_cached_processes                 (int)
         * </pre>
         *
         * <p>
         * Type: string
         * @hide
         * @see com.android.server.am.ActivityManagerConstants
         */
        public static final String ACTIVITY_MANAGER_CONSTANTS = "activity_manager_constants";

        /**
         * Device Idle (Doze) specific settings.
         * This is encoded as a key=value list, separated by commas. Ex:
@@ -8806,6 +8827,25 @@ public final class Settings {
         */
        public static final String APP_IDLE_CONSTANTS = "app_idle_constants";

        /**
         * Power manager specific settings.
         * This is encoded as a key=value list, separated by commas. Ex:
         *
         * "no_cached_wake_locks=1"
         *
         * The following keys are supported:
         *
         * <pre>
         * no_cached_wake_locks                 (boolean)
         * </pre>
         *
         * <p>
         * Type: string
         * @hide
         * @see com.android.server.power.PowerManagerConstants
         */
        public static final String POWER_MANAGER_CONSTANTS = "power_manager_constants";

        /**
         * Alarm manager specific settings.
         * This is encoded as a key=value list, separated by commas. Ex:
@@ -9355,7 +9395,7 @@ public final class Settings {
        /**
         * WFC mode on roaming network.
         * <p>
         * Type: int - see {@link WFC_IMS_MODE} for values
         * Type: int - see {@link #WFC_IMS_MODE} for values
         *
         * @hide
         */
+18 −0
Original line number Diff line number Diff line
@@ -129,4 +129,22 @@ public class KeyValueListParser {
        }
        return def;
    }

    /**
     * Get the value for key as a boolean.
     * @param key The key to lookup.
     * @param def The value to return if the key was not found.
     * @return the string value associated with the key.
     */
    public boolean getBoolean(String key, boolean def) {
        String value = mValues.get(key);
        if (value != null) {
            try {
                return Boolean.parseBoolean(value);
            } catch (NumberFormatException e) {
                // fallthrough
            }
        }
        return def;
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -275,7 +275,7 @@ class AlarmManagerService extends SystemService {
                } catch (IllegalArgumentException e) {
                    // Failed to parse the settings string, log this and move on
                    // with defaults.
                    Slog.e(TAG, "Bad device idle settings", e);
                    Slog.e(TAG, "Bad alarm manager settings", e);
                }

                MIN_FUTURITY = mParser.getLong(KEY_MIN_FUTURITY, DEFAULT_MIN_FUTURITY);
+157 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.am;

import android.content.ContentResolver;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.os.SystemProperties;
import android.provider.Settings;
import android.util.KeyValueListParser;
import android.util.Slog;

import java.io.PrintWriter;

/**
 * Settings constants that can modify the activity manager's behavior.
 */
final class ActivityManagerConstants extends ContentObserver {
    // Key names stored in the settings value.
    private static final String KEY_ENFORCE_BG_CHECK = "enforce_bg_check";
    private static final String KEY_MAX_CACHED_PROCESSES = "max_cached_processes";

    private static final boolean DEFAULT_ENFORCE_BG_CHECK = SystemProperties.getBoolean(
            "debug.bgcheck", false);
    private static final int DEFAULT_MAX_CACHED_PROCESSES = 32;

    // Enforce background check on apps targeting O?
    public boolean ENFORCE_BG_CHECK = DEFAULT_ENFORCE_BG_CHECK;

    // Maximum number of cached processes we will allow.
    public int MAX_CACHED_PROCESSES = DEFAULT_MAX_CACHED_PROCESSES;

    private final ActivityManagerService mService;
    private ContentResolver mResolver;
    private final KeyValueListParser mParser = new KeyValueListParser(',');

    private int mOverrideMaxCachedProcesses = -1;

    // The maximum number of cached processes we will keep around before killing them.
    // NOTE: this constant is *only* a control to not let us go too crazy with
    // keeping around processes on devices with large amounts of RAM.  For devices that
    // are tighter on RAM, the out of memory killer is responsible for killing background
    // processes as RAM is needed, and we should *never* be relying on this limit to
    // kill them.  Also note that this limit only applies to cached background processes;
    // we have no limit on the number of service, visible, foreground, or other such
    // processes and the number of those processes does not count against the cached
    // process limit.
    public int CUR_MAX_CACHED_PROCESSES;

    // The maximum number of empty app processes we will let sit around.
    public int CUR_MAX_EMPTY_PROCESSES;

    // The number of empty apps at which we don't consider it necessary to do
    // memory trimming.
    public int CUR_TRIM_EMPTY_PROCESSES;

    // The number of cached at which we don't consider it necessary to do
    // memory trimming.
    public int CUR_TRIM_CACHED_PROCESSES;

    public ActivityManagerConstants(ActivityManagerService service, Handler handler) {
        super(handler);
        mService = service;
        updateMaxCachedProcesses();
    }

    public void start(ContentResolver resolver) {
        mResolver = resolver;
        mResolver.registerContentObserver(Settings.Global.getUriFor(
                Settings.Global.ACTIVITY_MANAGER_CONSTANTS), false, this);
        updateConstants();
    }

    public void setOverrideMaxCachedProcesses(int value) {
        mOverrideMaxCachedProcesses = value;
        updateMaxCachedProcesses();
    }

    public int getOverrideMaxCachedProcesses() {
        return mOverrideMaxCachedProcesses;
    }

    public static int computeEmptyProcessLimit(int totalProcessLimit) {
        return totalProcessLimit/2;
    }

    @Override
    public void onChange(boolean selfChange, Uri uri) {
        updateConstants();
    }

    private void updateConstants() {
        synchronized (mService) {
            try {
                mParser.setString(Settings.Global.getString(mResolver,
                        Settings.Global.ACTIVITY_MANAGER_CONSTANTS));
            } catch (IllegalArgumentException e) {
                // Failed to parse the settings string, log this and move on
                // with defaults.
                Slog.e("ActivityManagerConstants", "Bad activity manager config settings", e);
            }

            ENFORCE_BG_CHECK = mParser.getBoolean(KEY_ENFORCE_BG_CHECK, DEFAULT_ENFORCE_BG_CHECK);
            MAX_CACHED_PROCESSES = mParser.getInt(KEY_MAX_CACHED_PROCESSES,
                    DEFAULT_MAX_CACHED_PROCESSES);
            updateMaxCachedProcesses();
        }
    }

    private void updateMaxCachedProcesses() {
        CUR_MAX_CACHED_PROCESSES = mOverrideMaxCachedProcesses < 0
                ? MAX_CACHED_PROCESSES : mOverrideMaxCachedProcesses;
        CUR_MAX_EMPTY_PROCESSES = computeEmptyProcessLimit(CUR_MAX_CACHED_PROCESSES);

        // Note the trim levels do NOT depend on the override process limit, we want
        // to consider the same level the point where we do trimming regardless of any
        // additional enforced limit.
        final int rawMaxEmptyProcesses = computeEmptyProcessLimit(MAX_CACHED_PROCESSES);
        CUR_TRIM_EMPTY_PROCESSES = rawMaxEmptyProcesses/2;
        CUR_TRIM_CACHED_PROCESSES = (MAX_CACHED_PROCESSES-rawMaxEmptyProcesses)/3;
    }

    void dump(PrintWriter pw) {
        pw.println("ACTIVITY MANAGER SETTINGS (dumpsys activity settings) "
                + Settings.Global.ACTIVITY_MANAGER_CONSTANTS + ":");

        pw.print("  "); pw.print(KEY_ENFORCE_BG_CHECK); pw.print("=");
        pw.println(ENFORCE_BG_CHECK);

        pw.print("  "); pw.print(KEY_MAX_CACHED_PROCESSES); pw.print("=");
        pw.println(MAX_CACHED_PROCESSES);

        pw.println();
        if (mOverrideMaxCachedProcesses >= 0) {
            pw.print("  mOverrideMaxCachedProcesses="); pw.println(mOverrideMaxCachedProcesses);
        }
        pw.print("  CUR_MAX_CACHED_PROCESSES="); pw.println(CUR_MAX_CACHED_PROCESSES);
        pw.print("  CUR_MAX_EMPTY_PROCESSES="); pw.println(CUR_MAX_EMPTY_PROCESSES);
        pw.print("  CUR_TRIM_EMPTY_PROCESSES="); pw.println(CUR_TRIM_EMPTY_PROCESSES);
        pw.print("  CUR_TRIM_CACHED_PROCESSES="); pw.println(CUR_TRIM_CACHED_PROCESSES);
    }
}
+28 −31
Original line number Diff line number Diff line
@@ -760,11 +760,6 @@ public class ActivityManagerService extends IActivityManager.Stub
     */
    ProcessRecord mHeavyWeightProcess = null;
    /**
     * Are we enforcing background restrictions?
     */
    final boolean mEnforceBackgroundCheck;
    /**
     * Non-persistent app uid whitelist for background restrictions
     */
@@ -1515,9 +1510,6 @@ public class ActivityManagerService extends IActivityManager.Stub
     */
    boolean mBooted = false;
    int mProcessLimit = ProcessList.MAX_CACHED_APPS;
    int mProcessLimitOverride = -1;
    WindowManagerService mWindowManager;
    final ActivityThread mSystemThread;
@@ -1639,6 +1631,8 @@ public class ActivityManagerService extends IActivityManager.Stub
    final MainHandler mHandler;
    final UiHandler mUiHandler;
    final ActivityManagerConstants mConstants;
    PackageManagerInternal mPackageManagerInt;
    // VoiceInteraction session ID that changes for each new request except when
@@ -2620,10 +2614,9 @@ public class ActivityManagerService extends IActivityManager.Stub
        mPermissionReviewRequired = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_permissionReviewRequired);
        mEnforceBackgroundCheck = SystemProperties.getBoolean("debug.bgcheck", false);
        mBackgroundLaunchBroadcasts = SystemConfig.getInstance().getAllowImplicitBroadcasts();
        if (DEBUG_BACKGROUND_CHECK) {
            Slog.d(TAG, "Enforcing O+ bg restrictions: " + mEnforceBackgroundCheck);
            Slog.d(TAG, "Enforcing O+ bg restrictions: " + mConstants.ENFORCE_BG_CHECK);
            StringBuilder sb = new StringBuilder(200);
            sb.append("  ");
            for (String a : mBackgroundLaunchBroadcasts) {
@@ -2639,6 +2632,8 @@ public class ActivityManagerService extends IActivityManager.Stub
        mHandler = new MainHandler(mHandlerThread.getLooper());
        mUiHandler = new UiHandler();
        mConstants = new ActivityManagerConstants(this, mHandler);
        /* static; one-time init here */
        if (sKillHandler == null) {
            sKillThread = new ServiceThread(TAG + ":kill",
@@ -7276,9 +7271,6 @@ public class ActivityManagerService extends IActivityManager.Stub
    /**
     * Whitelists {@code targetUid} to temporarily bypass Power Save mode.
     *
     * <p>{@code callerUid} must be allowed to request such whitelist by calling
     * {@link #addTempPowerSaveWhitelistGrantorUid(int)}.
     */
    void tempWhitelistAppForPowerSave(int callerPid, int callerUid, int targetUid, long duration) {
        if (DEBUG_WHITELISTS) {
@@ -7470,8 +7462,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
                "setProcessLimit()");
        synchronized (this) {
            mProcessLimit = max < 0 ? ProcessList.MAX_CACHED_APPS : max;
            mProcessLimitOverride = max;
            mConstants.setOverrideMaxCachedProcesses(max);
        }
        trimApplications();
    }
@@ -7479,7 +7470,7 @@ public class ActivityManagerService extends IActivityManager.Stub
    @Override
    public int getProcessLimit() {
        synchronized (this) {
            return mProcessLimitOverride;
            return mConstants.getOverrideMaxCachedProcesses();
        }
    }
@@ -8036,7 +8027,7 @@ public class ActivityManagerService extends IActivityManager.Stub
    // Unified app-op and target sdk check
    int appRestrictedInBackgroundLocked(int uid, String packageName, int packageTargetSdk) {
        // Apps that target O+ are always subject to background check
        if (mEnforceBackgroundCheck && packageTargetSdk >= Build.VERSION_CODES.O) {
        if (mConstants.ENFORCE_BG_CHECK && packageTargetSdk >= Build.VERSION_CODES.O) {
            if (DEBUG_BACKGROUND_CHECK) {
                Slog.i(TAG, "App " + uid + "/" + packageName + " targets O+, restricted");
            }
@@ -11559,6 +11550,7 @@ public class ActivityManagerService extends IActivityManager.Stub
            mSystemThread.installSystemProviders(providers);
        }
        mConstants.start(mContext.getContentResolver());
        mCoreSettingsObserver = new CoreSettingsObserver(this);
        mFontScaleSettingObserver = new FontScaleSettingObserver();
@@ -14496,6 +14488,10 @@ public class ActivityManagerService extends IActivityManager.Stub
                synchronized (this) {
                    dumpAssociationsLocked(fd, pw, args, opti, true, dumpClient, dumpPackage);
                }
            } else if ("settings".equals(cmd)) {
                synchronized (this) {
                    mConstants.dump(pw);
                }
            } else if ("services".equals(cmd) || "s".equals(cmd)) {
                if (dumpClient) {
                    ActiveServices.ServiceDumper dumper;
@@ -14536,6 +14532,11 @@ public class ActivityManagerService extends IActivityManager.Stub
        } else if (dumpClient) {
            ActiveServices.ServiceDumper sdumper;
            synchronized (this) {
                mConstants.dump(pw);
                pw.println();
                if (dumpAll) {
                    pw.println("-------------------------------------------------------------------------------");
                }
                dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
                pw.println();
                if (dumpAll) {
@@ -14594,6 +14595,11 @@ public class ActivityManagerService extends IActivityManager.Stub
        } else {
            synchronized (this) {
                mConstants.dump(pw);
                pw.println();
                if (dumpAll) {
                    pw.println("-------------------------------------------------------------------------------");
                }
                dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
                pw.println();
                if (dumpAll) {
@@ -21393,17 +21399,8 @@ public class ActivityManagerService extends IActivityManager.Stub
        mNewNumServiceProcs = 0;
        mNewNumAServiceProcs = 0;
        final int emptyProcessLimit;
        final int cachedProcessLimit;
        if (mProcessLimit <= 0) {
            emptyProcessLimit = cachedProcessLimit = 0;
        } else if (mProcessLimit == 1) {
            emptyProcessLimit = 1;
            cachedProcessLimit = 0;
        } else {
            emptyProcessLimit = ProcessList.computeEmptyProcessLimit(mProcessLimit);
            cachedProcessLimit = mProcessLimit - emptyProcessLimit;
        }
        final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES;
        final int cachedProcessLimit = mConstants.CUR_MAX_CACHED_PROCESSES - emptyProcessLimit;
        // Let's determine how many processes we have running vs.
        // how many slots we have for background processes; we may want
@@ -21511,7 +21508,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                        }
                        break;
                    case ActivityManager.PROCESS_STATE_CACHED_EMPTY:
                        if (numEmpty > ProcessList.TRIM_EMPTY_APPS
                        if (numEmpty > mConstants.CUR_TRIM_EMPTY_PROCESSES
                                && app.lastActivityTime < oldTime) {
                            app.kill("empty for "
                                    + ((oldTime + ProcessList.MAX_EMPTY_TIME - app.lastActivityTime)
@@ -21564,8 +21561,8 @@ public class ActivityManagerService extends IActivityManager.Stub
        // memory they want.
        final int numCachedAndEmpty = numCached + numEmpty;
        int memFactor;
        if (numCached <= ProcessList.TRIM_CACHED_APPS
                && numEmpty <= ProcessList.TRIM_EMPTY_APPS) {
        if (numCached <= mConstants.CUR_TRIM_CACHED_PROCESSES
                && numEmpty <= mConstants.CUR_TRIM_EMPTY_PROCESSES) {
            if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
                memFactor = ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
            } else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
Loading