blob: 54f25d341d09fe13a69340cbcccadee616855a61 [file] [log] [blame]
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001/*
2 * Copyright (C) 2014 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;
18
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -070019import static com.android.internal.util.ArrayUtils.appendInt;
20
Winsond9d17362019-10-02 12:41:29 -070021import android.annotation.NonNull;
Dianne Hackbornc0e4aaa2014-11-14 10:55:50 -080022import android.app.ActivityManager;
Ruben Brunk98576cf2016-03-07 18:54:28 -080023import android.content.ComponentName;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070024import android.content.pm.FeatureInfo;
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -070025import android.content.pm.PackageManager;
Jiyong Parkfad99442018-03-12 10:39:07 +090026import android.os.Build;
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -070027import android.os.Environment;
Luke Huang1414c612019-12-16 20:22:12 +080028import android.os.FileUtils;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070029import android.os.Process;
Steven Morelandd7827fd2018-12-03 10:27:01 -080030import android.os.SystemProperties;
Felipe Leme3eb78092019-10-22 09:22:20 -070031import android.os.Trace;
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -070032import android.os.storage.StorageManager;
Zimuzocc2932f2018-10-29 16:04:41 +000033import android.permission.PermissionManager.SplitPermissionInfo;
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -080034import android.text.TextUtils;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070035import android.util.ArrayMap;
36import android.util.ArraySet;
37import android.util.Slog;
38import android.util.SparseArray;
Felipe Leme3eb78092019-10-22 09:22:20 -070039import android.util.TimingsTraceLog;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070040import android.util.Xml;
Jeff Sharkey1c4ae802014-12-19 11:08:55 -080041
Bookatz04d7ae52019-08-05 14:07:12 -070042import com.android.internal.annotations.VisibleForTesting;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070043import com.android.internal.util.XmlUtils;
Jeff Sharkey1c4ae802014-12-19 11:08:55 -080044
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -070045import libcore.io.IoUtils;
46
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070047import org.xmlpull.v1.XmlPullParser;
48import org.xmlpull.v1.XmlPullParserException;
49
50import java.io.File;
51import java.io.FileNotFoundException;
52import java.io.FileReader;
53import java.io.IOException;
Jeff Davidson24b9d962016-07-21 12:35:10 -070054import java.util.ArrayList;
Svet Ganov087dce22017-09-07 15:42:16 -070055import java.util.Collections;
Jeff Davidson24b9d962016-07-21 12:35:10 -070056import java.util.List;
Svet Ganov087dce22017-09-07 15:42:16 -070057import java.util.Map;
Bookatz04d7ae52019-08-05 14:07:12 -070058import java.util.Set;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070059
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070060/**
61 * Loads global system configuration info.
Anthony Hughde787d42019-08-22 15:35:48 -070062 * Note: Initializing this class hits the disk and is slow. This class should generally only be
63 * accessed by the system_server process.
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070064 */
65public class SystemConfig {
66 static final String TAG = "SystemConfig";
67
68 static SystemConfig sInstance;
69
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +080070 // permission flag, determines which types of configuration are allowed to be read
71 private static final int ALLOW_FEATURES = 0x01;
72 private static final int ALLOW_LIBS = 0x02;
73 private static final int ALLOW_PERMISSIONS = 0x04;
74 private static final int ALLOW_APP_CONFIGS = 0x08;
Jaekyun Seoke3b6bf12017-02-16 13:48:30 +090075 private static final int ALLOW_PRIVAPP_PERMISSIONS = 0x10;
Svet Ganov087dce22017-09-07 15:42:16 -070076 private static final int ALLOW_OEM_PERMISSIONS = 0x20;
Mathew Inwood4693a752018-02-20 16:04:25 +000077 private static final int ALLOW_HIDDENAPI_WHITELISTING = 0x40;
Dianne Hackborn769b2e72018-12-05 08:51:20 -080078 private static final int ALLOW_ASSOCIATIONS = 0x80;
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +080079 private static final int ALLOW_ALL = ~0;
80
Steven Morelandd7827fd2018-12-03 10:27:01 -080081 // property for runtime configuration differentiation
82 private static final String SKU_PROPERTY = "ro.boot.product.hardware.sku";
83
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070084 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
85 int[] mGlobalGids;
86
87 // These are the built-in uid -> permission mappings that were read from the
88 // system configuration files.
Jeff Sharkey9f837a92014-10-24 12:07:24 -070089 final SparseArray<ArraySet<String>> mSystemPermissions = new SparseArray<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070090
Zimuzocc2932f2018-10-29 16:04:41 +000091 final ArrayList<SplitPermissionInfo> mSplitPermissions = new ArrayList<>();
92
Ben Lin71c16d72018-12-06 18:34:51 -080093 public static final class SharedLibraryEntry {
94 public final String name;
95 public final String filename;
96 public final String[] dependencies;
97
98 SharedLibraryEntry(String name, String filename, String[] dependencies) {
99 this.name = name;
100 this.filename = filename;
101 this.dependencies = dependencies;
102 }
103 }
104
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700105 // These are the built-in shared libraries that were read from the
Ben Lin71c16d72018-12-06 18:34:51 -0800106 // system configuration files. Keys are the library names; values are
107 // the individual entries that contain information such as filename
108 // and dependencies.
109 final ArrayMap<String, SharedLibraryEntry> mSharedLibraries = new ArrayMap<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700110
111 // These are the features this devices supports that were read from the
112 // system configuration files.
Jeff Sharkey9f837a92014-10-24 12:07:24 -0700113 final ArrayMap<String, FeatureInfo> mAvailableFeatures = new ArrayMap<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700114
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800115 // These are the features which this device doesn't support; the OEM
116 // partition uses these to opt-out of features from the system image.
117 final ArraySet<String> mUnavailableFeatures = new ArraySet<>();
118
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700119 public static final class PermissionEntry {
120 public final String name;
121 public int[] gids;
Jeff Sharkey00f39042015-03-23 16:51:22 -0700122 public boolean perUser;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700123
Jeff Sharkey00f39042015-03-23 16:51:22 -0700124 PermissionEntry(String name, boolean perUser) {
125 this.name = name;
126 this.perUser = perUser;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700127 }
128 }
129
130 // These are the permission -> gid mappings that were read from the
131 // system configuration files.
Dianne Hackbornbb8aa5a2014-09-17 13:20:38 -0700132 final ArrayMap<String, PermissionEntry> mPermissions = new ArrayMap<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700133
134 // These are the packages that are white-listed to be able to run in the
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700135 // background while in power save mode (but not whitelisted from device idle modes),
136 // as read from the configuration files.
137 final ArraySet<String> mAllowInPowerSaveExceptIdle = new ArraySet<>();
138
139 // These are the packages that are white-listed to be able to run in the
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700140 // background while in power save mode, as read from the configuration files.
Dianne Hackbornbb8aa5a2014-09-17 13:20:38 -0700141 final ArraySet<String> mAllowInPowerSave = new ArraySet<>();
142
Felipe Lemea9505cc2016-02-26 10:28:41 -0800143 // These are the packages that are white-listed to be able to run in the
144 // background while in data-usage save mode, as read from the configuration files.
145 final ArraySet<String> mAllowInDataUsageSave = new ArraySet<>();
146
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800147 // These are the packages that are white-listed to be able to run background location
148 // without throttling, as read from the configuration files.
149 final ArraySet<String> mAllowUnthrottledLocation = new ArraySet<>();
150
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800151 // These are the packages that are white-listed to be able to retrieve location even when user
152 // location settings are off, for emergency purposes, as read from the configuration files.
153 final ArraySet<String> mAllowIgnoreLocationSettings = new ArraySet<>();
154
Christopher Tate42a386b2016-11-07 12:21:21 -0800155 // These are the action strings of broadcasts which are whitelisted to
156 // be delivered anonymously even to apps which target O+.
157 final ArraySet<String> mAllowImplicitBroadcasts = new ArraySet<>();
158
Christopher Tate01e18642015-07-07 18:10:38 -0700159 // These are the package names of apps which should be in the 'always'
160 // URL-handling state upon factory reset.
161 final ArraySet<String> mLinkedApps = new ArraySet<>();
162
Fyodor Kupolov7db5af12015-07-31 16:50:27 -0700163 // These are the packages that are whitelisted to be able to run as system user
164 final ArraySet<String> mSystemUserWhitelistedApps = new ArraySet<>();
165
166 // These are the packages that should not run under system user
167 final ArraySet<String> mSystemUserBlacklistedApps = new ArraySet<>();
168
Ruben Brunk98576cf2016-03-07 18:54:28 -0800169 // These are the components that are enabled by default as VR mode listener services.
170 final ArraySet<ComponentName> mDefaultVrComponents = new ArraySet<>();
171
Christopher Tate494df792016-05-10 17:05:38 -0700172 // These are the permitted backup transport service components
173 final ArraySet<ComponentName> mBackupTransportWhitelist = new ArraySet<>();
174
Ryan Mitchell4fd8e6f2019-10-07 16:31:34 -0700175 // These are packages mapped to maps of component class name to default enabled state.
176 final ArrayMap<String, ArrayMap<String, Boolean>> mPackageComponentEnabledState =
177 new ArrayMap<>();
178
Mathew Inwood4693a752018-02-20 16:04:25 +0000179 // Package names that are exempted from private API blacklisting
180 final ArraySet<String> mHiddenApiPackageWhitelist = new ArraySet<>();
181
goneileb31cd42018-02-28 15:22:08 -0800182 // The list of carrier applications which should be disabled until used.
183 // This function suppresses update notifications for these pre-installed apps.
184 // In SubscriptionInfoUpdater, the listed applications are disabled until used when all of the
185 // following conditions are met.
186 // 1. Not currently carrier-privileged according to the inserted SIM
187 // 2. Pre-installed
188 // 3. In the default state (enabled but not explicitly)
189 // And SubscriptionInfoUpdater undoes this and marks the app enabled when a SIM is inserted
190 // that marks the app as carrier privileged. It also grants the app default permissions
191 // for Phone and Location. As such, apps MUST only ever be added to this list if they
192 // obtain user consent to access their location through other means.
193 final ArraySet<String> mDisabledUntilUsedPreinstalledCarrierApps = new ArraySet<>();
194
Jeff Davidson24b9d962016-07-21 12:35:10 -0700195 // These are the packages of carrier-associated apps which should be disabled until used until
196 // a SIM is inserted which grants carrier privileges to that carrier app.
197 final ArrayMap<String, List<String>> mDisabledUntilUsedPreinstalledCarrierAssociatedApps =
198 new ArrayMap<>();
199
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800200 final ArrayMap<String, ArraySet<String>> mPrivAppPermissions = new ArrayMap<>();
Todd Kennedy74629e32017-08-15 14:48:07 -0700201 final ArrayMap<String, ArraySet<String>> mPrivAppDenyPermissions = new ArrayMap<>();
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800202
Jiyong Park002fdbd2017-02-13 20:50:31 +0900203 final ArrayMap<String, ArraySet<String>> mVendorPrivAppPermissions = new ArrayMap<>();
204 final ArrayMap<String, ArraySet<String>> mVendorPrivAppDenyPermissions = new ArrayMap<>();
205
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900206 final ArrayMap<String, ArraySet<String>> mProductPrivAppPermissions = new ArrayMap<>();
207 final ArrayMap<String, ArraySet<String>> mProductPrivAppDenyPermissions = new ArrayMap<>();
208
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900209 final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppPermissions = new ArrayMap<>();
210 final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppDenyPermissions = new ArrayMap<>();
Dario Freni2bef1762018-06-01 14:02:08 +0100211
Svet Ganov087dce22017-09-07 15:42:16 -0700212 final ArrayMap<String, ArrayMap<String, Boolean>> mOemPermissions = new ArrayMap<>();
213
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800214 // Allowed associations between applications. If there are any entries
215 // for an app, those are the only associations allowed; otherwise, all associations
216 // are allowed. Allowing an association from app A to app B means app A can not
217 // associate with any other apps, but does not limit what apps B can associate with.
218 final ArrayMap<String, ArraySet<String>> mAllowedAssociations = new ArrayMap<>();
219
Nikita Ioffe07964b42019-02-28 21:35:02 +0000220 private final ArraySet<String> mBugreportWhitelistedPackages = new ArraySet<>();
221
Bookatz04d7ae52019-08-05 14:07:12 -0700222 // Map of packagesNames to userTypes. Stored temporarily until cleared by UserManagerService().
223 private ArrayMap<String, Set<String>> mPackageToUserTypeWhitelist = new ArrayMap<>();
224 private ArrayMap<String, Set<String>> mPackageToUserTypeBlacklist = new ArrayMap<>();
225
JW Wangf0a70b12019-12-11 17:12:02 +0800226 private final ArraySet<String> mRollbackWhitelistedPackages = new ArraySet<>();
227
Winsond9d17362019-10-02 12:41:29 -0700228 /**
229 * Map of system pre-defined, uniquely named actors; keys are namespace,
230 * value maps actor name to package name.
231 */
Ram Muthiah637138d2019-12-11 17:37:37 -0800232 private ArrayMap<String, ArrayMap<String, String>> mNamedActors = null;
Winsond9d17362019-10-02 12:41:29 -0700233
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700234 public static SystemConfig getInstance() {
Anthony Hughde787d42019-08-22 15:35:48 -0700235 if (!isSystemProcess()) {
236 Slog.wtf(TAG, "SystemConfig is being accessed by a process other than "
237 + "system_server.");
238 }
239
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700240 synchronized (SystemConfig.class) {
241 if (sInstance == null) {
242 sInstance = new SystemConfig();
243 }
244 return sInstance;
245 }
246 }
247
248 public int[] getGlobalGids() {
249 return mGlobalGids;
250 }
251
Jeff Sharkey9f837a92014-10-24 12:07:24 -0700252 public SparseArray<ArraySet<String>> getSystemPermissions() {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700253 return mSystemPermissions;
254 }
255
Zimuzocc2932f2018-10-29 16:04:41 +0000256 public ArrayList<SplitPermissionInfo> getSplitPermissions() {
257 return mSplitPermissions;
258 }
259
Ben Lin71c16d72018-12-06 18:34:51 -0800260 public ArrayMap<String, SharedLibraryEntry> getSharedLibraries() {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700261 return mSharedLibraries;
262 }
263
Jeff Sharkey9f837a92014-10-24 12:07:24 -0700264 public ArrayMap<String, FeatureInfo> getAvailableFeatures() {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700265 return mAvailableFeatures;
266 }
267
268 public ArrayMap<String, PermissionEntry> getPermissions() {
269 return mPermissions;
270 }
271
Christopher Tate42a386b2016-11-07 12:21:21 -0800272 public ArraySet<String> getAllowImplicitBroadcasts() {
273 return mAllowImplicitBroadcasts;
274 }
275
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700276 public ArraySet<String> getAllowInPowerSaveExceptIdle() {
277 return mAllowInPowerSaveExceptIdle;
278 }
279
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700280 public ArraySet<String> getAllowInPowerSave() {
281 return mAllowInPowerSave;
282 }
283
Felipe Lemea9505cc2016-02-26 10:28:41 -0800284 public ArraySet<String> getAllowInDataUsageSave() {
285 return mAllowInDataUsageSave;
286 }
287
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800288 public ArraySet<String> getAllowUnthrottledLocation() {
289 return mAllowUnthrottledLocation;
290 }
291
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800292 public ArraySet<String> getAllowIgnoreLocationSettings() {
293 return mAllowIgnoreLocationSettings;
294 }
295
Christopher Tate01e18642015-07-07 18:10:38 -0700296 public ArraySet<String> getLinkedApps() {
297 return mLinkedApps;
298 }
299
Fyodor Kupolov7db5af12015-07-31 16:50:27 -0700300 public ArraySet<String> getSystemUserWhitelistedApps() {
301 return mSystemUserWhitelistedApps;
302 }
303
304 public ArraySet<String> getSystemUserBlacklistedApps() {
305 return mSystemUserBlacklistedApps;
306 }
307
Mathew Inwood4693a752018-02-20 16:04:25 +0000308 public ArraySet<String> getHiddenApiWhitelistedApps() {
309 return mHiddenApiPackageWhitelist;
310 }
311
Ruben Brunk98576cf2016-03-07 18:54:28 -0800312 public ArraySet<ComponentName> getDefaultVrComponents() {
313 return mDefaultVrComponents;
314 }
315
Christopher Tate494df792016-05-10 17:05:38 -0700316 public ArraySet<ComponentName> getBackupTransportWhitelist() {
317 return mBackupTransportWhitelist;
318 }
319
Ryan Mitchell4fd8e6f2019-10-07 16:31:34 -0700320 public ArrayMap<String, Boolean> getComponentsEnabledStates(String packageName) {
321 return mPackageComponentEnabledState.get(packageName);
322 }
323
goneileb31cd42018-02-28 15:22:08 -0800324 public ArraySet<String> getDisabledUntilUsedPreinstalledCarrierApps() {
325 return mDisabledUntilUsedPreinstalledCarrierApps;
326 }
327
Jeff Davidson24b9d962016-07-21 12:35:10 -0700328 public ArrayMap<String, List<String>> getDisabledUntilUsedPreinstalledCarrierAssociatedApps() {
329 return mDisabledUntilUsedPreinstalledCarrierAssociatedApps;
330 }
331
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800332 public ArraySet<String> getPrivAppPermissions(String packageName) {
333 return mPrivAppPermissions.get(packageName);
334 }
335
Todd Kennedy74629e32017-08-15 14:48:07 -0700336 public ArraySet<String> getPrivAppDenyPermissions(String packageName) {
337 return mPrivAppDenyPermissions.get(packageName);
338 }
339
Jiyong Park002fdbd2017-02-13 20:50:31 +0900340 public ArraySet<String> getVendorPrivAppPermissions(String packageName) {
341 return mVendorPrivAppPermissions.get(packageName);
342 }
343
344 public ArraySet<String> getVendorPrivAppDenyPermissions(String packageName) {
345 return mVendorPrivAppDenyPermissions.get(packageName);
346 }
347
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900348 public ArraySet<String> getProductPrivAppPermissions(String packageName) {
349 return mProductPrivAppPermissions.get(packageName);
350 }
351
352 public ArraySet<String> getProductPrivAppDenyPermissions(String packageName) {
353 return mProductPrivAppDenyPermissions.get(packageName);
354 }
355
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900356 /**
357 * Read from "permission" tags in /system_ext/etc/permissions/*.xml
358 * @return Set of privileged permissions that are explicitly granted.
359 */
360 public ArraySet<String> getSystemExtPrivAppPermissions(String packageName) {
361 return mSystemExtPrivAppPermissions.get(packageName);
Dario Freni2bef1762018-06-01 14:02:08 +0100362 }
363
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900364 /**
365 * Read from "deny-permission" tags in /system_ext/etc/permissions/*.xml
366 * @return Set of privileged permissions that are explicitly denied.
367 */
368 public ArraySet<String> getSystemExtPrivAppDenyPermissions(String packageName) {
369 return mSystemExtPrivAppDenyPermissions.get(packageName);
Dario Freni2bef1762018-06-01 14:02:08 +0100370 }
371
Svet Ganov087dce22017-09-07 15:42:16 -0700372 public Map<String, Boolean> getOemPermissions(String packageName) {
373 final Map<String, Boolean> oemPermissions = mOemPermissions.get(packageName);
374 if (oemPermissions != null) {
375 return oemPermissions;
376 }
377 return Collections.emptyMap();
378 }
379
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800380 public ArrayMap<String, ArraySet<String>> getAllowedAssociations() {
381 return mAllowedAssociations;
382 }
383
Nikita Ioffe07964b42019-02-28 21:35:02 +0000384 public ArraySet<String> getBugreportWhitelistedPackages() {
385 return mBugreportWhitelistedPackages;
386 }
387
JW Wangf0a70b12019-12-11 17:12:02 +0800388 public Set<String> getRollbackWhitelistedPackages() {
389 return mRollbackWhitelistedPackages;
390 }
391
Bookatz04d7ae52019-08-05 14:07:12 -0700392 /**
393 * Gets map of packagesNames to userTypes, dictating on which user types each package should be
394 * initially installed, and then removes this map from SystemConfig.
395 * Called by UserManagerService when it is constructed.
396 */
397 public ArrayMap<String, Set<String>> getAndClearPackageToUserTypeWhitelist() {
398 ArrayMap<String, Set<String>> r = mPackageToUserTypeWhitelist;
399 mPackageToUserTypeWhitelist = new ArrayMap<>(0);
400 return r;
401 }
402
403 /**
404 * Gets map of packagesNames to userTypes, dictating on which user types each package should NOT
405 * be initially installed, even if they are whitelisted, and then removes this map from
406 * SystemConfig.
407 * Called by UserManagerService when it is constructed.
408 */
409 public ArrayMap<String, Set<String>> getAndClearPackageToUserTypeBlacklist() {
410 ArrayMap<String, Set<String>> r = mPackageToUserTypeBlacklist;
411 mPackageToUserTypeBlacklist = new ArrayMap<>(0);
412 return r;
413 }
414
Winsond9d17362019-10-02 12:41:29 -0700415 @NonNull
Ram Muthiah637138d2019-12-11 17:37:37 -0800416 public Map<String, ? extends Map<String, String>> getNamedActors() {
Winsond9d17362019-10-02 12:41:29 -0700417 return mNamedActors != null ? mNamedActors : Collections.emptyMap();
418 }
419
Bookatz04d7ae52019-08-05 14:07:12 -0700420 /**
421 * Only use for testing. Do NOT use in production code.
422 * @param readPermissions false to create an empty SystemConfig; true to read the permissions.
423 */
424 @VisibleForTesting
Winsond9d17362019-10-02 12:41:29 -0700425 public SystemConfig(boolean readPermissions) {
Bookatz04d7ae52019-08-05 14:07:12 -0700426 if (readPermissions) {
427 Slog.w(TAG, "Constructing a test SystemConfig");
428 readAllPermissions();
429 } else {
430 Slog.w(TAG, "Constructing an empty test SystemConfig");
431 }
432 }
433
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700434 SystemConfig() {
Felipe Leme3eb78092019-10-22 09:22:20 -0700435 TimingsTraceLog log = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
436 log.traceBegin("readAllPermissions");
437 try {
438 readAllPermissions();
439 } finally {
440 log.traceEnd();
441 }
Bookatz04d7ae52019-08-05 14:07:12 -0700442 }
443
444 private void readAllPermissions() {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700445 // Read configuration from system
446 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800447 Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL);
Svet Ganov087dce22017-09-07 15:42:16 -0700448
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700449 // Read configuration from the old permissions dir
450 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800451 Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);
Svet Ganov087dce22017-09-07 15:42:16 -0700452
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800453 // Vendors are only allowed to customize these
454 int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS
455 | ALLOW_ASSOCIATIONS;
Jiyong Parkfad99442018-03-12 10:39:07 +0900456 if (Build.VERSION.FIRST_SDK_INT <= Build.VERSION_CODES.O_MR1) {
457 // For backward compatibility
458 vendorPermissionFlag |= (ALLOW_PERMISSIONS | ALLOW_APP_CONFIGS);
459 }
Jaekyun Seoke3b6bf12017-02-16 13:48:30 +0900460 readPermissions(Environment.buildPath(
461 Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
462 readPermissions(Environment.buildPath(
463 Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag);
Svet Ganov087dce22017-09-07 15:42:16 -0700464
Jiyong Park090c6b12017-12-28 12:03:28 +0900465 // Allow ODM to customize system configs as much as Vendor, because /odm is another
466 // vendor partition other than /vendor.
467 int odmPermissionFlag = vendorPermissionFlag;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700468 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800469 Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700470 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800471 Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);
Svet Ganov087dce22017-09-07 15:42:16 -0700472
Steven Morelandd7827fd2018-12-03 10:27:01 -0800473 String skuProperty = SystemProperties.get(SKU_PROPERTY, "");
474 if (!skuProperty.isEmpty()) {
475 String skuDir = "sku_" + skuProperty;
476
477 readPermissions(Environment.buildPath(
478 Environment.getOdmDirectory(), "etc", "sysconfig", skuDir), odmPermissionFlag);
479 readPermissions(Environment.buildPath(
480 Environment.getOdmDirectory(), "etc", "permissions", skuDir),
481 odmPermissionFlag);
482 }
483
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800484 // Allow OEM to customize these
485 int oemPermissionFlag = ALLOW_FEATURES | ALLOW_OEM_PERMISSIONS | ALLOW_ASSOCIATIONS;
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800486 readPermissions(Environment.buildPath(
Svet Ganov087dce22017-09-07 15:42:16 -0700487 Environment.getOemDirectory(), "etc", "sysconfig"), oemPermissionFlag);
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800488 readPermissions(Environment.buildPath(
Svet Ganov087dce22017-09-07 15:42:16 -0700489 Environment.getOemDirectory(), "etc", "permissions"), oemPermissionFlag);
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900490
Hung-ying Tyan38cd31c2018-09-26 15:05:07 +0800491 // Allow Product to customize all system configs
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900492 readPermissions(Environment.buildPath(
Hung-ying Tyan38cd31c2018-09-26 15:05:07 +0800493 Environment.getProductDirectory(), "etc", "sysconfig"), ALLOW_ALL);
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900494 readPermissions(Environment.buildPath(
Hung-ying Tyan38cd31c2018-09-26 15:05:07 +0800495 Environment.getProductDirectory(), "etc", "permissions"), ALLOW_ALL);
Dario Freni2bef1762018-06-01 14:02:08 +0100496
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900497 // Allow /system_ext to customize all system configs
Dario Freni2bef1762018-06-01 14:02:08 +0100498 readPermissions(Environment.buildPath(
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900499 Environment.getSystemExtDirectory(), "etc", "sysconfig"), ALLOW_ALL);
Dario Freni2bef1762018-06-01 14:02:08 +0100500 readPermissions(Environment.buildPath(
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900501 Environment.getSystemExtDirectory(), "etc", "permissions"), ALLOW_ALL);
Luke Huang1414c612019-12-16 20:22:12 +0800502
503 // Skip loading configuration from apex if it is not a system process.
504 if (!isSystemProcess()) {
505 return;
506 }
507 // Read configuration of libs from apex module.
508 // TODO: Use a solid way to filter apex module folders?
509 for (File f: FileUtils.listFilesOrEmpty(Environment.getApexDirectory())) {
510 if (f.isFile() || f.getPath().contains("@")) {
511 continue;
512 }
513 readPermissions(Environment.buildPath(f, "etc", "permissions"), ALLOW_LIBS);
514 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700515 }
516
Bookatz04d7ae52019-08-05 14:07:12 -0700517 @VisibleForTesting
518 public void readPermissions(File libraryDir, int permissionFlag) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700519 // Read permissions from given directory.
520 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800521 if (permissionFlag == ALLOW_ALL) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700522 Slog.w(TAG, "No directory " + libraryDir + ", skipping");
523 }
524 return;
525 }
526 if (!libraryDir.canRead()) {
527 Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
528 return;
529 }
530
531 // Iterate over the files in the directory and scan .xml files
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800532 File platformFile = null;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700533 for (File f : libraryDir.listFiles()) {
Steven Morelandd7827fd2018-12-03 10:27:01 -0800534 if (!f.isFile()) {
535 continue;
536 }
537
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700538 // We'll read platform.xml last
539 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800540 platformFile = f;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700541 continue;
542 }
543
544 if (!f.getPath().endsWith(".xml")) {
545 Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
546 continue;
547 }
548 if (!f.canRead()) {
549 Slog.w(TAG, "Permissions library file " + f + " cannot be read");
550 continue;
551 }
552
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800553 readPermissionsFromXml(f, permissionFlag);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700554 }
555
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800556 // Read platform permissions last so it will take precedence
557 if (platformFile != null) {
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800558 readPermissionsFromXml(platformFile, permissionFlag);
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800559 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700560 }
561
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800562 private void logNotAllowedInPartition(String name, File permFile, XmlPullParser parser) {
563 Slog.w(TAG, "<" + name + "> not allowed in partition of "
564 + permFile + " at " + parser.getPositionDescription());
565 }
566
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800567 private void readPermissionsFromXml(File permFile, int permissionFlag) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700568 FileReader permReader = null;
569 try {
570 permReader = new FileReader(permFile);
571 } catch (FileNotFoundException e) {
572 Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
573 return;
574 }
Felipe Leme1fbe9b52019-10-21 14:20:08 -0700575 Slog.i(TAG, "Reading permissions from " + permFile);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700576
Dianne Hackbornc0e4aaa2014-11-14 10:55:50 -0800577 final boolean lowRam = ActivityManager.isLowRamDeviceStatic();
578
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700579 try {
580 XmlPullParser parser = Xml.newPullParser();
581 parser.setInput(permReader);
582
583 int type;
584 while ((type=parser.next()) != parser.START_TAG
585 && type != parser.END_DOCUMENT) {
586 ;
587 }
588
589 if (type != parser.START_TAG) {
590 throw new XmlPullParserException("No start tag found");
591 }
592
593 if (!parser.getName().equals("permissions") && !parser.getName().equals("config")) {
Dianne Hackbornb3d4cb32015-01-09 09:54:06 -0800594 throw new XmlPullParserException("Unexpected start tag in " + permFile
595 + ": found " + parser.getName() + ", expected 'permissions' or 'config'");
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700596 }
597
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800598 final boolean allowAll = permissionFlag == ALLOW_ALL;
599 final boolean allowLibs = (permissionFlag & ALLOW_LIBS) != 0;
600 final boolean allowFeatures = (permissionFlag & ALLOW_FEATURES) != 0;
601 final boolean allowPermissions = (permissionFlag & ALLOW_PERMISSIONS) != 0;
602 final boolean allowAppConfigs = (permissionFlag & ALLOW_APP_CONFIGS) != 0;
603 final boolean allowPrivappPermissions = (permissionFlag & ALLOW_PRIVAPP_PERMISSIONS)
604 != 0;
605 final boolean allowOemPermissions = (permissionFlag & ALLOW_OEM_PERMISSIONS) != 0;
606 final boolean allowApiWhitelisting = (permissionFlag & ALLOW_HIDDENAPI_WHITELISTING)
607 != 0;
608 final boolean allowAssociations = (permissionFlag & ALLOW_ASSOCIATIONS) != 0;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700609 while (true) {
610 XmlUtils.nextElement(parser);
611 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
612 break;
613 }
614
615 String name = parser.getName();
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800616 if (name == null) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700617 XmlUtils.skipCurrentTag(parser);
618 continue;
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800619 }
620 switch (name) {
621 case "group": {
622 if (allowAll) {
623 String gidStr = parser.getAttributeValue(null, "gid");
624 if (gidStr != null) {
625 int gid = android.os.Process.getGidForName(gidStr);
626 mGlobalGids = appendInt(mGlobalGids, gid);
627 } else {
628 Slog.w(TAG, "<" + name + "> without gid in " + permFile + " at "
goneileb31cd42018-02-28 15:22:08 -0800629 + parser.getPositionDescription());
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800630 }
631 } else {
632 logNotAllowedInPartition(name, permFile, parser);
633 }
634 XmlUtils.skipCurrentTag(parser);
635 } break;
636 case "permission": {
637 if (allowPermissions) {
638 String perm = parser.getAttributeValue(null, "name");
639 if (perm == null) {
640 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
641 + parser.getPositionDescription());
642 XmlUtils.skipCurrentTag(parser);
643 break;
644 }
645 perm = perm.intern();
646 readPermission(parser, perm);
647 } else {
648 logNotAllowedInPartition(name, permFile, parser);
649 XmlUtils.skipCurrentTag(parser);
650 }
651 } break;
652 case "assign-permission": {
653 if (allowPermissions) {
654 String perm = parser.getAttributeValue(null, "name");
655 if (perm == null) {
656 Slog.w(TAG, "<" + name + "> without name in " + permFile
657 + " at " + parser.getPositionDescription());
658 XmlUtils.skipCurrentTag(parser);
659 break;
660 }
661 String uidStr = parser.getAttributeValue(null, "uid");
662 if (uidStr == null) {
663 Slog.w(TAG, "<" + name + "> without uid in " + permFile
664 + " at " + parser.getPositionDescription());
665 XmlUtils.skipCurrentTag(parser);
666 break;
667 }
668 int uid = Process.getUidForName(uidStr);
669 if (uid < 0) {
670 Slog.w(TAG, "<" + name + "> with unknown uid \""
671 + uidStr + " in " + permFile + " at "
672 + parser.getPositionDescription());
673 XmlUtils.skipCurrentTag(parser);
674 break;
675 }
676 perm = perm.intern();
677 ArraySet<String> perms = mSystemPermissions.get(uid);
678 if (perms == null) {
679 perms = new ArraySet<String>();
680 mSystemPermissions.put(uid, perms);
681 }
682 perms.add(perm);
683 } else {
684 logNotAllowedInPartition(name, permFile, parser);
685 }
686 XmlUtils.skipCurrentTag(parser);
687 } break;
688 case "split-permission": {
689 if (allowPermissions) {
690 readSplitPermission(parser, permFile);
691 } else {
692 logNotAllowedInPartition(name, permFile, parser);
693 XmlUtils.skipCurrentTag(parser);
694 }
695 } break;
696 case "library": {
697 if (allowLibs) {
698 String lname = parser.getAttributeValue(null, "name");
699 String lfile = parser.getAttributeValue(null, "file");
700 String ldependency = parser.getAttributeValue(null, "dependency");
701 if (lname == null) {
702 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
703 + parser.getPositionDescription());
704 } else if (lfile == null) {
705 Slog.w(TAG, "<" + name + "> without file in " + permFile + " at "
706 + parser.getPositionDescription());
707 } else {
708 //Log.i(TAG, "Got library " + lname + " in " + lfile);
709 SharedLibraryEntry entry = new SharedLibraryEntry(lname, lfile,
710 ldependency == null ? new String[0] : ldependency.split(":"));
711 mSharedLibraries.put(lname, entry);
712 }
713 } else {
714 logNotAllowedInPartition(name, permFile, parser);
715 }
716 XmlUtils.skipCurrentTag(parser);
717 } break;
718 case "feature": {
719 if (allowFeatures) {
720 String fname = parser.getAttributeValue(null, "name");
721 int fversion = XmlUtils.readIntAttribute(parser, "version", 0);
722 boolean allowed;
723 if (!lowRam) {
724 allowed = true;
725 } else {
726 String notLowRam = parser.getAttributeValue(null, "notLowRam");
727 allowed = !"true".equals(notLowRam);
728 }
729 if (fname == null) {
730 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
731 + parser.getPositionDescription());
732 } else if (allowed) {
733 addFeature(fname, fversion);
734 }
735 } else {
736 logNotAllowedInPartition(name, permFile, parser);
737 }
738 XmlUtils.skipCurrentTag(parser);
739 } break;
740 case "unavailable-feature": {
741 if (allowFeatures) {
742 String fname = parser.getAttributeValue(null, "name");
743 if (fname == null) {
744 Slog.w(TAG, "<" + name + "> without name in " + permFile
745 + " at " + parser.getPositionDescription());
746 } else {
747 mUnavailableFeatures.add(fname);
748 }
749 } else {
750 logNotAllowedInPartition(name, permFile, parser);
751 }
752 XmlUtils.skipCurrentTag(parser);
753 } break;
754 case "allow-in-power-save-except-idle": {
755 if (allowAll) {
756 String pkgname = parser.getAttributeValue(null, "package");
757 if (pkgname == null) {
758 Slog.w(TAG, "<" + name + "> without package in "
759 + permFile + " at " + parser.getPositionDescription());
760 } else {
761 mAllowInPowerSaveExceptIdle.add(pkgname);
762 }
763 } else {
764 logNotAllowedInPartition(name, permFile, parser);
765 }
766 XmlUtils.skipCurrentTag(parser);
767 } break;
768 case "allow-in-power-save": {
769 if (allowAll) {
770 String pkgname = parser.getAttributeValue(null, "package");
771 if (pkgname == null) {
772 Slog.w(TAG, "<" + name + "> without package in "
773 + permFile + " at " + parser.getPositionDescription());
774 } else {
775 mAllowInPowerSave.add(pkgname);
776 }
777 } else {
778 logNotAllowedInPartition(name, permFile, parser);
779 }
780 XmlUtils.skipCurrentTag(parser);
781 } break;
782 case "allow-in-data-usage-save": {
783 if (allowAll) {
784 String pkgname = parser.getAttributeValue(null, "package");
785 if (pkgname == null) {
786 Slog.w(TAG, "<" + name + "> without package in "
787 + permFile + " at " + parser.getPositionDescription());
788 } else {
789 mAllowInDataUsageSave.add(pkgname);
790 }
791 } else {
792 logNotAllowedInPartition(name, permFile, parser);
793 }
794 XmlUtils.skipCurrentTag(parser);
795 } break;
796 case "allow-unthrottled-location": {
797 if (allowAll) {
798 String pkgname = parser.getAttributeValue(null, "package");
799 if (pkgname == null) {
800 Slog.w(TAG, "<" + name + "> without package in "
801 + permFile + " at " + parser.getPositionDescription());
802 } else {
803 mAllowUnthrottledLocation.add(pkgname);
804 }
805 } else {
806 logNotAllowedInPartition(name, permFile, parser);
807 }
808 XmlUtils.skipCurrentTag(parser);
809 } break;
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800810 case "allow-ignore-location-settings": {
811 if (allowAll) {
812 String pkgname = parser.getAttributeValue(null, "package");
813 if (pkgname == null) {
814 Slog.w(TAG, "<" + name + "> without package in "
815 + permFile + " at " + parser.getPositionDescription());
816 } else {
817 mAllowIgnoreLocationSettings.add(pkgname);
818 }
819 } else {
820 logNotAllowedInPartition(name, permFile, parser);
821 }
822 XmlUtils.skipCurrentTag(parser);
823 } break;
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800824 case "allow-implicit-broadcast": {
825 if (allowAll) {
826 String action = parser.getAttributeValue(null, "action");
827 if (action == null) {
828 Slog.w(TAG, "<" + name + "> without action in "
829 + permFile + " at " + parser.getPositionDescription());
830 } else {
831 mAllowImplicitBroadcasts.add(action);
832 }
833 } else {
834 logNotAllowedInPartition(name, permFile, parser);
835 }
836 XmlUtils.skipCurrentTag(parser);
837 } break;
838 case "app-link": {
839 if (allowAppConfigs) {
840 String pkgname = parser.getAttributeValue(null, "package");
841 if (pkgname == null) {
842 Slog.w(TAG, "<" + name + "> without package in " + permFile
843 + " at " + parser.getPositionDescription());
844 } else {
845 mLinkedApps.add(pkgname);
846 }
847 } else {
848 logNotAllowedInPartition(name, permFile, parser);
849 }
850 XmlUtils.skipCurrentTag(parser);
851 } break;
852 case "system-user-whitelisted-app": {
853 if (allowAppConfigs) {
854 String pkgname = parser.getAttributeValue(null, "package");
855 if (pkgname == null) {
856 Slog.w(TAG, "<" + name + "> without package in "
857 + permFile + " at " + parser.getPositionDescription());
858 } else {
859 mSystemUserWhitelistedApps.add(pkgname);
860 }
861 } else {
862 logNotAllowedInPartition(name, permFile, parser);
863 }
864 XmlUtils.skipCurrentTag(parser);
865 } break;
866 case "system-user-blacklisted-app": {
867 if (allowAppConfigs) {
868 String pkgname = parser.getAttributeValue(null, "package");
869 if (pkgname == null) {
870 Slog.w(TAG, "<" + name + "> without package in "
871 + permFile + " at " + parser.getPositionDescription());
872 } else {
873 mSystemUserBlacklistedApps.add(pkgname);
874 }
875 } else {
876 logNotAllowedInPartition(name, permFile, parser);
877 }
878 XmlUtils.skipCurrentTag(parser);
879 } break;
880 case "default-enabled-vr-app": {
881 if (allowAppConfigs) {
882 String pkgname = parser.getAttributeValue(null, "package");
883 String clsname = parser.getAttributeValue(null, "class");
884 if (pkgname == null) {
885 Slog.w(TAG, "<" + name + "> without package in "
886 + permFile + " at " + parser.getPositionDescription());
887 } else if (clsname == null) {
888 Slog.w(TAG, "<" + name + "> without class in "
889 + permFile + " at " + parser.getPositionDescription());
890 } else {
891 mDefaultVrComponents.add(new ComponentName(pkgname, clsname));
892 }
893 } else {
894 logNotAllowedInPartition(name, permFile, parser);
895 }
896 XmlUtils.skipCurrentTag(parser);
897 } break;
Ryan Mitchell4fd8e6f2019-10-07 16:31:34 -0700898 case "component-override": {
Ryan Mitchell61a30322019-10-30 08:52:43 -0700899 readComponentOverrides(parser, permFile);
Ryan Mitchell4fd8e6f2019-10-07 16:31:34 -0700900 XmlUtils.skipCurrentTag(parser);
901 } break;
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800902 case "backup-transport-whitelisted-service": {
903 if (allowFeatures) {
904 String serviceName = parser.getAttributeValue(null, "service");
905 if (serviceName == null) {
906 Slog.w(TAG, "<" + name + "> without service in "
907 + permFile + " at " + parser.getPositionDescription());
908 } else {
909 ComponentName cn = ComponentName.unflattenFromString(serviceName);
910 if (cn == null) {
911 Slog.w(TAG, "<" + name + "> with invalid service name "
912 + serviceName + " in " + permFile
913 + " at " + parser.getPositionDescription());
914 } else {
915 mBackupTransportWhitelist.add(cn);
916 }
917 }
918 } else {
919 logNotAllowedInPartition(name, permFile, parser);
920 }
921 XmlUtils.skipCurrentTag(parser);
922 } break;
923 case "disabled-until-used-preinstalled-carrier-associated-app": {
924 if (allowAppConfigs) {
925 String pkgname = parser.getAttributeValue(null, "package");
926 String carrierPkgname = parser.getAttributeValue(null,
927 "carrierAppPackage");
928 if (pkgname == null || carrierPkgname == null) {
929 Slog.w(TAG, "<" + name
930 + "> without package or carrierAppPackage in " + permFile
931 + " at " + parser.getPositionDescription());
932 } else {
933 List<String> associatedPkgs =
934 mDisabledUntilUsedPreinstalledCarrierAssociatedApps.get(
935 carrierPkgname);
936 if (associatedPkgs == null) {
937 associatedPkgs = new ArrayList<>();
938 mDisabledUntilUsedPreinstalledCarrierAssociatedApps.put(
939 carrierPkgname, associatedPkgs);
940 }
941 associatedPkgs.add(pkgname);
942 }
943 } else {
944 logNotAllowedInPartition(name, permFile, parser);
945 }
946 XmlUtils.skipCurrentTag(parser);
947 } break;
948 case "disabled-until-used-preinstalled-carrier-app": {
949 if (allowAppConfigs) {
950 String pkgname = parser.getAttributeValue(null, "package");
951 if (pkgname == null) {
952 Slog.w(TAG,
953 "<" + name + "> without "
954 + "package in " + permFile + " at "
955 + parser.getPositionDescription());
956 } else {
957 mDisabledUntilUsedPreinstalledCarrierApps.add(pkgname);
958 }
959 } else {
960 logNotAllowedInPartition(name, permFile, parser);
961 }
962 XmlUtils.skipCurrentTag(parser);
963 } break;
964 case "privapp-permissions": {
965 if (allowPrivappPermissions) {
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900966 // privapp permissions from system, vendor, product and system_ext
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800967 // partitions are stored separately. This is to prevent xml files in
968 // the vendor partition from granting permissions to priv apps in the
969 // system partition and vice versa.
970 boolean vendor = permFile.toPath().startsWith(
971 Environment.getVendorDirectory().toPath() + "/")
972 || permFile.toPath().startsWith(
973 Environment.getOdmDirectory().toPath() + "/");
974 boolean product = permFile.toPath().startsWith(
975 Environment.getProductDirectory().toPath() + "/");
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900976 boolean systemExt = permFile.toPath().startsWith(
977 Environment.getSystemExtDirectory().toPath() + "/");
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800978 if (vendor) {
979 readPrivAppPermissions(parser, mVendorPrivAppPermissions,
980 mVendorPrivAppDenyPermissions);
981 } else if (product) {
982 readPrivAppPermissions(parser, mProductPrivAppPermissions,
983 mProductPrivAppDenyPermissions);
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900984 } else if (systemExt) {
985 readPrivAppPermissions(parser, mSystemExtPrivAppPermissions,
986 mSystemExtPrivAppDenyPermissions);
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800987 } else {
988 readPrivAppPermissions(parser, mPrivAppPermissions,
989 mPrivAppDenyPermissions);
990 }
991 } else {
992 logNotAllowedInPartition(name, permFile, parser);
993 XmlUtils.skipCurrentTag(parser);
994 }
995 } break;
996 case "oem-permissions": {
997 if (allowOemPermissions) {
998 readOemPermissions(parser);
999 } else {
1000 logNotAllowedInPartition(name, permFile, parser);
1001 XmlUtils.skipCurrentTag(parser);
1002 }
1003 } break;
1004 case "hidden-api-whitelisted-app": {
1005 if (allowApiWhitelisting) {
1006 String pkgname = parser.getAttributeValue(null, "package");
1007 if (pkgname == null) {
1008 Slog.w(TAG, "<" + name + "> without package in "
1009 + permFile + " at " + parser.getPositionDescription());
1010 } else {
1011 mHiddenApiPackageWhitelist.add(pkgname);
1012 }
1013 } else {
1014 logNotAllowedInPartition(name, permFile, parser);
1015 }
1016 XmlUtils.skipCurrentTag(parser);
1017 } break;
1018 case "allow-association": {
1019 if (allowAssociations) {
1020 String target = parser.getAttributeValue(null, "target");
1021 if (target == null) {
1022 Slog.w(TAG, "<" + name + "> without target in " + permFile
1023 + " at " + parser.getPositionDescription());
1024 XmlUtils.skipCurrentTag(parser);
1025 break;
1026 }
1027 String allowed = parser.getAttributeValue(null, "allowed");
1028 if (allowed == null) {
1029 Slog.w(TAG, "<" + name + "> without allowed in " + permFile
1030 + " at " + parser.getPositionDescription());
1031 XmlUtils.skipCurrentTag(parser);
1032 break;
1033 }
1034 target = target.intern();
1035 allowed = allowed.intern();
1036 ArraySet<String> associations = mAllowedAssociations.get(target);
1037 if (associations == null) {
1038 associations = new ArraySet<>();
1039 mAllowedAssociations.put(target, associations);
1040 }
1041 Slog.i(TAG, "Adding association: " + target + " <- " + allowed);
1042 associations.add(allowed);
1043 } else {
1044 logNotAllowedInPartition(name, permFile, parser);
1045 }
1046 XmlUtils.skipCurrentTag(parser);
1047 } break;
Nikita Ioffe07964b42019-02-28 21:35:02 +00001048 case "bugreport-whitelisted": {
1049 String pkgname = parser.getAttributeValue(null, "package");
1050 if (pkgname == null) {
1051 Slog.w(TAG, "<" + name + "> without package in " + permFile
1052 + " at " + parser.getPositionDescription());
1053 } else {
1054 mBugreportWhitelistedPackages.add(pkgname);
1055 }
Nikita Ioffe08146ef2019-03-13 17:04:21 +00001056 XmlUtils.skipCurrentTag(parser);
Nikita Ioffe07964b42019-02-28 21:35:02 +00001057 } break;
Bookatz04d7ae52019-08-05 14:07:12 -07001058 case "install-in-user-type": {
1059 // NB: We allow any directory permission to declare install-in-user-type.
1060 readInstallInUserType(parser,
1061 mPackageToUserTypeWhitelist, mPackageToUserTypeBlacklist);
1062 } break;
Winsond9d17362019-10-02 12:41:29 -07001063 case "named-actor": {
1064 String namespace = TextUtils.safeIntern(
1065 parser.getAttributeValue(null, "namespace"));
1066 String actorName = parser.getAttributeValue(null, "name");
1067 String pkgName = TextUtils.safeIntern(
1068 parser.getAttributeValue(null, "package"));
1069 if (TextUtils.isEmpty(namespace)) {
1070 Slog.wtf(TAG, "<" + name + "> without namespace in " + permFile
1071 + " at " + parser.getPositionDescription());
1072 } else if (TextUtils.isEmpty(actorName)) {
1073 Slog.wtf(TAG, "<" + name + "> without actor name in " + permFile
1074 + " at " + parser.getPositionDescription());
1075 } else if (TextUtils.isEmpty(pkgName)) {
1076 Slog.wtf(TAG, "<" + name + "> without package name in " + permFile
1077 + " at " + parser.getPositionDescription());
1078 } else if ("android".equalsIgnoreCase(namespace)) {
1079 throw new IllegalStateException("Defining " + actorName + " as "
1080 + pkgName + " for the android namespace is not allowed");
1081 } else {
1082 if (mNamedActors == null) {
1083 mNamedActors = new ArrayMap<>();
1084 }
1085
Ram Muthiah637138d2019-12-11 17:37:37 -08001086 ArrayMap<String, String> nameToPkgMap = mNamedActors.get(namespace);
Winsond9d17362019-10-02 12:41:29 -07001087 if (nameToPkgMap == null) {
1088 nameToPkgMap = new ArrayMap<>();
1089 mNamedActors.put(namespace, nameToPkgMap);
1090 } else if (nameToPkgMap.containsKey(actorName)) {
1091 String existing = nameToPkgMap.get(actorName);
1092 throw new IllegalStateException("Duplicate actor definition for "
1093 + namespace + "/" + actorName
1094 + "; defined as both " + existing + " and " + pkgName);
1095 }
1096
1097 nameToPkgMap.put(actorName, pkgName);
1098 }
1099 XmlUtils.skipCurrentTag(parser);
1100 } break;
JW Wangf0a70b12019-12-11 17:12:02 +08001101 case "rollback-whitelisted-app": {
1102 String pkgname = parser.getAttributeValue(null, "package");
1103 if (pkgname == null) {
1104 Slog.w(TAG, "<" + name + "> without package in " + permFile
1105 + " at " + parser.getPositionDescription());
1106 } else {
1107 mRollbackWhitelistedPackages.add(pkgname);
1108 }
1109 XmlUtils.skipCurrentTag(parser);
1110 } break;
Dianne Hackborn769b2e72018-12-05 08:51:20 -08001111 default: {
1112 Slog.w(TAG, "Tag " + name + " is unknown in "
1113 + permFile + " at " + parser.getPositionDescription());
1114 XmlUtils.skipCurrentTag(parser);
1115 } break;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001116 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001117 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001118 } catch (XmlPullParserException e) {
Jeff Sharkey1c4ae802014-12-19 11:08:55 -08001119 Slog.w(TAG, "Got exception parsing permissions.", e);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001120 } catch (IOException e) {
Jeff Sharkey1c4ae802014-12-19 11:08:55 -08001121 Slog.w(TAG, "Got exception parsing permissions.", e);
1122 } finally {
1123 IoUtils.closeQuietly(permReader);
1124 }
1125
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -07001126 // Some devices can be field-converted to FBE, so offer to splice in
1127 // those features if not already defined by the static config
Paul Lawrence20be5d62016-02-26 13:51:17 -08001128 if (StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkey115d2c12016-02-15 17:25:57 -07001129 addFeature(PackageManager.FEATURE_FILE_BASED_ENCRYPTION, 0);
1130 addFeature(PackageManager.FEATURE_SECURELY_REMOVES_USERS, 0);
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -07001131 }
1132
Jeff Sharkey8eb783b2018-01-04 16:46:48 -07001133 // Help legacy devices that may not have updated their static config
1134 if (StorageManager.hasAdoptable()) {
1135 addFeature(PackageManager.FEATURE_ADOPTABLE_STORAGE, 0);
1136 }
1137
Dianne Hackborn2a103f12017-08-08 15:50:31 -07001138 if (ActivityManager.isLowRamDeviceStatic()) {
1139 addFeature(PackageManager.FEATURE_RAM_LOW, 0);
1140 } else {
1141 addFeature(PackageManager.FEATURE_RAM_NORMAL, 0);
1142 }
1143
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -07001144 for (String featureName : mUnavailableFeatures) {
1145 removeFeature(featureName);
1146 }
1147 }
1148
Jeff Sharkey115d2c12016-02-15 17:25:57 -07001149 private void addFeature(String name, int version) {
1150 FeatureInfo fi = mAvailableFeatures.get(name);
1151 if (fi == null) {
1152 fi = new FeatureInfo();
1153 fi.name = name;
1154 fi.version = version;
1155 mAvailableFeatures.put(name, fi);
1156 } else {
1157 fi.version = Math.max(fi.version, version);
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -07001158 }
1159 }
1160
Jeff Sharkey115d2c12016-02-15 17:25:57 -07001161 private void removeFeature(String name) {
1162 if (mAvailableFeatures.remove(name) != null) {
1163 Slog.d(TAG, "Removed unavailable feature " + name);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001164 }
1165 }
1166
1167 void readPermission(XmlPullParser parser, String name)
1168 throws IOException, XmlPullParserException {
Jeff Sharkey00f39042015-03-23 16:51:22 -07001169 if (mPermissions.containsKey(name)) {
1170 throw new IllegalStateException("Duplicate permission definition for " + name);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001171 }
Jeff Sharkey00f39042015-03-23 16:51:22 -07001172
1173 final boolean perUser = XmlUtils.readBooleanAttribute(parser, "perUser", false);
1174 final PermissionEntry perm = new PermissionEntry(name, perUser);
1175 mPermissions.put(name, perm);
1176
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001177 int outerDepth = parser.getDepth();
1178 int type;
1179 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1180 && (type != XmlPullParser.END_TAG
1181 || parser.getDepth() > outerDepth)) {
1182 if (type == XmlPullParser.END_TAG
1183 || type == XmlPullParser.TEXT) {
1184 continue;
1185 }
1186
1187 String tagName = parser.getName();
1188 if ("group".equals(tagName)) {
1189 String gidStr = parser.getAttributeValue(null, "gid");
1190 if (gidStr != null) {
1191 int gid = Process.getGidForName(gidStr);
1192 perm.gids = appendInt(perm.gids, gid);
1193 } else {
1194 Slog.w(TAG, "<group> without gid at "
1195 + parser.getPositionDescription());
1196 }
1197 }
1198 XmlUtils.skipCurrentTag(parser);
1199 }
1200 }
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001201
Jiyong Park002fdbd2017-02-13 20:50:31 +09001202 private void readPrivAppPermissions(XmlPullParser parser,
1203 ArrayMap<String, ArraySet<String>> grantMap,
1204 ArrayMap<String, ArraySet<String>> denyMap)
1205 throws IOException, XmlPullParserException {
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001206 String packageName = parser.getAttributeValue(null, "package");
1207 if (TextUtils.isEmpty(packageName)) {
1208 Slog.w(TAG, "package is required for <privapp-permissions> in "
1209 + parser.getPositionDescription());
1210 return;
1211 }
1212
Jiyong Park002fdbd2017-02-13 20:50:31 +09001213 ArraySet<String> permissions = grantMap.get(packageName);
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001214 if (permissions == null) {
1215 permissions = new ArraySet<>();
1216 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09001217 ArraySet<String> denyPermissions = denyMap.get(packageName);
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001218 int depth = parser.getDepth();
1219 while (XmlUtils.nextElementWithin(parser, depth)) {
1220 String name = parser.getName();
1221 if ("permission".equals(name)) {
1222 String permName = parser.getAttributeValue(null, "name");
1223 if (TextUtils.isEmpty(permName)) {
1224 Slog.w(TAG, "name is required for <permission> in "
1225 + parser.getPositionDescription());
1226 continue;
1227 }
1228 permissions.add(permName);
Todd Kennedy74629e32017-08-15 14:48:07 -07001229 } else if ("deny-permission".equals(name)) {
1230 String permName = parser.getAttributeValue(null, "name");
1231 if (TextUtils.isEmpty(permName)) {
1232 Slog.w(TAG, "name is required for <deny-permission> in "
1233 + parser.getPositionDescription());
1234 continue;
1235 }
1236 if (denyPermissions == null) {
1237 denyPermissions = new ArraySet<>();
1238 }
1239 denyPermissions.add(permName);
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001240 }
1241 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09001242 grantMap.put(packageName, permissions);
Todd Kennedy74629e32017-08-15 14:48:07 -07001243 if (denyPermissions != null) {
Jiyong Park002fdbd2017-02-13 20:50:31 +09001244 denyMap.put(packageName, denyPermissions);
Todd Kennedy74629e32017-08-15 14:48:07 -07001245 }
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001246 }
Svet Ganov087dce22017-09-07 15:42:16 -07001247
Bookatz04d7ae52019-08-05 14:07:12 -07001248 private void readInstallInUserType(XmlPullParser parser,
1249 Map<String, Set<String>> doInstallMap,
1250 Map<String, Set<String>> nonInstallMap)
1251 throws IOException, XmlPullParserException {
1252 final String packageName = parser.getAttributeValue(null, "package");
1253 if (TextUtils.isEmpty(packageName)) {
1254 Slog.w(TAG, "package is required for <install-in-user-type> in "
1255 + parser.getPositionDescription());
1256 return;
1257 }
1258
1259 Set<String> userTypesYes = doInstallMap.get(packageName);
1260 Set<String> userTypesNo = nonInstallMap.get(packageName);
1261 final int depth = parser.getDepth();
1262 while (XmlUtils.nextElementWithin(parser, depth)) {
1263 final String name = parser.getName();
1264 if ("install-in".equals(name)) {
1265 final String userType = parser.getAttributeValue(null, "user-type");
1266 if (TextUtils.isEmpty(userType)) {
1267 Slog.w(TAG, "user-type is required for <install-in-user-type> in "
1268 + parser.getPositionDescription());
1269 continue;
1270 }
1271 if (userTypesYes == null) {
1272 userTypesYes = new ArraySet<>();
1273 doInstallMap.put(packageName, userTypesYes);
1274 }
1275 userTypesYes.add(userType);
1276 } else if ("do-not-install-in".equals(name)) {
1277 final String userType = parser.getAttributeValue(null, "user-type");
1278 if (TextUtils.isEmpty(userType)) {
1279 Slog.w(TAG, "user-type is required for <install-in-user-type> in "
1280 + parser.getPositionDescription());
1281 continue;
1282 }
1283 if (userTypesNo == null) {
1284 userTypesNo = new ArraySet<>();
1285 nonInstallMap.put(packageName, userTypesNo);
1286 }
1287 userTypesNo.add(userType);
1288 } else {
1289 Slog.w(TAG, "unrecognized tag in <install-in-user-type> in "
1290 + parser.getPositionDescription());
1291 }
1292 }
1293 }
1294
Svet Ganov087dce22017-09-07 15:42:16 -07001295 void readOemPermissions(XmlPullParser parser) throws IOException, XmlPullParserException {
1296 final String packageName = parser.getAttributeValue(null, "package");
1297 if (TextUtils.isEmpty(packageName)) {
1298 Slog.w(TAG, "package is required for <oem-permissions> in "
1299 + parser.getPositionDescription());
1300 return;
1301 }
1302
1303 ArrayMap<String, Boolean> permissions = mOemPermissions.get(packageName);
1304 if (permissions == null) {
1305 permissions = new ArrayMap<>();
1306 }
1307 final int depth = parser.getDepth();
1308 while (XmlUtils.nextElementWithin(parser, depth)) {
1309 final String name = parser.getName();
1310 if ("permission".equals(name)) {
1311 final String permName = parser.getAttributeValue(null, "name");
1312 if (TextUtils.isEmpty(permName)) {
1313 Slog.w(TAG, "name is required for <permission> in "
1314 + parser.getPositionDescription());
1315 continue;
1316 }
1317 permissions.put(permName, Boolean.TRUE);
1318 } else if ("deny-permission".equals(name)) {
1319 String permName = parser.getAttributeValue(null, "name");
1320 if (TextUtils.isEmpty(permName)) {
1321 Slog.w(TAG, "name is required for <deny-permission> in "
1322 + parser.getPositionDescription());
1323 continue;
1324 }
1325 permissions.put(permName, Boolean.FALSE);
1326 }
1327 }
1328 mOemPermissions.put(packageName, permissions);
1329 }
Zimuzocc2932f2018-10-29 16:04:41 +00001330
1331 private void readSplitPermission(XmlPullParser parser, File permFile)
1332 throws IOException, XmlPullParserException {
1333 String splitPerm = parser.getAttributeValue(null, "name");
1334 if (splitPerm == null) {
1335 Slog.w(TAG, "<split-permission> without name in " + permFile + " at "
1336 + parser.getPositionDescription());
1337 XmlUtils.skipCurrentTag(parser);
1338 return;
1339 }
1340 String targetSdkStr = parser.getAttributeValue(null, "targetSdk");
1341 int targetSdk = Build.VERSION_CODES.CUR_DEVELOPMENT + 1;
1342 if (!TextUtils.isEmpty(targetSdkStr)) {
1343 try {
1344 targetSdk = Integer.parseInt(targetSdkStr);
1345 } catch (NumberFormatException e) {
1346 Slog.w(TAG, "<split-permission> targetSdk not an integer in " + permFile + " at "
1347 + parser.getPositionDescription());
1348 XmlUtils.skipCurrentTag(parser);
1349 return;
1350 }
1351 }
1352 final int depth = parser.getDepth();
1353 List<String> newPermissions = new ArrayList<>();
1354 while (XmlUtils.nextElementWithin(parser, depth)) {
1355 String name = parser.getName();
1356 if ("new-permission".equals(name)) {
1357 final String newName = parser.getAttributeValue(null, "name");
1358 if (TextUtils.isEmpty(newName)) {
1359 Slog.w(TAG, "name is required for <new-permission> in "
1360 + parser.getPositionDescription());
1361 continue;
1362 }
1363 newPermissions.add(newName);
1364 } else {
1365 XmlUtils.skipCurrentTag(parser);
1366 }
1367 }
1368 if (!newPermissions.isEmpty()) {
1369 mSplitPermissions.add(new SplitPermissionInfo(splitPerm, newPermissions, targetSdk));
1370 }
1371 }
Anthony Hughde787d42019-08-22 15:35:48 -07001372
Ryan Mitchell4fd8e6f2019-10-07 16:31:34 -07001373 private void readComponentOverrides(XmlPullParser parser, File permFile)
1374 throws IOException, XmlPullParserException {
1375 String pkgname = parser.getAttributeValue(null, "package");
1376 if (pkgname == null) {
1377 Slog.w(TAG, "<component-override> without package in "
1378 + permFile + " at " + parser.getPositionDescription());
1379 return;
1380 }
1381
1382 pkgname = pkgname.intern();
1383
1384 final int depth = parser.getDepth();
1385 while (XmlUtils.nextElementWithin(parser, depth)) {
1386 String name = parser.getName();
1387 if ("component".equals(name)) {
1388 String clsname = parser.getAttributeValue(null, "class");
1389 String enabled = parser.getAttributeValue(null, "enabled");
1390 if (clsname == null) {
1391 Slog.w(TAG, "<component> without class in "
1392 + permFile + " at " + parser.getPositionDescription());
1393 return;
1394 } else if (enabled == null) {
1395 Slog.w(TAG, "<component> without enabled in "
1396 + permFile + " at " + parser.getPositionDescription());
1397 return;
1398 }
1399
1400 if (clsname.startsWith(".")) {
1401 clsname = pkgname + clsname;
1402 }
1403
1404 clsname = clsname.intern();
1405
1406 ArrayMap<String, Boolean> componentEnabledStates =
1407 mPackageComponentEnabledState.get(pkgname);
1408 if (componentEnabledStates == null) {
1409 componentEnabledStates = new ArrayMap<>();
1410 mPackageComponentEnabledState.put(pkgname,
1411 componentEnabledStates);
1412 }
1413
1414 componentEnabledStates.put(clsname, !"false".equals(enabled));
1415 } else {
1416 XmlUtils.skipCurrentTag(parser);
1417 }
1418 }
1419 }
1420
Anthony Hughde787d42019-08-22 15:35:48 -07001421 private static boolean isSystemProcess() {
1422 return Process.myUid() == Process.SYSTEM_UID;
1423 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001424}