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 "