Enforce CALL_PHONE permission for default/system dialer for non emergency calls
This CL fixes a bug where a default/system dialer targeting SDK 23 would
be allowed to place phone calls without the CALL_PHONE permission. This is
because for the default/system dialer, the Telecom system was only enforcing
the CALL_PHONE app_op.
In order to enforce runtime permissions for both SDK 23 and pre SDK 23 apps,
both OP_CALL_PHONE and CALL_PHONE permission must be checked.
Bug: 23607431
Change-Id: I57b6388349e0637df02799c14a2850c2c6e5a300
diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java
index 5c498c0..0f0a456 100644
--- a/src/com/android/server/telecom/TelecomServiceImpl.java
+++ b/src/com/android/server/telecom/TelecomServiceImpl.java
@@ -808,9 +808,19 @@
+ " is not allowed to place phone calls");
}
+ // Note: we can still get here for the default/system dialer, even if the Phone
+ // permission is turned off. This is because the default/system dialer is always
+ // allowed to attempt to place a call (regardless of permission state), in case
+ // it turns out to be an emergency call. If the permission is denied and the
+ // call is being made to a non-emergency number, the call will be denied later on
+ // by {@link UserCallIntentProcessor}.
+
final boolean hasCallAppOp = mAppOpsManager.noteOp(AppOpsManager.OP_CALL_PHONE,
Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED;
+ final boolean hasCallPermission = mContext.checkCallingPermission(CALL_PHONE) ==
+ PackageManager.PERMISSION_GRANTED;
+
synchronized (mLock) {
final UserHandle userHandle = Binder.getCallingUserHandle();
long token = Binder.clearCallingIdentity();
@@ -818,7 +828,7 @@
final Intent intent = new Intent(Intent.ACTION_CALL, handle);
intent.putExtras(extras);
new UserCallIntentProcessor(mContext, userHandle).processIntent(intent,
- callingPackage, hasCallAppOp);
+ callingPackage, hasCallAppOp && hasCallPermission);
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/src/com/android/server/telecom/components/UserCallIntentProcessor.java b/src/com/android/server/telecom/components/UserCallIntentProcessor.java
index 1374d3b..8f451b5 100644
--- a/src/com/android/server/telecom/components/UserCallIntentProcessor.java
+++ b/src/com/android/server/telecom/components/UserCallIntentProcessor.java
@@ -70,7 +70,8 @@
*
* @param intent The intent.
*/
- public void processIntent(Intent intent, String callingPackageName, boolean hasCallAppOp) {
+ public void processIntent(Intent intent, String callingPackageName,
+ boolean canCallNonEmergency) {
// Ensure call intents are not processed on devices that are not capable of calling.
if (!isVoiceCapable()) {
return;
@@ -81,12 +82,12 @@
if (Intent.ACTION_CALL.equals(action) ||
Intent.ACTION_CALL_PRIVILEGED.equals(action) ||
Intent.ACTION_CALL_EMERGENCY.equals(action)) {
- processOutgoingCallIntent(intent, callingPackageName, hasCallAppOp);
+ processOutgoingCallIntent(intent, callingPackageName, canCallNonEmergency);
}
}
private void processOutgoingCallIntent(Intent intent, String callingPackageName,
- boolean hasCallAppOp) {
+ boolean canCallNonEmergency) {
Uri handle = intent.getData();
String scheme = handle.getScheme();
String uriString = handle.getSchemeSpecificPart();
@@ -109,7 +110,7 @@
return;
}
- if (!hasCallAppOp && !TelephonyUtil.shouldProcessAsEmergency(mContext, handle)) {
+ if (!canCallNonEmergency && !TelephonyUtil.shouldProcessAsEmergency(mContext, handle)) {
showErrorDialogForRestrictedOutgoingCall(mContext,
R.string.outgoing_call_not_allowed_no_permission);
Log.w(this, "Rejecting non-emergency phone call because "