DownloadManager flags for network policy.

Handful of DownloadManager flags to record when a download was paused
because of NetworkPolicyManager rules.

Change-Id: I99fc47f529cb6c8a42dbeca049e0cd0f1556eac4
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 20dc792..94a4afa 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -52,6 +52,8 @@
 import android.media.AudioManager;
 import android.net.ConnectivityManager;
 import android.net.IConnectivityManager;
+import android.net.INetworkPolicyManager;
+import android.net.NetworkPolicyManager;
 import android.net.ThrottleManager;
 import android.net.IThrottleManager;
 import android.net.Uri;
@@ -339,6 +341,14 @@
                     return new LocationManager(ILocationManager.Stub.asInterface(b));
                 }});
 
+        registerService(NETWORK_POLICY_SERVICE, new ServiceFetcher() {
+            @Override
+            public Object createService(ContextImpl ctx) {
+                return new NetworkPolicyManager(INetworkPolicyManager.Stub.asInterface(
+                        ServiceManager.getService(NETWORK_POLICY_SERVICE)));
+            }
+        });
+
         registerService(NOTIFICATION_SERVICE, new ServiceFetcher() {
                 public Object createService(ContextImpl ctx) {
                     final Context outerContext = ctx.getOuterContext();
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index b88e5cf..28559cc 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -23,6 +23,7 @@
 import android.database.Cursor;
 import android.database.CursorWrapper;
 import android.net.ConnectivityManager;
+import android.net.NetworkPolicyManager;
 import android.net.Uri;
 import android.os.Environment;
 import android.os.ParcelFileDescriptor;
@@ -170,7 +171,6 @@
      */
     public final static int STATUS_FAILED = 1 << 4;
 
-
     /**
      * Value of COLUMN_ERROR_CODE when the download has completed with an error that doesn't fit
      * under any other error code.
@@ -249,6 +249,14 @@
     public final static int PAUSED_UNKNOWN = 4;
 
     /**
+     * Value of {@link #COLUMN_REASON} when the download has been paused because
+     * of {@link NetworkPolicyManager} controls on the requesting application.
+     *
+     * @hide
+     */
+    public final static int PAUSED_BY_POLICY = 5;
+
+    /**
      * Broadcast intent action sent by the download manager when a download completes.
      */
     public final static String ACTION_DOWNLOAD_COMPLETE = "android.intent.action.DOWNLOAD_COMPLETE";
@@ -796,6 +804,7 @@
                     parts.add(statusClause("=", Downloads.Impl.STATUS_WAITING_TO_RETRY));
                     parts.add(statusClause("=", Downloads.Impl.STATUS_WAITING_FOR_NETWORK));
                     parts.add(statusClause("=", Downloads.Impl.STATUS_QUEUED_FOR_WIFI));
+                    parts.add(statusClause("=", Downloads.Impl.STATUS_PAUSED_BY_POLICY));
                 }
                 if ((mStatusFlags & STATUS_SUCCESSFUL) != 0) {
                     parts.add(statusClause("=", Downloads.Impl.STATUS_SUCCESS));
@@ -1266,6 +1275,9 @@
                 case Downloads.Impl.STATUS_QUEUED_FOR_WIFI:
                     return PAUSED_QUEUED_FOR_WIFI;
 
+                case Downloads.Impl.STATUS_PAUSED_BY_POLICY:
+                    return PAUSED_BY_POLICY;
+
                 default:
                     return PAUSED_UNKNOWN;
             }
@@ -1321,6 +1333,7 @@
                 case Downloads.Impl.STATUS_WAITING_TO_RETRY:
                 case Downloads.Impl.STATUS_WAITING_FOR_NETWORK:
                 case Downloads.Impl.STATUS_QUEUED_FOR_WIFI:
+                case Downloads.Impl.STATUS_PAUSED_BY_POLICY:
                     return STATUS_PAUSED;
 
                 case Downloads.Impl.STATUS_SUCCESS:
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 538a06e..0d4d9a9 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -115,6 +115,20 @@
         }
     }
 
+    public void registerListener(INetworkPolicyListener listener) {
+        try {
+            mService.registerListener(listener);
+        } catch (RemoteException e) {
+        }
+    }
+
+    public void unregisterListener(INetworkPolicyListener listener) {
+        try {
+            mService.unregisterListener(listener);
+        } catch (RemoteException e) {
+        }
+    }
+
     /**
      * Compute the last cycle boundary for the given {@link NetworkPolicy}. For
      * example, if cycle day is 20th, and today is June 15th, it will return May
diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java
index 3c4bb79..0a8c3ca 100644
--- a/core/java/android/provider/Downloads.java
+++ b/core/java/android/provider/Downloads.java
@@ -17,6 +17,7 @@
 package android.provider;
 
 import android.app.DownloadManager;
+import android.net.NetworkPolicyManager;
 import android.net.Uri;
 
 /**
@@ -547,6 +548,14 @@
         }
 
         /**
+         * This download has been paused because requesting application has been
+         * blocked by {@link NetworkPolicyManager}.
+         *
+         * @hide
+         */
+        public static final int STATUS_PAUSED_BY_POLICY = 189;
+
+        /**
          * This download hasn't stated yet
          */
         public static final int STATUS_PENDING = 190;
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index c6f4c20..c39b24fc 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -16,8 +16,7 @@
 
 package com.android.server;
 
-import static android.Manifest.permission.READ_PHONE_STATE;
-import static android.Manifest.permission.UPDATE_DEVICE_STATS;
+import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
 import static android.net.ConnectivityManager.isNetworkTypeValid;
 import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
 import static android.net.NetworkPolicyManager.RULE_REJECT_PAID;
@@ -1142,8 +1141,7 @@
         @Override
         public void onRulesChanged(int uid, int uidRules) {
             // only someone like NPMS should only be calling us
-            // TODO: create permission for modifying data policy
-            mContext.enforceCallingOrSelfPermission(UPDATE_DEVICE_STATS, TAG);
+            mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
 
             if (LOGD_RULES) {
                 Slog.d(TAG, "onRulesChanged(uid=" + uid + ", uidRules=" + uidRules + ")");
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index dac0044..9cbe82d 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -747,6 +747,9 @@
 
     @Override
     public void registerListener(INetworkPolicyListener listener) {
+        // TODO: create permission for observing network policy
+        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+
         mListeners.register(listener);
 
         synchronized (mRulesLock) {
@@ -767,6 +770,9 @@
 
     @Override
     public void unregisterListener(INetworkPolicyListener listener) {
+        // TODO: create permission for observing network policy
+        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+
         mListeners.unregister(listener);
     }