Observe screen on/off events in NetworkPolicy.

The POLICY_REJECT_BACKGROUND policy requires that network traffic be
blocked when a UID goes into the background.  Even if the UID has an
activity in the foreground, it's considered "background" if the screen
is turned off.

This changes watches for SCREEN_ON/OFF broadcasts, and rule generation
now observes screen state.  It also introduces an observer pattern so
that ActivityManager doesn't directly know about NetworkPolicy, and
moves the service management into SystemServer.

Change-Id: Ie7a84929d3ca60ae4578d47e19d5a8da10fd8d58
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 5aae539..568183b 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -43,6 +43,7 @@
 import android.app.IApplicationThread;
 import android.app.IInstrumentationWatcher;
 import android.app.INotificationManager;
+import android.app.IProcessObserver;
 import android.app.IServiceConnection;
 import android.app.IThumbnailReceiver;
 import android.app.IThumbnailRetriever;
@@ -752,8 +753,6 @@
      */
     final UsageStatsService mUsageStatsService;
 
-    final NetworkPolicyManagerService mNetworkPolicyService;
-
     /**
      * Current configuration information.  HistoryRecord objects are given
      * a reference to this object to indicate which configuration they are
@@ -885,7 +884,10 @@
 
     final RemoteCallbackList<IActivityWatcher> mWatchers
             = new RemoteCallbackList<IActivityWatcher>();
-    
+
+    final RemoteCallbackList<IProcessObserver> mProcessObservers
+            = new RemoteCallbackList<IProcessObserver>();
+
     /**
      * Callback of last caller to {@link #requestPss}.
      */
@@ -1277,16 +1279,15 @@
                 }
             } break;
             case DISPATCH_FOREGROUND_ACTIVITIES_CHANGED: {
-                // Flag might have changed during dispatch, but it's always
-                // consistent since we dispatch for every change.
                 final ProcessRecord app = (ProcessRecord) msg.obj;
-                mNetworkPolicyService.onForegroundActivitiesChanged(
-                        app.info.uid, app.pid, app.foregroundActivities);
+                final boolean foregroundActivities = msg.arg1 != 0;
+                dispatchForegroundActivitiesChanged(
+                        app.pid, app.info.uid, foregroundActivities);
                 break;
             }
             case DISPATCH_PROCESS_DIED: {
                 final ProcessRecord app = (ProcessRecord) msg.obj;
-                mNetworkPolicyService.onProcessDied(app.info.uid, app.pid);
+                dispatchProcessDied(app.pid, app.info.uid);
                 break;
             }
             }
@@ -1358,7 +1359,6 @@
         
         m.mBatteryStatsService.publish(context);
         m.mUsageStatsService.publish(context);
-        m.mNetworkPolicyService.publish(context);
         
         synchronized (thr) {
             thr.mReady = true;
@@ -1480,8 +1480,6 @@
         mUsageStatsService = new UsageStatsService(new File(
                 systemDir, "usagestats").toString());
 
-        mNetworkPolicyService = new NetworkPolicyManagerService();
-
         GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
             ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
 
@@ -2152,6 +2150,36 @@
         mWatchers.finishBroadcast();
     }
 
+    private void dispatchForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
+        int i = mProcessObservers.beginBroadcast();
+        while (i > 0) {
+            i--;
+            final IProcessObserver observer = mProcessObservers.getBroadcastItem(i);
+            if (observer != null) {
+                try {
+                    observer.onForegroundActivitiesChanged(pid, uid, foregroundActivities);
+                } catch (RemoteException e) {
+                }
+            }
+        }
+        mProcessObservers.finishBroadcast();
+    }
+
+    private void dispatchProcessDied(int pid, int uid) {
+        int i = mProcessObservers.beginBroadcast();
+        while (i > 0) {
+            i--;
+            final IProcessObserver observer = mProcessObservers.getBroadcastItem(i);
+            if (observer != null) {
+                try {
+                    observer.onProcessDied(pid, uid);
+                } catch (RemoteException e) {
+                }
+            }
+        }
+        mProcessObservers.finishBroadcast();
+    }
+
     final void doPendingActivityLaunchesLocked(boolean doResume) {
         final int N = mPendingActivityLaunches.size();
         if (N <= 0) {
@@ -6084,7 +6112,6 @@
         
         mUsageStatsService.shutdown();
         mBatteryStatsService.shutdown();
-        mNetworkPolicyService.shutdown();
         
         return timedout;
     }
@@ -6241,6 +6268,14 @@
         }
     }
 
+    public void registerProcessObserver(IProcessObserver observer) {
+        mProcessObservers.register(observer);
+    }
+
+    public void unregisterProcessObserver(IProcessObserver observer) {
+        mProcessObservers.unregister(observer);
+    }
+
     public void setImmersive(IBinder token, boolean immersive) {
         synchronized(this) {
             int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
@@ -12755,7 +12790,8 @@
         app.curSchedGroup = schedGroup;
 
         if (hadForegroundActivities != app.foregroundActivities) {
-            mHandler.obtainMessage(DISPATCH_FOREGROUND_ACTIVITIES_CHANGED, app).sendToTarget();
+            mHandler.obtainMessage(DISPATCH_FOREGROUND_ACTIVITIES_CHANGED,
+                    app.foregroundActivities ? 1 : 0, 0, app).sendToTarget();
         }
 
         return adj;