diff options
12 files changed, 218 insertions, 111 deletions
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java index 844900d..9f4bc52 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java @@ -1003,8 +1003,10 @@ public class Am extends BaseCommand { private void sendBroadcast() throws Exception { Intent intent = makeIntent(UserHandle.USER_CURRENT); IntentReceiver receiver = new IntentReceiver(); + String[] requiredPermissions = mReceiverPermission == null ? null + : new String[] {mReceiverPermission}; System.out.println("Broadcasting: " + intent); - mAm.broadcastIntent(null, intent, null, receiver, 0, null, null, mReceiverPermission, + mAm.broadcastIntent(null, intent, null, receiver, 0, null, null, requiredPermissions, android.app.AppOpsManager.OP_NONE, null, true, false, mUserId); receiver.waitForFinish(); } diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index cc93ac9..fc408a8 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -456,14 +456,14 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM int resultCode = data.readInt(); String resultData = data.readString(); Bundle resultExtras = data.readBundle(); - String perm = data.readString(); + String[] perms = data.readStringArray(); int appOp = data.readInt(); Bundle options = data.readBundle(); boolean serialized = data.readInt() != 0; boolean sticky = data.readInt() != 0; int userId = data.readInt(); int res = broadcastIntent(app, intent, resolvedType, resultTo, - resultCode, resultData, resultExtras, perm, appOp, + resultCode, resultData, resultExtras, perms, appOp, options, serialized, sticky, userId); reply.writeNoException(); reply.writeInt(res); @@ -3007,7 +3007,7 @@ class ActivityManagerProxy implements IActivityManager public int broadcastIntent(IApplicationThread caller, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle map, - String requiredPermission, int appOp, Bundle options, boolean serialized, + String[] requiredPermissions, int appOp, Bundle options, boolean serialized, boolean sticky, int userId) throws RemoteException { Parcel data = Parcel.obtain(); @@ -3020,7 +3020,7 @@ class ActivityManagerProxy implements IActivityManager data.writeInt(resultCode); data.writeString(resultData); data.writeBundle(map); - data.writeString(requiredPermission); + data.writeStringArray(requiredPermissions); data.writeInt(appOp); data.writeBundle(options); data.writeInt(serialized ? 1 : 0); diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 75dd35c..c07140c 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -180,7 +180,7 @@ class ContextImpl extends Context { @GuardedBy("mSync") private File[] mExternalMediaDirs; - private static final String[] EMPTY_FILE_LIST = {}; + private static final String[] EMPTY_STRING_ARRAY = {}; // The system service cache for the system services that are cached per-ContextImpl. final Object[] mServiceCache = SystemServiceRegistry.createServiceCache(); @@ -552,7 +552,7 @@ class ContextImpl extends Context { @Override public String[] fileList() { final String[] list = getFilesDir().list(); - return (list != null) ? list : EMPTY_FILE_LIST; + return (list != null) ? list : EMPTY_STRING_ARRAY; } @Override @@ -591,7 +591,7 @@ class ContextImpl extends Context { @Override public String[] databaseList() { final String[] list = getDatabasesDir().list(); - return (list != null) ? list : EMPTY_FILE_LIST; + return (list != null) ? list : EMPTY_STRING_ARRAY; } @@ -777,11 +777,28 @@ class ContextImpl extends Context { public void sendBroadcast(Intent intent, String receiverPermission) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); + String[] receiverPermissions = receiverPermission == null ? null + : new String[] {receiverPermission}; try { intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, - Activity.RESULT_OK, null, null, receiverPermission, AppOpsManager.OP_NONE, + Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE, + null, false, false, getUserId()); + } catch (RemoteException e) { + throw new RuntimeException("Failure from system", e); + } + } + + @Override + public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions) { + warnIfCallingFromSystemProcess(); + String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); + try { + intent.prepareToLeaveProcess(); + ActivityManagerNative.getDefault().broadcastIntent( + mMainThread.getApplicationThread(), intent, resolvedType, null, + Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE, null, false, false, getUserId()); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); @@ -792,11 +809,13 @@ class ContextImpl extends Context { public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); + String[] receiverPermissions = receiverPermission == null ? null + : new String[] {receiverPermission}; try { intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, - Activity.RESULT_OK, null, null, receiverPermission, AppOpsManager.OP_NONE, + Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE, options, false, false, getUserId()); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); @@ -807,11 +826,13 @@ class ContextImpl extends Context { public void sendBroadcast(Intent intent, String receiverPermission, int appOp) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); + String[] receiverPermissions = receiverPermission == null ? null + : new String[] {receiverPermission}; try { intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, - Activity.RESULT_OK, null, null, receiverPermission, appOp, null, false, false, + Activity.RESULT_OK, null, null, receiverPermissions, appOp, null, false, false, getUserId()); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); @@ -822,11 +843,13 @@ class ContextImpl extends Context { public void sendOrderedBroadcast(Intent intent, String receiverPermission) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); + String[] receiverPermissions = receiverPermission == null ? null + : new String[] {receiverPermission}; try { intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, - Activity.RESULT_OK, null, null, receiverPermission, AppOpsManager.OP_NONE, + Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE, null, true, false, getUserId()); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); @@ -883,11 +906,13 @@ class ContextImpl extends Context { } } String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); + String[] receiverPermissions = receiverPermission == null ? null + : new String[] {receiverPermission}; try { intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, rd, - initialCode, initialData, initialExtras, receiverPermission, appOp, + initialCode, initialData, initialExtras, receiverPermissions, appOp, options, true, false, getUserId()); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); @@ -917,11 +942,13 @@ class ContextImpl extends Context { public void sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, int appOp) { String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); + String[] receiverPermissions = receiverPermission == null ? null + : new String[] {receiverPermission}; try { intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, - Activity.RESULT_OK, null, null, receiverPermission, appOp, null, false, false, + Activity.RESULT_OK, null, null, receiverPermissions, appOp, null, false, false, user.getIdentifier()); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); @@ -959,11 +986,13 @@ class ContextImpl extends Context { } } String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); + String[] receiverPermissions = receiverPermission == null ? null + : new String[] {receiverPermission}; try { intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, rd, - initialCode, initialData, initialExtras, receiverPermission, + initialCode, initialData, initialExtras, receiverPermissions, appOp, null, true, false, user.getIdentifier()); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index acce81c..1d87d77 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -106,7 +106,7 @@ public interface IActivityManager extends IInterface { public void unregisterReceiver(IIntentReceiver receiver) throws RemoteException; public int broadcastIntent(IApplicationThread caller, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, - String resultData, Bundle map, String requiredPermission, + String resultData, Bundle map, String[] requiredPermissions, int appOp, Bundle options, boolean serialized, boolean sticky, int userId) throws RemoteException; public void unbroadcastIntent(IApplicationThread caller, Intent intent, int userId) throws RemoteException; public void finishReceiver(IBinder who, int resultCode, String resultData, Bundle map, diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 675515b..0bfe108 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -1516,6 +1516,33 @@ public abstract class Context { public abstract void sendBroadcast(Intent intent, @Nullable String receiverPermission); + + /** + * Broadcast the given intent to all interested BroadcastReceivers, allowing + * an array of required permissions to be enforced. This call is asynchronous; it returns + * immediately, and you will continue executing while the receivers are run. No results are + * propagated from receivers and receivers can not abort the broadcast. If you want to allow + * receivers to propagate results or abort the broadcast, you must send an ordered broadcast + * using {@link #sendOrderedBroadcast(Intent, String)}. + * + * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts. + * + * @param intent The Intent to broadcast; all receivers matching this + * Intent will receive the broadcast. + * @param receiverPermissions Array of names of permissions that a receiver must hold + * in order to receive your broadcast. + * If null or empty, no permissions are required. + * + * @see android.content.BroadcastReceiver + * @see #registerReceiver + * @see #sendBroadcast(Intent) + * @see #sendOrderedBroadcast(Intent, String) + * @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle) + * @hide + */ + public abstract void sendBroadcastMultiplePermissions(Intent intent, + String[] receiverPermissions); + /** * Broadcast the given intent to all interested BroadcastReceivers, allowing * an optional required permission to be enforced. This diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index 4e7c832..8ad3d21 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -402,6 +402,12 @@ public class ContextWrapper extends Context { } /** @hide */ + @Override + public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions) { + mBase.sendBroadcastMultiplePermissions(intent, receiverPermissions); + } + + /** @hide */ @SystemApi @Override public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 5bfca10..37aa408 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -6355,7 +6355,7 @@ public final class ActivityManagerService extends ActivityManagerNative } }, 0, null, null, - android.Manifest.permission.RECEIVE_BOOT_COMPLETED, + new String[] {android.Manifest.permission.RECEIVE_BOOT_COMPLETED}, AppOpsManager.OP_NONE, null, true, false, MY_PID, Process.SYSTEM_UID, userId); } @@ -11773,7 +11773,7 @@ public final class ActivityManagerService extends ActivityManagerNative throws RemoteException { } }, 0, null, null, - INTERACT_ACROSS_USERS, AppOpsManager.OP_NONE, + new String[] {INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE, null, true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL); } catch (Throwable t) { Slog.wtf(TAG, "Failed sending first user broadcasts", t); @@ -16327,7 +16327,7 @@ public final class ActivityManagerService extends ActivityManagerNative private final int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, - Bundle resultExtras, String requiredPermission, int appOp, Bundle options, + Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle options, boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) { intent = new Intent(intent); @@ -16580,9 +16580,9 @@ public final class ActivityManagerService extends ActivityManagerNative Slog.w(TAG, msg); throw new SecurityException(msg); } - if (requiredPermission != null) { + if (requiredPermissions != null && requiredPermissions.length > 0) { Slog.w(TAG, "Can't broadcast sticky intent " + intent - + " and enforce permission " + requiredPermission); + + " and enforce permissions " + Arrays.toString(requiredPermissions)); return ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION; } if (intent.getComponent() != null) { @@ -16690,7 +16690,7 @@ public final class ActivityManagerService extends ActivityManagerNative // components to be launched. final BroadcastQueue queue = broadcastQueueForIntent(intent); BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, - callerPackage, callingPid, callingUid, resolvedType, requiredPermission, + callerPackage, callingPid, callingUid, resolvedType, requiredPermissions, appOp, brOptions, registeredReceivers, resultTo, resultCode, resultData, resultExtras, ordered, sticky, false, userId); if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r); @@ -16780,7 +16780,7 @@ public final class ActivityManagerService extends ActivityManagerNative BroadcastQueue queue = broadcastQueueForIntent(intent); BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage, callingPid, callingUid, resolvedType, - requiredPermission, appOp, brOptions, receivers, resultTo, resultCode, + requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode, resultData, resultExtras, ordered, sticky, false, userId); if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r @@ -16829,7 +16829,7 @@ public final class ActivityManagerService extends ActivityManagerNative public final int broadcastIntent(IApplicationThread caller, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle resultExtras, - String requiredPermission, int appOp, Bundle options, + String[] requiredPermissions, int appOp, Bundle options, boolean serialized, boolean sticky, int userId) { enforceNotIsolatedCaller("broadcastIntent"); synchronized(this) { @@ -16842,13 +16842,14 @@ public final class ActivityManagerService extends ActivityManagerNative int res = broadcastIntentLocked(callerApp, callerApp != null ? callerApp.info.packageName : null, intent, resolvedType, resultTo, resultCode, resultData, resultExtras, - requiredPermission, appOp, null, serialized, sticky, + requiredPermissions, appOp, null, serialized, sticky, callingPid, callingUid, userId); Binder.restoreCallingIdentity(origId); return res; } } + int broadcastIntentInPackage(String packageName, int uid, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle resultExtras, @@ -16858,9 +16859,12 @@ public final class ActivityManagerService extends ActivityManagerNative intent = verifyBroadcastLocked(intent); final long origId = Binder.clearCallingIdentity(); + String[] requiredPermissions = requiredPermission == null ? null + : new String[] {requiredPermission}; int res = broadcastIntentLocked(null, packageName, intent, resolvedType, - resultTo, resultCode, resultData, resultExtras, requiredPermission, - AppOpsManager.OP_NONE, options, serialized, sticky, -1, uid, userId); + resultTo, resultCode, resultData, resultExtras, + requiredPermissions, AppOpsManager.OP_NONE, options, serialized, + sticky, -1, uid, userId); Binder.restoreCallingIdentity(origId); return res; } @@ -19795,7 +19799,7 @@ public final class ActivityManagerService extends ActivityManagerNative int sendingUser) throws RemoteException { } }, 0, null, null, - INTERACT_ACROSS_USERS, AppOpsManager.OP_NONE, + new String[] {INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE, null, true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL); } } @@ -19857,8 +19861,9 @@ public final class ActivityManagerService extends ActivityManagerNative intent.putExtra(Intent.EXTRA_USER_HANDLE, newUserId); broadcastIntentLocked(null, null, intent, null, null, 0, null, null, - android.Manifest.permission.MANAGE_USERS, AppOpsManager.OP_NONE, - null, false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL); + new String[] {android.Manifest.permission.MANAGE_USERS}, + AppOpsManager.OP_NONE, null, false, false, MY_PID, Process.SYSTEM_UID, + UserHandle.USER_ALL); } } finally { Binder.restoreCallingIdentity(ident); @@ -20041,8 +20046,9 @@ public final class ActivityManagerService extends ActivityManagerNative intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT); broadcastIntentLocked(null, null, intent, null, null, 0, null, null, - android.Manifest.permission.RECEIVE_BOOT_COMPLETED, AppOpsManager.OP_NONE, - null, true, false, MY_PID, Process.SYSTEM_UID, userId); + new String[] {android.Manifest.permission.RECEIVE_BOOT_COMPLETED}, + AppOpsManager.OP_NONE, null, true, false, MY_PID, Process.SYSTEM_UID, + userId); } } } @@ -20180,7 +20186,7 @@ public final class ActivityManagerService extends ActivityManagerNative // Kick things off. broadcastIntentLocked(null, null, stoppingIntent, null, stoppingReceiver, 0, null, null, - INTERACT_ACROSS_USERS, AppOpsManager.OP_NONE, + new String[] {INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE, null, true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL); } finally { Binder.restoreCallingIdentity(ident); diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index 30aa411..7766539 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -493,59 +493,74 @@ public final class BroadcastQueue { } } } - if (!skip) { - int perm = mService.checkComponentPermission(r.requiredPermission, - filter.receiverList.pid, filter.receiverList.uid, -1, true); - if (perm != PackageManager.PERMISSION_GRANTED) { - Slog.w(TAG, "Permission Denial: receiving " - + r.intent.toString() - + " to " + filter.receiverList.app - + " (pid=" + filter.receiverList.pid - + ", uid=" + filter.receiverList.uid + ")" - + " requires " + r.requiredPermission - + " due to sender " + r.callerPackage - + " (uid " + r.callingUid + ")"); - skip = true; - } - int appOp = AppOpsManager.OP_NONE; - if (r.requiredPermission != null) { - appOp = AppOpsManager.permissionToOpCode(r.requiredPermission); - if (appOp != AppOpsManager.OP_NONE - && mService.mAppOpsService.noteOperation(appOp, - filter.receiverList.uid, filter.packageName) - != AppOpsManager.MODE_ALLOWED) { - Slog.w(TAG, "Appop Denial: receiving " + if (!skip && r.requiredPermissions != null && r.requiredPermissions.length > 0) { + for (int i = 0; i < r.requiredPermissions.length; i++) { + String requiredPermission = r.requiredPermissions[i]; + int perm = mService.checkComponentPermission(requiredPermission, + filter.receiverList.pid, filter.receiverList.uid, -1, true); + if (perm != PackageManager.PERMISSION_GRANTED) { + Slog.w(TAG, "Permission Denial: receiving " + r.intent.toString() + " to " + filter.receiverList.app + " (pid=" + filter.receiverList.pid + ", uid=" + filter.receiverList.uid + ")" - + " requires appop " + AppOpsManager.permissionToOp( - r.requiredPermission) + + " requires " + requiredPermission + " due to sender " + r.callerPackage + " (uid " + r.callingUid + ")"); skip = true; + break; } - } - if (!skip && r.appOp != appOp && r.appOp != AppOpsManager.OP_NONE - && mService.mAppOpsService.noteOperation(r.appOp, - filter.receiverList.uid, filter.packageName) - != AppOpsManager.MODE_ALLOWED) { + int appOp = AppOpsManager.permissionToOpCode(requiredPermission); + if (appOp != r.appOp + && mService.mAppOpsService.noteOperation(appOp, + filter.receiverList.uid, filter.packageName) + != AppOpsManager.MODE_ALLOWED) { Slog.w(TAG, "Appop Denial: receiving " + r.intent.toString() + " to " + filter.receiverList.app + " (pid=" + filter.receiverList.pid + ", uid=" + filter.receiverList.uid + ")" + " requires appop " + AppOpsManager.permissionToOp( - r.requiredPermission) + requiredPermission) + " due to sender " + r.callerPackage + " (uid " + r.callingUid + ")"); skip = true; + break; + } + } + } + if (!skip && (r.requiredPermissions == null || r.requiredPermissions.length == 0)) { + int perm = mService.checkComponentPermission(null, + filter.receiverList.pid, filter.receiverList.uid, -1, true); + if (perm != PackageManager.PERMISSION_GRANTED) { + Slog.w(TAG, "Permission Denial: security check failed when receiving " + + r.intent.toString() + + " to " + filter.receiverList.app + + " (pid=" + filter.receiverList.pid + + ", uid=" + filter.receiverList.uid + ")" + + " due to sender " + r.callerPackage + + " (uid " + r.callingUid + ")"); + skip = true; } } + if (!skip && r.appOp != AppOpsManager.OP_NONE + && mService.mAppOpsService.noteOperation(r.appOp, + filter.receiverList.uid, filter.packageName) + != AppOpsManager.MODE_ALLOWED) { + Slog.w(TAG, "Appop Denial: receiving " + + r.intent.toString() + + " to " + filter.receiverList.app + + " (pid=" + filter.receiverList.pid + + ", uid=" + filter.receiverList.uid + ")" + + " requires appop " + AppOpsManager.opToName(r.appOp) + + " due to sender " + r.callerPackage + + " (uid " + r.callingUid + ")"); + skip = true; + } - if (!skip) { - skip = !mService.mIntentFirewall.checkBroadcast(r.intent, r.callingUid, - r.callingPid, r.resolvedType, filter.receiverList.uid); + if (!mService.mIntentFirewall.checkBroadcast(r.intent, r.callingUid, + r.callingPid, r.resolvedType, filter.receiverList.uid)) { + return; } if (filter.receiverList.app == null || filter.receiverList.app.crashing) { @@ -860,51 +875,53 @@ public final class BroadcastQueue { } } if (!skip && info.activityInfo.applicationInfo.uid != Process.SYSTEM_UID && - r.requiredPermission != null) { - try { - perm = AppGlobals.getPackageManager(). - checkPermission(r.requiredPermission, - info.activityInfo.applicationInfo.packageName, - UserHandle.getUserId(info.activityInfo.applicationInfo.uid)); - } catch (RemoteException e) { - perm = PackageManager.PERMISSION_DENIED; - } - if (perm != PackageManager.PERMISSION_GRANTED) { - Slog.w(TAG, "Permission Denial: receiving " - + r.intent + " to " - + component.flattenToShortString() - + " requires " + r.requiredPermission - + " due to sender " + r.callerPackage - + " (uid " + r.callingUid + ")"); - skip = true; - } - } - int appOp = AppOpsManager.OP_NONE; - if (!skip && r.requiredPermission != null) { - appOp = AppOpsManager.permissionToOpCode(r.requiredPermission); - if (appOp != AppOpsManager.OP_NONE - && mService.mAppOpsService.noteOperation(appOp, - info.activityInfo.applicationInfo.uid, info.activityInfo.packageName) - != AppOpsManager.MODE_ALLOWED) { - Slog.w(TAG, "Appop Denial: receiving " - + r.intent + " to " - + component.flattenToShortString() - + " requires appop " + AppOpsManager.permissionToOp( - r.requiredPermission) - + " due to sender " + r.callerPackage - + " (uid " + r.callingUid + ")"); - skip = true; + r.requiredPermissions != null && r.requiredPermissions.length > 0) { + for (int i = 0; i < r.requiredPermissions.length; i++) { + String requiredPermission = r.requiredPermissions[i]; + try { + perm = AppGlobals.getPackageManager(). + checkPermission(requiredPermission, + info.activityInfo.applicationInfo.packageName, + UserHandle + .getUserId(info.activityInfo.applicationInfo.uid)); + } catch (RemoteException e) { + perm = PackageManager.PERMISSION_DENIED; + } + if (perm != PackageManager.PERMISSION_GRANTED) { + Slog.w(TAG, "Permission Denial: receiving " + + r.intent + " to " + + component.flattenToShortString() + + " requires " + requiredPermission + + " due to sender " + r.callerPackage + + " (uid " + r.callingUid + ")"); + skip = true; + break; + } + int appOp = AppOpsManager.permissionToOpCode(requiredPermission); + if (appOp != AppOpsManager.OP_NONE && appOp != r.appOp + && mService.mAppOpsService.noteOperation(appOp, + info.activityInfo.applicationInfo.uid, info.activityInfo.packageName) + != AppOpsManager.MODE_ALLOWED) { + Slog.w(TAG, "Appop Denial: receiving " + + r.intent + " to " + + component.flattenToShortString() + + " requires appop " + AppOpsManager.permissionToOp( + requiredPermission) + + " due to sender " + r.callerPackage + + " (uid " + r.callingUid + ")"); + skip = true; + break; + } } } - if (!skip && r.appOp != appOp && r.appOp != AppOpsManager.OP_NONE + if (!skip && r.appOp != AppOpsManager.OP_NONE && mService.mAppOpsService.noteOperation(r.appOp, - info.activityInfo.applicationInfo.uid, info.activityInfo.packageName) - != AppOpsManager.MODE_ALLOWED) { + info.activityInfo.applicationInfo.uid, info.activityInfo.packageName) + != AppOpsManager.MODE_ALLOWED) { Slog.w(TAG, "Appop Denial: receiving " + r.intent + " to " + component.flattenToShortString() - + " requires appop " + AppOpsManager.permissionToOp( - r.requiredPermission) + + " requires appop " + AppOpsManager.opToName(r.appOp) + " due to sender " + r.callerPackage + " (uid " + r.callingUid + ")"); skip = true; diff --git a/services/core/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java index b943222..a7e6471 100644 --- a/services/core/java/com/android/server/am/BroadcastRecord.java +++ b/services/core/java/com/android/server/am/BroadcastRecord.java @@ -32,6 +32,7 @@ import android.util.PrintWriterPrinter; import android.util.TimeUtils; import java.io.PrintWriter; +import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Set; @@ -51,7 +52,7 @@ final class BroadcastRecord extends Binder { 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 String[] requiredPermissions; // permissions the caller has required final int appOp; // an app op that is associated with this broadcast final BroadcastOptions options; // BroadcastOptions supplied by caller final List receivers; // contains BroadcastFilter and ResolveInfo @@ -103,9 +104,11 @@ final class BroadcastRecord extends Binder { pw.print(callerApp != null ? callerApp.toShortString() : "null"); pw.print(" pid="); pw.print(callingPid); pw.print(" uid="); pw.println(callingUid); - if (requiredPermission != null || appOp != AppOpsManager.OP_NONE) { - pw.print(prefix); pw.print("requiredPermission="); pw.print(requiredPermission); - pw.print(" appOp="); pw.println(appOp); + if ((requiredPermissions != null && requiredPermissions.length > 0) + || appOp != AppOpsManager.OP_NONE) { + pw.print(prefix); pw.print("requiredPermissions="); + pw.print(Arrays.toString(requiredPermissions)); + pw.print(" appOp="); pw.println(appOp); } if (options != null) { pw.print(prefix); pw.print("options="); pw.println(options.toBundle()); @@ -184,7 +187,7 @@ final class BroadcastRecord extends Binder { BroadcastRecord(BroadcastQueue _queue, Intent _intent, ProcessRecord _callerApp, String _callerPackage, - int _callingPid, int _callingUid, String _resolvedType, String _requiredPermission, + int _callingPid, int _callingUid, String _resolvedType, String[] _requiredPermissions, int _appOp, BroadcastOptions _options, List _receivers, IIntentReceiver _resultTo, int _resultCode, String _resultData, Bundle _resultExtras, boolean _serialized, boolean _sticky, boolean _initialSticky, @@ -197,7 +200,7 @@ final class BroadcastRecord extends Binder { callingPid = _callingPid; callingUid = _callingUid; resolvedType = _resolvedType; - requiredPermission = _requiredPermission; + requiredPermissions = _requiredPermissions; appOp = _appOp; options = _options; receivers = _receivers; diff --git a/services/tests/servicestests/src/com/android/server/BroadcastInterceptingContext.java b/services/tests/servicestests/src/com/android/server/BroadcastInterceptingContext.java index ffd1568..757f1c6 100644 --- a/services/tests/servicestests/src/com/android/server/BroadcastInterceptingContext.java +++ b/services/tests/servicestests/src/com/android/server/BroadcastInterceptingContext.java @@ -139,6 +139,11 @@ public class BroadcastInterceptingContext extends ContextWrapper { } @Override + public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions) { + sendBroadcast(intent); + } + + @Override public void sendBroadcastAsUser(Intent intent, UserHandle user) { sendBroadcast(intent); } diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java index e5e3e44..e5ea562 100644 --- a/test-runner/src/android/test/mock/MockContext.java +++ b/test-runner/src/android/test/mock/MockContext.java @@ -318,6 +318,12 @@ public class MockContext extends Context { } /** @hide */ + @Override + public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions) { + throw new UnsupportedOperationException(); + } + + /** @hide */ @SystemApi @Override public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) { diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java index 362048d..933420f 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java @@ -1509,6 +1509,12 @@ public final class BridgeContext extends Context { } @Override + public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions) { + // pass + + } + + @Override public void sendBroadcast(Intent arg0, String arg1, Bundle arg2) { // pass |