summaryrefslogtreecommitdiff
path: root/telephony/common
diff options
context:
space:
mode:
Diffstat (limited to 'telephony/common')
-rw-r--r--telephony/common/android/telephony/LocationAccessPolicy.java56
-rw-r--r--telephony/common/com/android/internal/telephony/CarrierAppUtils.java24
-rw-r--r--telephony/common/com/android/internal/telephony/SmsApplication.java53
-rw-r--r--telephony/common/com/android/internal/telephony/TelephonyPermissions.java56
-rw-r--r--telephony/common/com/android/internal/telephony/util/TelephonyUtils.java4
5 files changed, 168 insertions, 25 deletions
diff --git a/telephony/common/android/telephony/LocationAccessPolicy.java b/telephony/common/android/telephony/LocationAccessPolicy.java
index 25b062f85d3e..85d59a216f25 100644
--- a/telephony/common/android/telephony/LocationAccessPolicy.java
+++ b/telephony/common/android/telephony/LocationAccessPolicy.java
@@ -86,8 +86,9 @@ public final class LocationAccessPolicy {
private String mCallingFeatureId;
private int mCallingUid;
private int mCallingPid;
- private int mMinSdkVersionForCoarse = Integer.MAX_VALUE;
- private int mMinSdkVersionForFine = Integer.MAX_VALUE;
+ private int mMinSdkVersionForCoarse = -1;
+ private int mMinSdkVersionForFine = -1;
+ private int mMinSdkVersionForEnforcement = -1;
private boolean mLogAsInfo = false;
private String mMethod;
@@ -125,7 +126,14 @@ public final class LocationAccessPolicy {
/**
* Apps that target at least this sdk version will be checked for coarse location
- * permission. Defaults to INT_MAX (which means don't check)
+ * permission. This method MUST be called before calling {@link #build()}. Otherwise, an
+ * {@link IllegalArgumentException} will be thrown.
+ *
+ * Additionally, if both the argument to this method and
+ * {@link #setMinSdkVersionForFine} are greater than {@link Build.VERSION_CODES#BASE},
+ * you must call {@link #setMinSdkVersionForEnforcement} with the min of the two to
+ * affirm that you do not want any location checks below a certain SDK version.
+ * Otherwise, {@link #build} will throw an {@link IllegalArgumentException}.
*/
public Builder setMinSdkVersionForCoarse(
int minSdkVersionForCoarse) {
@@ -135,7 +143,14 @@ public final class LocationAccessPolicy {
/**
* Apps that target at least this sdk version will be checked for fine location
- * permission. Defaults to INT_MAX (which means don't check)
+ * permission. This method MUST be called before calling {@link #build()}.
+ * Otherwise, an {@link IllegalArgumentException} will be thrown.
+ *
+ * Additionally, if both the argument to this method and
+ * {@link #setMinSdkVersionForCoarse} are greater than {@link Build.VERSION_CODES#BASE},
+ * you must call {@link #setMinSdkVersionForEnforcement} with the min of the two to
+ * affirm that you do not want any location checks below a certain SDK version.
+ * Otherwise, {@link #build} will throw an {@link IllegalArgumentException}.
*/
public Builder setMinSdkVersionForFine(
int minSdkVersionForFine) {
@@ -144,6 +159,17 @@ public final class LocationAccessPolicy {
}
/**
+ * If both the argument to {@link #setMinSdkVersionForFine} and
+ * {@link #setMinSdkVersionForCoarse} are greater than {@link Build.VERSION_CODES#BASE},
+ * this method must be called with the min of the two to
+ * affirm that you do not want any location checks below a certain SDK version.
+ */
+ public Builder setMinSdkVersionForEnforcement(int minSdkVersionForEnforcement) {
+ mMinSdkVersionForEnforcement = minSdkVersionForEnforcement;
+ return this;
+ }
+
+ /**
* Optional, for logging purposes only.
*/
public Builder setMethod(String method) {
@@ -161,6 +187,26 @@ public final class LocationAccessPolicy {
/** build LocationPermissionQuery */
public LocationPermissionQuery build() {
+ if (mMinSdkVersionForCoarse < 0 || mMinSdkVersionForFine < 0) {
+ throw new IllegalArgumentException("Must specify min sdk versions for"
+ + " enforcement for both coarse and fine permissions");
+ }
+ if (mMinSdkVersionForFine > Build.VERSION_CODES.BASE
+ && mMinSdkVersionForCoarse > Build.VERSION_CODES.BASE) {
+ if (mMinSdkVersionForEnforcement != Math.min(
+ mMinSdkVersionForCoarse, mMinSdkVersionForFine)) {
+ throw new IllegalArgumentException("setMinSdkVersionForEnforcement must be"
+ + " called.");
+ }
+ }
+
+ if (mMinSdkVersionForFine < mMinSdkVersionForCoarse) {
+ throw new IllegalArgumentException("Since fine location permission includes"
+ + " access to coarse location, the min sdk level for enforcement of"
+ + " the fine location permission must not be less than the min sdk"
+ + " level for enforcement of the coarse location permission.");
+ }
+
return new LocationPermissionQuery(mCallingPackage, mCallingFeatureId,
mCallingUid, mCallingPid, mMinSdkVersionForCoarse, mMinSdkVersionForFine,
mLogAsInfo, mMethod);
@@ -331,7 +377,7 @@ public final class LocationAccessPolicy {
}
private static boolean isCurrentProfile(@NonNull Context context, int uid) {
- long token = Binder.clearCallingIdentity();
+ final long token = Binder.clearCallingIdentity();
try {
if (UserHandle.getUserHandleForUid(uid).getIdentifier()
== ActivityManager.getCurrentUser()) {
diff --git a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
index d1412b772eef..8531b507a92f 100644
--- a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
+++ b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
@@ -17,6 +17,7 @@
package com.android.internal.telephony;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -25,7 +26,7 @@ import android.os.Build;
import android.os.CarrierAssociatedAppEntry;
import android.os.SystemConfigManager;
import android.os.UserHandle;
-import android.permission.PermissionManager;
+import android.permission.LegacyPermissionManager;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.util.ArrayMap;
@@ -75,7 +76,7 @@ public final class CarrierAppUtils {
* privileged apps may have changed.
*/
public static synchronized void disableCarrierAppsUntilPrivileged(String callingPackage,
- TelephonyManager telephonyManager, int userId, Context context) {
+ TelephonyManager telephonyManager, @UserIdInt int userId, Context context) {
if (DEBUG) {
Log.d(TAG, "disableCarrierAppsUntilPrivileged");
}
@@ -102,7 +103,7 @@ public final class CarrierAppUtils {
* Manager can kill it, and this can lead to crashes as the app is in an unexpected state.
*/
public static synchronized void disableCarrierAppsUntilPrivileged(String callingPackage,
- int userId, Context context) {
+ @UserIdInt int userId, Context context) {
if (DEBUG) {
Log.d(TAG, "disableCarrierAppsUntilPrivileged");
}
@@ -118,9 +119,9 @@ public final class CarrierAppUtils {
systemCarrierAssociatedAppsDisabledUntilUsed, context);
}
- private static ContentResolver getContentResolverForUser(Context context, int userId) {
- Context userContext = context.createContextAsUser(UserHandle.getUserHandleForUid(userId),
- 0);
+ private static ContentResolver getContentResolverForUser(Context context,
+ @UserIdInt int userId) {
+ Context userContext = context.createContextAsUser(UserHandle.of(userId), 0);
return userContext.getContentResolver();
}
@@ -140,8 +141,8 @@ public final class CarrierAppUtils {
Map<String, List<CarrierAssociatedAppEntry>>
systemCarrierAssociatedAppsDisabledUntilUsed, Context context) {
PackageManager packageManager = context.getPackageManager();
- PermissionManager permissionManager =
- (PermissionManager) context.getSystemService(Context.PERMISSION_SERVICE);
+ LegacyPermissionManager permissionManager = (LegacyPermissionManager)
+ context.getSystemService(Context.LEGACY_PERMISSION_SERVICE);
List<ApplicationInfo> candidates = getDefaultCarrierAppCandidatesHelper(
userId, systemCarrierAppsDisabledUntilUsed, context);
if (candidates == null || candidates.isEmpty()) {
@@ -153,7 +154,8 @@ public final class CarrierAppUtils {
List<String> enabledCarrierPackages = new ArrayList<>();
int carrierAppsHandledSdk =
- Settings.Secure.getInt(contentResolver, Settings.Secure.CARRIER_APPS_HANDLED, 0);
+ Settings.Secure.getIntForUser(contentResolver, Settings.Secure.CARRIER_APPS_HANDLED,
+ 0, contentResolver.getUserId());
if (DEBUG) {
Log.i(TAG, "Last execution SDK: " + carrierAppsHandledSdk);
}
@@ -305,8 +307,8 @@ public final class CarrierAppUtils {
// Mark the execution so we do not disable apps again on this SDK version.
if (!hasRunEver || !hasRunForSdk) {
- Settings.Secure.putInt(contentResolver, Settings.Secure.CARRIER_APPS_HANDLED,
- Build.VERSION.SDK_INT);
+ Settings.Secure.putIntForUser(contentResolver, Settings.Secure.CARRIER_APPS_HANDLED,
+ Build.VERSION.SDK_INT, contentResolver.getUserId());
}
if (!enabledCarrierPackages.isEmpty()) {
diff --git a/telephony/common/com/android/internal/telephony/SmsApplication.java b/telephony/common/com/android/internal/telephony/SmsApplication.java
index b8b60da019af..32533cbf97fb 100644
--- a/telephony/common/com/android/internal/telephony/SmsApplication.java
+++ b/telephony/common/com/android/internal/telephony/SmsApplication.java
@@ -17,8 +17,10 @@
package com.android.internal.telephony;
import android.Manifest.permission;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppOpsManager;
+import android.app.role.OnRoleHoldersChangedListener;
import android.app.role.RoleManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
@@ -38,17 +40,20 @@ import android.os.Binder;
import android.os.Build;
import android.os.Process;
import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.Telephony;
import android.provider.Telephony.Sms.Intents;
import android.telephony.PackageChangeReceiver;
import android.telephony.TelephonyManager;
import android.util.Log;
+import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
+import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
@@ -86,6 +91,8 @@ public final class SmsApplication {
private static SmsPackageMonitor sSmsPackageMonitor = null;
+ private static SmsRoleListener sSmsRoleListener = null;
+
public static class SmsApplicationData {
/**
* Name of this SMS app for display.
@@ -525,7 +532,7 @@ public final class SmsApplication {
}
private static String getDefaultSmsPackage(Context context, int userId) {
- return context.getSystemService(RoleManager.class).getDefaultSmsPackage(userId);
+ return context.getSystemService(RoleManager.class).getSmsRoleHolder(userId);
}
/**
@@ -686,7 +693,7 @@ public final class SmsApplication {
* {@link Intent#ACTION_DEFAULT_SMS_PACKAGE_CHANGED}
* {@link #ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL}
*/
- public static void broadcastSmsAppChange(Context context,
+ private static void broadcastSmsAppChange(Context context,
UserHandle userHandle, @Nullable String oldPackage, @Nullable String newPackage) {
Collection<SmsApplicationData> apps = getApplicationCollection(context);
@@ -845,9 +852,51 @@ public final class SmsApplication {
}
}
+ /**
+ * Tracks SMS role changes and sends broadcasts for default SMS app change.
+ */
+ private static final class SmsRoleListener implements OnRoleHoldersChangedListener {
+ private final Context mContext;
+ private final RoleManager mRoleManager;
+ private final SparseArray<String> mSmsPackageNames = new SparseArray<>();
+
+ public SmsRoleListener(@NonNull Context context) {
+ mContext = context;
+ mRoleManager = context.getSystemService(RoleManager.class);
+ final List<UserHandle> users = context.getSystemService(UserManager.class)
+ .getUserHandles(true);
+ final int usersSize = users.size();
+ for (int i = 0; i < usersSize; i++) {
+ final UserHandle user = users.get(i);
+ mSmsPackageNames.put(user.getIdentifier(), getSmsPackageName(user));
+ }
+ mRoleManager.addOnRoleHoldersChangedListenerAsUser(context.getMainExecutor(), this,
+ UserHandle.ALL);
+ }
+
+ @Override
+ public void onRoleHoldersChanged(@NonNull String roleName, @NonNull UserHandle user) {
+ if (!Objects.equals(roleName, RoleManager.ROLE_SMS)) {
+ return;
+ }
+ final int userId = user.getIdentifier();
+ final String newSmsPackageName = getSmsPackageName(user);
+ broadcastSmsAppChange(mContext, user, mSmsPackageNames.get(userId), newSmsPackageName);
+ mSmsPackageNames.put(userId, newSmsPackageName);
+ }
+
+ @Nullable
+ private String getSmsPackageName(@NonNull UserHandle user) {
+ final List<String> roleHolders = mRoleManager.getRoleHoldersAsUser(
+ RoleManager.ROLE_SMS, user);
+ return !roleHolders.isEmpty() ? roleHolders.get(0) : null;
+ }
+ }
+
public static void initSmsPackageMonitor(Context context) {
sSmsPackageMonitor = new SmsPackageMonitor(context);
sSmsPackageMonitor.register(context, context.getMainLooper(), UserHandle.ALL);
+ sSmsRoleListener = new SmsRoleListener(context);
}
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
index 38fa9077f188..5e50bea05057 100644
--- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
@@ -27,7 +27,7 @@ import android.os.Binder;
import android.os.Build;
import android.os.Process;
import android.os.UserHandle;
-import android.permission.PermissionManager;
+import android.permission.LegacyPermissionManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.Log;
@@ -244,7 +244,9 @@ public final class TelephonyPermissions {
* <ul>
* <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling
* package passes a DevicePolicyManager Device Owner / Profile Owner device identifier
- * access check, or the calling package has carrier privileges on any active subscription.
+ * access check, or the calling package has carrier privileges on any active
+ * subscription, or the calling package has the {@link
+ * Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} appop permission.
* <li>throw SecurityException: if the caller does not meet any of the requirements and is
* targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission
* or carrier privileges of any active subscription.
@@ -256,6 +258,10 @@ public final class TelephonyPermissions {
*/
public static boolean checkCallingOrSelfReadDeviceIdentifiers(Context context, int subId,
String callingPackage, @Nullable String callingFeatureId, String message) {
+ if (checkCallingOrSelfUseIccAuthWithDeviceIdentifier(context, callingPackage,
+ callingFeatureId, message)) {
+ return true;
+ }
return checkPrivilegedReadPermissionOrCarrierPrivilegePermission(
context, subId, callingPackage, callingFeatureId, message, true);
}
@@ -267,7 +273,9 @@ public final class TelephonyPermissions {
* <ul>
* <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling
* package passes a DevicePolicyManager Device Owner / Profile Owner device identifier
- * access check, or the calling package has carrier privileges on specified subscription.
+ * access check, or the calling package has carrier privileges on specified subscription,
+ * or the calling package has the {@link
+ * Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} appop permission.
* <li>throw SecurityException: if the caller does not meet any of the requirements and is
* targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission.
* <li>return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE
@@ -278,6 +286,10 @@ public final class TelephonyPermissions {
*/
public static boolean checkCallingOrSelfReadSubscriberIdentifiers(Context context, int subId,
String callingPackage, @Nullable String callingFeatureId, String message) {
+ if (checkCallingOrSelfUseIccAuthWithDeviceIdentifier(context, callingPackage,
+ callingFeatureId, message)) {
+ return true;
+ }
return checkPrivilegedReadPermissionOrCarrierPrivilegePermission(
context, subId, callingPackage, callingFeatureId, message, false);
}
@@ -315,8 +327,8 @@ public final class TelephonyPermissions {
return true;
}
- PermissionManager permissionManager = (PermissionManager) context.getSystemService(
- Context.PERMISSION_SERVICE);
+ LegacyPermissionManager permissionManager = (LegacyPermissionManager)
+ context.getSystemService(Context.LEGACY_PERMISSION_SERVICE);
if (permissionManager.checkDeviceIdentifierAccess(callingPackage, message, callingFeatureId,
pid, uid) == PackageManager.PERMISSION_GRANTED) {
return true;
@@ -385,6 +397,40 @@ public final class TelephonyPermissions {
}
/**
+ * Check whether the caller (or self, if not processing an IPC) has {@link
+ * Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} AppOp permission.
+ *
+ * <p>With the permission, the caller can access device/subscriber identifiers and use ICC
+ * authentication like EAP-AKA.
+ */
+ public static boolean checkCallingOrSelfUseIccAuthWithDeviceIdentifier(Context context,
+ String callingPackage, String callingFeatureId, String message) {
+ // The implementation follows PermissionChecker.checkAppOpPermission, but it cannot be
+ // used directly: because it uses noteProxyOpNoThrow which requires the phone process
+ // having the permission, which doesn't make sense since phone process is the ower of
+ // data/action.
+ // Cannot perform appop check if the calling package is null
+ if (callingPackage == null) {
+ return false;
+ }
+ int callingUid = Binder.getCallingUid();
+ AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+ int opMode = appOps.noteOpNoThrow(AppOpsManager.OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER,
+ callingUid, callingPackage, callingFeatureId, message);
+ switch (opMode) {
+ case AppOpsManager.MODE_ALLOWED:
+ case AppOpsManager.MODE_FOREGROUND:
+ return true;
+ case AppOpsManager.MODE_DEFAULT:
+ return context.checkCallingOrSelfPermission(
+ Manifest.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER)
+ == PERMISSION_GRANTED;
+ default:
+ return false;
+ }
+ }
+
+ /**
* 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.
diff --git a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
index 02d741011220..125296540688 100644
--- a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
+++ b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
@@ -99,7 +99,7 @@ public final class TelephonyUtils {
*/
public static void runWithCleanCallingIdentity(
@NonNull Runnable action) {
- long callingIdentity = Binder.clearCallingIdentity();
+ final long callingIdentity = Binder.clearCallingIdentity();
try {
action.run();
} finally {
@@ -118,7 +118,7 @@ public final class TelephonyUtils {
*/
public static <T> T runWithCleanCallingIdentity(
@NonNull Supplier<T> action) {
- long callingIdentity = Binder.clearCallingIdentity();
+ final long callingIdentity = Binder.clearCallingIdentity();
try {
return action.get();
} finally {