diff options
author | Xin Li <delphij@google.com> | 2020-08-31 21:21:38 -0700 |
---|---|---|
committer | Xin Li <delphij@google.com> | 2020-08-31 21:21:38 -0700 |
commit | 628590d7ec80e10a3fc24b1c18a1afb55cca10a8 (patch) | |
tree | 4b1c3f52d86d7fb53afbe9e9438468588fa489f8 /telephony/common | |
parent | b11b8ec3aec8bb42f2c07e1c5ac7942da293baa8 (diff) | |
parent | d2d3a20624d968199353ccf6ddbae6f3ac39c9af (diff) |
Merge Android R (rvc-dev-plus-aosp-without-vendor@6692709)
Bug: 166295507
Merged-In: I3d92a6de21a938f6b352ec26dc23420c0fe02b27
Change-Id: Ifdb80563ef042738778ebb8a7581a97c4e3d96e2
Diffstat (limited to 'telephony/common')
6 files changed, 285 insertions, 262 deletions
diff --git a/telephony/common/android/telephony/LocationAccessPolicy.java b/telephony/common/android/telephony/LocationAccessPolicy.java index 892e55942d3f..1985f7810873 100644 --- a/telephony/common/android/telephony/LocationAccessPolicy.java +++ b/telephony/common/android/telephony/LocationAccessPolicy.java @@ -24,20 +24,16 @@ import android.app.ActivityManager; import android.app.AppOpsManager; import android.content.Context; import android.content.pm.PackageManager; -import android.content.pm.UserInfo; import android.location.LocationManager; import android.os.Binder; import android.os.Build; import android.os.Process; import android.os.UserHandle; -import android.os.UserManager; import android.util.Log; import android.widget.Toast; import com.android.internal.telephony.util.TelephonyUtils; -import java.util.List; - /** * Helper for performing location access checks. * @hide @@ -111,6 +107,9 @@ public final class LocationAccessPolicy { return this; } + /** + * Mandatory parameter, used for performing permission checks. + */ public Builder setCallingUid(int callingUid) { mCallingUid = callingUid; return this; @@ -195,6 +194,17 @@ public final class LocationAccessPolicy { } } + private static String getAppOpsString(String manifestPermission) { + switch (manifestPermission) { + case Manifest.permission.ACCESS_FINE_LOCATION: + return AppOpsManager.OPSTR_FINE_LOCATION; + case Manifest.permission.ACCESS_COARSE_LOCATION: + return AppOpsManager.OPSTR_COARSE_LOCATION; + default: + return null; + } + } + private static LocationPermissionResult checkAppLocationPermissionHelper(Context context, LocationPermissionQuery query, String permissionToCheck) { String locationTypeForLog = @@ -208,8 +218,8 @@ public final class LocationAccessPolicy { if (hasManifestPermission) { // Only check the app op if the app has the permission. int appOpMode = context.getSystemService(AppOpsManager.class) - .noteOpNoThrow(AppOpsManager.permissionToOpCode(permissionToCheck), - query.callingUid, query.callingPackage); + .noteOpNoThrow(getAppOpsString(permissionToCheck), query.callingUid, + query.callingPackage, query.callingFeatureId, null); if (appOpMode == AppOpsManager.MODE_ALLOWED) { // If the app did everything right, return without logging. return LocationPermissionResult.ALLOWED; @@ -295,7 +305,7 @@ public final class LocationAccessPolicy { } private static boolean checkSystemLocationAccess(@NonNull Context context, int uid, int pid) { - if (!isLocationModeEnabled(context, UserHandle.getUserId(uid))) { + if (!isLocationModeEnabled(context, UserHandle.getUserHandleForUid(uid).getIdentifier())) { if (DBG) Log.w(TAG, "Location disabled, failed, (" + uid + ")"); return false; } @@ -322,20 +332,17 @@ public final class LocationAccessPolicy { private static boolean isCurrentProfile(@NonNull Context context, int uid) { long token = Binder.clearCallingIdentity(); try { - final int currentUser = ActivityManager.getCurrentUser(); - final int callingUserId = UserHandle.getUserId(uid); - if (callingUserId == currentUser) { + if (UserHandle.getUserHandleForUid(uid).getIdentifier() + == ActivityManager.getCurrentUser()) { return true; + } + ActivityManager activityManager = context.getSystemService(ActivityManager.class); + if (activityManager != null) { + return activityManager.isProfileForeground( + UserHandle.getUserHandleForUid(ActivityManager.getCurrentUser())); } else { - List<UserInfo> userProfiles = context.getSystemService( - UserManager.class).getProfiles(currentUser); - for (UserInfo user : userProfiles) { - if (user.id == callingUserId) { - return true; - } - } + return false; } - return false; } finally { Binder.restoreCallingIdentity(token); } diff --git a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java index 4af19b5489ca..e57b03098758 100644 --- a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java +++ b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java @@ -20,25 +20,23 @@ import android.annotation.Nullable; import android.content.ContentResolver; import android.content.Context; import android.content.pm.ApplicationInfo; -import android.content.pm.IPackageManager; import android.content.pm.PackageManager; -import android.content.res.Resources; -import android.os.RemoteException; +import android.os.Build; +import android.os.CarrierAssociatedAppEntry; +import android.os.SystemConfigManager; import android.os.UserHandle; +import android.permission.PermissionManager; import android.provider.Settings; import android.telephony.TelephonyManager; import android.util.ArrayMap; -import android.util.ArraySet; import android.util.Log; -import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.telephony.util.ArrayUtils; -import com.android.server.SystemConfig; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Set; /** * Utilities for handling carrier applications. @@ -55,19 +53,19 @@ public final class CarrierAppUtils { * Handle preinstalled carrier apps which should be disabled until a matching SIM is inserted. * * Evaluates the list of applications in - * {@link SystemConfig#getDisabledUntilUsedPreinstalledCarrierApps()}. We want to disable each - * such application which is present on the system image until the user inserts a SIM which - * causes that application to gain carrier privilege (indicating a "match"), without interfering - * with the user if they opt to enable/disable the app explicitly. + * {@link SystemConfigManager#getDisabledUntilUsedPreinstalledCarrierApps()}. We want to disable + * each such application which is present on the system image until the user inserts a SIM + * which causes that application to gain carrier privilege (indicating a "match"), without + * interfering with the user if they opt to enable/disable the app explicitly. * * So, for each such app, we either disable until used IFF the app is not carrier privileged AND * in the default state (e.g. not explicitly DISABLED/DISABLED_BY_USER/ENABLED), or we enable if * the app is carrier privileged and in either the default state or DISABLED_UNTIL_USED. * * In addition, there is a list of carrier-associated applications in - * {@link SystemConfig#getDisabledUntilUsedPreinstalledCarrierAssociatedApps}. Each app in this - * list is associated with a carrier app. When the given carrier app is enabled/disabled per the - * above, the associated applications are enabled/disabled to match. + * {@link SystemConfigManager#getDisabledUntilUsedPreinstalledCarrierAssociatedApps}. Each app + * in this list is associated with a carrier app. When the given carrier app is enabled/disabled + * per the above, the associated applications are enabled/disabled to match. * * When enabling a carrier app we also grant it default permissions. * @@ -76,25 +74,24 @@ public final class CarrierAppUtils { * privileged apps may have changed. */ public static synchronized void disableCarrierAppsUntilPrivileged(String callingPackage, - IPackageManager packageManager, TelephonyManager telephonyManager, - int userId, Context context) { + TelephonyManager telephonyManager, int userId, Context context) { if (DEBUG) { Log.d(TAG, "disableCarrierAppsUntilPrivileged"); } - SystemConfig config = SystemConfig.getInstance(); - ArraySet<String> systemCarrierAppsDisabledUntilUsed = + SystemConfigManager config = context.getSystemService(SystemConfigManager.class); + Set<String> systemCarrierAppsDisabledUntilUsed = config.getDisabledUntilUsedPreinstalledCarrierApps(); - ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed = - config.getDisabledUntilUsedPreinstalledCarrierAssociatedApps(); + Map<String, List<CarrierAssociatedAppEntry>> systemCarrierAssociatedAppsDisabledUntilUsed = + config.getDisabledUntilUsedPreinstalledCarrierAssociatedAppEntries(); ContentResolver contentResolver = getContentResolverForUser(context, userId); - disableCarrierAppsUntilPrivileged(callingPackage, packageManager, telephonyManager, - contentResolver, userId, systemCarrierAppsDisabledUntilUsed, - systemCarrierAssociatedAppsDisabledUntilUsed); + disableCarrierAppsUntilPrivileged(callingPackage, telephonyManager, contentResolver, + userId, systemCarrierAppsDisabledUntilUsed, + systemCarrierAssociatedAppsDisabledUntilUsed, context); } /** - * Like {@link #disableCarrierAppsUntilPrivileged(String, IPackageManager, TelephonyManager, - * ContentResolver, int)}, but assumes that no carrier apps have carrier privileges. + * Like {@link #disableCarrierAppsUntilPrivileged(String, TelephonyManager, int, Context)}, + * but assumes that no carrier apps have carrier privileges. * * This prevents a potential race condition on first boot - since the app's default state is * enabled, we will initially disable it when the telephony stack is first initialized as it has @@ -104,21 +101,20 @@ 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, - IPackageManager packageManager, int userId, Context context) { + int userId, Context context) { if (DEBUG) { Log.d(TAG, "disableCarrierAppsUntilPrivileged"); } - SystemConfig config = SystemConfig.getInstance(); - ArraySet<String> systemCarrierAppsDisabledUntilUsed = + SystemConfigManager config = context.getSystemService(SystemConfigManager.class); + Set<String> systemCarrierAppsDisabledUntilUsed = config.getDisabledUntilUsedPreinstalledCarrierApps(); - - ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed = - config.getDisabledUntilUsedPreinstalledCarrierAssociatedApps(); + Map<String, List<CarrierAssociatedAppEntry>> systemCarrierAssociatedAppsDisabledUntilUsed = + config.getDisabledUntilUsedPreinstalledCarrierAssociatedAppEntries(); ContentResolver contentResolver = getContentResolverForUser(context, userId); - disableCarrierAppsUntilPrivileged(callingPackage, packageManager, - null /* telephonyManager */, contentResolver, userId, - systemCarrierAppsDisabledUntilUsed, systemCarrierAssociatedAppsDisabledUntilUsed); + disableCarrierAppsUntilPrivileged(callingPackage, null /* telephonyManager */, + contentResolver, userId, systemCarrierAppsDisabledUntilUsed, + systemCarrierAssociatedAppsDisabledUntilUsed, context); } private static ContentResolver getContentResolverForUser(Context context, int userId) { @@ -142,49 +138,51 @@ public final class CarrierAppUtils { // Must be public b/c framework unit tests can't access package-private methods. @VisibleForTesting public static void disableCarrierAppsUntilPrivileged(String callingPackage, - IPackageManager packageManager, @Nullable TelephonyManager telephonyManager, - ContentResolver contentResolver, int userId, - ArraySet<String> systemCarrierAppsDisabledUntilUsed, - ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed) { + @Nullable TelephonyManager telephonyManager, ContentResolver contentResolver, + int userId, Set<String> systemCarrierAppsDisabledUntilUsed, + Map<String, List<CarrierAssociatedAppEntry>> + systemCarrierAssociatedAppsDisabledUntilUsed, Context context) { + PackageManager packageManager = context.getPackageManager(); + PermissionManager permissionManager = + (PermissionManager) context.getSystemService(Context.PERMISSION_SERVICE); List<ApplicationInfo> candidates = getDefaultCarrierAppCandidatesHelper( - packageManager, userId, systemCarrierAppsDisabledUntilUsed); + userId, systemCarrierAppsDisabledUntilUsed, context); if (candidates == null || candidates.isEmpty()) { return; } - Map<String, List<ApplicationInfo>> associatedApps = getDefaultCarrierAssociatedAppsHelper( - packageManager, - userId, - systemCarrierAssociatedAppsDisabledUntilUsed); + Map<String, List<AssociatedAppInfo>> associatedApps = getDefaultCarrierAssociatedAppsHelper( + userId, systemCarrierAssociatedAppsDisabledUntilUsed, context); List<String> enabledCarrierPackages = new ArrayList<>(); - boolean hasRunOnce = Settings.Secure.getInt(contentResolver, - Settings.Secure.CARRIER_APPS_HANDLED, 0) == 1; + int carrierAppsHandledSdk = + Settings.Secure.getInt(contentResolver, Settings.Secure.CARRIER_APPS_HANDLED, 0); + if (DEBUG) { + Log.i(TAG, "Last execution SDK: " + carrierAppsHandledSdk); + } + boolean hasRunEver = carrierAppsHandledSdk != 0; // SDKs < R used to just set 1 here + boolean hasRunForSdk = carrierAppsHandledSdk == Build.VERSION.SDK_INT; try { for (ApplicationInfo ai : candidates) { String packageName = ai.packageName; - String[] restrictedCarrierApps = Resources.getSystem().getStringArray( - R.array.config_restrictedPreinstalledCarrierApps); boolean hasPrivileges = telephonyManager != null && telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName) - == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS - && !ArrayUtils.contains(restrictedCarrierApps, packageName); + == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; // add hiddenUntilInstalled flag for carrier apps and associated apps - packageManager.setSystemAppHiddenUntilInstalled(packageName, true); - List<ApplicationInfo> associatedAppList = associatedApps.get(packageName); + packageManager.setSystemAppState( + packageName, PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN); + List<AssociatedAppInfo> associatedAppList = associatedApps.get(packageName); if (associatedAppList != null) { - for (ApplicationInfo associatedApp : associatedAppList) { - packageManager.setSystemAppHiddenUntilInstalled( - associatedApp.packageName, - true - ); + for (AssociatedAppInfo associatedApp : associatedAppList) { + packageManager.setSystemAppState(associatedApp.appInfo.packageName, + PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN); } } - int enabledSetting = packageManager.getApplicationEnabledSetting(packageName, - userId); + int enabledSetting = context.createContextAsUser(UserHandle.of(userId), 0) + .getPackageManager().getApplicationEnabledSetting(packageName); if (hasPrivileges) { // Only update enabled state for the app on /system. Once it has been // updated we shouldn't touch it. @@ -193,44 +191,55 @@ public final class CarrierAppUtils { || enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED || (ai.flags & ApplicationInfo.FLAG_INSTALLED) == 0) { - Log.i(TAG, "Update state(" + packageName + "): ENABLED for user " + Log.i(TAG, "Update state (" + packageName + "): ENABLED for user " + userId); - packageManager.setSystemAppInstallState( - packageName, - true /*installed*/, - userId); - packageManager.setApplicationEnabledSetting( - packageName, - PackageManager.COMPONENT_ENABLED_STATE_ENABLED, - PackageManager.DONT_KILL_APP, - userId, - callingPackage); + context.createContextAsUser(UserHandle.of(userId), 0) + .getPackageManager() + .setSystemAppState( + packageName, PackageManager.SYSTEM_APP_STATE_INSTALLED); + context.createPackageContextAsUser(callingPackage, 0, UserHandle.of(userId)) + .getPackageManager() + .setApplicationEnabledSetting( + packageName, + PackageManager.COMPONENT_ENABLED_STATE_ENABLED, + PackageManager.DONT_KILL_APP); } // Also enable any associated apps for this carrier app. if (associatedAppList != null) { - for (ApplicationInfo associatedApp : associatedAppList) { - int associatedAppEnabledSetting = - packageManager.getApplicationEnabledSetting( - associatedApp.packageName, userId); + for (AssociatedAppInfo associatedApp : associatedAppList) { + int associatedAppEnabledSetting = context + .createContextAsUser(UserHandle.of(userId), 0) + .getPackageManager() + .getApplicationEnabledSetting( + associatedApp.appInfo.packageName); + boolean associatedAppInstalled = (associatedApp.appInfo.flags + & ApplicationInfo.FLAG_INSTALLED) != 0; + if (DEBUG) { + Log.i(TAG, "(hasPrivileges) associated app " + + associatedApp.appInfo.packageName + ", enabled = " + + associatedAppEnabledSetting + ", installed = " + + associatedAppInstalled); + } if (associatedAppEnabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT || associatedAppEnabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED - || (associatedApp.flags - & ApplicationInfo.FLAG_INSTALLED) == 0) { - Log.i(TAG, "Update associated state(" + associatedApp.packageName - + "): ENABLED for user " + userId); - packageManager.setSystemAppInstallState( - associatedApp.packageName, - true /*installed*/, - userId); - packageManager.setApplicationEnabledSetting( - associatedApp.packageName, - PackageManager.COMPONENT_ENABLED_STATE_ENABLED, - PackageManager.DONT_KILL_APP, - userId, - callingPackage); + || !associatedAppInstalled) { + Log.i(TAG, "Update associated state (" + + associatedApp.appInfo.packageName + "): ENABLED for user " + + userId); + context.createContextAsUser(UserHandle.of(userId), 0) + .getPackageManager() + .setSystemAppState(associatedApp.appInfo.packageName, + PackageManager.SYSTEM_APP_STATE_INSTALLED); + context.createPackageContextAsUser( + callingPackage, 0, UserHandle.of(userId)) + .getPackageManager() + .setApplicationEnabledSetting( + associatedApp.appInfo.packageName, + PackageManager.COMPONENT_ENABLED_STATE_ENABLED, + PackageManager.DONT_KILL_APP); } } } @@ -243,44 +252,64 @@ public final class CarrierAppUtils { if (!isUpdatedSystemApp(ai) && enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT && (ai.flags & ApplicationInfo.FLAG_INSTALLED) != 0) { - Log.i(TAG, "Update state(" + packageName + Log.i(TAG, "Update state (" + packageName + "): DISABLED_UNTIL_USED for user " + userId); - packageManager.setSystemAppInstallState( - packageName, - false /*installed*/, - userId); + context.createContextAsUser(UserHandle.of(userId), 0) + .getPackageManager() + .setSystemAppState( + packageName, PackageManager.SYSTEM_APP_STATE_UNINSTALLED); } - // Also disable any associated apps for this carrier app if this is the first - // run. We avoid doing this a second time because it is brittle to rely on the - // distinction between "default" and "enabled". - if (!hasRunOnce) { - if (associatedAppList != null) { - for (ApplicationInfo associatedApp : associatedAppList) { - int associatedAppEnabledSetting = - packageManager.getApplicationEnabledSetting( - associatedApp.packageName, userId); - if (associatedAppEnabledSetting - == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT - && (associatedApp.flags - & ApplicationInfo.FLAG_INSTALLED) != 0) { - Log.i(TAG, - "Update associated state(" + associatedApp.packageName - + "): DISABLED_UNTIL_USED for user " + userId); - packageManager.setSystemAppInstallState( - associatedApp.packageName, - false /*installed*/, - userId); - } + // Associated apps are more brittle, because we can't rely on the distinction + // between "default" and "enabled". To account for this, we have two cases: + // 1. We've never run before, so we're fine to disable all associated apps. + // 2. We've run before, but not on this SDK version, so we will only operate on + // apps with addedInSdk in the range (lastHandledSdk, currentSdk]. + // Otherwise, don't touch the associated apps. + if (associatedAppList != null) { + for (AssociatedAppInfo associatedApp : associatedAppList) { + boolean allowDisable = !hasRunEver || (!hasRunForSdk + && associatedApp.addedInSdk + != CarrierAssociatedAppEntry.SDK_UNSPECIFIED + && associatedApp.addedInSdk > carrierAppsHandledSdk + && associatedApp.addedInSdk <= Build.VERSION.SDK_INT); + int associatedAppEnabledSetting = context + .createContextAsUser(UserHandle.of(userId), 0) + .getPackageManager() + .getApplicationEnabledSetting( + associatedApp.appInfo.packageName); + boolean associatedAppInstalled = (associatedApp.appInfo.flags + & ApplicationInfo.FLAG_INSTALLED) != 0; + if (DEBUG) { + Log.i(TAG, "(!hasPrivileges) associated app " + + associatedApp.appInfo.packageName + ", allowDisable = " + + allowDisable + ", addedInSdk = " + + associatedApp.addedInSdk + ", enabled = " + + associatedAppEnabledSetting + ", installed = " + + associatedAppInstalled); + } + if (allowDisable + && associatedAppEnabledSetting + == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT + && associatedAppInstalled) { + Log.i(TAG, + "Update associated state (" + + associatedApp.appInfo.packageName + + "): DISABLED_UNTIL_USED for user " + userId); + context.createContextAsUser(UserHandle.of(userId), 0) + .getPackageManager() + .setSystemAppState(associatedApp.appInfo.packageName, + PackageManager.SYSTEM_APP_STATE_UNINSTALLED); } } } } } - // Mark the execution so we do not disable apps again. - if (!hasRunOnce) { - Settings.Secure.putInt(contentResolver, Settings.Secure.CARRIER_APPS_HANDLED, 1); + // 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); } if (!enabledCarrierPackages.isEmpty()) { @@ -288,9 +317,10 @@ public final class CarrierAppUtils { // apps. String[] packageNames = new String[enabledCarrierPackages.size()]; enabledCarrierPackages.toArray(packageNames); - packageManager.grantDefaultPermissionsToEnabledCarrierApps(packageNames, userId); + permissionManager.grantDefaultPermissionsToEnabledCarrierApps(packageNames, + UserHandle.of(userId), Runnable::run, isSuccess -> { }); } - } catch (RemoteException e) { + } catch (PackageManager.NameNotFoundException e) { Log.w(TAG, "Could not reach PackageManager", e); } } @@ -299,13 +329,13 @@ public final class CarrierAppUtils { * Returns the list of "default" carrier apps. * * This is the subset of apps returned by - * {@link #getDefaultCarrierAppCandidates(IPackageManager, int)} which currently have carrier + * {@link #getDefaultCarrierAppCandidates(int, Context)} which currently have carrier * privileges per the SIM(s) inserted in the device. */ - public static List<ApplicationInfo> getDefaultCarrierApps(IPackageManager packageManager, - TelephonyManager telephonyManager, int userId) { + public static List<ApplicationInfo> getDefaultCarrierApps( + TelephonyManager telephonyManager, int userId, Context context) { // Get all system apps from the default list. - List<ApplicationInfo> candidates = getDefaultCarrierAppCandidates(packageManager, userId); + List<ApplicationInfo> candidates = getDefaultCarrierAppCandidates(userId, context); if (candidates == null || candidates.isEmpty()) { return null; } @@ -331,39 +361,33 @@ public final class CarrierAppUtils { * Returns the list of "default" carrier app candidates. * * These are the apps subject to the hiding/showing logic in - * {@link CarrierAppUtils#disableCarrierAppsUntilPrivileged(String, IPackageManager, - * TelephonyManager, ContentResolver, int)}, as well as the apps which should have default + * {@link CarrierAppUtils#disableCarrierAppsUntilPrivileged(String, TelephonyManager, int, + * Context)}, as well as the apps which should have default * permissions granted, when a matching SIM is inserted. * * Whether or not the app is actually considered a default app depends on whether the app has * carrier privileges as determined by the SIMs in the device. */ public static List<ApplicationInfo> getDefaultCarrierAppCandidates( - IPackageManager packageManager, int userId) { - ArraySet<String> systemCarrierAppsDisabledUntilUsed = - SystemConfig.getInstance().getDisabledUntilUsedPreinstalledCarrierApps(); - return getDefaultCarrierAppCandidatesHelper(packageManager, userId, - systemCarrierAppsDisabledUntilUsed); + int userId, Context context) { + Set<String> systemCarrierAppsDisabledUntilUsed = + context.getSystemService(SystemConfigManager.class) + .getDisabledUntilUsedPreinstalledCarrierApps(); + return getDefaultCarrierAppCandidatesHelper(userId, systemCarrierAppsDisabledUntilUsed, + context); } private static List<ApplicationInfo> getDefaultCarrierAppCandidatesHelper( - IPackageManager packageManager, - int userId, - ArraySet<String> systemCarrierAppsDisabledUntilUsed) { - if (systemCarrierAppsDisabledUntilUsed == null) { - return null; - } - - int size = systemCarrierAppsDisabledUntilUsed.size(); - if (size == 0) { + int userId, Set<String> systemCarrierAppsDisabledUntilUsed, Context context) { + if (systemCarrierAppsDisabledUntilUsed == null + || systemCarrierAppsDisabledUntilUsed.isEmpty()) { return null; } - List<ApplicationInfo> apps = new ArrayList<>(size); - for (int i = 0; i < size; i++) { - String packageName = systemCarrierAppsDisabledUntilUsed.valueAt(i); + List<ApplicationInfo> apps = new ArrayList<>(systemCarrierAppsDisabledUntilUsed.size()); + for (String packageName : systemCarrierAppsDisabledUntilUsed) { ApplicationInfo ai = - getApplicationInfoIfSystemApp(packageManager, userId, packageName); + getApplicationInfoIfSystemApp(userId, packageName, context); if (ai != null) { apps.add(ai); } @@ -371,29 +395,28 @@ public final class CarrierAppUtils { return apps; } - private static Map<String, List<ApplicationInfo>> getDefaultCarrierAssociatedAppsHelper( - IPackageManager packageManager, - int userId, - ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed) { + private static Map<String, List<AssociatedAppInfo>> getDefaultCarrierAssociatedAppsHelper( + int userId, Map<String, List<CarrierAssociatedAppEntry>> + systemCarrierAssociatedAppsDisabledUntilUsed, Context context) { int size = systemCarrierAssociatedAppsDisabledUntilUsed.size(); - Map<String, List<ApplicationInfo>> associatedApps = new ArrayMap<>(size); - for (int i = 0; i < size; i++) { - String carrierAppPackage = systemCarrierAssociatedAppsDisabledUntilUsed.keyAt(i); - List<String> associatedAppPackages = - systemCarrierAssociatedAppsDisabledUntilUsed.valueAt(i); + Map<String, List<AssociatedAppInfo>> associatedApps = new ArrayMap<>(size); + for (Map.Entry<String, List<CarrierAssociatedAppEntry>> entry + : systemCarrierAssociatedAppsDisabledUntilUsed.entrySet()) { + String carrierAppPackage = entry.getKey(); + List<CarrierAssociatedAppEntry> associatedAppPackages = entry.getValue(); for (int j = 0; j < associatedAppPackages.size(); j++) { + CarrierAssociatedAppEntry associatedApp = associatedAppPackages.get(j); ApplicationInfo ai = - getApplicationInfoIfSystemApp( - packageManager, userId, associatedAppPackages.get(j)); + getApplicationInfoIfSystemApp(userId, associatedApp.packageName, context); // Only update enabled state for the app on /system. Once it has been updated we // shouldn't touch it. if (ai != null && !isUpdatedSystemApp(ai)) { - List<ApplicationInfo> appList = associatedApps.get(carrierAppPackage); + List<AssociatedAppInfo> appList = associatedApps.get(carrierAppPackage); if (appList == null) { appList = new ArrayList<>(); associatedApps.put(carrierAppPackage, appList); } - appList.add(ai); + appList.add(new AssociatedAppInfo(ai, associatedApp.addedInSdk)); } } } @@ -402,20 +425,31 @@ public final class CarrierAppUtils { @Nullable private static ApplicationInfo getApplicationInfoIfSystemApp( - IPackageManager packageManager, - int userId, - String packageName) { + int userId, String packageName, Context context) { try { - ApplicationInfo ai = packageManager.getApplicationInfo(packageName, - PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS - | PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS - | PackageManager.MATCH_SYSTEM_ONLY, userId); + ApplicationInfo ai = context.createContextAsUser(UserHandle.of(userId), 0) + .getPackageManager() + .getApplicationInfo(packageName, + PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS + | PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS + | PackageManager.MATCH_SYSTEM_ONLY); if (ai != null) { return ai; } - } catch (RemoteException e) { + } catch (PackageManager.NameNotFoundException e) { Log.w(TAG, "Could not reach PackageManager", e); } return null; } + + private static final class AssociatedAppInfo { + public final ApplicationInfo appInfo; + // Might be CarrierAssociatedAppEntry.SDK_UNSPECIFIED. + public final int addedInSdk; + + AssociatedAppInfo(ApplicationInfo appInfo, int addedInSdk) { + this.appInfo = appInfo; + this.addedInSdk = addedInSdk; + } + } } diff --git a/telephony/common/com/android/internal/telephony/GsmAlphabet.java b/telephony/common/com/android/internal/telephony/GsmAlphabet.java index 60cd40094950..5c53f7e5a4d0 100644 --- a/telephony/common/com/android/internal/telephony/GsmAlphabet.java +++ b/telephony/common/com/android/internal/telephony/GsmAlphabet.java @@ -40,6 +40,8 @@ import java.util.List; public class GsmAlphabet { private static final String TAG = "GSM"; + private GsmAlphabet() { } + /** * This escapes extended characters, and when present indicates that the * following character should be looked up in the "extended" table. diff --git a/telephony/common/com/android/internal/telephony/SmsApplication.java b/telephony/common/com/android/internal/telephony/SmsApplication.java index d69282579b77..b35b3236afc6 100644 --- a/telephony/common/com/android/internal/telephony/SmsApplication.java +++ b/telephony/common/com/android/internal/telephony/SmsApplication.java @@ -35,13 +35,11 @@ import android.content.pm.ServiceInfo; import android.net.Uri; import android.os.AsyncTask; import android.os.Binder; -import android.os.Debug; import android.os.Process; import android.os.UserHandle; import android.provider.Telephony; import android.provider.Telephony.Sms.Intents; import android.telephony.PackageChangeReceiver; -import android.util.Log; import android.telephony.TelephonyManager; import android.util.Log; @@ -57,7 +55,6 @@ import java.util.concurrent.TimeoutException; import java.util.function.Consumer; import java.util.stream.Collectors; - /** * Class for managing the primary application that we will deliver SMS/MMS messages to * @@ -197,13 +194,13 @@ public final class SmsApplication { final int callingUid = Binder.getCallingUid(); if (DEBUG_MULTIUSER) { Log.i(LOG_TAG, "getIncomingUserHandle caller=" + callingUid + ", myuid=" - + android.os.Process.myUid() + "\n\t" + Debug.getCallers(4)); + + android.os.Process.myUid()); } if (UserHandle.getAppId(callingUid) < android.os.Process.FIRST_APPLICATION_UID) { return contextUserId; } else { - return UserHandle.getUserId(callingUid); + return UserHandle.getUserHandleForUid(callingUid).getIdentifier(); } } @@ -429,9 +426,6 @@ public final class SmsApplication { final SmsApplicationData smsApplicationData = receivers.get(packageName); if (smsApplicationData != null) { if (!smsApplicationData.isComplete()) { - Log.w(LOG_TAG, "Package " + packageName - + " lacks required manifest declarations to be a default sms app: " - + smsApplicationData); receivers.remove(packageName); } } @@ -675,9 +669,21 @@ public final class SmsApplication { } /** + * Broadcast action: + * Same as {@link Intent#ACTION_DEFAULT_SMS_PACKAGE_CHANGED} but it's implicit (e.g. sent to + * all apps) and requires + * {@link #PERMISSION_MONITOR_DEFAULT_SMS_PACKAGE} to receive. + */ + public static final String ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL = + "android.provider.action.DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL"; + + public static final String PERMISSION_MONITOR_DEFAULT_SMS_PACKAGE = + "android.permission.MONITOR_DEFAULT_SMS_PACKAGE"; + + /** * Sends broadcasts on sms app change: * {@link Intent#ACTION_DEFAULT_SMS_PACKAGE_CHANGED} - * {@link Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL} + * {@link #ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL} */ public static void broadcastSmsAppChange(Context context, UserHandle userHandle, @Nullable String oldPackage, @Nullable String newPackage) { @@ -727,11 +733,11 @@ public final class SmsApplication { } // Send an implicit broadcast for the system server. - // (or anyone with MONITOR_DEFAULT_SMS_PACKAGE, really.) + // (or anyone with PERMISSION_MONITOR_DEFAULT_SMS_PACKAGE, really.) final Intent intent = - new Intent(Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL); + new Intent(ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL); context.sendBroadcastAsUser(intent, userHandle, - permission.MONITOR_DEFAULT_SMS_PACKAGE); + PERMISSION_MONITOR_DEFAULT_SMS_PACKAGE); } /** @@ -816,10 +822,10 @@ public final class SmsApplication { // This should never happen in prod -- unit tests will put the receiver into a // unusual state where the pending result is null, which produces a NPE when calling // getSendingUserId. Just pretend like it's the system user for testing. - userId = UserHandle.USER_SYSTEM; + userId = UserHandle.SYSTEM.getIdentifier(); } Context userContext = mContext; - if (userId != UserHandle.USER_SYSTEM) { + if (userId != UserHandle.SYSTEM.getIdentifier()) { try { userContext = mContext.createPackageContextAsUser(mContext.getPackageName(), 0, UserHandle.of(userId)); diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java index 0f53fe65463f..0c463949b14a 100644 --- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java +++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java @@ -20,7 +20,6 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED; import android.Manifest; import android.annotation.Nullable; import android.app.AppOpsManager; -import android.app.admin.DevicePolicyManager; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; @@ -28,10 +27,10 @@ import android.os.Binder; import android.os.Build; import android.os.Process; import android.os.UserHandle; +import android.permission.PermissionManager; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.util.Log; -import android.util.StatsLog; import com.android.internal.annotations.VisibleForTesting; @@ -157,8 +156,8 @@ public final class TelephonyPermissions { // We have READ_PHONE_STATE permission, so return true as long as the AppOps bit hasn't been // revoked. AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); - return appOps.noteOp(AppOpsManager.OPSTR_READ_PHONE_STATE, uid, callingPackage) - == AppOpsManager.MODE_ALLOWED; + return appOps.noteOp(AppOpsManager.OPSTR_READ_PHONE_STATE, uid, callingPackage, + callingFeatureId, null) == AppOpsManager.MODE_ALLOWED; } /** @@ -210,8 +209,8 @@ public final class TelephonyPermissions { // We have READ_PHONE_STATE permission, so return true as long as the AppOps bit hasn't been // revoked. AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); - return appOps.noteOp(AppOpsManager.OPSTR_READ_PHONE_STATE, uid, callingPackage) == - AppOpsManager.MODE_ALLOWED; + return appOps.noteOp(AppOpsManager.OPSTR_READ_PHONE_STATE, uid, callingPackage, + callingFeatureId, null) == AppOpsManager.MODE_ALLOWED; } /** @@ -306,16 +305,6 @@ public final class TelephonyPermissions { String message, boolean allowCarrierPrivilegeOnAnySub) { int uid = Binder.getCallingUid(); int pid = Binder.getCallingPid(); - // Allow system and root access to the device identifiers. - final int appId = UserHandle.getAppId(uid); - if (appId == Process.SYSTEM_UID || appId == Process.ROOT_UID) { - return true; - } - // Allow access to packages that have the READ_PRIVILEGED_PHONE_STATE permission. - if (context.checkPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, pid, - uid) == PackageManager.PERMISSION_GRANTED) { - return true; - } // If the calling package has carrier privileges for specified sub, then allow access. if (checkCarrierPrivilegeForSubId(context, subId)) return true; @@ -326,30 +315,13 @@ public final class TelephonyPermissions { return true; } - // if the calling package is not null then perform the DevicePolicyManager device / - // profile owner and Appop checks. - if (callingPackage != null) { - // Allow access to an app that has been granted the READ_DEVICE_IDENTIFIERS app op. - long token = Binder.clearCallingIdentity(); - AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService( - Context.APP_OPS_SERVICE); - try { - if (appOpsManager.noteOpNoThrow(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS, uid, - callingPackage) == AppOpsManager.MODE_ALLOWED) { - return true; - } - } finally { - Binder.restoreCallingIdentity(token); - } - // Allow access to a device / profile owner app. - DevicePolicyManager devicePolicyManager = - (DevicePolicyManager) context.getSystemService( - Context.DEVICE_POLICY_SERVICE); - if (devicePolicyManager != null && devicePolicyManager.checkDeviceIdentifierAccess( - callingPackage, pid, uid)) { - return true; - } + PermissionManager permissionManager = (PermissionManager) context.getSystemService( + Context.PERMISSION_SERVICE); + if (permissionManager.checkDeviceIdentifierAccess(callingPackage, message, callingFeatureId, + pid, uid) == PackageManager.PERMISSION_GRANTED) { + return true; } + return reportAccessDeniedToReadIdentifiers(context, subId, pid, uid, callingPackage, message); } @@ -366,16 +338,10 @@ public final class TelephonyPermissions { */ private static boolean reportAccessDeniedToReadIdentifiers(Context context, int subId, int pid, int uid, String callingPackage, String message) { - boolean isPreinstalled = false; ApplicationInfo callingPackageInfo = null; try { callingPackageInfo = context.getPackageManager().getApplicationInfoAsUser( callingPackage, 0, UserHandle.getUserHandleForUid(uid)); - if (callingPackageInfo != null) { - if (callingPackageInfo.isSystemApp()) { - isPreinstalled = true; - } - } } catch (PackageManager.NameNotFoundException e) { // If the application info for the calling package could not be found then assume the // calling app is a non-preinstalled app to detect any issues with the check @@ -395,11 +361,11 @@ public final class TelephonyPermissions { invokedMethods = sReportedDeviceIDPackages.get(callingPackage); } invokedMethods.add(message); - StatsLog.write(StatsLog.DEVICE_IDENTIFIER_ACCESS_DENIED, callingPackage, message, - isPreinstalled, false); + TelephonyCommonStatsLog.write(TelephonyCommonStatsLog.DEVICE_IDENTIFIER_ACCESS_DENIED, + callingPackage, message, /* isPreinstalled= */ false, false); } - Log.w(LOG_TAG, "reportAccessDeniedToReadIdentifiers:" + callingPackage + ":" + message - + ":isPreinstalled=" + isPreinstalled); + Log.w(LOG_TAG, "reportAccessDeniedToReadIdentifiers:" + callingPackage + ":" + message + ":" + + subId); // if the target SDK is pre-Q then check if the calling package would have previously // had access to device identifiers. if (callingPackageInfo != null && ( @@ -440,8 +406,8 @@ public final class TelephonyPermissions { // We have READ_CALL_LOG permission, so return true as long as the AppOps bit hasn't been // revoked. AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); - return appOps.noteOp(AppOpsManager.OPSTR_READ_CALL_LOG, uid, callingPackage) == - AppOpsManager.MODE_ALLOWED; + return appOps.noteOp(AppOpsManager.OPSTR_READ_CALL_LOG, uid, callingPackage, + callingPackageName, null) == AppOpsManager.MODE_ALLOWED; } /** @@ -470,16 +436,6 @@ public final class TelephonyPermissions { public static boolean checkReadPhoneNumber( 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); - if (appOps.noteOp(AppOpsManager.OPSTR_WRITE_SMS, uid, callingPackage) == - AppOpsManager.MODE_ALLOWED) { - return true; - } - - // NOTE(b/73308711): If an app has one of the following AppOps bits explicitly revoked, they - // will be denied access, even if they have another permission and AppOps bit if needed. - // First, check if the SDK version is below R boolean preR = false; try { @@ -514,21 +470,29 @@ public final class TelephonyPermissions { } } + // Default SMS app can always read it. + AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); + if (appOps.noteOp(AppOpsManager.OPSTR_WRITE_SMS, uid, callingPackage, callingFeatureId, + null) == AppOpsManager.MODE_ALLOWED) { + return true; + } // Can be read with READ_SMS too. try { context.enforcePermission(android.Manifest.permission.READ_SMS, pid, uid, message); - return appOps.noteOp(AppOpsManager.OPSTR_READ_SMS, uid, callingPackage) - == AppOpsManager.MODE_ALLOWED; - + if (appOps.noteOp(AppOpsManager.OPSTR_READ_SMS, uid, callingPackage, + callingFeatureId, null) == AppOpsManager.MODE_ALLOWED) { + return true; + } } catch (SecurityException readSmsSecurityException) { } // Can be read with READ_PHONE_NUMBERS too. try { context.enforcePermission(android.Manifest.permission.READ_PHONE_NUMBERS, pid, uid, message); - return appOps.noteOp(AppOpsManager.OPSTR_READ_PHONE_NUMBERS, uid, callingPackage) - == AppOpsManager.MODE_ALLOWED; - + if (appOps.noteOp(AppOpsManager.OPSTR_READ_PHONE_NUMBERS, uid, callingPackage, + callingFeatureId, null) == AppOpsManager.MODE_ALLOWED) { + return true; + } } catch (SecurityException readPhoneNumberSecurityException) { } diff --git a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java index ec1c6c90905a..682697469af9 100644 --- a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java +++ b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java @@ -30,6 +30,8 @@ import android.os.SystemProperties; import java.io.PrintWriter; import java.util.Collections; import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import java.util.function.Supplier; /** @@ -144,4 +146,12 @@ public final class TelephonyUtils { } return ret; } + + /** Wait for latch to trigger */ + public static void waitUntilReady(CountDownLatch latch, long timeoutMs) { + try { + latch.await(timeoutMs, TimeUnit.MILLISECONDS); + } catch (InterruptedException ignored) { + } + } } |