Wrap some privileged Telecom operations with permission checks

If the Dialer is not the default dialer and does not have the
CALL_PHONE permission, don't call TelecomManager methods that
will cause SecurityExceptions.

Bug: 20266292
Change-Id: I229dd045269a262632c4a911e2321203443de684
diff --git a/src/com/android/dialer/DialtactsActivity.java b/src/com/android/dialer/DialtactsActivity.java
index dbff276..127ec44 100644
--- a/src/com/android/dialer/DialtactsActivity.java
+++ b/src/com/android/dialer/DialtactsActivity.java
@@ -83,6 +83,7 @@
 import com.android.dialer.list.SpeedDialFragment;
 import com.android.dialer.settings.DialerSettingsActivity;
 import com.android.dialer.util.IntentUtil;
+import com.android.dialer.util.TelecomUtil;
 import com.android.dialer.util.IntentUtil.CallIntentBuilder;
 import com.android.dialer.util.DialerUtils;
 import com.android.dialer.widget.ActionBarController;
@@ -1182,7 +1183,7 @@
     }
 
     private boolean phoneIsInUse() {
-        return getTelecomManager().isInCall();
+        return TelecomUtil.isInCall(this);
     }
 
     private boolean canIntentBeHandled(Intent intent) {
diff --git a/src/com/android/dialer/dialpad/DialpadFragment.java b/src/com/android/dialer/dialpad/DialpadFragment.java
index d2628da..54e4b89 100644
--- a/src/com/android/dialer/dialpad/DialpadFragment.java
+++ b/src/com/android/dialer/dialpad/DialpadFragment.java
@@ -81,6 +81,7 @@
 import com.android.dialer.SpecialCharSequenceMgr;
 import com.android.dialer.calllog.PhoneAccountUtils;
 import com.android.dialer.util.DialerUtils;
+import com.android.dialer.util.TelecomUtil;
 import com.android.dialer.util.IntentUtil.CallIntentBuilder;
 import com.android.incallui.Call.LogState;
 import com.android.phone.common.CallLogAsync;
@@ -1478,8 +1479,12 @@
      * @return true if the phone is "in use", meaning that at least one line
      *              is active (ie. off hook or ringing or dialing, or on hold).
      */
-    public boolean isPhoneInUse() {
-        return getTelecomManager().isInCall();
+    private boolean isPhoneInUse() {
+        final Context context = getActivity();
+        if (context != null) {
+            return TelecomUtil.isInCall(context);
+        }
+        return false;
     }
 
     /**
diff --git a/src/com/android/dialer/util/DialerUtils.java b/src/com/android/dialer/util/DialerUtils.java
index fbe14ba..8870f76 100644
--- a/src/com/android/dialer/util/DialerUtils.java
+++ b/src/com/android/dialer/util/DialerUtils.java
@@ -33,18 +33,12 @@
 import android.text.TextUtils;
 import android.view.View;
 import android.view.inputmethod.InputMethodManager;
-import android.widget.ImageView;
-import android.widget.TextView;
 import android.widget.Toast;
 
 import com.android.contacts.common.ContactsUtils;
 import com.android.contacts.common.interactions.TouchPointManager;
 import com.android.dialer.R;
-import com.android.dialer.widget.EmptyContentView;
-import com.android.incallui.CallCardFragment;
-import com.android.incallui.Log;
 
-import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
@@ -94,7 +88,14 @@
                 }
                 final TelecomManager tm =
                         (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
-                tm.placeCall(intent.getData(), intent.getExtras());
+                if (TelecomUtil.hasCallPhonePermission(context)) {
+                    tm.placeCall(intent.getData(), intent.getExtras());
+                } else {
+                    // TODO: Make calling activity show request permission dialog and handle
+                    // callback results appropriately.
+                    Toast.makeText(context, "Cannot place call without Phone permission",
+                            Toast.LENGTH_SHORT);
+                }
             } else {
                 context.startActivity(intent);
             }
diff --git a/src/com/android/dialer/util/TelecomUtil.java b/src/com/android/dialer/util/TelecomUtil.java
index 1cd270c..43b9a72 100644
--- a/src/com/android/dialer/util/TelecomUtil.java
+++ b/src/com/android/dialer/util/TelecomUtil.java
@@ -26,6 +26,9 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import java.util.ArrayList;
+import java.util.List;
+
 public class TelecomUtil {
     private static final String TAG = "TelecomUtil";
     private static boolean sWarningLogged = false;
@@ -78,6 +81,20 @@
         return false;
     }
 
+    public static List<PhoneAccountHandle> getCallCapablePhoneAccounts(Context context) {
+        if (hasReadPhoneStatePermission(context)) {
+            return getTelecomManager(context).getCallCapablePhoneAccounts();
+        }
+        return new ArrayList<>();
+    }
+
+    public static boolean isInCall(Context context) {
+        if (hasReadPhoneStatePermission(context)) {
+            return getTelecomManager(context).isInCall();
+        }
+        return false;
+    }
+
     public static Uri getCallLogUri(Context context) {
         return hasReadWriteVoicemailPermissions(context) ? Calls.CONTENT_URI_WITH_VOICEMAIL
                 : Calls.CONTENT_URI;
@@ -94,6 +111,16 @@
                 || hasPermission(context, Manifest.permission.MODIFY_PHONE_STATE);
     }
 
+    public static boolean hasReadPhoneStatePermission(Context context) {
+        return isDefaultDialer(context)
+                || hasPermission(context, Manifest.permission.READ_PHONE_STATE);
+    }
+
+    public static boolean hasCallPhonePermission(Context context) {
+        return isDefaultDialer(context)
+                || hasPermission(context, Manifest.permission.CALL_PHONE);
+    }
+
     private static boolean hasPermission(Context context, String permission) {
         return context.checkSelfPermission(permission)
                 == PackageManager.PERMISSION_GRANTED;