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