Merge "Cleanup ITelephony in TelephonyPermissions with new System API. This method is used by Telephony Module for permission checking."
diff --git a/api/system-current.txt b/api/system-current.txt
index 1a83a2c..39c0882 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -9584,6 +9584,7 @@
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int);
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCarrierPrivilegeStatus(int);
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<java.lang.String> getCarrierPrivilegedPackagesForAllActiveSubscriptions();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CarrierRestrictionRules getCarrierRestrictionRules();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn();
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index b560761..6bc117b 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -1313,7 +1313,8 @@
// only CarrierService with carrier privilege rule should have the permission
int[] subIds = Arrays.stream(SubscriptionManager.from(mContext)
.getActiveSubscriptionIdList(false))
- .filter(i -> TelephonyPermissions.checkCarrierPrivilegeForSubId(i)).toArray();
+ .filter(i -> TelephonyPermissions.checkCarrierPrivilegeForSubId(mContext,
+ i)).toArray();
if (ArrayUtils.isEmpty(subIds)) {
loge("notifyCarrierNetworkChange without carrier privilege");
// the active subId does not have carrier privilege.
@@ -2304,7 +2305,7 @@
return;
}
- TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(
+ TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mContext,
SubscriptionManager.getDefaultSubscriptionId(), method);
}
diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
index 86630b0..4d01e33 100644
--- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
@@ -27,8 +27,6 @@
import android.os.Binder;
import android.os.Build;
import android.os.Process;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.UserHandle;
import android.telephony.Rlog;
import android.telephony.SubscriptionManager;
@@ -42,7 +40,6 @@
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
-import java.util.function.Supplier;
/** Utility class for Telephony permission enforcement. */
public final class TelephonyPermissions {
@@ -50,9 +47,6 @@
private static final boolean DBG = false;
- private static final Supplier<ITelephony> TELEPHONY_SUPPLIER = () ->
- ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
-
/**
* Whether to disable the new device identifier access restrictions.
*/
@@ -138,49 +132,6 @@
public static boolean checkReadPhoneState(
Context context, int subId, int pid, int uid, String callingPackage,
@Nullable String callingFeatureId, String message) {
- return checkReadPhoneState(
- context, TELEPHONY_SUPPLIER, subId, pid, uid, callingPackage, callingFeatureId,
- message);
- }
-
- /**
- * Check whether the calling packages has carrier privileges for the passing subscription.
- * @return {@code true} if the caller has carrier privileges, {@false} otherwise.
- */
- public static boolean checkCarrierPrivilegeForSubId(int subId) {
- if (SubscriptionManager.isValidSubscriptionId(subId)
- && getCarrierPrivilegeStatus(TELEPHONY_SUPPLIER, subId, Binder.getCallingUid())
- == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
- return true;
- }
- return false;
- }
-
- /**
- * Check whether the app with the given pid/uid can read phone state.
- *
- * <p>This method behaves in one of the following ways:
- * <ul>
- * <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the
- * READ_PHONE_STATE runtime permission, or carrier privileges on the given subId.
- * <li>throw SecurityException: if the caller didn't declare any of these permissions, or, for
- * apps which support runtime permissions, if the caller does not currently have any of
- * these permissions.
- * <li>return false: if the caller lacks all of these permissions and doesn't support runtime
- * permissions. This implies that the user revoked the ability to read phone state
- * manually (via AppOps). In this case we can't throw as it would break app compatibility,
- * so we return false to indicate that the calling function should return dummy data.
- * </ul>
- *
- * <p>Note: for simplicity, this method always returns false for callers using legacy
- * permissions and who have had READ_PHONE_STATE revoked, even if they are carrier-privileged.
- * Such apps should migrate to runtime permissions or stop requiring READ_PHONE_STATE on P+
- * devices.
- */
- @VisibleForTesting
- public static boolean checkReadPhoneState(
- Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid,
- String callingPackage, @Nullable String callingFeatureId, String message) {
try {
context.enforcePermission(
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, pid, uid, message);
@@ -195,7 +146,7 @@
// If we don't have the runtime permission, but do have carrier privileges, that
// suffices for reading phone state.
if (SubscriptionManager.isValidSubscriptionId(subId)) {
- enforceCarrierPrivilege(telephonySupplier, subId, uid, message);
+ enforceCarrierPrivilege(context, subId, uid, message);
return true;
}
throw phoneStateException;
@@ -210,6 +161,19 @@
}
/**
+ * Check whether the calling packages has carrier privileges for the passing subscription.
+ * @return {@code true} if the caller has carrier privileges, {@false} otherwise.
+ */
+ public static boolean checkCarrierPrivilegeForSubId(Context context, int subId) {
+ if (SubscriptionManager.isValidSubscriptionId(subId)
+ && getCarrierPrivilegeStatus(context, subId, Binder.getCallingUid())
+ == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
* Check whether the app with the given pid/uid can read phone state, or has carrier
* privileges on any active subscription.
*
@@ -225,28 +189,6 @@
*/
public static boolean checkReadPhoneStateOnAnyActiveSub(Context context, int pid, int uid,
String callingPackage, @Nullable String callingFeatureId, String message) {
- return checkReadPhoneStateOnAnyActiveSub(context, TELEPHONY_SUPPLIER, pid, uid,
- callingPackage, callingFeatureId, message);
- }
-
- /**
- * Check whether the app with the given pid/uid can read phone state, or has carrier
- * privileges on any active subscription.
- *
- * <p>If the app does not have carrier privilege, this method will return {@code false} instead
- * of throwing a SecurityException. Therefore, the callers cannot tell the difference
- * between M+ apps which declare the runtime permission but do not have it, and pre-M apps
- * which declare the static permission but had access revoked via AppOps. Apps in the former
- * category expect SecurityExceptions; apps in the latter don't. So this method is suitable for
- * use only if the behavior in both scenarios is meant to be identical.
- *
- * @return {@code true} if the app can read phone state or has carrier privilege;
- * {@code false} otherwise.
- */
- @VisibleForTesting
- public static boolean checkReadPhoneStateOnAnyActiveSub(
- Context context, Supplier<ITelephony> telephonySupplier, int pid, int uid,
- String callingPackage, @Nullable String callingFeatureId, String message) {
try {
context.enforcePermission(
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, pid, uid, message);
@@ -260,7 +202,7 @@
} catch (SecurityException phoneStateException) {
// If we don't have the runtime permission, but do have carrier privileges, that
// suffices for reading phone state.
- return checkCarrierPrivilegeForAnySubId(context, telephonySupplier, uid);
+ return checkCarrierPrivilegeForAnySubId(context, uid);
}
}
@@ -375,12 +317,11 @@
}
// If the calling package has carrier privileges for specified sub, then allow access.
- if (checkCarrierPrivilegeForSubId(subId)) return true;
+ if (checkCarrierPrivilegeForSubId(context, subId)) return true;
// If the calling package has carrier privileges for any subscription
// and allowCarrierPrivilegeOnAnySub is set true, then allow access.
- if (allowCarrierPrivilegeOnAnySub && checkCarrierPrivilegeForAnySubId(
- context, TELEPHONY_SUPPLIER, uid)) {
+ if (allowCarrierPrivilegeOnAnySub && checkCarrierPrivilegeForAnySubId(context, uid)) {
return true;
}
@@ -468,7 +409,7 @@
uid) == PackageManager.PERMISSION_GRANTED) {
return false;
}
- if (checkCarrierPrivilegeForSubId(subId)) {
+ if (checkCarrierPrivilegeForSubId(context, subId)) {
return false;
}
}
@@ -484,26 +425,12 @@
public static boolean checkReadCallLog(
Context context, int subId, int pid, int uid, String callingPackage,
@Nullable String callingPackageName) {
- return checkReadCallLog(
- context, TELEPHONY_SUPPLIER, subId, pid, uid, callingPackage, callingPackageName);
- }
-
- /**
- * Check whether the app with the given pid/uid can read the call log.
- * @return {@code true} if the specified app has the read call log permission and AppOpp granted
- * to it, {@code false} otherwise.
- */
- @VisibleForTesting
- public static boolean checkReadCallLog(
- Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid,
- String callingPackage, @Nullable String callingFeatureId) {
-
if (context.checkPermission(Manifest.permission.READ_CALL_LOG, pid, uid)
!= PERMISSION_GRANTED) {
// If we don't have the runtime permission, but do have carrier privileges, that
// suffices for being able to see the call phone numbers.
if (SubscriptionManager.isValidSubscriptionId(subId)) {
- enforceCarrierPrivilege(telephonySupplier, subId, uid, "readCallLog");
+ enforceCarrierPrivilege(context, subId, uid, "readCallLog");
return true;
}
return false;
@@ -513,7 +440,7 @@
// revoked.
AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
return appOps.noteOp(AppOpsManager.OPSTR_READ_CALL_LOG, uid, callingPackage,
- callingFeatureId, null) == AppOpsManager.MODE_ALLOWED;
+ callingPackageName, null) == AppOpsManager.MODE_ALLOWED;
}
/**
@@ -526,7 +453,7 @@
Context context, int subId, String callingPackage, @Nullable String callingFeatureId,
String message) {
return checkReadPhoneNumber(
- context, TELEPHONY_SUPPLIER, subId, Binder.getCallingPid(), Binder.getCallingUid(),
+ context, subId, Binder.getCallingPid(), Binder.getCallingUid(),
callingPackage, callingFeatureId, message);
}
@@ -538,7 +465,7 @@
*/
@VisibleForTesting
public static boolean checkReadPhoneNumber(
- Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid,
+ Context context, int subId, int pid, int uid,
String callingPackage, @Nullable String callingFeatureId, String message) {
// Default SMS app can always read it.
AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
@@ -553,7 +480,7 @@
// First, check if we can read the phone state.
try {
return checkReadPhoneState(
- context, telephonySupplier, subId, pid, uid, callingPackage, callingFeatureId,
+ context, subId, pid, uid, callingPackage, callingFeatureId,
message);
} catch (SecurityException readPhoneStateSecurityException) {
}
@@ -595,7 +522,7 @@
}
if (DBG) Rlog.d(LOG_TAG, "No modify permission, check carrier privilege next.");
- enforceCallingOrSelfCarrierPrivilege(subId, message);
+ enforceCallingOrSelfCarrierPrivilege(context, subId, message);
}
/**
@@ -615,7 +542,7 @@
Rlog.d(LOG_TAG, "No READ_PHONE_STATE permission, check carrier privilege next.");
}
- enforceCallingOrSelfCarrierPrivilege(subId, message);
+ enforceCallingOrSelfCarrierPrivilege(context, subId, message);
}
/**
@@ -636,7 +563,7 @@
+ "check carrier privilege next.");
}
- enforceCallingOrSelfCarrierPrivilege(subId, message);
+ enforceCallingOrSelfCarrierPrivilege(context, subId, message);
}
/**
@@ -644,21 +571,18 @@
*
* @throws SecurityException if the caller does not have the required privileges
*/
- public static void enforceCallingOrSelfCarrierPrivilege(int subId, String message) {
+ public static void enforceCallingOrSelfCarrierPrivilege(
+ Context context, int subId, String message) {
// NOTE: It's critical that we explicitly pass the calling UID here rather than call
// TelephonyManager#hasCarrierPrivileges directly, as the latter only works when called from
// the phone process. When called from another process, it will check whether that process
// has carrier privileges instead.
- enforceCarrierPrivilege(subId, Binder.getCallingUid(), message);
- }
-
- private static void enforceCarrierPrivilege(int subId, int uid, String message) {
- enforceCarrierPrivilege(TELEPHONY_SUPPLIER, subId, uid, message);
+ enforceCarrierPrivilege(context, subId, Binder.getCallingUid(), message);
}
private static void enforceCarrierPrivilege(
- Supplier<ITelephony> telephonySupplier, int subId, int uid, String message) {
- if (getCarrierPrivilegeStatus(telephonySupplier, subId, uid)
+ Context context, int subId, int uid, String message) {
+ if (getCarrierPrivilegeStatus(context, subId, uid)
!= TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
if (DBG) Rlog.e(LOG_TAG, "No Carrier Privilege.");
throw new SecurityException(message);
@@ -666,13 +590,12 @@
}
/** Returns whether the provided uid has carrier privileges for any active subscription ID. */
- private static boolean checkCarrierPrivilegeForAnySubId(
- Context context, Supplier<ITelephony> telephonySupplier, int uid) {
+ private static boolean checkCarrierPrivilegeForAnySubId(Context context, int uid) {
SubscriptionManager sm = (SubscriptionManager) context.getSystemService(
Context.TELEPHONY_SUBSCRIPTION_SERVICE);
int[] activeSubIds = sm.getActiveSubscriptionIdList(/* visibleOnly */ false);
for (int activeSubId : activeSubIds) {
- if (getCarrierPrivilegeStatus(telephonySupplier, activeSubId, uid)
+ if (getCarrierPrivilegeStatus(context, activeSubId, uid)
== TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
return true;
}
@@ -680,18 +603,10 @@
return false;
}
- private static int getCarrierPrivilegeStatus(
- Supplier<ITelephony> telephonySupplier, int subId, int uid) {
- ITelephony telephony = telephonySupplier.get();
- try {
- if (telephony != null) {
- return telephony.getCarrierPrivilegeStatusForUid(subId, uid);
- }
- } catch (RemoteException e) {
- // Fallback below.
- }
- Rlog.e(LOG_TAG, "Phone process is down, cannot check carrier privileges");
- return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
+ private static int getCarrierPrivilegeStatus(Context context, int subId, int uid) {
+ TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(
+ Context.TELEPHONY_SERVICE);
+ return telephonyManager.createForSubscriptionId(subId).getCarrierPrivilegeStatus(uid);
}
/**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 62eab1c..5b7ad12 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -11768,6 +11768,32 @@
}
/**
+ * Get the calling application status about carrier privileges for the subscription created
+ * in TelephonyManager. Used by Telephony Module for permission checking.
+ *
+ * @param uid Uid to check.
+ * @return any value of {@link #CARRIER_PRIVILEGE_STATUS_HAS_ACCESS},
+ * {@link #CARRIER_PRIVILEGE_STATUS_NO_ACCESS},
+ * {@link #CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED}, or
+ * {@link #CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES}
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public int getCarrierPrivilegeStatus(int uid) {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ return telephony.getCarrierPrivilegeStatusForUid(getSubId(), uid);
+ }
+ } catch (RemoteException ex) {
+ Log.e(TAG, "getCarrierPrivilegeStatus RemoteException", ex);
+ }
+ return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
+ }
+
+ /**
* Return whether data is enabled for certain APN type. This will tell if framework will accept
* corresponding network requests on a subId.
*