CarrierAppUtils.java revision b7e26fb1ad1802025cc3a01eeba6acfbc8f3f444
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 17package com.android.internal.telephony; 18 19import android.content.pm.ApplicationInfo; 20import android.content.pm.IPackageManager; 21import android.content.pm.PackageManager; 22import android.content.res.Resources; 23import android.os.RemoteException; 24import android.telephony.TelephonyManager; 25import android.util.Slog; 26 27import com.android.internal.annotations.VisibleForTesting; 28 29import java.util.ArrayList; 30import java.util.List; 31 32/** 33 * Utilities for handling carrier applications. 34 * @hide 35 */ 36public final class CarrierAppUtils { 37 private static final String TAG = "CarrierAppUtils"; 38 39 private static final boolean DEBUG = false; // STOPSHIP if true 40 41 private CarrierAppUtils() {} 42 43 /** 44 * Handle preinstalled carrier apps which should be disabled until a matching SIM is inserted. 45 * 46 * Evaluates the list of applications in config_disabledUntilUsedPreinstalledCarrierApps. We 47 * want to disable each such application which is present on the system image until the user 48 * inserts a SIM which causes that application to gain carrier privilege (indicating a "match"), 49 * without interfering with the user if they opt to enable/disable the app explicitly. 50 * 51 * So, for each such app, we either disable until used IFF the app is not carrier privileged AND 52 * in the default state (e.g. not explicitly DISABLED/DISABLED_BY_USER/ENABLED), or we enable if 53 * the app is carrier privileged and in either the default state or DISABLED_UNTIL_USED. 54 * 55 * When enabling a carrier app we also grant it default permissions. 56 * 57 * This method is idempotent and is safe to be called at any time; it should be called once at 58 * system startup prior to any application running, as well as any time the set of carrier 59 * privileged apps may have changed. 60 */ 61 public synchronized static void disableCarrierAppsUntilPrivileged(String callingPackage, 62 IPackageManager packageManager, TelephonyManager telephonyManager, int userId) { 63 if (DEBUG) { 64 Slog.d(TAG, "disableCarrierAppsUntilPrivileged"); 65 } 66 String[] systemCarrierAppsDisabledUntilUsed = Resources.getSystem().getStringArray( 67 com.android.internal.R.array.config_disabledUntilUsedPreinstalledCarrierApps); 68 disableCarrierAppsUntilPrivileged(callingPackage, packageManager, telephonyManager, userId, 69 systemCarrierAppsDisabledUntilUsed); 70 } 71 72 // Must be public b/c framework unit tests can't access package-private methods. 73 @VisibleForTesting 74 public static void disableCarrierAppsUntilPrivileged(String callingPackage, 75 IPackageManager packageManager, TelephonyManager telephonyManager, int userId, 76 String[] systemCarrierAppsDisabledUntilUsed) { 77 List<ApplicationInfo> candidates = getDefaultCarrierAppCandidatesHelper(packageManager, 78 userId, systemCarrierAppsDisabledUntilUsed); 79 if (candidates == null || candidates.isEmpty()) { 80 return; 81 } 82 83 List<String> enabledCarrierPackages = new ArrayList<>(); 84 85 try { 86 for (ApplicationInfo ai : candidates) { 87 String packageName = ai.packageName; 88 boolean hasPrivileges = 89 telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName) == 90 TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; 91 92 // Only update enabled state for the app on /system. Once it has been updated we 93 // shouldn't touch it. 94 if (!ai.isUpdatedSystemApp()) { 95 if (hasPrivileges 96 && (ai.enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT 97 || ai.enabledSetting == 98 PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) { 99 Slog.i(TAG, "Update state(" + packageName + "): ENABLED for user " 100 + userId); 101 packageManager.setApplicationEnabledSetting(packageName, 102 PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 103 PackageManager.DONT_KILL_APP, userId, callingPackage); 104 } else if (!hasPrivileges 105 && ai.enabledSetting == 106 PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) { 107 Slog.i(TAG, "Update state(" + packageName 108 + "): DISABLED_UNTIL_USED for user " + userId); 109 packageManager.setApplicationEnabledSetting(packageName, 110 PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED, 0, 111 userId, callingPackage); 112 } 113 } 114 115 // Always re-grant default permissions to carrier apps w/ privileges. 116 if (hasPrivileges) { 117 enabledCarrierPackages.add(ai.packageName); 118 } 119 } 120 121 if (!enabledCarrierPackages.isEmpty()) { 122 // Since we enabled at least one app, ensure we grant default permissions to those 123 // apps. 124 String[] packageNames = new String[enabledCarrierPackages.size()]; 125 enabledCarrierPackages.toArray(packageNames); 126 packageManager.grantDefaultPermissionsToEnabledCarrierApps(packageNames, userId); 127 } 128 } catch (RemoteException e) { 129 Slog.w(TAG, "Could not reach PackageManager", e); 130 } 131 } 132 133 /** 134 * Returns the list of "default" carrier apps. 135 * 136 * This is the subset of apps returned by 137 * {@link #getDefaultCarrierAppCandidates(IPackageManager, int)} which currently have carrier 138 * privileges per the SIM(s) inserted in the device. 139 */ 140 public static List<ApplicationInfo> getDefaultCarrierApps(IPackageManager packageManager, 141 TelephonyManager telephonyManager, int userId) { 142 // Get all system apps from the default list. 143 List<ApplicationInfo> candidates = getDefaultCarrierAppCandidates(packageManager, userId); 144 if (candidates == null || candidates.isEmpty()) { 145 return null; 146 } 147 148 // Filter out apps without carrier privileges. 149 // Iterate from the end to avoid creating an Iterator object and because we will be removing 150 // elements from the list as we pass through it. 151 for (int i = candidates.size() - 1; i >= 0; i--) { 152 ApplicationInfo ai = candidates.get(i); 153 String packageName = ai.packageName; 154 boolean hasPrivileges = 155 telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName) == 156 TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; 157 if (!hasPrivileges) { 158 candidates.remove(i); 159 } 160 } 161 162 return candidates; 163 } 164 165 /** 166 * Returns the list of "default" carrier app candidates. 167 * 168 * These are the apps subject to the hiding/showing logic in 169 * {@link CarrierAppUtils#disableCarrierAppsUntilPrivileged(String, IPackageManager, 170 * TelephonyManager, int)}, as well as the apps which should have default permissions granted, 171 * when a matching SIM is inserted. 172 * 173 * Whether or not the app is actually considered a default app depends on whether the app has 174 * carrier privileges as determined by the SIMs in the device. 175 */ 176 public static List<ApplicationInfo> getDefaultCarrierAppCandidates( 177 IPackageManager packageManager, int userId) { 178 String[] systemCarrierAppsDisabledUntilUsed = Resources.getSystem().getStringArray( 179 com.android.internal.R.array.config_disabledUntilUsedPreinstalledCarrierApps); 180 return getDefaultCarrierAppCandidatesHelper(packageManager, userId, 181 systemCarrierAppsDisabledUntilUsed); 182 } 183 184 private static List<ApplicationInfo> getDefaultCarrierAppCandidatesHelper( 185 IPackageManager packageManager, int userId, 186 String[] systemCarrierAppsDisabledUntilUsed) { 187 if (systemCarrierAppsDisabledUntilUsed == null 188 || systemCarrierAppsDisabledUntilUsed.length == 0) { 189 return null; 190 } 191 List<ApplicationInfo> apps = null; 192 try { 193 apps = new ArrayList<>(systemCarrierAppsDisabledUntilUsed.length); 194 for (String packageName : systemCarrierAppsDisabledUntilUsed) { 195 ApplicationInfo ai = packageManager.getApplicationInfo(packageName, 196 PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS, userId); 197 if (ai == null) { 198 // No app found for packageName 199 continue; 200 } 201 if (!ai.isSystemApp()) { 202 continue; 203 } 204 apps.add(ai); 205 } 206 } catch (RemoteException e) { 207 Slog.w(TAG, "Could not reach PackageManager", e); 208 } 209 return apps; 210 } 211} 212