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