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