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

Commit f76c853a authored by Jing Ji's avatar Jing Ji
Browse files

Keep warming services out of cached adj

Add a pre-configured list that will help to prevent those services
which will keep critical code path of the host processes warm
from falling into cached adj; in case of multi-user, such service
running in the background user won't get this capability, unless it's
singleton.

The list will be empty by default and subjected to be overlaid
by device configurations.

Bug: 158685897
Test: atest MockingOomAdjusterTests
Test: Manual - Add test service into the pre-configured list
      start it and verify it won't get into cached state
Change-Id: I062f5ec3947ad3acebcc2ffe79e420beb23443a2
Merged-In: I062f5ec3947ad3acebcc2ffe79e420beb23443a2
parent d03b5017
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -4362,4 +4362,7 @@
    <bool name="config_pdp_reject_enable_retry">false</bool>
    <!-- pdp data reject retry delay in ms -->
    <integer name="config_pdp_reject_retry_delay_ms">-1</integer>

    <!-- Component names of the services which will keep critical code path warm -->
    <string-array name="config_keep_warming_services" translatable="false" />
</resources>
+2 −0
Original line number Diff line number Diff line
@@ -4048,4 +4048,6 @@
  <java-symbol type="string" name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" />

  <java-symbol type="array" name="config_notificationMsgPkgsAllowedAsConvos" />

  <java-symbol type="array" name="config_keep_warming_services" />
</resources>
+10 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.server.am;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_POWER_QUICK;

import android.app.ActivityThread;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
@@ -336,6 +337,11 @@ final class ActivityManagerConstants extends ContentObserver {
     */
    public int PENDINGINTENT_WARNING_THRESHOLD =  DEFAULT_PENDINGINTENT_WARNING_THRESHOLD;

    /**
     * Component names of the services which will keep critical code path of the host warm
     */
    public final ArraySet<ComponentName> KEEP_WARMING_SERVICES = new ArraySet<ComponentName>();

    private List<String> mDefaultImperceptibleKillExemptPackages;
    private List<Integer> mDefaultImperceptibleKillExemptProcStates;

@@ -442,6 +448,10 @@ final class ActivityManagerConstants extends ContentObserver {
                .boxed().collect(Collectors.toList());
        IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES.addAll(mDefaultImperceptibleKillExemptPackages);
        IMPERCEPTIBLE_KILL_EXEMPT_PROC_STATES.addAll(mDefaultImperceptibleKillExemptProcStates);
        KEEP_WARMING_SERVICES.addAll(Arrays.stream(
                context.getResources().getStringArray(
                        com.android.internal.R.array.config_keep_warming_services))
                .map(ComponentName::unflattenFromString).collect(Collectors.toSet()));
    }

    public void start(ContentResolver resolver) {
+44 −2
Original line number Diff line number Diff line
@@ -76,7 +76,11 @@ import android.app.ApplicationExitInfo;
import android.app.usage.UsageEvents;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledAfter;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ServiceInfo;
import android.os.Debug;
import android.os.Handler;
@@ -265,6 +269,43 @@ public final class OomAdjuster {

    void initSettings() {
        mCachedAppOptimizer.init();
        if (mService.mConstants.KEEP_WARMING_SERVICES.size() > 0) {
            final IntentFilter filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
            mService.mContext.registerReceiverForAllUsers(new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    synchronized (mService) {
                        handleUserSwitchedLocked();
                    }
                }
            }, filter, null, mService.mHandler);
        }
    }

    /**
     * Update the keep-warming service flags upon user switches
     */
    @VisibleForTesting
    @GuardedBy("mService")
    void handleUserSwitchedLocked() {
        final ArraySet<ComponentName> warmServices = mService.mConstants.KEEP_WARMING_SERVICES;
        final ArrayList<ProcessRecord> processes = mProcessList.mLruProcesses;
        for (int i = processes.size() - 1; i >= 0; i--) {
            final ProcessRecord app = processes.get(i);
            boolean includeWarmPkg = false;
            for (int j = warmServices.size() - 1; j >= 0; j--) {
                if (app.pkgList.containsKey(warmServices.valueAt(j).getPackageName())) {
                    includeWarmPkg = true;
                    break;
                }
            }
            if (!includeWarmPkg) {
                continue;
            }
            for (int j = app.numberOfRunningServices() - 1; j >= 0; j--) {
                app.getRunningServiceAt(j).updateKeepWarmLocked();
            }
        }
    }

    /**
@@ -1470,7 +1511,7 @@ public final class OomAdjuster {
                                "Raise procstate to started service: " + app);
                    }
                }
                if (app.hasShownUi && !app.getCachedIsHomeProcess()) {
                if (!s.mKeepWarming && app.hasShownUi && !app.getCachedIsHomeProcess()) {
                    // If this process has shown some UI, let it immediately
                    // go to the LRU list because it may be pretty heavy with
                    // UI stuff.  We'll tag it with a label just to help
@@ -1479,7 +1520,8 @@ public final class OomAdjuster {
                        app.adjType = "cch-started-ui-services";
                    }
                } else {
                    if (now < (s.lastActivity + mConstants.MAX_SERVICE_INACTIVITY)) {
                    if (s.mKeepWarming
                            || now < (s.lastActivity + mConstants.MAX_SERVICE_INACTIVITY)) {
                        // This service has seen some activity within
                        // recent memory, so we will keep its process ahead
                        // of the background processes.
+12 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
import android.util.proto.ProtoUtils;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.procstats.ServiceState;
import com.android.internal.os.BatteryStatsImpl;
import com.android.server.LocalServices;
@@ -146,6 +147,8 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN

    private int lastStartId;    // identifier of most recent start request.

    boolean mKeepWarming; // Whether or not it'll keep critical code path of the host warm

    static class StartItem {
        final ServiceRecord sr;
        final boolean taskRemoved;
@@ -514,6 +517,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
        lastActivity = SystemClock.uptimeMillis();
        userId = UserHandle.getUserId(appInfo.uid);
        createdFromFg = callerIsFg;
        updateKeepWarmLocked();
    }

    public ServiceState getTracker() {
@@ -732,6 +736,14 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
        }
    }

    @GuardedBy("ams")
    void updateKeepWarmLocked() {
        mKeepWarming = ams.mConstants.KEEP_WARMING_SERVICES.contains(name)
                && (ams.mUserController.getCurrentUserId() == userId
                || ams.isSingleton(processName, appInfo, instanceName.getClassName(),
                        serviceInfo.flags));
    }

    public AppBindRecord retrieveAppBindingLocked(Intent intent,
            ProcessRecord app) {
        Intent.FilterComparison filter = new Intent.FilterComparison(intent);
Loading