Home | History | Annotate | Download | only in telephony
      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