OSDN Git Service

Revert "Hide system apps until installed (1/2)"
[android-x86/frameworks-base.git] / telephony / java / com / android / internal / telephony / CarrierAppUtils.java
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 }