summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorke Lee <yorkelee@google.com>2015-09-18 12:54:59 -0700
committerYorke Lee <yorkelee@google.com>2015-09-22 09:47:04 -0700
commit762b357ec94aef3e7ee6f991c553aa950840a8bc (patch)
treeae5834a64f7f38fe8698c166156d92f9c9f0c06f
parenta5dd7f93654181ebf927723d19e2f84a7e4c6ceb (diff)
Protect against more Telecom privileged operations
Make sure that all invocations of TelecomManager methods that could possibly require a permission are protected by a permission check. Some of these are overcautious - for example, the UI should never show the option to return to a call (READ_PHONE_STATE) if we didn't detect an active call (READ_PHONE_STATE) in the first place, so it is not strictly necessary to protect against the former. But not crashing is the most preferable of all options. Bug: 20266292 Change-Id: Id91dd16e34320a5e607f91dbce9a4296025eeaaf
-rw-r--r--src/com/android/dialer/DialtactsActivity.java8
-rw-r--r--src/com/android/dialer/SpecialCharSequenceMgr.java24
-rw-r--r--src/com/android/dialer/calllog/PhoneAccountUtils.java6
-rw-r--r--src/com/android/dialer/dialpad/DialpadFragment.java16
-rw-r--r--src/com/android/dialer/util/DialerUtils.java9
-rw-r--r--src/com/android/dialer/util/PhoneNumberUtil.java6
-rw-r--r--src/com/android/dialer/util/TelecomUtil.java59
7 files changed, 85 insertions, 43 deletions
diff --git a/src/com/android/dialer/DialtactsActivity.java b/src/com/android/dialer/DialtactsActivity.java
index f8fb17f6b..fe828a3bb 100644
--- a/src/com/android/dialer/DialtactsActivity.java
+++ b/src/com/android/dialer/DialtactsActivity.java
@@ -34,7 +34,6 @@ import android.support.design.widget.CoordinatorLayout;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.telecom.PhoneAccount;
-import android.telecom.TelecomManager;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
@@ -370,7 +369,6 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
TouchPointManager.getInstance().setPoint((int) ev.getRawX(), (int) ev.getRawY());
}
return super.dispatchTouchEvent(ev);
-
}
@Override
@@ -929,7 +927,7 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
final boolean callKey = Intent.ACTION_CALL_BUTTON.equals(intent.getAction());
if (callKey) {
- getTelecomManager().showInCallScreen(false);
+ TelecomUtil.showInCallScreen(this, false);
return true;
}
@@ -1340,10 +1338,6 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
public void onPageScrollStateChanged(int state) {
}
- private TelecomManager getTelecomManager() {
- return (TelecomManager) getSystemService(Context.TELECOM_SERVICE);
- }
-
@Override
public boolean isActionBarShowing() {
return mActionBarController.isActionBarShowing();
diff --git a/src/com/android/dialer/SpecialCharSequenceMgr.java b/src/com/android/dialer/SpecialCharSequenceMgr.java
index 31aa5c3c7..994829a50 100644
--- a/src/com/android/dialer/SpecialCharSequenceMgr.java
+++ b/src/com/android/dialer/SpecialCharSequenceMgr.java
@@ -32,7 +32,6 @@ import android.os.Looper;
import android.provider.Settings;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
-import android.telecom.TelecomManager;
import android.telephony.PhoneNumberUtils;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
@@ -48,7 +47,6 @@ import com.android.contacts.common.widget.SelectPhoneAccountDialogFragment.Selec
import com.android.dialer.calllog.PhoneAccountUtils;
import com.android.dialer.util.TelecomUtil;
-import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
@@ -91,13 +89,13 @@ public class SpecialCharSequenceMgr {
private static QueryHandler sPreviousAdnQueryHandler;
public static class HandleAdnEntryAccountSelectedCallback extends SelectPhoneAccountListener{
- final private TelecomManager mTelecomManager;
+ final private Context mContext;
final private QueryHandler mQueryHandler;
final private SimContactQueryCookie mCookie;
- public HandleAdnEntryAccountSelectedCallback(TelecomManager telecomManager,
+ public HandleAdnEntryAccountSelectedCallback(Context context,
QueryHandler queryHandler, SimContactQueryCookie cookie) {
- mTelecomManager = telecomManager;
+ mContext = context;
mQueryHandler = queryHandler;
mCookie = cookie;
}
@@ -105,7 +103,7 @@ public class SpecialCharSequenceMgr {
@Override
public void onPhoneAccountSelected(PhoneAccountHandle selectedAccountHandle,
boolean setDefault) {
- Uri uri = mTelecomManager.getAdnUriForPhoneAccount(selectedAccountHandle);
+ Uri uri = TelecomUtil.getAdnUriForPhoneAccount(mContext, selectedAccountHandle);
handleAdnQuery(mQueryHandler, mCookie, uri);
// TODO: Show error dialog if result isn't valid.
}
@@ -193,6 +191,7 @@ public class SpecialCharSequenceMgr {
* and query cancel handler implemented in {@link SimContactQueryCookie}.
*/
static boolean handleAdnEntry(Context context, String input, EditText textField) {
+ context = context.getApplicationContext();
/* ADN entries are of the form "N(N)(N)#" */
TelephonyManager telephonyManager =
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
@@ -245,20 +244,19 @@ public class SpecialCharSequenceMgr {
sc.progressDialog.getWindow().addFlags(
WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
- final TelecomManager telecomManager =
- (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
List<PhoneAccountHandle> subscriptionAccountHandles =
PhoneAccountUtils.getSubscriptionPhoneAccounts(context);
boolean hasUserSelectedDefault = subscriptionAccountHandles.contains(
- telecomManager.getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL));
+ TelecomUtil.getDefaultOutgoingPhoneAccount(context,
+ PhoneAccount.SCHEME_TEL));
if (subscriptionAccountHandles.size() == 1 || hasUserSelectedDefault) {
- Uri uri = telecomManager.getAdnUriForPhoneAccount(null);
+ Uri uri = TelecomUtil.getAdnUriForPhoneAccount(context, null);
handleAdnQuery(handler, sc, uri);
} else if (subscriptionAccountHandles.size() > 1){
SelectPhoneAccountListener callback =
- new HandleAdnEntryAccountSelectedCallback(telecomManager, handler, sc);
+ new HandleAdnEntryAccountSelectedCallback(context, handler, sc);
DialogFragment dialogFragment = SelectPhoneAccountDialogFragment.newInstance(
subscriptionAccountHandles, callback);
@@ -299,12 +297,10 @@ public class SpecialCharSequenceMgr {
static boolean handlePinEntry(final Context context, final String input) {
if ((input.startsWith("**04") || input.startsWith("**05")) && input.endsWith("#")) {
- final TelecomManager telecomManager =
- (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
List<PhoneAccountHandle> subscriptionAccountHandles =
PhoneAccountUtils.getSubscriptionPhoneAccounts(context);
boolean hasUserSelectedDefault = subscriptionAccountHandles.contains(
- telecomManager.getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL));
+ TelecomUtil.getDefaultOutgoingPhoneAccount(context, PhoneAccount.SCHEME_TEL));
if (subscriptionAccountHandles.size() == 1 || hasUserSelectedDefault) {
// Don't bring up the dialog for single-SIM or if the default outgoing account is
diff --git a/src/com/android/dialer/calllog/PhoneAccountUtils.java b/src/com/android/dialer/calllog/PhoneAccountUtils.java
index 143d13e86..ceadabce2 100644
--- a/src/com/android/dialer/calllog/PhoneAccountUtils.java
+++ b/src/com/android/dialer/calllog/PhoneAccountUtils.java
@@ -23,6 +23,9 @@ import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.text.TextUtils;
+import com.android.contacts.common.util.PermissionsUtil;
+import com.android.dialer.util.TelecomUtil;
+
import java.util.ArrayList;
import java.util.List;
@@ -38,7 +41,8 @@ public class PhoneAccountUtils {
(TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
List<PhoneAccountHandle> subscriptionAccountHandles = new ArrayList<PhoneAccountHandle>();
- List<PhoneAccountHandle> accountHandles = telecomManager.getCallCapablePhoneAccounts();
+ final List<PhoneAccountHandle> accountHandles =
+ TelecomUtil.getCallCapablePhoneAccounts(context);
for (PhoneAccountHandle accountHandle : accountHandles) {
PhoneAccount account = telecomManager.getPhoneAccount(accountHandle);
if (account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
diff --git a/src/com/android/dialer/dialpad/DialpadFragment.java b/src/com/android/dialer/dialpad/DialpadFragment.java
index 54e4b8946..9c77f30c5 100644
--- a/src/com/android/dialer/dialpad/DialpadFragment.java
+++ b/src/com/android/dialer/dialpad/DialpadFragment.java
@@ -42,7 +42,6 @@ import android.provider.Contacts.PhonesColumns;
import android.provider.Settings;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
-import android.telecom.TelecomManager;
import android.telephony.PhoneNumberUtils;
import android.telephony.TelephonyManager;
import android.text.Editable;
@@ -274,10 +273,6 @@ public class DialpadFragment extends Fragment
return (TelephonyManager) getActivity().getSystemService(Context.TELEPHONY_SERVICE);
}
- private TelecomManager getTelecomManager() {
- return (TelecomManager) getActivity().getSystemService(Context.TELECOM_SERVICE);
- }
-
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
mWasEmptyBeforeTextChange = TextUtils.isEmpty(s);
@@ -980,7 +975,7 @@ public class DialpadFragment extends Fragment
List<PhoneAccountHandle> subscriptionAccountHandles =
PhoneAccountUtils.getSubscriptionPhoneAccounts(getActivity());
boolean hasUserSelectedDefault = subscriptionAccountHandles.contains(
- getTelecomManager().getDefaultOutgoingPhoneAccount(
+ TelecomUtil.getDefaultOutgoingPhoneAccount(getActivity(),
PhoneAccount.SCHEME_VOICEMAIL));
boolean needsAccountDisambiguation = subscriptionAccountHandles.size() > 1
&& !hasUserSelectedDefault;
@@ -1462,7 +1457,7 @@ public class DialpadFragment extends Fragment
* or "return to call" from the dialpad chooser.
*/
private void returnToInCallScreen(boolean showDialpad) {
- getTelecomManager().showInCallScreen(showDialpad);
+ TelecomUtil.showInCallScreen(getActivity(), showDialpad);
// Finally, finish() ourselves so that we don't stay on the
// activity stack.
@@ -1579,20 +1574,19 @@ public class DialpadFragment extends Fragment
*
* @return true if voicemail is enabled and accessible. Note that this can be false
* "temporarily" after the app boot.
- * @see TelecomManager#getVoiceMailNumber(PhoneAccountHandle)
*/
private boolean isVoicemailAvailable() {
try {
PhoneAccountHandle defaultUserSelectedAccount =
- getTelecomManager().getDefaultOutgoingPhoneAccount(
+ TelecomUtil.getDefaultOutgoingPhoneAccount(getActivity(),
PhoneAccount.SCHEME_VOICEMAIL);
if (defaultUserSelectedAccount == null) {
// In a single-SIM phone, there is no default outgoing phone account selected by
// the user, so just call TelephonyManager#getVoicemailNumber directly.
return !TextUtils.isEmpty(getTelephonyManager().getVoiceMailNumber());
} else {
- return !TextUtils.isEmpty(
- getTelecomManager().getVoiceMailNumber(defaultUserSelectedAccount));
+ return !TextUtils.isEmpty(TelecomUtil.getVoicemailNumber(getActivity(),
+ defaultUserSelectedAccount));
}
} catch (SecurityException se) {
// Possibly no READ_PHONE_STATE privilege.
diff --git a/src/com/android/dialer/util/DialerUtils.java b/src/com/android/dialer/util/DialerUtils.java
index 8870f76e4..3d5c257ea 100644
--- a/src/com/android/dialer/util/DialerUtils.java
+++ b/src/com/android/dialer/util/DialerUtils.java
@@ -86,11 +86,10 @@ public class DialerUtils {
extras.putParcelable(TouchPointManager.TOUCH_POINT, touchPoint);
intent.putExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, extras);
}
- final TelecomManager tm =
- (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
- if (TelecomUtil.hasCallPhonePermission(context)) {
- tm.placeCall(intent.getData(), intent.getExtras());
- } else {
+
+ final boolean hasCallPermission = TelecomUtil.placeCall(context, intent.getData(),
+ intent.getExtras());
+ if (!hasCallPermission) {
// TODO: Make calling activity show request permission dialog and handle
// callback results appropriately.
Toast.makeText(context, "Cannot place call without Phone permission",
diff --git a/src/com/android/dialer/util/PhoneNumberUtil.java b/src/com/android/dialer/util/PhoneNumberUtil.java
index 539d8b9ba..26998037d 100644
--- a/src/com/android/dialer/util/PhoneNumberUtil.java
+++ b/src/com/android/dialer/util/PhoneNumberUtil.java
@@ -19,7 +19,6 @@ package com.android.dialer.util;
import android.content.Context;
import android.provider.CallLog;
import android.telecom.PhoneAccountHandle;
-import android.telecom.TelecomManager;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
@@ -55,10 +54,7 @@ public class PhoneNumberUtil {
if (TextUtils.isEmpty(number)) {
return false;
}
-
- final TelecomManager telecomManager =
- (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
- return telecomManager.isVoiceMailNumber(accountHandle, number.toString());
+ return TelecomUtil.isVoicemailNumber(context, accountHandle, number.toString());
}
/**
diff --git a/src/com/android/dialer/util/TelecomUtil.java b/src/com/android/dialer/util/TelecomUtil.java
index 43b9a72a3..bab1adeea 100644
--- a/src/com/android/dialer/util/TelecomUtil.java
+++ b/src/com/android/dialer/util/TelecomUtil.java
@@ -20,6 +20,7 @@ import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.Uri;
+import android.os.Bundle;
import android.provider.CallLog.Calls;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
@@ -29,10 +30,27 @@ import android.util.Log;
import java.util.ArrayList;
import java.util.List;
+/**
+ * Performs permission checks before calling into TelecomManager. Each method is self-explanatory -
+ * perform the required check and return the fallback default if the permission is missing,
+ * otherwise return the value from TelecomManager.
+ *
+ */
public class TelecomUtil {
private static final String TAG = "TelecomUtil";
private static boolean sWarningLogged = false;
+ public static void showInCallScreen(Context context, boolean showDialpad) {
+ if (hasReadPhoneStatePermission(context)) {
+ try {
+ getTelecomManager(context).showInCallScreen(showDialpad);
+ } catch (SecurityException e) {
+ // Just in case
+ Log.w(TAG, "TelecomManager.showInCallScreen called without permission.");
+ }
+ }
+ }
+
public static void silenceRinger(Context context) {
if (hasModifyPhoneStatePermission(context)) {
try {
@@ -81,6 +99,14 @@ public class TelecomUtil {
return false;
}
+ public static PhoneAccountHandle getDefaultOutgoingPhoneAccount(Context context,
+ String uriScheme) {
+ if (hasReadPhoneStatePermission(context)) {
+ return getTelecomManager(context).getDefaultOutgoingPhoneAccount(uriScheme);
+ }
+ return null;
+ }
+
public static List<PhoneAccountHandle> getCallCapablePhoneAccounts(Context context) {
if (hasReadPhoneStatePermission(context)) {
return getTelecomManager(context).getCallCapablePhoneAccounts();
@@ -95,6 +121,39 @@ public class TelecomUtil {
return false;
}
+ public static boolean isVoicemailNumber(Context context, PhoneAccountHandle accountHandle,
+ String number) {
+ if (hasReadPhoneStatePermission(context)) {
+ return getTelecomManager(context).isVoiceMailNumber(accountHandle, number);
+ }
+ return false;
+ }
+
+ public static String getVoicemailNumber(Context context, PhoneAccountHandle accountHandle) {
+ if (hasReadPhoneStatePermission(context)) {
+ return getTelecomManager(context).getVoiceMailNumber(accountHandle);
+ }
+ return null;
+ }
+
+ /**
+ * Tries to place a call using the {@link TelecomManager}.
+ *
+ * @param context a valid context.
+ * @param address Handle to call.
+ * @param extras Bundle of extras to attach to the call intent.
+ *
+ * @return {@code true} if we successfully attempted to place the call, {@code false} if it
+ * failed due to a permission check.
+ */
+ public static boolean placeCall(Context context, Uri address, Bundle extras) {
+ if (hasCallPhonePermission(context)) {
+ getTelecomManager(context).placeCall(address, extras);
+ return true;
+ }
+ return false;
+ }
+
public static Uri getCallLogUri(Context context) {
return hasReadWriteVoicemailPermissions(context) ? Calls.CONTENT_URI_WITH_VOICEMAIL
: Calls.CONTENT_URI;