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;