Fix issue #21626564: MMS should be receivied while Dozing

We now place whoever is receiving the MMS on the temporary
whitelist while doing so, so they can get network access to
download it.

There was also an issue that needed to be fixed where we
were no longer updating the list of allowed uids while
dozing based on their proc states...  we now do that.

Also did a bit of optimization of the temp white list update
path do the network policy manager, instead of going through
a broadcast we now directly call in to the network policy
manager.  This also allows us to have a synchronous version
of updating the list, so we can know the app has network access
before we tell it to do anything.

Finally added battery stats events for things going on and off
the whitelist so we can diagnose the behavior there.

Change-Id: Ic7fe010af680034d9f8cb014bb135b2addef7455
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index c07140c..235f294 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -960,14 +960,21 @@
             String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler,
             int initialCode, String initialData, Bundle initialExtras) {
         sendOrderedBroadcastAsUser(intent, user, receiverPermission, AppOpsManager.OP_NONE,
-                resultReceiver, scheduler, initialCode, initialData, initialExtras);
+                null, resultReceiver, scheduler, initialCode, initialData, initialExtras);
     }
 
     @Override
     public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
             String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
-            Handler scheduler,
-            int initialCode, String initialData, Bundle initialExtras) {
+            Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
+        sendOrderedBroadcastAsUser(intent, user, receiverPermission, appOp,
+                null, resultReceiver, scheduler, initialCode, initialData, initialExtras);
+    }
+
+    @Override
+    public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
+            String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver,
+            Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
         IIntentReceiver rd = null;
         if (resultReceiver != null) {
             if (mPackageInfo != null) {
@@ -981,8 +988,8 @@
                 if (scheduler == null) {
                     scheduler = mMainThread.getHandler();
                 }
-                rd = new LoadedApk.ReceiverDispatcher(
-                        resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();
+                rd = new LoadedApk.ReceiverDispatcher(resultReceiver, getOuterContext(),
+                        scheduler, null, false).getIIntentReceiver();
             }
         }
         String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
@@ -993,7 +1000,7 @@
             ActivityManagerNative.getDefault().broadcastIntent(
                 mMainThread.getApplicationThread(), intent, resolvedType, rd,
                 initialCode, initialData, initialExtras, receiverPermissions,
-                    appOp, null, true, false, user.getIdentifier());
+                    appOp, options, true, false, user.getIdentifier());
         } catch (RemoteException e) {
             throw new RuntimeException("Failure from system", e);
         }
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 0bfe108..4c7dd10 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1809,6 +1809,17 @@
             @Nullable  Bundle initialExtras);
 
     /**
+     * Similar to above but takes an appOp as well, to enforce restrictions, and an options Bundle.
+     * @see #sendOrderedBroadcastAsUser(Intent, UserHandle, String,
+     *       BroadcastReceiver, Handler, int, String, Bundle)
+     * @hide
+     */
+    public abstract void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
+            @Nullable String receiverPermission, int appOp, @Nullable Bundle options,
+            BroadcastReceiver resultReceiver, @Nullable Handler scheduler, int initialCode,
+            @Nullable String initialData, @Nullable  Bundle initialExtras);
+
+    /**
      * <p>Perform a {@link #sendBroadcast(Intent)} that is "sticky," meaning the
      * Intent you are sending stays around after the broadcast is complete,
      * so that others can quickly retrieve that data through the return
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 8ad3d21..8359edf 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -489,12 +489,20 @@
     @Override
     public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
             String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
-            Handler scheduler,
-            int initialCode, String initialData, Bundle initialExtras) {
+            Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
         mBase.sendOrderedBroadcastAsUser(intent, user, receiverPermission, appOp, resultReceiver,
                 scheduler, initialCode, initialData, initialExtras);
     }
 
+    /** @hide */
+    @Override
+    public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
+            String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver,
+            Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
+        mBase.sendOrderedBroadcastAsUser(intent, user, receiverPermission, appOp, options,
+                resultReceiver, scheduler, initialCode, initialData, initialExtras);
+    }
+
     @Override
     @Deprecated
     public void sendStickyBroadcast(Intent intent) {
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index adc84bc2..452e4d5 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1193,9 +1193,11 @@
         public static final int EVENT_PACKAGE_INACTIVE = 0x000f;
         // Event for a package becoming active due to an interaction.
         public static final int EVENT_PACKAGE_ACTIVE = 0x0010;
+        // Event for a package being on the temporary whitelist.
+        public static final int EVENT_TEMP_WHITELIST = 0x0011;
 
         // Number of event types.
-        public static final int EVENT_COUNT = 0x0011;
+        public static final int EVENT_COUNT = 0x0012;
         // Mask to extract out only the type part of the event.
         public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH);
 
@@ -1219,6 +1221,10 @@
                 EVENT_USER_FOREGROUND | EVENT_FLAG_FINISH;
         public static final int EVENT_ALARM_START = EVENT_ALARM | EVENT_FLAG_START;
         public static final int EVENT_ALARM_FINISH = EVENT_ALARM | EVENT_FLAG_FINISH;
+        public static final int EVENT_TEMP_WHITELIST_START =
+                EVENT_TEMP_WHITELIST | EVENT_FLAG_START;
+        public static final int EVENT_TEMP_WHITELIST_FINISH =
+                EVENT_TEMP_WHITELIST | EVENT_FLAG_FINISH;
 
         // For CMD_EVENT.
         public int eventCode;
@@ -1852,12 +1858,12 @@
 
     public static final String[] HISTORY_EVENT_NAMES = new String[] {
             "null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg", "conn",
-            "active", "pkginst", "pkgunin", "alarm", "stats", "inactive", "active"
+            "active", "pkginst", "pkgunin", "alarm", "stats", "inactive", "active", "tmpwhitelist"
     };
 
     public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] {
             "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf", "Ecn",
-            "Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa"
+            "Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa", "Etw"
     };
 
     /**
diff --git a/core/java/android/os/IDeviceIdleController.aidl b/core/java/android/os/IDeviceIdleController.aidl
index fe4aa13..b768852 100644
--- a/core/java/android/os/IDeviceIdleController.aidl
+++ b/core/java/android/os/IDeviceIdleController.aidl
@@ -27,6 +27,7 @@
     int[] getAppIdWhitelist();
     int[] getAppIdTempWhitelist();
     boolean isPowerSaveWhitelistApp(String name);
-    void addPowerSaveTempWhitelistApp(String name, long duration, int userId);
+    void addPowerSaveTempWhitelistApp(String name, long duration, int userId, String reason);
+    long addPowerSaveTempWhitelistAppForMms(String name, int userId, String reason);
     void exitIdle(String reason);
 }