1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.telephony; 18 19 import android.annotation.Nullable; 20 import android.content.ContentResolver; 21 import android.content.Context; 22 import android.content.pm.ApplicationInfo; 23 import android.content.pm.IPackageManager; 24 import android.content.pm.PackageManager; 25 import android.content.res.Resources; 26 import android.os.RemoteException; 27 import android.os.UserHandle; 28 import android.provider.Settings; 29 import android.telephony.TelephonyManager; 30 import android.util.ArrayMap; 31 import android.util.ArraySet; 32 import android.util.Log; 33 34 import com.android.internal.R; 35 import com.android.internal.annotations.VisibleForTesting; 36 import com.android.internal.telephony.util.ArrayUtils; 37 import com.android.server.SystemConfig; 38 39 import java.util.ArrayList; 40 import java.util.List; 41 import java.util.Map; 42 43 /** 44 * Utilities for handling carrier applications. 45 * @hide 46 */ 47 public final class CarrierAppUtils { 48 private static final String TAG = "CarrierAppUtils"; 49 50 private static final boolean DEBUG = false; // STOPSHIP if true 51 CarrierAppUtils()52 private CarrierAppUtils() {} 53 54 /** 55 * Handle preinstalled carrier apps which should be disabled until a matching SIM is inserted. 56 * 57 * Evaluates the list of applications in 58 * {@link SystemConfig#getDisabledUntilUsedPreinstalledCarrierApps()}. We want to disable each 59 * such application which is present on the system image until the user inserts a SIM which 60 * causes that application to gain carrier privilege (indicating a "match"), without interfering 61 * with the user if they opt to enable/disable the app explicitly. 62 * 63 * So, for each such app, we either disable until used IFF the app is not carrier privileged AND 64 * in the default state (e.g. not explicitly DISABLED/DISABLED_BY_USER/ENABLED), or we enable if 65 * the app is carrier privileged and in either the default state or DISABLED_UNTIL_USED. 66 * 67 * In addition, there is a list of carrier-associated applications in 68 * {@link SystemConfig#getDisabledUntilUsedPreinstalledCarrierAssociatedApps}. Each app in this 69 * list is associated with a carrier app. When the given carrier app is enabled/disabled per the 70 * above, the associated applications are enabled/disabled to match. 71 * 72 * When enabling a carrier app we also grant it default permissions. 73 * 74 * This method is idempotent and is safe to be called at any time; it should be called once at 75 * system startup prior to any application running, as well as any time the set of carrier 76 * privileged apps may have changed. 77 */ disableCarrierAppsUntilPrivileged(String callingPackage, IPackageManager packageManager, TelephonyManager telephonyManager, int userId, Context context)78 public static synchronized void disableCarrierAppsUntilPrivileged(String callingPackage, 79 IPackageManager packageManager, TelephonyManager telephonyManager, 80 int userId, Context context) { 81 if (DEBUG) { 82 Log.d(TAG, "disableCarrierAppsUntilPrivileged"); 83 } 84 SystemConfig config = SystemConfig.getInstance(); 85 ArraySet<String> systemCarrierAppsDisabledUntilUsed = 86 config.getDisabledUntilUsedPreinstalledCarrierApps(); 87 ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed = 88 config.getDisabledUntilUsedPreinstalledCarrierAssociatedApps(); 89 ContentResolver contentResolver = getContentResolverForUser(context, userId); 90 disableCarrierAppsUntilPrivileged(callingPackage, packageManager, telephonyManager, 91 contentResolver, userId, systemCarrierAppsDisabledUntilUsed, 92 systemCarrierAssociatedAppsDisabledUntilUsed); 93 } 94 95 /** 96 * Like {@link #disableCarrierAppsUntilPrivileged(String, IPackageManager, TelephonyManager, 97 * ContentResolver, int)}, but assumes that no carrier apps have carrier privileges. 98 * 99 * This prevents a potential race condition on first boot - since the app's default state is 100 * enabled, we will initially disable it when the telephony stack is first initialized as it has 101 * not yet read the carrier privilege rules. However, since telephony is initialized later on 102 * late in boot, the app being disabled may have already been started in response to certain 103 * broadcasts. The app will continue to run (briefly) after being disabled, before the Package 104 * Manager can kill it, and this can lead to crashes as the app is in an unexpected state. 105 */ disableCarrierAppsUntilPrivileged(String callingPackage, IPackageManager packageManager, int userId, Context context)106 public static synchronized void disableCarrierAppsUntilPrivileged(String callingPackage, 107 IPackageManager packageManager, int userId, Context context) { 108 if (DEBUG) { 109 Log.d(TAG, "disableCarrierAppsUntilPrivileged"); 110 } 111 SystemConfig config = SystemConfig.getInstance(); 112 ArraySet<String> systemCarrierAppsDisabledUntilUsed = 113 config.getDisabledUntilUsedPreinstalledCarrierApps(); 114 115 116 ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed = 117 config.getDisabledUntilUsedPreinstalledCarrierAssociatedApps(); 118 ContentResolver contentResolver = getContentResolverForUser(context, userId); 119 disableCarrierAppsUntilPrivileged(callingPackage, packageManager, 120 null /* telephonyManager */, contentResolver, userId, 121 systemCarrierAppsDisabledUntilUsed, systemCarrierAssociatedAppsDisabledUntilUsed); 122 } 123 getContentResolverForUser(Context context, int userId)124 private static ContentResolver getContentResolverForUser(Context context, int userId) { 125 Context userContext = context.createContextAsUser(UserHandle.getUserHandleForUid(userId), 126 0); 127 return userContext.getContentResolver(); 128 } 129 isUpdatedSystemApp(ApplicationInfo ai)130 private static boolean isUpdatedSystemApp(ApplicationInfo ai) { 131 if ((ai.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) { 132 return true; 133 } 134 135 return false; 136 } 137 138 /** 139 * Disable carrier apps until they are privileged 140 * Must be public b/c framework unit tests can't access package-private methods. 141 */ 142 // Must be public b/c framework unit tests can't access package-private methods. 143 @VisibleForTesting disableCarrierAppsUntilPrivileged(String callingPackage, IPackageManager packageManager, @Nullable TelephonyManager telephonyManager, ContentResolver contentResolver, int userId, ArraySet<String> systemCarrierAppsDisabledUntilUsed, ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed)144 public static void disableCarrierAppsUntilPrivileged(String callingPackage, 145 IPackageManager packageManager, @Nullable TelephonyManager telephonyManager, 146 ContentResolver contentResolver, int userId, 147 ArraySet<String> systemCarrierAppsDisabledUntilUsed, 148 ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed) { 149 List<ApplicationInfo> candidates = getDefaultCarrierAppCandidatesHelper( 150 packageManager, userId, systemCarrierAppsDisabledUntilUsed); 151 if (candidates == null || candidates.isEmpty()) { 152 return; 153 } 154 155 Map<String, List<ApplicationInfo>> associatedApps = getDefaultCarrierAssociatedAppsHelper( 156 packageManager, 157 userId, 158 systemCarrierAssociatedAppsDisabledUntilUsed); 159 160 List<String> enabledCarrierPackages = new ArrayList<>(); 161 boolean hasRunOnce = Settings.Secure.getInt(contentResolver, 162 Settings.Secure.CARRIER_APPS_HANDLED, 0) == 1; 163 164 try { 165 for (ApplicationInfo ai : candidates) { 166 String packageName = ai.packageName; 167 String[] restrictedCarrierApps = Resources.getSystem().getStringArray( 168 R.array.config_restrictedPreinstalledCarrierApps); 169 boolean hasPrivileges = telephonyManager != null 170 && telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName) 171 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS 172 && !ArrayUtils.contains(restrictedCarrierApps, packageName); 173 174 // add hiddenUntilInstalled flag for carrier apps and associated apps 175 packageManager.setSystemAppHiddenUntilInstalled(packageName, true); 176 List<ApplicationInfo> associatedAppList = associatedApps.get(packageName); 177 if (associatedAppList != null) { 178 for (ApplicationInfo associatedApp : associatedAppList) { 179 packageManager.setSystemAppHiddenUntilInstalled( 180 associatedApp.packageName, 181 true 182 ); 183 } 184 } 185 186 int enabledSetting = packageManager.getApplicationEnabledSetting(packageName, 187 userId); 188 if (hasPrivileges) { 189 // Only update enabled state for the app on /system. Once it has been 190 // updated we shouldn't touch it. 191 if (!isUpdatedSystemApp(ai) && enabledSetting 192 == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT 193 || enabledSetting 194 == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED 195 || (ai.flags & ApplicationInfo.FLAG_INSTALLED) == 0) { 196 Log.i(TAG, "Update state(" + packageName + "): ENABLED for user " 197 + userId); 198 packageManager.setSystemAppInstallState( 199 packageName, 200 true /*installed*/, 201 userId); 202 packageManager.setApplicationEnabledSetting( 203 packageName, 204 PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 205 PackageManager.DONT_KILL_APP, 206 userId, 207 callingPackage); 208 } 209 210 // Also enable any associated apps for this carrier app. 211 if (associatedAppList != null) { 212 for (ApplicationInfo associatedApp : associatedAppList) { 213 int associatedAppEnabledSetting = 214 packageManager.getApplicationEnabledSetting( 215 associatedApp.packageName, userId); 216 if (associatedAppEnabledSetting 217 == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT 218 || associatedAppEnabledSetting 219 == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED 220 || (associatedApp.flags 221 & ApplicationInfo.FLAG_INSTALLED) == 0) { 222 Log.i(TAG, "Update associated state(" + associatedApp.packageName 223 + "): ENABLED for user " + userId); 224 packageManager.setSystemAppInstallState( 225 associatedApp.packageName, 226 true /*installed*/, 227 userId); 228 packageManager.setApplicationEnabledSetting( 229 associatedApp.packageName, 230 PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 231 PackageManager.DONT_KILL_APP, 232 userId, 233 callingPackage); 234 } 235 } 236 } 237 238 // Always re-grant default permissions to carrier apps w/ privileges. 239 enabledCarrierPackages.add(ai.packageName); 240 } else { // No carrier privileges 241 // Only update enabled state for the app on /system. Once it has been 242 // updated we shouldn't touch it. 243 if (!isUpdatedSystemApp(ai) && enabledSetting 244 == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT 245 && (ai.flags & ApplicationInfo.FLAG_INSTALLED) != 0) { 246 Log.i(TAG, "Update state(" + packageName 247 + "): DISABLED_UNTIL_USED for user " + userId); 248 packageManager.setSystemAppInstallState( 249 packageName, 250 false /*installed*/, 251 userId); 252 } 253 254 // Also disable any associated apps for this carrier app if this is the first 255 // run. We avoid doing this a second time because it is brittle to rely on the 256 // distinction between "default" and "enabled". 257 if (!hasRunOnce) { 258 if (associatedAppList != null) { 259 for (ApplicationInfo associatedApp : associatedAppList) { 260 int associatedAppEnabledSetting = 261 packageManager.getApplicationEnabledSetting( 262 associatedApp.packageName, userId); 263 if (associatedAppEnabledSetting 264 == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT 265 && (associatedApp.flags 266 & ApplicationInfo.FLAG_INSTALLED) != 0) { 267 Log.i(TAG, 268 "Update associated state(" + associatedApp.packageName 269 + "): DISABLED_UNTIL_USED for user " + userId); 270 packageManager.setSystemAppInstallState( 271 associatedApp.packageName, 272 false /*installed*/, 273 userId); 274 } 275 } 276 } 277 } 278 } 279 } 280 281 // Mark the execution so we do not disable apps again. 282 if (!hasRunOnce) { 283 Settings.Secure.putInt(contentResolver, Settings.Secure.CARRIER_APPS_HANDLED, 1); 284 } 285 286 if (!enabledCarrierPackages.isEmpty()) { 287 // Since we enabled at least one app, ensure we grant default permissions to those 288 // apps. 289 String[] packageNames = new String[enabledCarrierPackages.size()]; 290 enabledCarrierPackages.toArray(packageNames); 291 packageManager.grantDefaultPermissionsToEnabledCarrierApps(packageNames, userId); 292 } 293 } catch (RemoteException e) { 294 Log.w(TAG, "Could not reach PackageManager", e); 295 } 296 } 297 298 /** 299 * Returns the list of "default" carrier apps. 300 * 301 * This is the subset of apps returned by 302 * {@link #getDefaultCarrierAppCandidates(IPackageManager, int)} which currently have carrier 303 * privileges per the SIM(s) inserted in the device. 304 */ getDefaultCarrierApps(IPackageManager packageManager, TelephonyManager telephonyManager, int userId)305 public static List<ApplicationInfo> getDefaultCarrierApps(IPackageManager packageManager, 306 TelephonyManager telephonyManager, int userId) { 307 // Get all system apps from the default list. 308 List<ApplicationInfo> candidates = getDefaultCarrierAppCandidates(packageManager, userId); 309 if (candidates == null || candidates.isEmpty()) { 310 return null; 311 } 312 313 // Filter out apps without carrier privileges. 314 // Iterate from the end to avoid creating an Iterator object and because we will be removing 315 // elements from the list as we pass through it. 316 for (int i = candidates.size() - 1; i >= 0; i--) { 317 ApplicationInfo ai = candidates.get(i); 318 String packageName = ai.packageName; 319 boolean hasPrivileges = 320 telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName) 321 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; 322 if (!hasPrivileges) { 323 candidates.remove(i); 324 } 325 } 326 327 return candidates; 328 } 329 330 /** 331 * Returns the list of "default" carrier app candidates. 332 * 333 * These are the apps subject to the hiding/showing logic in 334 * {@link CarrierAppUtils#disableCarrierAppsUntilPrivileged(String, IPackageManager, 335 * TelephonyManager, ContentResolver, int)}, as well as the apps which should have default 336 * permissions granted, when a matching SIM is inserted. 337 * 338 * Whether or not the app is actually considered a default app depends on whether the app has 339 * carrier privileges as determined by the SIMs in the device. 340 */ getDefaultCarrierAppCandidates( IPackageManager packageManager, int userId)341 public static List<ApplicationInfo> getDefaultCarrierAppCandidates( 342 IPackageManager packageManager, int userId) { 343 ArraySet<String> systemCarrierAppsDisabledUntilUsed = 344 SystemConfig.getInstance().getDisabledUntilUsedPreinstalledCarrierApps(); 345 return getDefaultCarrierAppCandidatesHelper(packageManager, userId, 346 systemCarrierAppsDisabledUntilUsed); 347 } 348 getDefaultCarrierAppCandidatesHelper( IPackageManager packageManager, int userId, ArraySet<String> systemCarrierAppsDisabledUntilUsed)349 private static List<ApplicationInfo> getDefaultCarrierAppCandidatesHelper( 350 IPackageManager packageManager, 351 int userId, 352 ArraySet<String> systemCarrierAppsDisabledUntilUsed) { 353 if (systemCarrierAppsDisabledUntilUsed == null) { 354 return null; 355 } 356 357 int size = systemCarrierAppsDisabledUntilUsed.size(); 358 if (size == 0) { 359 return null; 360 } 361 362 List<ApplicationInfo> apps = new ArrayList<>(size); 363 for (int i = 0; i < size; i++) { 364 String packageName = systemCarrierAppsDisabledUntilUsed.valueAt(i); 365 ApplicationInfo ai = 366 getApplicationInfoIfSystemApp(packageManager, userId, packageName); 367 if (ai != null) { 368 apps.add(ai); 369 } 370 } 371 return apps; 372 } 373 getDefaultCarrierAssociatedAppsHelper( IPackageManager packageManager, int userId, ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed)374 private static Map<String, List<ApplicationInfo>> getDefaultCarrierAssociatedAppsHelper( 375 IPackageManager packageManager, 376 int userId, 377 ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed) { 378 int size = systemCarrierAssociatedAppsDisabledUntilUsed.size(); 379 Map<String, List<ApplicationInfo>> associatedApps = new ArrayMap<>(size); 380 for (int i = 0; i < size; i++) { 381 String carrierAppPackage = systemCarrierAssociatedAppsDisabledUntilUsed.keyAt(i); 382 List<String> associatedAppPackages = 383 systemCarrierAssociatedAppsDisabledUntilUsed.valueAt(i); 384 for (int j = 0; j < associatedAppPackages.size(); j++) { 385 ApplicationInfo ai = 386 getApplicationInfoIfSystemApp( 387 packageManager, userId, associatedAppPackages.get(j)); 388 // Only update enabled state for the app on /system. Once it has been updated we 389 // shouldn't touch it. 390 if (ai != null && !isUpdatedSystemApp(ai)) { 391 List<ApplicationInfo> appList = associatedApps.get(carrierAppPackage); 392 if (appList == null) { 393 appList = new ArrayList<>(); 394 associatedApps.put(carrierAppPackage, appList); 395 } 396 appList.add(ai); 397 } 398 } 399 } 400 return associatedApps; 401 } 402 403 @Nullable getApplicationInfoIfSystemApp( IPackageManager packageManager, int userId, String packageName)404 private static ApplicationInfo getApplicationInfoIfSystemApp( 405 IPackageManager packageManager, 406 int userId, 407 String packageName) { 408 try { 409 ApplicationInfo ai = packageManager.getApplicationInfo(packageName, 410 PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS 411 | PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS 412 | PackageManager.MATCH_SYSTEM_ONLY, userId); 413 if (ai != null) { 414 return ai; 415 } 416 } catch (RemoteException e) { 417 Log.w(TAG, "Could not reach PackageManager", e); 418 } 419 return null; 420 } 421 } 422