• 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.content.pm.ApplicationInfo;
20 import android.content.pm.IPackageManager;
21 import android.content.pm.PackageManager;
22 import android.content.res.Resources;
23 import android.os.RemoteException;
24 import android.telephony.TelephonyManager;
25 import android.util.Slog;
26 
27 import com.android.internal.annotations.VisibleForTesting;
28 
29 import java.util.ArrayList;
30 import java.util.List;
31 
32 /**
33  * Utilities for handling carrier applications.
34  * @hide
35  */
36 public final class CarrierAppUtils {
37     private static final String TAG = "CarrierAppUtils";
38 
39     private static final boolean DEBUG = false; // STOPSHIP if true
40 
CarrierAppUtils()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      */
disableCarrierAppsUntilPrivileged(String callingPackage, IPackageManager packageManager, TelephonyManager telephonyManager, int userId)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
disableCarrierAppsUntilPrivileged(String callingPackage, IPackageManager packageManager, TelephonyManager telephonyManager, int userId, String[] systemCarrierAppsDisabledUntilUsed)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      */
getDefaultCarrierApps(IPackageManager packageManager, TelephonyManager telephonyManager, int userId)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      */
getDefaultCarrierAppCandidates( IPackageManager packageManager, int userId)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 
getDefaultCarrierAppCandidatesHelper( IPackageManager packageManager, int userId, String[] systemCarrierAppsDisabledUntilUsed)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