Loading core/java/android/app/ContextImpl.java +16 −0 Original line number Diff line number Diff line Loading @@ -1047,6 +1047,22 @@ class ContextImpl extends Context { } } @Override public void sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user, String[] receiverPermissions) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { intent.prepareToLeaveProcess(this); ActivityManager.getService().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE, null, false, false, user.getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) { warnIfCallingFromSystemProcess(); Loading core/java/android/content/Context.java +27 −0 Original line number Diff line number Diff line Loading @@ -1975,6 +1975,33 @@ public abstract class Context { public abstract void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions); /** * 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 user The user to send the broadcast to. * @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 sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user, String[] receiverPermissions); /** * Broadcast the given intent to all interested BroadcastReceivers, allowing * an optional required permission to be enforced. This Loading core/java/android/content/ContextWrapper.java +7 −0 Original line number Diff line number Diff line Loading @@ -455,6 +455,13 @@ public class ContextWrapper extends Context { mBase.sendBroadcastMultiplePermissions(intent, receiverPermissions); } /** @hide */ @Override public void sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user, String[] receiverPermissions) { mBase.sendBroadcastAsUserMultiplePermissions(intent, user, receiverPermissions); } /** @hide */ @SystemApi @Override Loading services/core/java/com/android/server/TelephonyRegistry.java +20 −14 Original line number Diff line number Diff line Loading @@ -117,10 +117,10 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { return (onSubscriptionsChangedListenerCallback != null); } boolean canReadPhoneState() { boolean canReadCallLog() { try { return TelephonyPermissions.checkReadPhoneState( context, subId, callerPid, callerUid, callingPackage, "listen"); return TelephonyPermissions.checkReadCallLog( context, subId, callerPid, callerUid, callingPackage); } catch (SecurityException e) { return false; } Loading Loading @@ -667,8 +667,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } private String getCallIncomingNumber(Record record, int phoneId) { // Hide the number if record's process can't currently read phone state. return record.canReadPhoneState() ? mCallIncomingNumber[phoneId] : ""; // Only reveal the incoming number if the record has read call log permission. return record.canReadCallLog() ? mCallIncomingNumber[phoneId] : ""; } private Record add(IBinder binder) { Loading Loading @@ -729,13 +729,13 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } } public void notifyCallState(int state, String incomingNumber) { public void notifyCallState(int state, String phoneNumber) { if (!checkNotifyPermission("notifyCallState()")) { return; } if (VDBG) { log("notifyCallState: state=" + state + " incomingNumber=" + incomingNumber); log("notifyCallState: state=" + state + " phoneNumber=" + phoneNumber); } synchronized (mRecords) { Loading @@ -743,8 +743,10 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_CALL_STATE) && (r.subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)) { try { String incomingNumberOrEmpty = r.canReadPhoneState() ? incomingNumber : ""; r.callback.onCallStateChanged(state, incomingNumberOrEmpty); // Ensure the listener has read call log permission; if they do not return // an empty phone number. String phoneNumberOrEmpty = r.canReadCallLog() ? phoneNumber : ""; r.callback.onCallStateChanged(state, phoneNumberOrEmpty); } catch (RemoteException ex) { mRemoveList.add(r.binder); } Loading @@ -755,7 +757,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { // Called only by Telecomm to communicate call state across different phone accounts. So // there is no need to add a valid subId or slotId. broadcastCallStateChanged(state, incomingNumber, broadcastCallStateChanged(state, phoneNumber, SubscriptionManager.INVALID_PHONE_INDEX, SubscriptionManager.INVALID_SUBSCRIPTION_ID); } Loading Loading @@ -1571,9 +1573,6 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { Intent intent = new Intent(TelephonyManager.ACTION_PHONE_STATE_CHANGED); intent.putExtra(PhoneConstants.STATE_KEY, PhoneConstantConversions.convertCallState(state).toString()); if (!TextUtils.isEmpty(incomingNumber)) { intent.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber); } // If a valid subId was specified, we should fire off a subId-specific state // change intent and include the subId. Loading @@ -1589,13 +1588,20 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { // Wakeup apps for the (SUBSCRIPTION_)PHONE_STATE broadcast. intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); Intent intentWithPhoneNumber = new Intent(intent); if (!TextUtils.isEmpty(incomingNumber)) { intentWithPhoneNumber.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber); } // Send broadcast twice, once for apps that have PRIVILEGED permission and once for those // that have the runtime one mContext.sendBroadcastAsUser(intent, UserHandle.ALL, mContext.sendBroadcastAsUser(intentWithPhoneNumber, UserHandle.ALL, android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE); mContext.sendBroadcastAsUser(intent, UserHandle.ALL, android.Manifest.permission.READ_PHONE_STATE, AppOpsManager.OP_READ_PHONE_STATE); mContext.sendBroadcastAsUserMultiplePermissions(intentWithPhoneNumber, UserHandle.ALL, new String[] { android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.READ_CALL_LOG}); } private void broadcastDataConnectionStateChanged(int state, Loading services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java +6 −0 Original line number Diff line number Diff line Loading @@ -253,6 +253,12 @@ public class DpmMockContext extends MockContext { spiedContext.sendBroadcastMultiplePermissions(intent, receiverPermissions); } @Override public void sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user, String[] receiverPermissions) { spiedContext.sendBroadcastAsUserMultiplePermissions(intent, user, receiverPermissions); } @Override public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) { spiedContext.sendBroadcast(intent, receiverPermission, options); Loading Loading
core/java/android/app/ContextImpl.java +16 −0 Original line number Diff line number Diff line Loading @@ -1047,6 +1047,22 @@ class ContextImpl extends Context { } } @Override public void sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user, String[] receiverPermissions) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { intent.prepareToLeaveProcess(this); ActivityManager.getService().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE, null, false, false, user.getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) { warnIfCallingFromSystemProcess(); Loading
core/java/android/content/Context.java +27 −0 Original line number Diff line number Diff line Loading @@ -1975,6 +1975,33 @@ public abstract class Context { public abstract void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions); /** * 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 user The user to send the broadcast to. * @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 sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user, String[] receiverPermissions); /** * Broadcast the given intent to all interested BroadcastReceivers, allowing * an optional required permission to be enforced. This Loading
core/java/android/content/ContextWrapper.java +7 −0 Original line number Diff line number Diff line Loading @@ -455,6 +455,13 @@ public class ContextWrapper extends Context { mBase.sendBroadcastMultiplePermissions(intent, receiverPermissions); } /** @hide */ @Override public void sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user, String[] receiverPermissions) { mBase.sendBroadcastAsUserMultiplePermissions(intent, user, receiverPermissions); } /** @hide */ @SystemApi @Override Loading
services/core/java/com/android/server/TelephonyRegistry.java +20 −14 Original line number Diff line number Diff line Loading @@ -117,10 +117,10 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { return (onSubscriptionsChangedListenerCallback != null); } boolean canReadPhoneState() { boolean canReadCallLog() { try { return TelephonyPermissions.checkReadPhoneState( context, subId, callerPid, callerUid, callingPackage, "listen"); return TelephonyPermissions.checkReadCallLog( context, subId, callerPid, callerUid, callingPackage); } catch (SecurityException e) { return false; } Loading Loading @@ -667,8 +667,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } private String getCallIncomingNumber(Record record, int phoneId) { // Hide the number if record's process can't currently read phone state. return record.canReadPhoneState() ? mCallIncomingNumber[phoneId] : ""; // Only reveal the incoming number if the record has read call log permission. return record.canReadCallLog() ? mCallIncomingNumber[phoneId] : ""; } private Record add(IBinder binder) { Loading Loading @@ -729,13 +729,13 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } } public void notifyCallState(int state, String incomingNumber) { public void notifyCallState(int state, String phoneNumber) { if (!checkNotifyPermission("notifyCallState()")) { return; } if (VDBG) { log("notifyCallState: state=" + state + " incomingNumber=" + incomingNumber); log("notifyCallState: state=" + state + " phoneNumber=" + phoneNumber); } synchronized (mRecords) { Loading @@ -743,8 +743,10 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_CALL_STATE) && (r.subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)) { try { String incomingNumberOrEmpty = r.canReadPhoneState() ? incomingNumber : ""; r.callback.onCallStateChanged(state, incomingNumberOrEmpty); // Ensure the listener has read call log permission; if they do not return // an empty phone number. String phoneNumberOrEmpty = r.canReadCallLog() ? phoneNumber : ""; r.callback.onCallStateChanged(state, phoneNumberOrEmpty); } catch (RemoteException ex) { mRemoveList.add(r.binder); } Loading @@ -755,7 +757,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { // Called only by Telecomm to communicate call state across different phone accounts. So // there is no need to add a valid subId or slotId. broadcastCallStateChanged(state, incomingNumber, broadcastCallStateChanged(state, phoneNumber, SubscriptionManager.INVALID_PHONE_INDEX, SubscriptionManager.INVALID_SUBSCRIPTION_ID); } Loading Loading @@ -1571,9 +1573,6 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { Intent intent = new Intent(TelephonyManager.ACTION_PHONE_STATE_CHANGED); intent.putExtra(PhoneConstants.STATE_KEY, PhoneConstantConversions.convertCallState(state).toString()); if (!TextUtils.isEmpty(incomingNumber)) { intent.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber); } // If a valid subId was specified, we should fire off a subId-specific state // change intent and include the subId. Loading @@ -1589,13 +1588,20 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { // Wakeup apps for the (SUBSCRIPTION_)PHONE_STATE broadcast. intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); Intent intentWithPhoneNumber = new Intent(intent); if (!TextUtils.isEmpty(incomingNumber)) { intentWithPhoneNumber.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber); } // Send broadcast twice, once for apps that have PRIVILEGED permission and once for those // that have the runtime one mContext.sendBroadcastAsUser(intent, UserHandle.ALL, mContext.sendBroadcastAsUser(intentWithPhoneNumber, UserHandle.ALL, android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE); mContext.sendBroadcastAsUser(intent, UserHandle.ALL, android.Manifest.permission.READ_PHONE_STATE, AppOpsManager.OP_READ_PHONE_STATE); mContext.sendBroadcastAsUserMultiplePermissions(intentWithPhoneNumber, UserHandle.ALL, new String[] { android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.READ_CALL_LOG}); } private void broadcastDataConnectionStateChanged(int state, Loading
services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java +6 −0 Original line number Diff line number Diff line Loading @@ -253,6 +253,12 @@ public class DpmMockContext extends MockContext { spiedContext.sendBroadcastMultiplePermissions(intent, receiverPermissions); } @Override public void sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user, String[] receiverPermissions) { spiedContext.sendBroadcastAsUserMultiplePermissions(intent, user, receiverPermissions); } @Override public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) { spiedContext.sendBroadcast(intent, receiverPermission, options); Loading