• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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