blob: 31ea01ef553cfa7ea0160be116066d5347c11f65 [file] [log] [blame]
Bookatz04d7ae52019-08-05 14:07:12 -07001/*
2 * Copyright (C) 2019 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
17package com.android.server.pm;
18
19import android.annotation.IntDef;
20import android.annotation.NonNull;
21import android.annotation.Nullable;
22import android.annotation.UserIdInt;
23import android.content.pm.PackageManagerInternal;
24import android.content.pm.PackageParser;
25import android.content.pm.UserInfo;
26import android.content.res.Resources;
27import android.os.SystemProperties;
28import android.os.UserHandle;
29import android.util.ArrayMap;
30import android.util.ArraySet;
31import android.util.Slog;
32
33import com.android.internal.annotations.VisibleForTesting;
34import com.android.server.LocalServices;
35import com.android.server.SystemConfig;
36
37import java.io.PrintWriter;
38import java.lang.annotation.Retention;
39import java.lang.annotation.RetentionPolicy;
40import java.util.Set;
41
42/**
43 * Responsible for un/installing system packages based on user type.
44 *
45 * <p>Uses the SystemConfig's install-in-user-type whitelist;
46 * see {@link SystemConfig#getAndClearPackageToUserTypeWhitelist} and
47 * {@link SystemConfig#getAndClearPackageToUserTypeBlacklist}.
48 *
49 * <p>If {@link #isEnforceMode()} is false, then all system packages are always installed for all
50 * users. The following applies when it is true.
51 *
52 * Any package can be in one of three states in the SystemConfig whitelist
53 * <ol>
54 * <li>Explicitly blacklisted for a particular user type</li>
55 * <li>Explicitly whitelisted for a particular user type</li>
56 * <li>Not mentioned at all, for any user type (neither whitelisted nor blacklisted)</li>
57 * </ol>
58 * Blacklisting always takes precedence - if a package is blacklisted for a particular user,
59 * it won't be installed on that type of user (even if it is also whitelisted for that user).
60 * Next comes whitelisting - if it is whitelisted for a particular user, it will be installed on
61 * that type of user (as long as it isn't blacklisted).
62 * Finally, if the package is not mentioned at all (i.e. neither whitelisted nor blacklisted for
63 * any user types) in the SystemConfig 'install-in-user-type' lists
64 * then:
65 * <ul>
66 * <li>If {@link #isImplicitWhitelistMode()}, the package is implicitly treated as whitelisted
67 * for all users</li>
68 * <li>Otherwise, the package is implicitly treated as blacklisted for all non-SYSTEM users</li>
69 * <li>Either way, for {@link UserHandle#USER_SYSTEM}, the package will be implicitly
70 * whitelisted so that it can be used for local development purposes.</li>
71 * </ul>
72 */
73class UserSystemPackageInstaller {
74 private static final String TAG = "UserManagerService";
75
76 /**
77 * System Property whether to only install system packages on a user if they're whitelisted for
78 * that user type. These are flags and can be freely combined.
79 * <ul>
80 * <li> 0 (0b000) - disable whitelist (install all system packages; no logging)</li>
81 * <li> 1 (0b001) - enforce (only install system packages if they are whitelisted)</li>
82 * <li> 2 (0b010) - log (log when a non-whitelisted package is run)</li>
83 * <li> 4 (0b100) - implicitly whitelist any package not mentioned in the whitelist</li>
84 * <li>-1 - use device default (as defined in res/res/values/config.xml)</li>
85 * </ul>
86 * Note: This list must be kept current with config_userTypePackageWhitelistMode in
87 * frameworks/base/core/res/res/values/config.xml
88 */
89 static final String PACKAGE_WHITELIST_MODE_PROP = "persist.debug.user.package_whitelist_mode";
90 static final int USER_TYPE_PACKAGE_WHITELIST_MODE_DISABLE = 0;
91 static final int USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE = 0b001;
92 static final int USER_TYPE_PACKAGE_WHITELIST_MODE_LOG = 0b010;
93 static final int USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST = 0b100;
94 static final int USER_TYPE_PACKAGE_WHITELIST_MODE_DEVICE_DEFAULT = -1;
95
96 @IntDef(flag = true, prefix = "USER_TYPE_PACKAGE_WHITELIST_MODE_", value = {
97 USER_TYPE_PACKAGE_WHITELIST_MODE_DISABLE,
98 USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE,
99 USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE,
100 USER_TYPE_PACKAGE_WHITELIST_MODE_LOG,
101 USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST,
102 })
103 @Retention(RetentionPolicy.SOURCE)
104 public @interface PackageWhitelistMode {}
105
106 /**
107 * Maps system package manifest names to the user flags on which they should be initially
108 * installed.
109 * <p>Packages that are whitelisted, but then blacklisted so that they aren't to be installed on
110 * any user, are purposefully still present in this list.
111 */
112 private final ArrayMap<String, Integer> mWhitelitsedPackagesForUserTypes;
113
114 private final UserManagerService mUm;
115
116 UserSystemPackageInstaller(UserManagerService ums) {
117 mUm = ums;
118 mWhitelitsedPackagesForUserTypes =
119 determineWhitelistedPackagesForUserTypes(SystemConfig.getInstance());
120 }
121
122 /** Constructor for testing purposes. */
123 @VisibleForTesting
124 UserSystemPackageInstaller(UserManagerService ums, ArrayMap<String, Integer> whitelist) {
125 mUm = ums;
126 mWhitelitsedPackagesForUserTypes = whitelist;
127 }
128
129 /**
130 * During OTAs and first boot, install/uninstall all system packages for all users based on the
131 * user's UserInfo flags and the SystemConfig whitelist.
132 * We do NOT uninstall packages during an OTA though.
133 *
134 * This is responsible for enforcing the whitelist for pre-existing users (i.e. USER_SYSTEM);
135 * enforcement for new users is done when they are created in UserManagerService.createUser().
136 */
137 boolean installWhitelistedSystemPackages(boolean isFirstBoot, boolean isUpgrade) {
138 final int mode = getWhitelistMode();
139 checkWhitelistedSystemPackages(mode);
140 if (!isUpgrade && !isFirstBoot) {
141 return false;
142 }
143 Slog.i(TAG, "Reviewing whitelisted packages due to "
144 + (isFirstBoot ? "[firstBoot]" : "") + (isUpgrade ? "[upgrade]" : ""));
145 final PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class);
146 // Install/uninstall system packages per user.
147 for (int userId : mUm.getUserIds()) {
148 final Set<String> userWhitelist = getInstallablePackagesForUserId(userId);
149 pmInt.forEachPackage(pkg -> {
150 if (!pkg.isSystem()) {
151 return;
152 }
153 final boolean install =
Winson Chiu8e18a0a2019-09-30 20:37:25 +0000154 (userWhitelist == null || userWhitelist.contains(pkg.packageName))
155 && !pkg.applicationInfo.hiddenUntilInstalled;
Bookatz04d7ae52019-08-05 14:07:12 -0700156 if (isUpgrade && !isFirstBoot && !install) {
157 return; // To be careful, we don’t uninstall apps during OTAs
158 }
159 final boolean changed = pmInt.setInstalled(pkg, userId, install);
160 if (changed) {
161 Slog.i(TAG, (install ? "Installed " : "Uninstalled ")
Winson Chiu8e18a0a2019-09-30 20:37:25 +0000162 + pkg.packageName + " for user " + userId);
Bookatz04d7ae52019-08-05 14:07:12 -0700163 }
164 });
165 }
166 return true;
167 }
168
169 /**
170 * Checks whether the system packages and the mWhitelistedPackagesForUserTypes whitelist are
171 * in 1-to-1 correspondence.
172 */
173 private void checkWhitelistedSystemPackages(@PackageWhitelistMode int mode) {
174 if (!isLogMode(mode) && !isEnforceMode(mode)) {
175 return;
176 }
177 Slog.v(TAG, "Checking that all system packages are whitelisted.");
178 final Set<String> allWhitelistedPackages = getWhitelistedSystemPackages();
179 PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class);
180
181 // Check whether all whitelisted packages are indeed on the system.
182 for (String pkgName : allWhitelistedPackages) {
Winson Chiu8e18a0a2019-09-30 20:37:25 +0000183 PackageParser.Package pkg = pmInt.getPackage(pkgName);
Bookatz04d7ae52019-08-05 14:07:12 -0700184 if (pkg == null) {
185 Slog.w(TAG, pkgName + " is whitelisted but not present.");
186 } else if (!pkg.isSystem()) {
187 Slog.w(TAG, pkgName + " is whitelisted and present but not a system package.");
188 }
189 }
190
191 // Check whether all system packages are indeed whitelisted.
192 if (isImplicitWhitelistMode(mode) && !isLogMode(mode)) {
193 return;
194 }
195 final boolean doWtf = isEnforceMode(mode);
196 pmInt.forEachPackage(pkg -> {
Winson Chiu8e18a0a2019-09-30 20:37:25 +0000197 if (pkg.isSystem() && !allWhitelistedPackages.contains(pkg.manifestPackageName)) {
198 final String msg = "System package " + pkg.manifestPackageName
Bookatz04d7ae52019-08-05 14:07:12 -0700199 + " is not whitelisted using 'install-in-user-type' in SystemConfig "
200 + "for any user types!";
201 if (doWtf) {
202 Slog.wtf(TAG, msg);
203 } else {
204 Slog.e(TAG, msg);
205 }
206 }
207 });
208 }
209
210 /** Whether to only install system packages in new users for which they are whitelisted. */
211 boolean isEnforceMode() {
212 return isEnforceMode(getWhitelistMode());
213 }
214
215 /**
216 * Whether to log a warning concerning potential problems with the user-type package whitelist.
217 */
218 boolean isLogMode() {
219 return isLogMode(getWhitelistMode());
220 }
221
222 /**
223 * Whether to treat all packages that are not mentioned at all in the whitelist to be implicitly
224 * whitelisted for all users.
225 */
226 boolean isImplicitWhitelistMode() {
227 return isImplicitWhitelistMode(getWhitelistMode());
228 }
229
230 /** See {@link #isEnforceMode()}. */
231 private static boolean isEnforceMode(int whitelistMode) {
232 return (whitelistMode & USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE) != 0;
233 }
234
235 /** See {@link #isLogMode()}. */
236 private static boolean isLogMode(int whitelistMode) {
237 return (whitelistMode & USER_TYPE_PACKAGE_WHITELIST_MODE_LOG) != 0;
238 }
239
240 /** See {@link #isImplicitWhitelistMode()}. */
241 private static boolean isImplicitWhitelistMode(int whitelistMode) {
242 return (whitelistMode & USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST) != 0;
243 }
244
245 /** Gets the PackageWhitelistMode for use of {@link #mWhitelitsedPackagesForUserTypes}. */
246 private @PackageWhitelistMode int getWhitelistMode() {
247 final int runtimeMode = SystemProperties.getInt(
248 PACKAGE_WHITELIST_MODE_PROP, USER_TYPE_PACKAGE_WHITELIST_MODE_DEVICE_DEFAULT);
249 if (runtimeMode != USER_TYPE_PACKAGE_WHITELIST_MODE_DEVICE_DEFAULT) {
250 return runtimeMode;
251 }
252 return Resources.getSystem()
253 .getInteger(com.android.internal.R.integer.config_userTypePackageWhitelistMode);
254 }
255
256 /**
257 * Gets the system packages names that should be installed on the given user.
258 * See {@link #getInstallablePackagesForUserType(int)}.
259 */
260 private @Nullable Set<String> getInstallablePackagesForUserId(@UserIdInt int userId) {
261 return getInstallablePackagesForUserType(mUm.getUserInfo(userId).flags);
262 }
263
264 /**
265 * Gets the system package names that should be installed on a user with the given flags, as
266 * determined by SystemConfig, the whitelist mode, and the apps actually on the device.
267 * Names are the {@link PackageParser.Package#packageName}, not necessarily the manifest names.
268 *
269 * Returns null if all system packages should be installed (due enforce-mode being off).
270 */
271 @Nullable Set<String> getInstallablePackagesForUserType(int flags) {
272 final int mode = getWhitelistMode();
273 if (!isEnforceMode(mode)) {
274 return null;
275 }
276 final boolean isSystemUser = (flags & UserInfo.FLAG_SYSTEM) != 0;
277 final boolean isImplicitWhitelistMode = isImplicitWhitelistMode(mode);
278 final Set<String> whitelistedPackages = getWhitelistedPackagesForUserType(flags);
279
280 final Set<String> installPackages = new ArraySet<>();
281 final PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class);
282 pmInt.forEachPackage(pkg -> {
283 if (!pkg.isSystem()) {
284 return;
285 }
286 if (shouldInstallPackage(pkg, mWhitelitsedPackagesForUserTypes,
287 whitelistedPackages, isImplicitWhitelistMode, isSystemUser)) {
288 // Although the whitelist uses manifest names, this function returns packageNames.
Winson Chiu8e18a0a2019-09-30 20:37:25 +0000289 installPackages.add(pkg.packageName);
Bookatz04d7ae52019-08-05 14:07:12 -0700290 }
291 });
292 return installPackages;
293 }
294
295 /**
296 * Returns whether the given system package should be installed on the given user, based on the
297 * the given whitelist of system packages.
298 *
299 * @param sysPkg the system package. Must be a system package; no verification for this is done.
300 * @param userTypeWhitelist map of package manifest names to user flags on which they should be
301 * installed
302 * @param userWhitelist set of package manifest names that should be installed on this
303 * particular user. This must be consistent with userTypeWhitelist, but is
304 * passed in separately to avoid repeatedly calculating it from
305 * userTypeWhitelist.
306 * @param isImplicitWhitelistMode whether non-mentioned packages are implicitly whitelisted.
307 * @param isSystemUser whether the user is USER_SYSTEM (which gets special treatment).
308 */
309 @VisibleForTesting
Winson Chiu8e18a0a2019-09-30 20:37:25 +0000310 static boolean shouldInstallPackage(PackageParser.Package sysPkg,
Bookatz04d7ae52019-08-05 14:07:12 -0700311 @NonNull ArrayMap<String, Integer> userTypeWhitelist,
312 @NonNull Set<String> userWhitelist, boolean isImplicitWhitelistMode,
313 boolean isSystemUser) {
314
Winson Chiu8e18a0a2019-09-30 20:37:25 +0000315 final String pkgName = sysPkg.manifestPackageName;
Bookatz04d7ae52019-08-05 14:07:12 -0700316 boolean install = (isImplicitWhitelistMode && !userTypeWhitelist.containsKey(pkgName))
317 || userWhitelist.contains(pkgName);
318
319 // For the purposes of local development, any package that isn't even mentioned in the
320 // whitelist at all is implicitly treated as whitelisted for the SYSTEM user.
321 if (!install && isSystemUser && !userTypeWhitelist.containsKey(pkgName)) {
322 install = true;
323 Slog.e(TAG, "System package " + pkgName + " is not mentioned "
324 + "in SystemConfig's 'install-in-user-type' but we are "
325 + "implicitly treating it as whitelisted for the SYSTEM user.");
326 }
327 return install;
328 }
329
330 /**
331 * Gets the package manifest names that are whitelisted for a user with the given flags,
332 * as determined by SystemConfig.
333 */
334 @VisibleForTesting
335 @NonNull Set<String> getWhitelistedPackagesForUserType(int flags) {
336 Set<String> installablePkgs = new ArraySet<>(mWhitelitsedPackagesForUserTypes.size());
337 for (int i = 0; i < mWhitelitsedPackagesForUserTypes.size(); i++) {
338 String pkgName = mWhitelitsedPackagesForUserTypes.keyAt(i);
339 int whitelistedUserTypes = mWhitelitsedPackagesForUserTypes.valueAt(i);
340 if ((flags & whitelistedUserTypes) != 0) {
341 installablePkgs.add(pkgName);
342 }
343 }
344 return installablePkgs;
345 }
346
347 /**
348 * Set of package manifest names that are included anywhere in the package-to-user-type
349 * whitelist, as determined by SystemConfig.
350 *
351 * Packages that are whitelisted, but then blacklisted so that they aren't to be installed on
352 * any user, are still present in this list, since that is a valid scenario (e.g. if an OEM
353 * completely blacklists an AOSP app).
354 */
355 private Set<String> getWhitelistedSystemPackages() {
356 return mWhitelitsedPackagesForUserTypes.keySet();
357 }
358
359 /**
360 * Returns a map of package manifest names to the user flags on which it is to be installed.
361 * Also, clears this data from SystemConfig where it was stored inefficiently (and therefore
362 * should be called exactly once, even if the data isn't useful).
363 *
364 * Any system packages not present in this map should not even be on the device at all.
365 * To enforce this:
366 * <ul>
367 * <li>Illegal user types are ignored.</li>
368 * <li>Packages that never whitelisted at all (even if they are explicitly blacklisted) are
369 * ignored.</li>
370 * <li>Packages that are blacklisted whenever they are whitelisted will be stored with the
371 * flag 0 (since this is a valid scenario, e.g. if an OEM completely blacklists an AOSP
372 * app).</li>
373 * </ul>
374 */
375 @VisibleForTesting
376 static ArrayMap<String, Integer> determineWhitelistedPackagesForUserTypes(
377 SystemConfig sysConfig) {
378
379 final ArrayMap<String, Set<String>> whitelist =
380 sysConfig.getAndClearPackageToUserTypeWhitelist();
381 // result maps packageName -> userTypes on which the package should be installed.
382 final ArrayMap<String, Integer> result = new ArrayMap<>(whitelist.size() + 1);
383 // First, do the whitelisted user types.
384 for (int i = 0; i < whitelist.size(); i++) {
385 final String pkgName = whitelist.keyAt(i);
386 final int flags = getFlagsFromUserTypes(whitelist.valueAt(i));
387 if (flags != 0) {
388 result.put(pkgName, flags);
389 }
390 }
391 // Then, un-whitelist any blacklisted user types.
392 // TODO(b/141370854): Right now, the blacklist is actually just an 'unwhitelist'. Which
393 // direction we go depends on how we design user subtypes, which is still
394 // being designed. For now, unwhitelisting works for current use-cases.
395 final ArrayMap<String, Set<String>> blacklist =
396 sysConfig.getAndClearPackageToUserTypeBlacklist();
397 for (int i = 0; i < blacklist.size(); i++) {
398 final String pkgName = blacklist.keyAt(i);
399 final int nonFlags = getFlagsFromUserTypes(blacklist.valueAt(i));
400 final Integer flags = result.get(pkgName);
401 if (flags != null) {
402 result.put(pkgName, flags & ~nonFlags);
403 }
404 }
405 // Regardless of the whitelists/blacklists, ensure mandatory packages.
406 result.put("android",
Bookatz029832a2019-10-04 16:50:22 -0700407 UserInfo.FLAG_SYSTEM | UserInfo.FLAG_FULL | UserInfo.FLAG_PROFILE);
Bookatz04d7ae52019-08-05 14:07:12 -0700408 return result;
409 }
410
411 /** Converts a user types, as used in SystemConfig, to a UserInfo flag. */
412 private static int getFlagsFromUserTypes(Iterable<String> userTypes) {
Bookatz029832a2019-10-04 16:50:22 -0700413 // TODO(b/142482943): Update all this for the new UserTypes.
Bookatz04d7ae52019-08-05 14:07:12 -0700414 int flags = 0;
415 for (String type : userTypes) {
416 switch (type) {
417 case "GUEST":
418 flags |= UserInfo.FLAG_GUEST;
419 break;
420 case "RESTRICTED":
421 flags |= UserInfo.FLAG_RESTRICTED;
422 break;
423 case "MANAGED_PROFILE":
424 flags |= UserInfo.FLAG_MANAGED_PROFILE;
425 break;
426 case "EPHEMERAL":
427 flags |= UserInfo.FLAG_EPHEMERAL;
428 break;
429 case "DEMO":
430 flags |= UserInfo.FLAG_DEMO;
431 break;
432 case "FULL":
433 flags |= UserInfo.FLAG_FULL;
434 break;
435 case "SYSTEM":
436 flags |= UserInfo.FLAG_SYSTEM;
437 break;
438 case "PROFILE":
Bookatz029832a2019-10-04 16:50:22 -0700439 flags |= UserInfo.FLAG_PROFILE;
Bookatz04d7ae52019-08-05 14:07:12 -0700440 break;
441 default:
442 Slog.w(TAG, "SystemConfig contained an invalid user type: " + type);
443 break;
444 // Other UserInfo flags are forbidden.
445 // In particular, FLAG_INITIALIZED, FLAG_DISABLED, FLAG_QUIET_MODE are inapplicable.
446 // The following are invalid now, but are reconsiderable: FLAG_PRIMARY, FLAG_ADMIN.
447 }
448 }
449 return flags;
450 }
451
452 void dump(PrintWriter pw) {
Felipe Leme2b8c51b2019-10-09 17:21:33 -0700453 pw.print("Whitelisted packages per user type");
454 final int size = mWhitelitsedPackagesForUserTypes.size();
455 if (size == 0) {
456 pw.println(": N/A");
457 return;
458 }
459 pw.println(" (" + size + " packages)");
460 for (int i = 0; i < size; i++) {
Bookatz04d7ae52019-08-05 14:07:12 -0700461 final String pkgName = mWhitelitsedPackagesForUserTypes.keyAt(i);
462 final String whitelistedUserTypes =
463 UserInfo.flagsToString(mWhitelitsedPackagesForUserTypes.valueAt(i));
464 pw.println(" " + pkgName + ": " + whitelistedUserTypes);
465 }
466 }
467}