Update use of procstate for services.

Now that we have a separate foreground service proc state
(above a sleeping top app), update various system services
to put their bindings into this state when appropriate.

There are two new bind flags for this -- one that just always
makes it a foreground service, another that only does it when
the device is awake (useful for things like the wallpaper).

And with all of that, tweak network policy manager to only
include apps that are at least foreground service state when
in power save and device idle modes.  This will allow us to
further reduce the set of apps that have network access
(in particular not giving access to the current top app when
the screen is off), hopefully leading to even better battery
life.

Change-Id: I91d85a5c5ed64e856149e9a5d94a634a7925ec7f
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 5eacce3..0bd60ef 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -252,6 +252,21 @@
     public static final int BIND_ADJUST_WITH_ACTIVITY = 0x0080;
 
     /**
+     * @hide Flag for {@link #bindService}: Like {@link #BIND_FOREGROUND_SERVICE},
+     * but only applies while the device is awake.
+     */
+    public static final int BIND_FOREGROUND_SERVICE_WHILE_AWAKE = 0x02000000;
+
+    /**
+     * @hide Flag for {@link #bindService}: For only the case where the binding
+     * is coming from the system, set the process state to FOREGROUND_SERVICE
+     * instead of the normal maximum of IMPORTANT_FOREGROUND.  That is, this is
+     * saying that the process shouldn't participate in the normal power reduction
+     * modes (removing network access etc).
+     */
+    public static final int BIND_FOREGROUND_SERVICE = 0x04000000;
+
+    /**
      * @hide Flag for {@link #bindService}: Treat the binding as hosting
      * an activity, an unbinding as the activity going in the background.
      * That is, when unbinding, the process when empty will go on the activity
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 82a77d2..860939c 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -2060,7 +2060,9 @@
             UserState userState = getUserStateLocked(mUserId);
             if (!mIsAutomation) {
                 if (mService == null && mContext.bindServiceAsUser(
-                        mIntent, this, Context.BIND_AUTO_CREATE, new UserHandle(mUserId))) {
+                        mIntent, this,
+                        Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
+                        new UserHandle(mUserId))) {
                     userState.mBindingServices.add(mComponentName);
                 }
             } else {
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index f42aef1..17c7e0c 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -1492,7 +1492,8 @@
         // RemoteViewsService.
         final long token = Binder.clearCallingIdentity();
         try {
-            mContext.bindServiceAsUser(intent, conn, Context.BIND_AUTO_CREATE,
+            mContext.bindServiceAsUser(intent, conn,
+                    Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
                     widget.provider.info.getProfile());
         } finally {
             Binder.restoreCallingIdentity(token);
@@ -2907,7 +2908,8 @@
             UserHandle userHandle) {
         final long token = Binder.clearCallingIdentity();
         try {
-            mContext.bindServiceAsUser(intent, connection, Context.BIND_AUTO_CREATE,
+            mContext.bindServiceAsUser(intent, connection,
+                    Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
                     userHandle);
         } finally {
             Binder.restoreCallingIdentity(token);
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 0f9090d..4fda370 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -1993,7 +1993,8 @@
             if (mHaveConnection && !mVisibleBound) {
                 bindCurrentInputMethodService(
                         mCurIntent, mVisibleConnection, Context.BIND_AUTO_CREATE
-                                | Context.BIND_TREAT_LIKE_ACTIVITY);
+                                | Context.BIND_TREAT_LIKE_ACTIVITY
+                                | Context.BIND_FOREGROUND_SERVICE);
                 mVisibleBound = true;
             }
             res = true;
diff --git a/services/core/java/com/android/server/TextServicesManagerService.java b/services/core/java/com/android/server/TextServicesManagerService.java
index 9a6f696..5bce6eb 100644
--- a/services/core/java/com/android/server/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/TextServicesManagerService.java
@@ -555,7 +555,8 @@
         if (DBG) {
             Slog.w(TAG, "bind service: " + info.getId());
         }
-        if (!bindCurrentSpellCheckerService(serviceIntent, connection, Context.BIND_AUTO_CREATE)) {
+        if (!bindCurrentSpellCheckerService(serviceIntent, connection,
+                Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE)) {
             Slog.e(TAG, "Failed to get a spell checker service.");
             return;
         }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 9fe0211..4091e10 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -10880,8 +10880,8 @@
             for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
                 ProcessRecord proc = mLruProcesses.get(i);
                 if (proc.notCachedSinceIdle) {
-                    if (proc.setProcState != ActivityManager.PROCESS_STATE_TOP
-                            && proc.setProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
+                    if (proc.setProcState != ActivityManager.PROCESS_STATE_TOP_SLEEPING
+                            && proc.setProcState >= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
                             && proc.setProcState <= ActivityManager.PROCESS_STATE_SERVICE) {
                         if (doKilling && proc.initialIdlePss != 0
                                 && proc.lastPss > ((proc.initialIdlePss*3)/2)) {
@@ -17042,7 +17042,7 @@
             adj = ProcessList.FOREGROUND_APP_ADJ;
             schedGroup = Process.THREAD_GROUP_DEFAULT;
             app.adjType = "instrumentation";
-            procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
+            procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
         } else if ((queue = isReceivingBroadcast(app)) != null) {
             // An app that is currently receiving a broadcast also
             // counts as being in the foreground for OOM killer purposes.
@@ -17380,8 +17380,19 @@
                                     // 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_IMPORTANT_FOREGROUND;
+                                    if ((cr.flags&Context.BIND_FOREGROUND_SERVICE) != 0) {
+                                        clientProcState =
+                                                ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
+                                    } else if (mWakefulness
+                                                    == PowerManagerInternal.WAKEFULNESS_AWAKE &&
+                                            (cr.flags&Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE)
+                                                    != 0) {
+                                        clientProcState =
+                                                ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
+                                    } else {
+                                        clientProcState =
+                                                ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
+                                    }
                                 }
                             }
                         } else {
@@ -17491,7 +17502,7 @@
                         // into the top state, since they are not on top.  Instead
                         // give them the best state after that.
                         clientProcState =
-                                ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
+                                ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
                     }
                 }
                 if (procState > clientProcState) {
@@ -17531,7 +17542,7 @@
                 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_IMPORTANT_FOREGROUND;
+                    procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
                     break;
                 default:
                     // Otherwise, top is a better choice, so take it.
diff --git a/services/core/java/com/android/server/am/ConnectionRecord.java b/services/core/java/com/android/server/am/ConnectionRecord.java
index 423e540..cd37041 100644
--- a/services/core/java/com/android/server/am/ConnectionRecord.java
+++ b/services/core/java/com/android/server/am/ConnectionRecord.java
@@ -87,7 +87,16 @@
             sb.append("IMP ");
         }
         if ((flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
-            sb.append("ACT ");
+            sb.append("WACT ");
+        }
+        if ((flags&Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE) != 0) {
+            sb.append("FGSA ");
+        }
+        if ((flags&Context.BIND_FOREGROUND_SERVICE) != 0) {
+            sb.append("FGS ");
+        }
+        if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
+            sb.append("LACT ");
         }
         if ((flags&Context.BIND_VISIBLE) != 0) {
             sb.append("VIS ");
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 3d478f9..a07591c9 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -529,8 +529,9 @@
                 throw new IllegalArgumentException("At least one address must be specified");
             }
             Connection connection = new Connection();
-            if (!mContext.bindServiceAsUser(intent, connection, Context.BIND_AUTO_CREATE,
-                        new UserHandle(mUserHandle))) {
+            if (!mContext.bindServiceAsUser(intent, connection,
+                    Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
+                    new UserHandle(mUserHandle))) {
                 throw new IllegalStateException("Cannot bind " + config.user);
             }
 
diff --git a/services/core/java/com/android/server/dreams/DreamController.java b/services/core/java/com/android/server/dreams/DreamController.java
index 768ccf2..cff4814 100644
--- a/services/core/java/com/android/server/dreams/DreamController.java
+++ b/services/core/java/com/android/server/dreams/DreamController.java
@@ -136,7 +136,8 @@
             intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
             try {
                 if (!mContext.bindServiceAsUser(intent, mCurrentDream,
-                        Context.BIND_AUTO_CREATE, new UserHandle(userId))) {
+                        Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
+                        new UserHandle(userId))) {
                     Slog.e(TAG, "Unable to bind dream service: " + intent);
                     stopDream(true /*immediate*/);
                     return;
diff --git a/services/core/java/com/android/server/media/RemoteDisplayProviderProxy.java b/services/core/java/com/android/server/media/RemoteDisplayProviderProxy.java
index a5fe9f2..ba98a0a 100644
--- a/services/core/java/com/android/server/media/RemoteDisplayProviderProxy.java
+++ b/services/core/java/com/android/server/media/RemoteDisplayProviderProxy.java
@@ -190,7 +190,8 @@
             Intent service = new Intent(RemoteDisplayState.SERVICE_INTERFACE);
             service.setComponent(mComponentName);
             try {
-                mBound = mContext.bindServiceAsUser(service, this, Context.BIND_AUTO_CREATE,
+                mBound = mContext.bindServiceAsUser(service, this,
+                        Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
                         new UserHandle(mUserId));
                 if (!mBound && DEBUG) {
                     Slog.d(TAG, this + ": Bind failed");
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index e45092c..a95ba35 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -2004,7 +2004,7 @@
         // to have data access.  Otherwise, we restrict data access to only
         // the top apps.
         mCurForegroundState = (!mRestrictBackground && (mRestrictPower || mDeviceIdleMode))
-                ? ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
+                ? ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
                 : ActivityManager.PROCESS_STATE_TOP;
 
         // update rules for all installed applications
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 9ccb2ea..b92c734 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -495,7 +495,7 @@
                                 Slog.v(TAG, getCaption() + " connection lost: " + name);
                             }
                         },
-                        Context.BIND_AUTO_CREATE,
+                        Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
                         new UserHandle(userid)))
                 {
                     mServicesBinding.remove(servicesBindingTag);
diff --git a/services/core/java/com/android/server/telecom/TelecomLoaderService.java b/services/core/java/com/android/server/telecom/TelecomLoaderService.java
index 22fee22..9abdf21 100644
--- a/services/core/java/com/android/server/telecom/TelecomLoaderService.java
+++ b/services/core/java/com/android/server/telecom/TelecomLoaderService.java
@@ -96,7 +96,8 @@
         TelecomServiceConnection serviceConnection = new TelecomServiceConnection();
         Intent intent = new Intent(SERVICE_ACTION);
         intent.setComponent(SERVICE_COMPONENT);
-        int flags = Context.BIND_IMPORTANT | Context.BIND_AUTO_CREATE;
+        int flags = Context.BIND_IMPORTANT | Context.BIND_FOREGROUND_SERVICE
+                | Context.BIND_AUTO_CREATE;
 
         // Bind to Telecom and register the service
         if (mContext.bindServiceAsUser(intent, serviceConnection, flags, UserHandle.OWNER)) {
diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
index fb7d186..e5c5b2bc 100644
--- a/services/core/java/com/android/server/trust/TrustAgentWrapper.java
+++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
@@ -276,7 +276,8 @@
         // Schedules a restart for when connecting times out. If the connection succeeds,
         // the restart is canceled in mCallback's onConnected.
         scheduleRestart();
-        mBound = context.bindServiceAsUser(intent, mConnection, Context.BIND_AUTO_CREATE, user);
+        mBound = context.bindServiceAsUser(intent, mConnection,
+                Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, user);
         if (mBound) {
             mContext.registerReceiver(mBroadcastReceiver, alarmFilter, PERMISSION, null);
         } else {
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 5972247..56816f9 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -529,7 +529,9 @@
 
             Intent i = new Intent(TvInputService.SERVICE_INTERFACE).setComponent(component);
             serviceState.bound = mContext.bindServiceAsUser(
-                    i, serviceState.connection, Context.BIND_AUTO_CREATE, new UserHandle(userId));
+                    i, serviceState.connection,
+                    Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
+                    new UserHandle(userId));
         } else if (serviceState.service != null && !maintainConnection) {
             // This means that the service is already connected but its state indicates that we have
             // nothing to do with it. Then, disconnect the service.
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 54be380..755c414 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -1038,7 +1038,8 @@
                             mContext.getText(com.android.internal.R.string.chooser_wallpaper)),
                     0, null, new UserHandle(serviceUserId)));
             if (!mContext.bindServiceAsUser(intent, newConn,
-                    Context.BIND_AUTO_CREATE | Context.BIND_SHOWING_UI,
+                    Context.BIND_AUTO_CREATE | Context.BIND_SHOWING_UI
+                            | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
                     new UserHandle(serviceUserId))) {
                 String msg = "Unable to bind service: "
                         + componentName;
diff --git a/services/print/java/com/android/server/print/RemotePrintService.java b/services/print/java/com/android/server/print/RemotePrintService.java
index a8c739c..0ab1657 100644
--- a/services/print/java/com/android/server/print/RemotePrintService.java
+++ b/services/print/java/com/android/server/print/RemotePrintService.java
@@ -507,7 +507,8 @@
         }
         mBinding = true;
         mContext.bindServiceAsUser(mIntent, mServiceConnection,
-                Context.BIND_AUTO_CREATE, new UserHandle(mUserId));
+                Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
+                new UserHandle(mUserId));
     }
 
     private void ensureUnbound() {
diff --git a/services/print/java/com/android/server/print/RemotePrintSpooler.java b/services/print/java/com/android/server/print/RemotePrintSpooler.java
index 7ab3840..85c876a 100644
--- a/services/print/java/com/android/server/print/RemotePrintSpooler.java
+++ b/services/print/java/com/android/server/print/RemotePrintSpooler.java
@@ -365,7 +365,7 @@
         }
 
         mContext.bindServiceAsUser(mIntent, mServiceConnection,
-                Context.BIND_AUTO_CREATE, mUserHandle);
+                Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, mUserHandle);
 
         final long startMillis = SystemClock.uptimeMillis();
         while (true) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 61ec162..f439915 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -229,7 +229,7 @@
         Intent intent = new Intent(VoiceInteractionService.SERVICE_INTERFACE);
         intent.setComponent(mComponent);
         mBound = mContext.bindServiceAsUser(intent, mConnection,
-                Context.BIND_AUTO_CREATE, new UserHandle(mUser));
+                Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, new UserHandle(mUser));
         if (!mBound) {
             Slog.w(TAG, "Failed binding to voice interaction service " + mComponent);
         }
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index 9634ab8..42eb6c3 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -180,7 +180,8 @@
         if (mBound) {
             if (!mFullyBound) {
                 mFullyBound = mContext.bindServiceAsUser(mBindIntent, mFullConnection,
-                        Context.BIND_AUTO_CREATE|Context.BIND_TREAT_LIKE_ACTIVITY,
+                        Context.BIND_AUTO_CREATE | Context.BIND_TREAT_LIKE_ACTIVITY
+                                | Context.BIND_FOREGROUND_SERVICE,
                         new UserHandle(mUser));
             }
             mShown = true;