OSDN Git Service

Avoid elevating apps to high proc states on binding
authorAmith Yamasani <yamasani@google.com>
Thu, 21 Mar 2019 05:49:43 +0000 (22:49 -0700)
committerAmith Yamasani <yamasani@google.com>
Tue, 2 Apr 2019 17:27:03 +0000 (10:27 -0700)
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

13 files changed:
core/java/android/app/ActivityManager.java
core/java/android/content/Context.java
core/java/android/os/BatteryStats.java
core/java/com/android/internal/app/procstats/ProcessState.java
core/proto/android/app/enums.proto
services/core/java/com/android/server/am/ActiveServices.java
services/core/java/com/android/server/am/ActivityManagerService.java
services/core/java/com/android/server/am/ConnectionRecord.java
services/core/java/com/android/server/am/OomAdjuster.java
services/core/java/com/android/server/am/ProcessList.java
services/core/java/com/android/server/appop/AppOpsService.java
services/core/java/com/android/server/content/ContentService.java
services/core/java/com/android/server/wm/ActivityStarter.java

index 80b6349..395c867 100644 (file)
@@ -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;
index d7a2e1b..af738da 100644 (file)
@@ -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;
index b64fe00..00d522b 100644 (file)
@@ -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
         };
 
index 0e4897f..b26efc0 100644 (file)
@@ -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
index 1754e42..9abe923 100644 (file)
@@ -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;
index 261ed4c..f0982d3 100644 (file)
@@ -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;
index 3eb7c03..69e69f0 100644 (file)
@@ -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);
+            }
         }
     }
 
index a1c941e..fe95542 100644 (file)
@@ -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.
index 924e331..5d47c9d 100644 (file)
 
 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<ConnectionRecord> 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;
         }
     }
index d02fd73..f1f40d4 100644 (file)
@@ -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
index 2e5dd3b..c9e7cfa 100644 (file)
@@ -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
index 4e4b15f..ba4dcdb 100644 (file)
@@ -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) {
index 7c12c1e..cd15587 100644 (file)
@@ -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) {