aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/com/android/providers/contacts/VoicemailContentProvider.java36
-rw-r--r--src/com/android/providers/contacts/VoicemailNotifier.java27
-rw-r--r--src/com/android/providers/contacts/VoicemailPermissions.java35
3 files changed, 76 insertions, 22 deletions
diff --git a/src/com/android/providers/contacts/VoicemailContentProvider.java b/src/com/android/providers/contacts/VoicemailContentProvider.java
index 01c10481..1ced1be6 100644
--- a/src/com/android/providers/contacts/VoicemailContentProvider.java
+++ b/src/com/android/providers/contacts/VoicemailContentProvider.java
@@ -15,6 +15,7 @@
*/
package com.android.providers.contacts;
+import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.provider.VoicemailContract.SOURCE_PACKAGE_FIELD;
import static com.android.providers.contacts.util.DbQueryUtils.concatenateClauses;
@@ -23,13 +24,13 @@ import static com.android.providers.contacts.util.DbQueryUtils.getEqualityClause
import android.annotation.NonNull;
import android.app.AppOpsManager;
import android.content.ContentProvider;
-import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Binder;
+import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.provider.BaseColumns;
import android.provider.VoicemailContract;
@@ -50,7 +51,6 @@ import com.google.common.annotations.VisibleForTesting;
import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.List;
-import java.util.Set;
/**
* An implementation of the Voicemail content provider. This class in the entry point for both
@@ -83,8 +83,15 @@ public class VoicemailContentProvider extends ContentProvider
}
Context context = context();
- // ADD_VOICEMAIL permission guards read and write. We do the same with app ops.
- // The permission name doesn't reflect its function but we cannot rename it.
+ // Read and write permission requires ADD_VOICEMAIL or carrier privileges. We can't declare
+ // any permission entries in the manifest because carrier-privileged apps without
+ // ADD_VOICEMAIL would be blocked by the platform without even reaching our custom
+ // enforce{Read,Write}PermissionInner functions. These overrides are what allow carrier-
+ // privileged apps to bypass these runtime-configured permissions.
+ // TODO(b/74245334): See if these can be removed since individual operations perform their
+ // own checks.
+ setReadPermission(android.Manifest.permission.ADD_VOICEMAIL);
+ setWritePermission(android.Manifest.permission.ADD_VOICEMAIL);
setAppOps(AppOpsManager.OP_ADD_VOICEMAIL, AppOpsManager.OP_ADD_VOICEMAIL);
mVoicemailPermissions = new VoicemailPermissions(context);
@@ -110,6 +117,27 @@ public class VoicemailContentProvider extends ContentProvider
return true;
}
+ @Override
+ protected int enforceReadPermissionInner(Uri uri, String callingPkg, IBinder callerToken)
+ throws SecurityException {
+ // Permit carrier-privileged apps regardless of ADD_VOICEMAIL permission state.
+ if (mVoicemailPermissions.callerHasCarrierPrivileges()) {
+ return MODE_ALLOWED;
+ }
+ return super.enforceReadPermissionInner(uri, callingPkg, callerToken);
+ }
+
+
+ @Override
+ protected int enforceWritePermissionInner(Uri uri, String callingPkg, IBinder callerToken)
+ throws SecurityException {
+ // Permit carrier-privileged apps regardless of ADD_VOICEMAIL permission state.
+ if (mVoicemailPermissions.callerHasCarrierPrivileges()) {
+ return MODE_ALLOWED;
+ }
+ return super.enforceWritePermissionInner(uri, callingPkg, callerToken);
+ }
+
@VisibleForTesting
void scheduleScanStalePackages() {
scheduleTask(BACKGROUND_TASK_SCAN_STALE_PACKAGES, null);
diff --git a/src/com/android/providers/contacts/VoicemailNotifier.java b/src/com/android/providers/contacts/VoicemailNotifier.java
index 04a9bd64..159cec73 100644
--- a/src/com/android/providers/contacts/VoicemailNotifier.java
+++ b/src/com/android/providers/contacts/VoicemailNotifier.java
@@ -1,8 +1,5 @@
package com.android.providers.contacts;
-import static android.Manifest.permission.ADD_VOICEMAIL;
-import static android.Manifest.permission.READ_VOICEMAIL;
-
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -15,6 +12,7 @@ import android.util.ArraySet;
import android.util.Log;
import com.google.android.collect.Lists;
+
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -68,11 +66,16 @@ public class VoicemailNotifier {
intentAction, uri));
for (ComponentName component :
getBroadcastReceiverComponents(intentAction, uri)) {
- // Ignore any package that is not affected by the change and don't have full access
- // either.
- if (!mModifiedPackages.contains(component.getPackageName()) &&
- !mVoicemailPermissions.packageHasReadAccess(
- component.getPackageName())) {
+ boolean hasFullReadAccess =
+ mVoicemailPermissions.packageHasReadAccess(component.getPackageName());
+ boolean hasOwnAccess =
+ mVoicemailPermissions.packageHasOwnVoicemailAccess(
+ component.getPackageName());
+ // If we don't have full access, ignore the broadcast if the package isn't affected
+ // by the change or doesn't have access to its own messages.
+ if (!hasFullReadAccess
+ && (!mModifiedPackages.contains(component.getPackageName())
+ || !hasOwnAccess)) {
continue;
}
@@ -82,12 +85,10 @@ public class VoicemailNotifier {
intent.putExtra(VoicemailContract.EXTRA_SELF_CHANGE,
callingPackages.contains(component.getPackageName()));
}
- String permissionNeeded = mModifiedPackages.contains(component.getPackageName()) ?
- ADD_VOICEMAIL : READ_VOICEMAIL;
- mContext.sendBroadcast(intent, permissionNeeded);
- Log.v(TAG, String.format("Sent intent. act:%s, url:%s, comp:%s, perm:%s," +
+ mContext.sendBroadcast(intent);
+ Log.v(TAG, String.format("Sent intent. act:%s, url:%s, comp:%s," +
" self_change:%s", intent.getAction(), intent.getData(),
- component.getClassName(), permissionNeeded,
+ component.getClassName(),
intent.hasExtra(VoicemailContract.EXTRA_SELF_CHANGE) ?
intent.getBooleanExtra(VoicemailContract.EXTRA_SELF_CHANGE, false) :
null));
diff --git a/src/com/android/providers/contacts/VoicemailPermissions.java b/src/com/android/providers/contacts/VoicemailPermissions.java
index 50f2447a..ed3815dc 100644
--- a/src/com/android/providers/contacts/VoicemailPermissions.java
+++ b/src/com/android/providers/contacts/VoicemailPermissions.java
@@ -16,10 +16,12 @@
package com.android.providers.contacts;
-import com.android.providers.contacts.util.ContactsPermissions;
-
import android.content.Context;
+import android.os.Binder;
import android.telecom.DefaultDialerManager;
+import android.telephony.TelephonyManager;
+
+import com.android.providers.contacts.util.ContactsPermissions;
/**
* Provides method related to check various voicemail permissions under the
@@ -35,7 +37,8 @@ public class VoicemailPermissions {
/** Determines if the calling process has access to its own voicemails. */
public boolean callerHasOwnVoicemailAccess() {
- return callerHasPermission(android.Manifest.permission.ADD_VOICEMAIL);
+ return callerHasPermission(android.Manifest.permission.ADD_VOICEMAIL)
+ || callerHasCarrierPrivileges();
}
/** Determine if the calling process has full read access to all voicemails. */
@@ -63,7 +66,7 @@ public class VoicemailPermissions {
public void checkCallerHasOwnVoicemailAccess() {
if (!callerHasOwnVoicemailAccess()) {
throw new SecurityException("The caller must have permission: " +
- android.Manifest.permission.ADD_VOICEMAIL);
+ android.Manifest.permission.ADD_VOICEMAIL + " or carrier privileges");
}
}
@@ -91,7 +94,8 @@ public class VoicemailPermissions {
/** Determines if the given package has access to its own voicemails. */
public boolean packageHasOwnVoicemailAccess(String packageName) {
return packageHasPermission(packageName,
- android.Manifest.permission.ADD_VOICEMAIL);
+ android.Manifest.permission.ADD_VOICEMAIL)
+ || packageHasCarrierPrivileges(packageName);
}
/** Determines if the given package has read access. */
@@ -113,4 +117,25 @@ public class VoicemailPermissions {
private boolean callerHasPermission(String permission) {
return ContactsPermissions.hasCallerOrSelfPermission(mContext, permission);
}
+
+ /** Determines if the calling process has carrier privileges. */
+ public boolean callerHasCarrierPrivileges() {
+ TelephonyManager tm =
+ (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ String[] packages = mContext.getPackageManager().getPackagesForUid(Binder.getCallingUid());
+ for (String packageName : packages) {
+ if (tm.checkCarrierPrivilegesForPackageAnyPhone(packageName)
+ == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /** Determines if the given package has carrier privileges. */
+ private boolean packageHasCarrierPrivileges(String packageName) {
+ TelephonyManager tm =
+ (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ return tm.getPackagesWithCarrierPrivileges().contains(packageName);
+ }
}