From: Amith Yamasani Date: Thu, 21 Mar 2019 05:49:43 +0000 (-0700) Subject: Avoid elevating apps to high proc states on binding X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=f235d0b53a0e33828ea23fe5aa7e668eaba3ce8b;p=android-x86%2Fframeworks-base.git Avoid elevating apps to high proc states on binding For service and provider bindings from TOP and FOREGROUND_SERVICE apps, don't elevate bound apps to above BOUND_FOREGROUND_SERVICE. For service bindings, it is possible to explicitly request the binding to match the foreground app such that the bound app can get similar privileges of foreground permissions. For instance, when a foreground service has a location type, providers it binds to don't automatically get the location privilege. On the other hand, sometimes apps showing UI want to treat their dependencies also as if they are showing UI. This change does not affect the oom_adj calculation, only the proc state calculation for bound processes. New BIND_INCLUDE_CAPABILITIES flag can be used to restore old behavior for bound services. Introduces a new state PROCESS_STATE_BOUND_TOP Bug: 128337543 Test: atest CtsAppTestCases:ActivityManagerProcessStateTest Change-Id: I13733e7f43a78903299254bc110cd8f7a8db4c40 --- diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 80b6349ca284..395c867de9d7 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -513,71 +513,75 @@ public class ActivityManager { /** @hide Process is hosting a foreground service with location type. */ public static final int PROCESS_STATE_FOREGROUND_SERVICE_LOCATION = 3; + /** @hide Process is bound to a TOP app. This is ranked below SERVICE_LOCATION so that + * it doesn't get the capability of location access while-in-use. */ + public static final int PROCESS_STATE_BOUND_TOP = 4; + /** @hide Process is hosting a foreground service. */ @UnsupportedAppUsage - public static final int PROCESS_STATE_FOREGROUND_SERVICE = 4; + public static final int PROCESS_STATE_FOREGROUND_SERVICE = 5; /** @hide Process is hosting a foreground service due to a system binding. */ @UnsupportedAppUsage - public static final int PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 5; + public static final int PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 6; /** @hide Process is important to the user, and something they are aware of. */ - public static final int PROCESS_STATE_IMPORTANT_FOREGROUND = 6; + public static final int PROCESS_STATE_IMPORTANT_FOREGROUND = 7; /** @hide Process is important to the user, but not something they are aware of. */ @UnsupportedAppUsage - public static final int PROCESS_STATE_IMPORTANT_BACKGROUND = 7; + public static final int PROCESS_STATE_IMPORTANT_BACKGROUND = 8; /** @hide Process is in the background transient so we will try to keep running. */ - public static final int PROCESS_STATE_TRANSIENT_BACKGROUND = 8; + public static final int PROCESS_STATE_TRANSIENT_BACKGROUND = 9; /** @hide Process is in the background running a backup/restore operation. */ - public static final int PROCESS_STATE_BACKUP = 9; + public static final int PROCESS_STATE_BACKUP = 10; /** @hide Process is in the background running a service. Unlike oom_adj, this level * is used for both the normal running in background state and the executing * operations state. */ @UnsupportedAppUsage - public static final int PROCESS_STATE_SERVICE = 10; + public static final int PROCESS_STATE_SERVICE = 11; /** @hide Process is in the background running a receiver. Note that from the * perspective of oom_adj, receivers run at a higher foreground level, but for our * prioritization here that is not necessary and putting them below services means * many fewer changes in some process states as they receive broadcasts. */ @UnsupportedAppUsage - public static final int PROCESS_STATE_RECEIVER = 11; + public static final int PROCESS_STATE_RECEIVER = 12; /** @hide Same as {@link #PROCESS_STATE_TOP} but while device is sleeping. */ - public static final int PROCESS_STATE_TOP_SLEEPING = 12; + public static final int PROCESS_STATE_TOP_SLEEPING = 13; /** @hide Process is in the background, but it can't restore its state so we want * to try to avoid killing it. */ - public static final int PROCESS_STATE_HEAVY_WEIGHT = 13; + public static final int PROCESS_STATE_HEAVY_WEIGHT = 14; /** @hide Process is in the background but hosts the home activity. */ @UnsupportedAppUsage - public static final int PROCESS_STATE_HOME = 14; + public static final int PROCESS_STATE_HOME = 15; /** @hide Process is in the background but hosts the last shown activity. */ - public static final int PROCESS_STATE_LAST_ACTIVITY = 15; + public static final int PROCESS_STATE_LAST_ACTIVITY = 16; /** @hide Process is being cached for later use and contains activities. */ @UnsupportedAppUsage - public static final int PROCESS_STATE_CACHED_ACTIVITY = 16; + public static final int PROCESS_STATE_CACHED_ACTIVITY = 17; /** @hide Process is being cached for later use and is a client of another cached * process that contains activities. */ - public static final int PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 17; + public static final int PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 18; /** @hide Process is being cached for later use and has an activity that corresponds * to an existing recent task. */ - public static final int PROCESS_STATE_CACHED_RECENT = 18; + public static final int PROCESS_STATE_CACHED_RECENT = 19; /** @hide Process is being cached for later use and is empty. */ - public static final int PROCESS_STATE_CACHED_EMPTY = 19; + public static final int PROCESS_STATE_CACHED_EMPTY = 20; /** @hide Process does not exist. */ - public static final int PROCESS_STATE_NONEXISTENT = 20; + public static final int PROCESS_STATE_NONEXISTENT = 21; // NOTE: If PROCESS_STATEs are added, then new fields must be added // to frameworks/base/core/proto/android/app/enums.proto and the following method must @@ -602,6 +606,8 @@ public class ActivityManager { return AppProtoEnums.PROCESS_STATE_PERSISTENT_UI; case PROCESS_STATE_TOP: return AppProtoEnums.PROCESS_STATE_TOP; + case PROCESS_STATE_BOUND_TOP: + return AppProtoEnums.PROCESS_STATE_BOUND_TOP; case PROCESS_STATE_FOREGROUND_SERVICE_LOCATION: case PROCESS_STATE_FOREGROUND_SERVICE: return AppProtoEnums.PROCESS_STATE_FOREGROUND_SERVICE; diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index d7a2e1b80f84..af738da20621 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -427,7 +427,7 @@ public abstract class Context { * invisible background activities. This will impact the number of * recent activities the user can switch between without having them * restart. There is no guarantee this will be respected, as the system - * tries to balance such requests from one app vs. the importantance of + * tries to balance such requests from one app vs. the importance of * keeping other apps around. */ public static final int BIND_VISIBLE = 0x10000000; diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index b64fe007bcd9..00d522bae27f 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -16,6 +16,7 @@ package android.os; +import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP; import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION; import android.annotation.UnsupportedAppUsage; @@ -859,7 +860,8 @@ public abstract class BatteryStats implements Parcelable { */ public static final int[] CRITICAL_PROC_STATES = { PROCESS_STATE_TOP, - PROCESS_STATE_FOREGROUND_SERVICE_LOCATION, PROCESS_STATE_FOREGROUND_SERVICE, + PROCESS_STATE_FOREGROUND_SERVICE_LOCATION, + PROCESS_STATE_BOUND_TOP, PROCESS_STATE_FOREGROUND_SERVICE, PROCESS_STATE_FOREGROUND }; diff --git a/core/java/com/android/internal/app/procstats/ProcessState.java b/core/java/com/android/internal/app/procstats/ProcessState.java index 0e4897f9eb9c..b26efc0dbd10 100644 --- a/core/java/com/android/internal/app/procstats/ProcessState.java +++ b/core/java/com/android/internal/app/procstats/ProcessState.java @@ -79,6 +79,7 @@ public final class ProcessState { STATE_TOP, // ActivityManager.PROCESS_STATE_TOP STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE + STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_TOP STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND STATE_IMPORTANT_BACKGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND diff --git a/core/proto/android/app/enums.proto b/core/proto/android/app/enums.proto index 1754e426fe93..9abe92330cb0 100644 --- a/core/proto/android/app/enums.proto +++ b/core/proto/android/app/enums.proto @@ -38,6 +38,7 @@ enum AppTransitionReasonEnum { } // ActivityManager.java PROCESS_STATEs +// Next tag: 1021 enum ProcessStateEnum { // Unlike the ActivityManager PROCESS_STATE values, the ordering and numerical values // here are completely fixed and arbitrary. Order is irrelevant. @@ -56,9 +57,11 @@ enum ProcessStateEnum { // Process is hosting the current top activities. Note that this covers // all activities that are visible to the user. PROCESS_STATE_TOP = 1002; + // Process is bound to a TOP app. + PROCESS_STATE_BOUND_TOP = 1020; // Process is hosting a foreground service. PROCESS_STATE_FOREGROUND_SERVICE = 1003; - // Process is hosting a foreground service due to a system binding. + // Process is hosting a service bound by the system or another foreground app. PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 1004; // Process is important to the user, and something they are aware of. PROCESS_STATE_IMPORTANT_FOREGROUND = 1005; diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 261ed4c7e854..f0982d3aa142 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -1344,7 +1344,8 @@ public final class ActiveServices { if (!r.isForeground) { final ServiceMap smap = getServiceMapLocked(r.userId); if (smap != null) { - ActiveForegroundApp active = smap.mActiveForegroundApps.get(r.packageName); + ActiveForegroundApp active = smap.mActiveForegroundApps + .get(r.packageName); if (active == null) { active = new ActiveForegroundApp(); active.mPackageName = r.packageName; diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 3eb7c0374a01..69e69f0f186d 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -15333,18 +15333,20 @@ public class ActivityManagerService extends IActivityManager.Stub final ProcessRecord callerApp = getRecordForAppLocked(caller); final int callingPid = Binder.getCallingPid(); final int callingUid = Binder.getCallingUid(); + final long origId = Binder.clearCallingIdentity(); - int res = broadcastIntentLocked(callerApp, - callerApp != null ? callerApp.info.packageName : null, - intent, resolvedType, resultTo, resultCode, resultData, resultExtras, - requiredPermissions, appOp, bOptions, serialized, sticky, - callingPid, callingUid, callingUid, callingPid, userId); - Binder.restoreCallingIdentity(origId); - return res; + try { + return broadcastIntentLocked(callerApp, + callerApp != null ? callerApp.info.packageName : null, + intent, resolvedType, resultTo, resultCode, resultData, resultExtras, + requiredPermissions, appOp, bOptions, serialized, sticky, + callingPid, callingUid, callingUid, callingPid, userId); + } finally { + Binder.restoreCallingIdentity(origId); + } } } - int broadcastIntentInPackage(String packageName, int uid, int realCallingUid, int realCallingPid, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle resultExtras, @@ -15356,13 +15358,15 @@ public class ActivityManagerService extends IActivityManager.Stub final long origId = Binder.clearCallingIdentity(); String[] requiredPermissions = requiredPermission == null ? null : new String[] {requiredPermission}; - int res = broadcastIntentLocked(null, packageName, intent, resolvedType, - resultTo, resultCode, resultData, resultExtras, - requiredPermissions, OP_NONE, bOptions, serialized, - sticky, -1, uid, realCallingUid, realCallingPid, userId, - allowBackgroundActivityStarts); - Binder.restoreCallingIdentity(origId); - return res; + try { + return broadcastIntentLocked(null, packageName, intent, resolvedType, + resultTo, resultCode, resultData, resultExtras, + requiredPermissions, OP_NONE, bOptions, serialized, + sticky, -1, uid, realCallingUid, realCallingPid, userId, + allowBackgroundActivityStarts); + } finally { + Binder.restoreCallingIdentity(origId); + } } } diff --git a/services/core/java/com/android/server/am/ConnectionRecord.java b/services/core/java/com/android/server/am/ConnectionRecord.java index a1c941e085a6..fe9554255feb 100644 --- a/services/core/java/com/android/server/am/ConnectionRecord.java +++ b/services/core/java/com/android/server/am/ConnectionRecord.java @@ -109,6 +109,14 @@ final class ConnectionRecord { clientPackageName = _clientPackageName; } + public boolean hasFlag(final int flag) { + return (flags & flag) != 0; + } + + public boolean notHasFlag(final int flag) { + return (flags & flag) == 0; + } + public void startAssociationIfNeeded() { // If we don't already have an active association, create one... but only if this // is an association between two different processes. diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index 924e3310fbd2..5d47c9dfdddd 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -16,10 +16,19 @@ package com.android.server.am; +import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE; +import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP; import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY; import static android.app.ActivityManager.PROCESS_STATE_CACHED_EMPTY; +import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; +import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION; +import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND; +import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY; import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; +import static android.app.ActivityManager.PROCESS_STATE_SERVICE; +import static android.app.ActivityManager.PROCESS_STATE_TOP; +import static android.app.ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND; import static android.os.Process.SCHED_OTHER; import static android.os.Process.THREAD_GROUP_BG_NONINTERACTIVE; import static android.os.Process.THREAD_GROUP_DEFAULT; @@ -413,7 +422,7 @@ public final class OomAdjuster { app.kill("cached #" + numCached, true); } break; - case ActivityManager.PROCESS_STATE_CACHED_EMPTY: + case PROCESS_STATE_CACHED_EMPTY: if (numEmpty > mConstants.CUR_TRIM_EMPTY_PROCESSES && app.lastActivityTime < oldTime) { app.kill("empty for " @@ -718,7 +727,7 @@ public final class OomAdjuster { if (app.thread == null) { app.adjSeq = mAdjSeq; app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_BACKGROUND); - app.setCurProcState(ActivityManager.PROCESS_STATE_CACHED_EMPTY); + app.setCurProcState(PROCESS_STATE_CACHED_EMPTY); app.curAdj = ProcessList.CACHED_APP_MAX_ADJ; app.setCurRawAdj(ProcessList.CACHED_APP_MAX_ADJ); app.completedAdjSeq = app.adjSeq; @@ -773,7 +782,7 @@ public final class OomAdjuster { app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_TOP_APP); } else { // screen off, restrict UI scheduling - app.setCurProcState(ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE); + app.setCurProcState(PROCESS_STATE_BOUND_FOREGROUND_SERVICE); app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_RESTRICTED); } } @@ -797,7 +806,7 @@ public final class OomAdjuster { boolean foregroundActivities = false; mTmpBroadcastQueue.clear(); - if (PROCESS_STATE_CUR_TOP == ActivityManager.PROCESS_STATE_TOP && app == TOP_APP) { + if (PROCESS_STATE_CUR_TOP == PROCESS_STATE_TOP && app == TOP_APP) { // The last app on the list is the foreground app. adj = ProcessList.FOREGROUND_APP_ADJ; schedGroup = ProcessList.SCHED_GROUP_TOP_APP; @@ -820,7 +829,7 @@ public final class OomAdjuster { adj = ProcessList.FOREGROUND_APP_ADJ; schedGroup = ProcessList.SCHED_GROUP_DEFAULT; app.adjType = "instrumentation"; - procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; + procState = PROCESS_STATE_FOREGROUND_SERVICE; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making instrumentation: " + app); } @@ -844,7 +853,7 @@ public final class OomAdjuster { schedGroup = app.execServicesFg ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND; app.adjType = "exec-service"; - procState = ActivityManager.PROCESS_STATE_SERVICE; + procState = PROCESS_STATE_SERVICE; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making exec-service: " + app); } @@ -864,7 +873,7 @@ public final class OomAdjuster { // At this point we don't actually know the adjustment. Use the cached adj // value that the caller wants us to. adj = cachedAdj; - procState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; + procState = PROCESS_STATE_CACHED_EMPTY; app.cached = true; app.empty = true; app.adjType = "cch-empty"; @@ -899,23 +908,28 @@ public final class OomAdjuster { } if (adj > ProcessList.PERCEPTIBLE_APP_ADJ - || procState > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION) { + || procState > PROCESS_STATE_FOREGROUND_SERVICE_LOCATION) { if (app.hasForegroundServices()) { // The user is aware of this app, so make it visible. adj = ProcessList.PERCEPTIBLE_APP_ADJ; - procState = app.hasLocationForegroundServices() - ? ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION - : ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; + if (app.hasLocationForegroundServices()) { + procState = PROCESS_STATE_FOREGROUND_SERVICE_LOCATION; + app.adjType = "fg-service-location"; + + } else { + procState = PROCESS_STATE_FOREGROUND_SERVICE; + app.adjType = "fg-service"; + } app.cached = false; - app.adjType = "fg-service"; schedGroup = ProcessList.SCHED_GROUP_DEFAULT; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { - reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to fg service: " + app); + reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + app.adjType + ": " + + app + " "); } } else if (app.hasOverlayUi()) { // The process is display an overlay UI. adj = ProcessList.PERCEPTIBLE_APP_ADJ; - procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; + procState = PROCESS_STATE_IMPORTANT_FOREGROUND; app.cached = false; app.adjType = "has-overlay-ui"; schedGroup = ProcessList.SCHED_GROUP_DEFAULT; @@ -930,7 +944,7 @@ public final class OomAdjuster { // services so that it can finish performing any persistence/processing of in-memory state. if (app.hasForegroundServices() && adj > ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ && (app.lastTopTime + mConstants.TOP_TO_FGS_GRACE_DURATION > now - || app.setProcState <= ActivityManager.PROCESS_STATE_TOP)) { + || app.setProcState <= PROCESS_STATE_TOP)) { adj = ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ; app.adjType = "fg-service-act"; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { @@ -939,13 +953,13 @@ public final class OomAdjuster { } if (adj > ProcessList.PERCEPTIBLE_APP_ADJ - || procState > ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND) { + || procState > PROCESS_STATE_TRANSIENT_BACKGROUND) { if (app.forcingToImportant != null) { // This is currently used for toasts... they are not interactive, and // we don't want them to cause the app to become fully foreground (and // thus out of background check), so we yes the best background level we can. adj = ProcessList.PERCEPTIBLE_APP_ADJ; - procState = ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND; + procState = PROCESS_STATE_TRANSIENT_BACKGROUND; app.cached = false; app.adjType = "force-imp"; app.adjSource = app.forcingToImportant; @@ -1041,8 +1055,8 @@ public final class OomAdjuster { if (adj > ProcessList.BACKUP_APP_ADJ) { if (DEBUG_BACKUP) Slog.v(TAG_BACKUP, "oom BACKUP_APP_ADJ for " + app); adj = ProcessList.BACKUP_APP_ADJ; - if (procState > ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND) { - procState = ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND; + if (procState > PROCESS_STATE_TRANSIENT_BACKGROUND) { + procState = PROCESS_STATE_TRANSIENT_BACKGROUND; } app.adjType = "backup"; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { @@ -1059,21 +1073,16 @@ public final class OomAdjuster { } } - boolean mayBeTop = false; - String mayBeTopType = null; - Object mayBeTopSource = null; - Object mayBeTopTarget = null; - for (int is = app.services.size() - 1; is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND - || procState > ActivityManager.PROCESS_STATE_TOP); + || procState > PROCESS_STATE_TOP); is--) { ServiceRecord s = app.services.valueAt(is); if (s.startRequested) { app.hasStartedServices = true; - if (procState > ActivityManager.PROCESS_STATE_SERVICE) { - procState = ActivityManager.PROCESS_STATE_SERVICE; + if (procState > PROCESS_STATE_SERVICE) { + procState = PROCESS_STATE_SERVICE; app.adjType = "started-services"; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, @@ -1116,13 +1125,13 @@ public final class OomAdjuster { for (int conni = serviceConnections.size() - 1; conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND - || procState > ActivityManager.PROCESS_STATE_TOP); + || procState > PROCESS_STATE_TOP); conni--) { ArrayList clist = serviceConnections.valueAt(conni); for (int i = 0; i < clist.size() && (adj > ProcessList.FOREGROUND_APP_ADJ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND - || procState > ActivityManager.PROCESS_STATE_TOP); + || procState > PROCESS_STATE_TOP); i++) { // XXX should compute this based on the max of // all connected clients. @@ -1148,7 +1157,7 @@ public final class OomAdjuster { // If the other app is cached for any reason, for purposes here // we are going to consider it empty. The specific cached state // doesn't propagate except under certain conditions. - clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; + clientProcState = PROCESS_STATE_CACHED_EMPTY; } String adjType = null; if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) { @@ -1219,6 +1228,7 @@ public final class OomAdjuster { newAdj = clientAdj; } else { if (adj > ProcessList.VISIBLE_APP_ADJ) { + // TODO: Is this too limiting for apps bound from TOP? newAdj = Math.max(clientAdj, ProcessList.VISIBLE_APP_ADJ); } else { newAdj = adj; @@ -1247,55 +1257,50 @@ public final class OomAdjuster { schedGroup = ProcessList.SCHED_GROUP_DEFAULT; } } - if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) { - if (clientProcState == ActivityManager.PROCESS_STATE_TOP) { - // Special handling of clients who are in the top state. - // We *may* want to consider this process to be in the - // top state as well, but only if there is not another - // reason for it to be running. Being on the top is a - // special state, meaning you are specifically running - // for the current top app. If the process is already - // running in the background for some other reason, it - // is more important to continue considering it to be - // in the background state. - mayBeTop = true; - mayBeTopType = "service"; - mayBeTopSource = cr.binding.client; - mayBeTopTarget = s.instanceName; - clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; + if (clientProcState < PROCESS_STATE_TOP) { + // Special handling for above-top states (persistent + // processes). These should not bring the current process + // into the top state, since they are not on top. Instead + // give them the best bound state after that. + if ((cr.flags & Context.BIND_FOREGROUND_SERVICE) != 0) { + clientProcState = + PROCESS_STATE_BOUND_FOREGROUND_SERVICE; + } else if (mService.mWakefulness + == PowerManagerInternal.WAKEFULNESS_AWAKE + && (cr.flags & Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE) + != 0) { + clientProcState = + PROCESS_STATE_BOUND_FOREGROUND_SERVICE; } else { - // Special handling for above-top states (persistent - // processes). These should not bring the current process - // into the top state, since they are not on top. Instead - // give them the best state after that. - if ((cr.flags&Context.BIND_FOREGROUND_SERVICE) != 0) { - clientProcState = - ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE; - } else if (mService.mWakefulness - == PowerManagerInternal.WAKEFULNESS_AWAKE && - (cr.flags&Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE) - != 0) { - clientProcState = - ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE; - } else { - clientProcState = - ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; - } + clientProcState = + PROCESS_STATE_IMPORTANT_FOREGROUND; + } + } else if (clientProcState == PROCESS_STATE_TOP) { + if (cr.notHasFlag(Context.BIND_INCLUDE_CAPABILITIES)) { + // Go at most to BOUND_TOP, unless requested to elevate + // to client's state. + clientProcState = PROCESS_STATE_BOUND_TOP; + } + } else if (clientProcState + <= PROCESS_STATE_FOREGROUND_SERVICE) { + if (cr.notHasFlag(Context.BIND_INCLUDE_CAPABILITIES)) { + clientProcState = PROCESS_STATE_FOREGROUND_SERVICE; } } } else if ((cr.flags & Context.BIND_IMPORTANT_BACKGROUND) == 0) { if (clientProcState < - ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND) { + PROCESS_STATE_TRANSIENT_BACKGROUND) { clientProcState = - ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND; + PROCESS_STATE_TRANSIENT_BACKGROUND; } } else { if (clientProcState < - ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND) { + PROCESS_STATE_IMPORTANT_BACKGROUND) { clientProcState = - ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND; + PROCESS_STATE_IMPORTANT_BACKGROUND; } } + if (schedGroup < ProcessList.SCHED_GROUP_TOP_APP && (cr.flags & Context.BIND_SCHEDULE_LIKE_TOP_APP) != 0) { schedGroup = ProcessList.SCHED_GROUP_TOP_APP; @@ -1304,6 +1309,7 @@ public final class OomAdjuster { if (!trackedProcState) { cr.trackProcState(clientProcState, mAdjSeq, now); } + if (procState > clientProcState) { procState = clientProcState; app.setCurRawProcState(procState); @@ -1311,7 +1317,7 @@ public final class OomAdjuster { adjType = "service"; } } - if (procState < ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND + if (procState < PROCESS_STATE_IMPORTANT_BACKGROUND && (cr.flags & Context.BIND_SHOWING_UI) != 0) { app.setPendingUiClean(true); } @@ -1366,13 +1372,13 @@ public final class OomAdjuster { for (int provi = app.pubProviders.size() - 1; provi >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND - || procState > ActivityManager.PROCESS_STATE_TOP); + || procState > PROCESS_STATE_TOP); provi--) { ContentProviderRecord cpr = app.pubProviders.valueAt(provi); for (int i = cpr.connections.size() - 1; i >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND - || procState > ActivityManager.PROCESS_STATE_TOP); + || procState > PROCESS_STATE_TOP); i--) { ContentProviderConnection conn = cpr.connections.get(i); ProcessRecord client = conn.client; @@ -1392,7 +1398,7 @@ public final class OomAdjuster { if (clientProcState >= PROCESS_STATE_CACHED_ACTIVITY) { // If the other app is cached for any reason, for purposes here // we are going to consider it empty. - clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; + clientProcState = PROCESS_STATE_CACHED_EMPTY; } String adjType = null; if (adj > clientAdj) { @@ -1407,34 +1413,18 @@ public final class OomAdjuster { } app.cached &= client.cached; } - if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) { - if (clientProcState == ActivityManager.PROCESS_STATE_TOP) { - // Special handling of clients who are in the top state. - // We *may* want to consider this process to be in the - // top state as well, but only if there is not another - // reason for it to be running. Being on the top is a - // special state, meaning you are specifically running - // for the current top app. If the process is already - // running in the background for some other reason, it - // is more important to continue considering it to be - // in the background state. - mayBeTop = true; - clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; - mayBeTopType = adjType = "provider-top"; - mayBeTopSource = client; - mayBeTopTarget = cpr.name; + + if (clientProcState <= PROCESS_STATE_FOREGROUND_SERVICE) { + if (adjType == null) { + adjType = "provider"; + } + if (clientProcState == PROCESS_STATE_TOP) { + clientProcState = PROCESS_STATE_BOUND_TOP; } else { - // Special handling for above-top states (persistent - // processes). These should not bring the current process - // into the top state, since they are not on top. Instead - // give them the best state after that. - clientProcState = - ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE; - if (adjType == null) { - adjType = "provider"; - } + clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE; } } + conn.trackProcState(clientProcState, mAdjSeq, now); if (procState > clientProcState) { procState = clientProcState; @@ -1474,8 +1464,8 @@ public final class OomAdjuster { "Raise adj to external provider: " + app); } } - if (procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) { - procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; + if (procState > PROCESS_STATE_IMPORTANT_FOREGROUND) { + procState = PROCESS_STATE_IMPORTANT_FOREGROUND; app.setCurRawProcState(procState); if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, @@ -1507,53 +1497,7 @@ public final class OomAdjuster { } } - if (mayBeTop && procState > ActivityManager.PROCESS_STATE_TOP) { - // A client of one of our services or providers is in the top state. We - // *may* want to be in the top state, but not if we are already running in - // the background for some other reason. For the decision here, we are going - // to pick out a few specific states that we want to remain in when a client - // is top (states that tend to be longer-term) and otherwise allow it to go - // to the top state. - switch (procState) { - case ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE: - case ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE: - case ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION: - // Something else is keeping it at this level, just leave it. - break; - case ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND: - case ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND: - case ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND: - case ActivityManager.PROCESS_STATE_SERVICE: - // These all are longer-term states, so pull them up to the top - // of the background states, but not all the way to the top state. - procState = ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE; - app.adjType = mayBeTopType; - app.adjSource = mayBeTopSource; - app.adjTarget = mayBeTopTarget; - if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { - reportOomAdjMessageLocked(TAG_OOM_ADJ, "May be top raise to " + mayBeTopType - + ": " + app + ", due to " + mayBeTopSource - + " adj=" + adj + " procState=" - + ProcessList.makeProcStateString(procState)); - } - break; - default: - // Otherwise, top is a better choice, so take it. - procState = ActivityManager.PROCESS_STATE_TOP; - app.adjType = mayBeTopType; - app.adjSource = mayBeTopSource; - app.adjTarget = mayBeTopTarget; - if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { - reportOomAdjMessageLocked(TAG_OOM_ADJ, "May be top raise to " + mayBeTopType - + ": " + app + ", due to " + mayBeTopSource - + " adj=" + adj + " procState=" - + ProcessList.makeProcStateString(procState)); - } - break; - } - } - - if (procState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY) { + if (procState >= PROCESS_STATE_CACHED_EMPTY) { if (app.hasClientActivities()) { // This is a cached process, but with client activities. Mark it so. procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT; @@ -1607,8 +1551,8 @@ public final class OomAdjuster { // Put bound foreground services in a special sched group for additional // restrictions on screen off - if (procState >= ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE && - mService.mWakefulness != PowerManagerInternal.WAKEFULNESS_AWAKE) { + if (procState >= PROCESS_STATE_BOUND_FOREGROUND_SERVICE + && mService.mWakefulness != PowerManagerInternal.WAKEFULNESS_AWAKE) { if (schedGroup > ProcessList.SCHED_GROUP_RESTRICTED) { schedGroup = ProcessList.SCHED_GROUP_RESTRICTED; } @@ -1905,8 +1849,8 @@ public final class OomAdjuster { + " (" + app.getCurProcState() + ")" + ": " + app.adjType; reportOomAdjMessageLocked(TAG_OOM_ADJ, msg); } - boolean setImportant = app.setProcState < ActivityManager.PROCESS_STATE_SERVICE; - boolean curImportant = app.getCurProcState() < ActivityManager.PROCESS_STATE_SERVICE; + boolean setImportant = app.setProcState < PROCESS_STATE_SERVICE; + boolean curImportant = app.getCurProcState() < PROCESS_STATE_SERVICE; if (setImportant && !curImportant) { // This app is no longer something we consider important enough to allow to use // arbitrary amounts of battery power. Note its current CPU time to later know to @@ -1969,10 +1913,11 @@ public final class OomAdjuster { // To avoid some abuse patterns, we are going to be careful about what we consider // to be an app interaction. Being the top activity doesn't count while the display // is sleeping, nor do short foreground services. - if (app.getCurProcState() <= ActivityManager.PROCESS_STATE_TOP) { + if (app.getCurProcState() <= PROCESS_STATE_TOP + || app.getCurProcState() == PROCESS_STATE_BOUND_TOP) { isInteraction = true; app.setFgInteractionTime(0); - } else if (app.getCurProcState() <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) { + } else if (app.getCurProcState() <= PROCESS_STATE_FOREGROUND_SERVICE) { if (app.getFgInteractionTime() == 0) { app.setFgInteractionTime(nowElapsed); isInteraction = false; @@ -1982,7 +1927,7 @@ public final class OomAdjuster { } } else { isInteraction = - app.getCurProcState() <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; + app.getCurProcState() <= PROCESS_STATE_IMPORTANT_FOREGROUND; app.setFgInteractionTime(0); } if (isInteraction @@ -2004,8 +1949,8 @@ public final class OomAdjuster { } private void maybeUpdateLastTopTime(ProcessRecord app, long nowUptime) { - if (app.setProcState <= ActivityManager.PROCESS_STATE_TOP - && app.getCurProcState() > ActivityManager.PROCESS_STATE_TOP) { + if (app.setProcState <= PROCESS_STATE_TOP + && app.getCurProcState() > PROCESS_STATE_TOP) { app.lastTopTime = nowUptime; } } diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index d02fd7387f59..f1f40d49ccd1 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -769,6 +769,9 @@ public final class ProcessList { case ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION: procState = "FGSL"; break; + case ActivityManager.PROCESS_STATE_BOUND_TOP: + procState = "BTOP"; + break; case ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE: procState = "FGS "; break; @@ -836,6 +839,9 @@ public final class ProcessList { case ActivityManager.PROCESS_STATE_TOP: return AppProtoEnums.PROCESS_STATE_TOP; case ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION: + return AppProtoEnums.PROCESS_STATE_FOREGROUND_SERVICE; + case ActivityManager.PROCESS_STATE_BOUND_TOP: + return AppProtoEnums.PROCESS_STATE_BOUND_TOP; case ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE: return AppProtoEnums.PROCESS_STATE_FOREGROUND_SERVICE; case ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE: @@ -966,6 +972,7 @@ public final class ProcessList { PROC_MEM_TOP, // ActivityManager.PROCESS_STATE_TOP PROC_MEM_IMPORTANT, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION PROC_MEM_IMPORTANT, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE + PROC_MEM_TOP, // ActivityManager.PROCESS_STATE_BOUND_TOP PROC_MEM_IMPORTANT, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE PROC_MEM_IMPORTANT, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND PROC_MEM_IMPORTANT, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index 2e5dd3b0941e..c9e7cfa73259 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -153,6 +153,7 @@ public class AppOpsService extends IAppOpsService.Stub { UID_STATE_TOP, // ActivityManager.PROCESS_STATE_TOP UID_STATE_FOREGROUND_SERVICE_LOCATION, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION + UID_STATE_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_TOP UID_STATE_FOREGROUND_SERVICE, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE UID_STATE_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE UID_STATE_FOREGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java index 4e4b15fc5b9b..ba4dcdbb7ee3 100644 --- a/services/core/java/com/android/server/content/ContentService.java +++ b/services/core/java/com/android/server/content/ContentService.java @@ -1317,7 +1317,9 @@ public final class ContentService extends IContentService.Stub { final int procState = ami.getUidProcessState(callingUid); final boolean isUidActive = ami.isUidActive(callingUid); - if (procState <= ActivityManager.PROCESS_STATE_TOP) { + // Providers bound by a TOP app will get PROCESS_STATE_BOUND_TOP, so include those as well + if (procState <= ActivityManager.PROCESS_STATE_TOP + || procState == ActivityManager.PROCESS_STATE_BOUND_TOP) { return ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP; } if (procState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND || isUidActive) { diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 7c12c1ebc2be..cd15587918ec 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -949,7 +949,8 @@ class ActivityStarter { final boolean callingUidHasAnyVisibleWindow = mService.mWindowManager.mRoot.isAnyNonToastWindowVisibleForUid(callingUid); final boolean isCallingUidForeground = callingUidHasAnyVisibleWindow - || callingUidProcState == ActivityManager.PROCESS_STATE_TOP; + || callingUidProcState == ActivityManager.PROCESS_STATE_TOP + || callingUidProcState == ActivityManager.PROCESS_STATE_BOUND_TOP; final boolean isCallingUidPersistentSystemProcess = (callingUid == Process.SYSTEM_UID) || callingUidProcState <= ActivityManager.PROCESS_STATE_PERSISTENT_UI; if (isCallingUidForeground || isCallingUidPersistentSystemProcess) {