Add support for broadcast intents

Change-Id: Icf61e7a202f489cb33b9fd95564285e48154b25b
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 1d26c2c..6fa1822 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -12371,7 +12371,7 @@
                     Intent intent = (Intent)allSticky.get(i);
                     BroadcastQueue queue = broadcastQueueForIntent(intent);
                     BroadcastRecord r = new BroadcastRecord(queue, intent, null,
-                            null, -1, -1, null, AppOpsManager.OP_NONE, receivers, null, 0,
+                            null, -1, -1, null, null, AppOpsManager.OP_NONE, receivers, null, 0,
                             null, null, false, true, true, -1);
                     queue.enqueueParallelBroadcastLocked(r);
                     queue.scheduleBroadcastsLocked();
@@ -12804,8 +12804,8 @@
             // components to be launched.
             final BroadcastQueue queue = broadcastQueueForIntent(intent);
             BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
-                    callerPackage, callingPid, callingUid, requiredPermission, appOp,
-                    registeredReceivers, resultTo, resultCode, resultData, map,
+                    callerPackage, callingPid, callingUid, resolvedType, requiredPermission,
+                    appOp, registeredReceivers, resultTo, resultCode, resultData, map,
                     ordered, sticky, false, userId);
             if (DEBUG_BROADCAST) Slog.v(
                     TAG, "Enqueueing parallel broadcast " + r);
@@ -12894,9 +12894,9 @@
                 || resultTo != null) {
             BroadcastQueue queue = broadcastQueueForIntent(intent);
             BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
-                    callerPackage, callingPid, callingUid, requiredPermission, appOp,
-                    receivers, resultTo, resultCode, resultData, map, ordered,
-                    sticky, false, userId);
+                    callerPackage, callingPid, callingUid, resolvedType,
+                    requiredPermission, appOp, receivers, resultTo, resultCode,
+                    resultData, map, ordered, sticky, false, userId);
             if (DEBUG_BROADCAST) Slog.v(
                     TAG, "Enqueueing ordered broadcast " + r
                     + ": prev had " + queue.mOrderedBroadcasts.size());
diff --git a/services/java/com/android/server/am/BroadcastQueue.java b/services/java/com/android/server/am/BroadcastQueue.java
index cb4b8ff..254a219 100644
--- a/services/java/com/android/server/am/BroadcastQueue.java
+++ b/services/java/com/android/server/am/BroadcastQueue.java
@@ -421,6 +421,10 @@
                 skip = true;
             }
         }
+        if (!skip) {
+            skip = !mService.mIntentFirewall.checkBroadcast(r.intent, r.callingUid,
+                    r.callingPid, r.resolvedType, filter.receiverList.uid);
+        }
 
         if (!skip) {
             // If this is not being sent as an ordered broadcast, then we
@@ -729,6 +733,10 @@
                     skip = true;
                 }
             }
+            if (!skip) {
+                skip = !mService.mIntentFirewall.checkBroadcast(r.intent, r.callingUid,
+                        r.callingPid, r.resolvedType, info.activityInfo.applicationInfo.uid);
+            }
             boolean isSingleton = false;
             try {
                 isSingleton = mService.isSingleton(info.activityInfo.processName,
diff --git a/services/java/com/android/server/am/BroadcastRecord.java b/services/java/com/android/server/am/BroadcastRecord.java
index eb1df6e..db61e88 100644
--- a/services/java/com/android/server/am/BroadcastRecord.java
+++ b/services/java/com/android/server/am/BroadcastRecord.java
@@ -47,6 +47,7 @@
     final boolean sticky;   // originated from existing sticky data?
     final boolean initialSticky; // initial broadcast from register to sticky?
     final int userId;       // user id this broadcast was for
+    final String resolvedType; // the resolved data type
     final String requiredPermission; // a permission the caller has required
     final int appOp;        // an app op that is associated with this broadcast
     final List receivers;   // contains BroadcastFilter and ResolveInfo
@@ -171,8 +172,8 @@
 
     BroadcastRecord(BroadcastQueue _queue,
             Intent _intent, ProcessRecord _callerApp, String _callerPackage,
-            int _callingPid, int _callingUid, String _requiredPermission, int _appOp,
-            List _receivers, IIntentReceiver _resultTo, int _resultCode,
+            int _callingPid, int _callingUid, String _resolvedType, String _requiredPermission,
+            int _appOp, List _receivers, IIntentReceiver _resultTo, int _resultCode,
             String _resultData, Bundle _resultExtras, boolean _serialized,
             boolean _sticky, boolean _initialSticky,
             int _userId) {
@@ -183,6 +184,7 @@
         callerPackage = _callerPackage;
         callingPid = _callingPid;
         callingUid = _callingUid;
+        resolvedType = _resolvedType;
         requiredPermission = _requiredPermission;
         appOp = _appOp;
         receivers = _receivers;
diff --git a/services/java/com/android/server/firewall/AndFilter.java b/services/java/com/android/server/firewall/AndFilter.java
index fa53945..13551de 100644
--- a/services/java/com/android/server/firewall/AndFilter.java
+++ b/services/java/com/android/server/firewall/AndFilter.java
@@ -18,7 +18,6 @@
 
 import android.content.ComponentName;
 import android.content.Intent;
-import android.content.pm.ApplicationInfo;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -27,10 +26,10 @@
 class AndFilter extends FilterList {
     @Override
     public boolean matches(IntentFirewall ifw, ComponentName resolvedComponent, Intent intent,
-            int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
+            int callerUid, int callerPid, String resolvedType, int receivingUid) {
         for (int i=0; i<children.size(); i++) {
             if (!children.get(i).matches(ifw, resolvedComponent, intent, callerUid, callerPid,
-                    resolvedType, resolvedApp)) {
+                    resolvedType, receivingUid)) {
                 return false;
             }
         }
diff --git a/services/java/com/android/server/firewall/CategoryFilter.java b/services/java/com/android/server/firewall/CategoryFilter.java
index 022dc9a..246c096 100644
--- a/services/java/com/android/server/firewall/CategoryFilter.java
+++ b/services/java/com/android/server/firewall/CategoryFilter.java
@@ -18,7 +18,6 @@
 
 import android.content.ComponentName;
 import android.content.Intent;
-import android.content.pm.ApplicationInfo;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -36,7 +35,7 @@
 
     @Override
     public boolean matches(IntentFirewall ifw, ComponentName resolvedComponent, Intent intent,
-            int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
+            int callerUid, int callerPid, String resolvedType, int receivingUid) {
         Set<String> categories = intent.getCategories();
         if (categories == null) {
             return false;
diff --git a/services/java/com/android/server/firewall/Filter.java b/services/java/com/android/server/firewall/Filter.java
index 25105e1..0a124f7 100644
--- a/services/java/com/android/server/firewall/Filter.java
+++ b/services/java/com/android/server/firewall/Filter.java
@@ -18,7 +18,6 @@
 
 import android.content.ComponentName;
 import android.content.Intent;
-import android.content.pm.ApplicationInfo;
 
 interface Filter {
     /**
@@ -30,8 +29,8 @@
      * @param callerUid The uid of the caller
      * @param callerPid The pid of the caller
      * @param resolvedType The resolved mime type of the intent
-     * @param resolvedApp The application that contains the resolved component that the intent is
+     * @param receivingUid The uid of the component receiving the intent
      */
     boolean matches(IntentFirewall ifw, ComponentName resolvedComponent, Intent intent,
-            int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp);
+            int callerUid, int callerPid, String resolvedType, int receivingUid);
 }
diff --git a/services/java/com/android/server/firewall/IntentFirewall.java b/services/java/com/android/server/firewall/IntentFirewall.java
index bd62de7..aaa0b58 100644
--- a/services/java/com/android/server/firewall/IntentFirewall.java
+++ b/services/java/com/android/server/firewall/IntentFirewall.java
@@ -124,18 +124,24 @@
     public boolean checkStartActivity(Intent intent, int callerUid, int callerPid,
             String resolvedType, ApplicationInfo resolvedApp) {
         return checkIntent(mActivityResolver, intent.getComponent(), TYPE_ACTIVITY, intent,
-                callerUid, callerPid, resolvedType, resolvedApp);
+                callerUid, callerPid, resolvedType, resolvedApp.uid);
     }
 
     public boolean checkService(ComponentName resolvedService, Intent intent, int callerUid,
             int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
         return checkIntent(mServiceResolver, resolvedService, TYPE_SERVICE, intent, callerUid,
-                callerPid, resolvedType, resolvedApp);
+                callerPid, resolvedType, resolvedApp.uid);
+    }
+
+    public boolean checkBroadcast(Intent intent, int callerUid, int callerPid,
+            String resolvedType, int receivingUid) {
+        return checkIntent(mBroadcastResolver, intent.getComponent(), TYPE_BROADCAST, intent,
+                callerUid, callerPid, resolvedType, receivingUid);
     }
 
     public boolean checkIntent(FirewallIntentResolver resolver, ComponentName resolvedComponent,
             int intentType, Intent intent, int callerUid, int callerPid, String resolvedType,
-            ApplicationInfo resolvedApp) {
+            int receivingUid) {
         boolean log = false;
         boolean block = false;
 
@@ -153,7 +159,7 @@
         for (int i=0; i<candidateRules.size(); i++) {
             Rule rule = candidateRules.get(i);
             if (rule.matches(this, resolvedComponent, intent, callerUid, callerPid, resolvedType,
-                    resolvedApp)) {
+                    receivingUid)) {
                 block |= rule.getBlock();
                 log |= rule.getLog();
 
diff --git a/services/java/com/android/server/firewall/NotFilter.java b/services/java/com/android/server/firewall/NotFilter.java
index 5f3d516..09bf629 100644
--- a/services/java/com/android/server/firewall/NotFilter.java
+++ b/services/java/com/android/server/firewall/NotFilter.java
@@ -18,7 +18,6 @@
 
 import android.content.ComponentName;
 import android.content.Intent;
-import android.content.pm.ApplicationInfo;
 import com.android.internal.util.XmlUtils;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -34,9 +33,9 @@
 
     @Override
     public boolean matches(IntentFirewall ifw, ComponentName resolvedComponent, Intent intent,
-            int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
+            int callerUid, int callerPid, String resolvedType, int receivingUid) {
         return !mChild.matches(ifw, resolvedComponent, intent, callerUid, callerPid, resolvedType,
-                resolvedApp);
+                receivingUid);
     }
 
     public static final FilterFactory FACTORY = new FilterFactory("not") {
diff --git a/services/java/com/android/server/firewall/OrFilter.java b/services/java/com/android/server/firewall/OrFilter.java
index e3811eb..f6a6f22 100644
--- a/services/java/com/android/server/firewall/OrFilter.java
+++ b/services/java/com/android/server/firewall/OrFilter.java
@@ -18,7 +18,6 @@
 
 import android.content.ComponentName;
 import android.content.Intent;
-import android.content.pm.ApplicationInfo;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -27,10 +26,10 @@
 class OrFilter extends FilterList {
     @Override
     public boolean matches(IntentFirewall ifw, ComponentName resolvedComponent, Intent intent,
-            int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
+            int callerUid, int callerPid, String resolvedType, int receivingUid) {
         for (int i=0; i<children.size(); i++) {
             if (children.get(i).matches(ifw, resolvedComponent, intent, callerUid, callerPid,
-                    resolvedType, resolvedApp)) {
+                    resolvedType, receivingUid)) {
                 return true;
             }
         }
diff --git a/services/java/com/android/server/firewall/PortFilter.java b/services/java/com/android/server/firewall/PortFilter.java
index d0cd17f..84ace553 100644
--- a/services/java/com/android/server/firewall/PortFilter.java
+++ b/services/java/com/android/server/firewall/PortFilter.java
@@ -18,7 +18,6 @@
 
 import android.content.ComponentName;
 import android.content.Intent;
-import android.content.pm.ApplicationInfo;
 import android.net.Uri;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -43,7 +42,7 @@
 
     @Override
     public boolean matches(IntentFirewall ifw, ComponentName resolvedComponent, Intent intent,
-            int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
+            int callerUid, int callerPid, String resolvedType, int receivingUid) {
         int port = -1;
         Uri uri = intent.getData();
         if (uri != null) {
diff --git a/services/java/com/android/server/firewall/SenderFilter.java b/services/java/com/android/server/firewall/SenderFilter.java
index 7306dbde..c0eee69 100644
--- a/services/java/com/android/server/firewall/SenderFilter.java
+++ b/services/java/com/android/server/firewall/SenderFilter.java
@@ -79,15 +79,15 @@
     private static final Filter SIGNATURE = new Filter() {
         @Override
         public boolean matches(IntentFirewall ifw, ComponentName resolvedComponent, Intent intent,
-                int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
-            return ifw.signaturesMatch(callerUid, resolvedApp.uid);
+                int callerUid, int callerPid, String resolvedType, int receivingUid) {
+            return ifw.signaturesMatch(callerUid, receivingUid);
         }
     };
 
     private static final Filter SYSTEM = new Filter() {
         @Override
         public boolean matches(IntentFirewall ifw, ComponentName resolvedComponent, Intent intent,
-                int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
+                int callerUid, int callerPid, String resolvedType, int receivingUid) {
             return isPrivilegedApp(callerUid, callerPid);
         }
     };
@@ -95,21 +95,21 @@
     private static final Filter SYSTEM_OR_SIGNATURE = new Filter() {
         @Override
         public boolean matches(IntentFirewall ifw, ComponentName resolvedComponent, Intent intent,
-                int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
+                int callerUid, int callerPid, String resolvedType, int receivingUid) {
             return isPrivilegedApp(callerUid, callerPid) ||
-                    ifw.signaturesMatch(callerUid, resolvedApp.uid);
+                    ifw.signaturesMatch(callerUid, receivingUid);
         }
     };
 
     private static final Filter USER_ID = new Filter() {
         @Override
         public boolean matches(IntentFirewall ifw, ComponentName resolvedComponent, Intent intent,
-                int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
+                int callerUid, int callerPid, String resolvedType, int receivingUid) {
             // This checks whether the caller is either the system process, or has the same user id
             // I.e. the same app, or an app that uses the same shared user id.
             // This is the same set of applications that would be able to access the component if
             // it wasn't exported.
-            return ifw.checkComponentPermission(null, callerPid, callerUid, resolvedApp.uid, false);
+            return ifw.checkComponentPermission(null, callerPid, callerUid, receivingUid, false);
         }
     };
 }
diff --git a/services/java/com/android/server/firewall/SenderPermissionFilter.java b/services/java/com/android/server/firewall/SenderPermissionFilter.java
index 60225a3..caa65f3 100644
--- a/services/java/com/android/server/firewall/SenderPermissionFilter.java
+++ b/services/java/com/android/server/firewall/SenderPermissionFilter.java
@@ -18,7 +18,6 @@
 
 import android.content.ComponentName;
 import android.content.Intent;
-import android.content.pm.ApplicationInfo;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -35,11 +34,11 @@
 
     @Override
     public boolean matches(IntentFirewall ifw, ComponentName resolvedComponent, Intent intent,
-            int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
+            int callerUid, int callerPid, String resolvedType, int receivingUid) {
         // We assume the component is exported here. If the component is not exported, then
         // ActivityManager would only resolve to this component for callers from the same uid.
         // In this case, it doesn't matter whether the component is exported or not.
-        return ifw.checkComponentPermission(mPermission, callerPid, callerUid, resolvedApp.uid,
+        return ifw.checkComponentPermission(mPermission, callerPid, callerUid, receivingUid,
                 true);
     }
 
diff --git a/services/java/com/android/server/firewall/StringFilter.java b/services/java/com/android/server/firewall/StringFilter.java
index fa8105f..28e99b3 100644
--- a/services/java/com/android/server/firewall/StringFilter.java
+++ b/services/java/com/android/server/firewall/StringFilter.java
@@ -18,7 +18,6 @@
 
 import android.content.ComponentName;
 import android.content.Intent;
-import android.content.pm.ApplicationInfo;
 import android.net.Uri;
 import android.os.PatternMatcher;
 import org.xmlpull.v1.XmlPullParser;
@@ -120,9 +119,8 @@
 
     @Override
     public boolean matches(IntentFirewall ifw, ComponentName resolvedComponent, Intent intent,
-            int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
-        String value = mValueProvider.getValue(resolvedComponent, intent, resolvedType,
-                resolvedApp);
+            int callerUid, int callerPid, String resolvedType, int receivingUid) {
+        String value = mValueProvider.getValue(resolvedComponent, intent, resolvedType);
         return matchesValue(value);
     }
 
@@ -137,7 +135,7 @@
         }
 
         public abstract String getValue(ComponentName resolvedComponent, Intent intent,
-                String resolvedType, ApplicationInfo resolvedApp);
+                String resolvedType);
     }
 
     private static class EqualsFilter extends StringFilter {
@@ -231,8 +229,8 @@
 
     public static final ValueProvider COMPONENT = new ValueProvider("component") {
         @Override
-        public String getValue(ComponentName resolvedComponent, Intent intent, String resolvedType,
-                ApplicationInfo resolvedApp) {
+        public String getValue(ComponentName resolvedComponent, Intent intent,
+                String resolvedType) {
             if (resolvedComponent != null) {
                 return resolvedComponent.flattenToString();
             }
@@ -242,8 +240,8 @@
 
     public static final ValueProvider COMPONENT_NAME = new ValueProvider("component-name") {
         @Override
-        public String getValue(ComponentName resolvedComponent, Intent intent, String resolvedType,
-                ApplicationInfo resolvedApp) {
+        public String getValue(ComponentName resolvedComponent, Intent intent,
+                String resolvedType) {
             if (resolvedComponent != null) {
                 return resolvedComponent.getClassName();
             }
@@ -253,8 +251,8 @@
 
     public static final ValueProvider COMPONENT_PACKAGE = new ValueProvider("component-package") {
         @Override
-        public String getValue(ComponentName resolvedComponent, Intent intent, String resolvedType,
-                ApplicationInfo resolvedApp) {
+        public String getValue(ComponentName resolvedComponent, Intent intent,
+                String resolvedType) {
             if (resolvedComponent != null) {
                 return resolvedComponent.getPackageName();
             }
@@ -264,16 +262,16 @@
 
     public static final FilterFactory ACTION = new ValueProvider("action") {
         @Override
-        public String getValue(ComponentName resolvedComponent, Intent intent, String resolvedType,
-                ApplicationInfo resolvedApp) {
+        public String getValue(ComponentName resolvedComponent, Intent intent,
+                String resolvedType) {
             return intent.getAction();
         }
     };
 
     public static final ValueProvider DATA = new ValueProvider("data") {
         @Override
-        public String getValue(ComponentName resolvedComponent, Intent intent, String resolvedType,
-                ApplicationInfo resolvedApp) {
+        public String getValue(ComponentName resolvedComponent, Intent intent,
+                String resolvedType) {
             Uri data = intent.getData();
             if (data != null) {
                 return data.toString();
@@ -284,16 +282,16 @@
 
     public static final ValueProvider MIME_TYPE = new ValueProvider("mime-type") {
         @Override
-        public String getValue(ComponentName resolvedComponent, Intent intent, String resolvedType,
-                ApplicationInfo resolvedApp) {
+        public String getValue(ComponentName resolvedComponent, Intent intent,
+                String resolvedType) {
             return resolvedType;
         }
     };
 
     public static final ValueProvider SCHEME = new ValueProvider("scheme") {
         @Override
-        public String getValue(ComponentName resolvedComponent, Intent intent, String resolvedType,
-                ApplicationInfo resolvedApp) {
+        public String getValue(ComponentName resolvedComponent, Intent intent,
+                String resolvedType) {
             Uri data = intent.getData();
             if (data != null) {
                 return data.getScheme();
@@ -304,8 +302,8 @@
 
     public static final ValueProvider SSP = new ValueProvider("scheme-specific-part") {
         @Override
-        public String getValue(ComponentName resolvedComponent, Intent intent, String resolvedType,
-                ApplicationInfo resolvedApp) {
+        public String getValue(ComponentName resolvedComponent, Intent intent,
+                String resolvedType) {
             Uri data = intent.getData();
             if (data != null) {
                 return data.getSchemeSpecificPart();
@@ -316,8 +314,8 @@
 
     public static final ValueProvider HOST = new ValueProvider("host") {
         @Override
-        public String getValue(ComponentName resolvedComponent, Intent intent, String resolvedType,
-                ApplicationInfo resolvedApp) {
+        public String getValue(ComponentName resolvedComponent, Intent intent,
+                String resolvedType) {
             Uri data = intent.getData();
             if (data != null) {
                 return data.getHost();
@@ -328,8 +326,8 @@
 
     public static final ValueProvider PATH = new ValueProvider("path") {
         @Override
-        public String getValue(ComponentName resolvedComponent, Intent intent, String resolvedType,
-                ApplicationInfo resolvedApp) {
+        public String getValue(ComponentName resolvedComponent, Intent intent,
+                String resolvedType) {
             Uri data = intent.getData();
             if (data != null) {
                 return data.getPath();