Add default dialer checks to Telecom/Telephony
Check for the default dialer or the modify phone state permission
for various TelecomManager/TelephonyManager methods.
Make sure to check the user-selected default rather than the
hardcoded package name.
Exercise this code in TestDialerActivity.
Bug: 20304458
Change-Id: Ic04cd8f2ba98e1d54c39549ae89d3e11cd5cdafb
diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java
index 8770e88..cd789ce 100644
--- a/src/com/android/server/telecom/TelecomServiceImpl.java
+++ b/src/com/android/server/telecom/TelecomServiceImpl.java
@@ -358,7 +358,7 @@
public boolean isVoiceMailNumber(PhoneAccountHandle accountHandle, String number,
String callingPackage) {
synchronized (mLock) {
- if (!isDefaultDialerCalling()
+ if (!isPrivilegedDialerCalling(callingPackage)
&& !canReadPhoneState(callingPackage, "isVoiceMailNumber")) {
return false;
}
@@ -382,7 +382,7 @@
@Override
public String getVoiceMailNumber(PhoneAccountHandle accountHandle, String callingPackage) {
synchronized (mLock) {
- if (!isDefaultDialerCalling()
+ if (!isPrivilegedDialerCalling(callingPackage)
&& !canReadPhoneState(callingPackage, "getVoiceMailNumber")) {
return null;
}
@@ -411,7 +411,7 @@
*/
@Override
public String getLine1Number(PhoneAccountHandle accountHandle, String callingPackage) {
- if (!isDefaultDialerCalling()
+ if (!isPrivilegedDialerCalling(callingPackage)
&& !canReadPhoneState(callingPackage, "getLine1Number")) {
return null;
}
@@ -436,9 +436,9 @@
* @see android.telecom.TelecomManager#silenceRinger
*/
@Override
- public void silenceRinger() {
+ public void silenceRinger(String callingPackage) {
synchronized (mLock) {
- enforceModifyPermissionOrDefaultDialer();
+ enforceModifyPermissionOrPrivilegedDialer(callingPackage);
mCallsManager.getRinger().silence();
}
}
@@ -543,7 +543,7 @@
*/
@Override
public void showInCallScreen(boolean showDialpad, String callingPackage) {
- if (!isDefaultDialerCalling()
+ if (!isPrivilegedDialerCalling(callingPackage)
&& !canReadPhoneState(callingPackage, "showInCallScreen")) {
return;
}
@@ -557,9 +557,9 @@
* @see android.telecom.TelecomManager#cancelMissedCallsNotification
*/
@Override
- public void cancelMissedCallsNotification() {
+ public void cancelMissedCallsNotification(String callingPackage) {
synchronized (mLock) {
- enforceModifyPermissionOrDefaultDialer();
+ enforceModifyPermissionOrPrivilegedDialer(callingPackage);
mCallsManager.getMissedCallNotifier().clearMissedCalls();
}
}
@@ -568,9 +568,9 @@
* @see android.telecom.TelecomManager#handleMmi
*/
@Override
- public boolean handlePinMmi(String dialString) {
+ public boolean handlePinMmi(String dialString, String callingPackage) {
synchronized (mLock) {
- enforceModifyPermissionOrDefaultDialer();
+ enforceModifyPermissionOrPrivilegedDialer(callingPackage);
// Switch identity so that TelephonyManager checks Telecom's permissions instead.
long token = Binder.clearCallingIdentity();
@@ -591,9 +591,10 @@
@Override
public boolean handlePinMmiForPhoneAccount(
PhoneAccountHandle accountHandle,
- String dialString) {
+ String dialString,
+ String callingPackage) {
synchronized (mLock) {
- enforceModifyPermissionOrDefaultDialer();
+ enforceModifyPermissionOrPrivilegedDialer(callingPackage);
if (!isVisibleToCaller(accountHandle)) {
Log.w(this, "%s is not visible for the calling user", accountHandle);
@@ -619,9 +620,10 @@
* @see android.telecom.TelecomManager#getAdnUriForPhoneAccount
*/
@Override
- public Uri getAdnUriForPhoneAccount(PhoneAccountHandle accountHandle) {
+ public Uri getAdnUriForPhoneAccount(PhoneAccountHandle accountHandle,
+ String callingPackage) {
synchronized (mLock) {
- enforceModifyPermissionOrDefaultDialer();
+ enforceModifyPermissionOrPrivilegedDialer(callingPackage);
if (!isVisibleToCaller(accountHandle)) {
Log.w(this, "%s is not visible for the calling user", accountHandle);
@@ -947,9 +949,15 @@
}
}
- private void enforceModifyPermissionOrDefaultDialer() {
- if (!isDefaultDialerCalling()) {
- enforceModifyPermission();
+ private void enforceModifyPermissionOrPrivilegedDialer(String packageName) {
+ if (!isPrivilegedDialerCalling(packageName)) {
+ try {
+ enforceModifyPermission();
+ } catch (SecurityException e) {
+ Log.e(this, e, "Caller must be the default or system dialer, or have the system"
+ + " only permission MODIFY_PHONE_STATE to perform this operation.");
+ throw e;
+ }
}
}
@@ -1033,25 +1041,9 @@
return false;
}
- private boolean isDefaultDialerCalling() {
- ComponentName defaultDialerComponent = getDefaultPhoneAppInternal();
- if (defaultDialerComponent != null) {
- try {
- mAppOpsManager.checkPackage(
- Binder.getCallingUid(), defaultDialerComponent.getPackageName());
- return true;
- } catch (SecurityException e) {
- Log.i(this, "Calling uid %d is not the default dialer.", Binder.getCallingUid());
- }
- }
- return false;
- }
-
- private ComponentName getDefaultPhoneAppInternal() {
- Resources resources = mContext.getResources();
- return new ComponentName(
- resources.getString(R.string.ui_default_package),
- resources.getString(R.string.dialer_default_class));
+ private boolean isPrivilegedDialerCalling(String callingPackage) {
+ mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage);
+ return DefaultDialerManager.isDefaultOrSystemDialer(mContext, callingPackage);
}
private TelephonyManager getTelephonyManager() {
diff --git a/testapps/res/layout/testdialer_main.xml b/testapps/res/layout/testdialer_main.xml
index 4f2d6bb..2c3e5e4 100644
--- a/testapps/res/layout/testdialer_main.xml
+++ b/testapps/res/layout/testdialer_main.xml
@@ -39,4 +39,9 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/testVoicemailButton" />
+ <Button
+ android:id="@+id/cancel_missed_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/cancelMissedButton" />
</LinearLayout>
diff --git a/testapps/res/values/donottranslate_strings.xml b/testapps/res/values/donottranslate_strings.xml
index 6a163d4..43c302d 100644
--- a/testapps/res/values/donottranslate_strings.xml
+++ b/testapps/res/values/donottranslate_strings.xml
@@ -33,4 +33,8 @@
<!-- String for button in TestDialerActivity that performs voicemail requests to verify
voicemail permissions -->
<string name="testVoicemailButton">Exercise voicemail permissions</string>
+
+ <!-- String for button in TestDialerActivity that tries to exercise the
+ TelecomManager.cancelMissedCallNotifications() functionality -->
+ <string name="cancelMissedButton">Cancel missed calls</string>
</resources>
diff --git a/testapps/src/com/android/server/telecom/testapps/TestDialerActivity.java b/testapps/src/com/android/server/telecom/testapps/TestDialerActivity.java
index dcef96a..a756284 100644
--- a/testapps/src/com/android/server/telecom/testapps/TestDialerActivity.java
+++ b/testapps/src/com/android/server/telecom/testapps/TestDialerActivity.java
@@ -2,11 +2,13 @@
import android.app.Activity;
import android.content.ContentValues;
+import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.CallLog.Calls;
import android.telecom.PhoneAccount;
+import android.telecom.TelecomManager;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
@@ -27,6 +29,7 @@
setDefault();
}
});
+
findViewById(R.id.place_call_button).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
@@ -41,6 +44,13 @@
}
});
+ findViewById(R.id.cancel_missed_button).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ cancelMissedCallNotification();
+ }
+ });
+
mNumberView = (EditText) findViewById(R.id.number);
updateEditTextWithNumber();
}
@@ -82,4 +92,15 @@
}
Toast.makeText(this, "Permission check succeeded", Toast.LENGTH_SHORT).show();
}
+
+ private void cancelMissedCallNotification() {
+ try {
+ final TelecomManager tm = (TelecomManager) getSystemService(Context.TELECOM_SERVICE);
+ tm.cancelMissedCallsNotification();
+ } catch (SecurityException e) {
+ Toast.makeText(this, "Privileged dialer operation failed", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ Toast.makeText(this, "Privileged dialer operation succeeded", Toast.LENGTH_SHORT).show();
+ }
}