blob: ed7f5de83fd14527244742d20688a7f69ae4e1e9 [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
Dianne Hackbornc0e4aaa2014-11-14 10:55:50 -080021import android.app.ActivityManager;
Ruben Brunk98576cf2016-03-07 18:54:28 -080022import android.content.ComponentName;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070023import android.content.pm.FeatureInfo;
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -070024import android.content.pm.PackageManager;
Jiyong Parkfad99442018-03-12 10:39:07 +090025import android.os.Build;
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -070026import android.os.Environment;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070027import android.os.Process;
Steven Morelandd7827fd2018-12-03 10:27:01 -080028import android.os.SystemProperties;
Felipe Leme3eb78092019-10-22 09:22:20 -070029import android.os.Trace;
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -070030import android.os.storage.StorageManager;
Zimuzocc2932f2018-10-29 16:04:41 +000031import android.permission.PermissionManager.SplitPermissionInfo;
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -080032import android.text.TextUtils;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070033import android.util.ArrayMap;
34import android.util.ArraySet;
35import android.util.Slog;
36import android.util.SparseArray;
Felipe Leme3eb78092019-10-22 09:22:20 -070037import android.util.TimingsTraceLog;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070038import android.util.Xml;
Jeff Sharkey1c4ae802014-12-19 11:08:55 -080039
Bookatz04d7ae52019-08-05 14:07:12 -070040import com.android.internal.annotations.VisibleForTesting;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070041import com.android.internal.util.XmlUtils;
Jeff Sharkey1c4ae802014-12-19 11:08:55 -080042
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -070043import libcore.io.IoUtils;
44
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070045import org.xmlpull.v1.XmlPullParser;
46import org.xmlpull.v1.XmlPullParserException;
47
48import java.io.File;
49import java.io.FileNotFoundException;
50import java.io.FileReader;
51import java.io.IOException;
Jeff Davidson24b9d962016-07-21 12:35:10 -070052import java.util.ArrayList;
Svet Ganov087dce22017-09-07 15:42:16 -070053import java.util.Collections;
Jeff Davidson24b9d962016-07-21 12:35:10 -070054import java.util.List;
Svet Ganov087dce22017-09-07 15:42:16 -070055import java.util.Map;
Bookatz04d7ae52019-08-05 14:07:12 -070056import java.util.Set;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070057
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070058/**
59 * Loads global system configuration info.
Anthony Hughde787d42019-08-22 15:35:48 -070060 * Note: Initializing this class hits the disk and is slow. This class should generally only be
61 * accessed by the system_server process.
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070062 */
63public class SystemConfig {
64 static final String TAG = "SystemConfig";
65
66 static SystemConfig sInstance;
67
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +080068 // permission flag, determines which types of configuration are allowed to be read
69 private static final int ALLOW_FEATURES = 0x01;
70 private static final int ALLOW_LIBS = 0x02;
71 private static final int ALLOW_PERMISSIONS = 0x04;
72 private static final int ALLOW_APP_CONFIGS = 0x08;
Jaekyun Seoke3b6bf12017-02-16 13:48:30 +090073 private static final int ALLOW_PRIVAPP_PERMISSIONS = 0x10;
Svet Ganov087dce22017-09-07 15:42:16 -070074 private static final int ALLOW_OEM_PERMISSIONS = 0x20;
Mathew Inwood4693a752018-02-20 16:04:25 +000075 private static final int ALLOW_HIDDENAPI_WHITELISTING = 0x40;
Dianne Hackborn769b2e72018-12-05 08:51:20 -080076 private static final int ALLOW_ASSOCIATIONS = 0x80;
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +080077 private static final int ALLOW_ALL = ~0;
78
Steven Morelandd7827fd2018-12-03 10:27:01 -080079 // property for runtime configuration differentiation
80 private static final String SKU_PROPERTY = "ro.boot.product.hardware.sku";
81
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070082 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
83 int[] mGlobalGids;
84
85 // These are the built-in uid -> permission mappings that were read from the
86 // system configuration files.
Jeff Sharkey9f837a92014-10-24 12:07:24 -070087 final SparseArray<ArraySet<String>> mSystemPermissions = new SparseArray<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070088
Zimuzocc2932f2018-10-29 16:04:41 +000089 final ArrayList<SplitPermissionInfo> mSplitPermissions = new ArrayList<>();
90
Ben Lin71c16d72018-12-06 18:34:51 -080091 public static final class SharedLibraryEntry {
92 public final String name;
93 public final String filename;
94 public final String[] dependencies;
95
96 SharedLibraryEntry(String name, String filename, String[] dependencies) {
97 this.name = name;
98 this.filename = filename;
99 this.dependencies = dependencies;
100 }
101 }
102
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700103 // These are the built-in shared libraries that were read from the
Ben Lin71c16d72018-12-06 18:34:51 -0800104 // system configuration files. Keys are the library names; values are
105 // the individual entries that contain information such as filename
106 // and dependencies.
107 final ArrayMap<String, SharedLibraryEntry> mSharedLibraries = new ArrayMap<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700108
109 // These are the features this devices supports that were read from the
110 // system configuration files.
Jeff Sharkey9f837a92014-10-24 12:07:24 -0700111 final ArrayMap<String, FeatureInfo> mAvailableFeatures = new ArrayMap<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700112
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800113 // These are the features which this device doesn't support; the OEM
114 // partition uses these to opt-out of features from the system image.
115 final ArraySet<String> mUnavailableFeatures = new ArraySet<>();
116
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700117 public static final class PermissionEntry {
118 public final String name;
119 public int[] gids;
Jeff Sharkey00f39042015-03-23 16:51:22 -0700120 public boolean perUser;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700121
Jeff Sharkey00f39042015-03-23 16:51:22 -0700122 PermissionEntry(String name, boolean perUser) {
123 this.name = name;
124 this.perUser = perUser;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700125 }
126 }
127
128 // These are the permission -> gid mappings that were read from the
129 // system configuration files.
Dianne Hackbornbb8aa5a2014-09-17 13:20:38 -0700130 final ArrayMap<String, PermissionEntry> mPermissions = new ArrayMap<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700131
132 // These are the packages that are white-listed to be able to run in the
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700133 // background while in power save mode (but not whitelisted from device idle modes),
134 // as read from the configuration files.
135 final ArraySet<String> mAllowInPowerSaveExceptIdle = new ArraySet<>();
136
137 // These are the packages that are white-listed to be able to run in the
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700138 // background while in power save mode, as read from the configuration files.
Dianne Hackbornbb8aa5a2014-09-17 13:20:38 -0700139 final ArraySet<String> mAllowInPowerSave = new ArraySet<>();
140
Felipe Lemea9505cc2016-02-26 10:28:41 -0800141 // These are the packages that are white-listed to be able to run in the
142 // background while in data-usage save mode, as read from the configuration files.
143 final ArraySet<String> mAllowInDataUsageSave = new ArraySet<>();
144
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800145 // These are the packages that are white-listed to be able to run background location
146 // without throttling, as read from the configuration files.
147 final ArraySet<String> mAllowUnthrottledLocation = new ArraySet<>();
148
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800149 // These are the packages that are white-listed to be able to retrieve location even when user
150 // location settings are off, for emergency purposes, as read from the configuration files.
151 final ArraySet<String> mAllowIgnoreLocationSettings = new ArraySet<>();
152
Christopher Tate42a386b2016-11-07 12:21:21 -0800153 // These are the action strings of broadcasts which are whitelisted to
154 // be delivered anonymously even to apps which target O+.
155 final ArraySet<String> mAllowImplicitBroadcasts = new ArraySet<>();
156
Christopher Tate01e18642015-07-07 18:10:38 -0700157 // These are the package names of apps which should be in the 'always'
158 // URL-handling state upon factory reset.
159 final ArraySet<String> mLinkedApps = new ArraySet<>();
160
Fyodor Kupolov7db5af12015-07-31 16:50:27 -0700161 // These are the packages that are whitelisted to be able to run as system user
162 final ArraySet<String> mSystemUserWhitelistedApps = new ArraySet<>();
163
164 // These are the packages that should not run under system user
165 final ArraySet<String> mSystemUserBlacklistedApps = new ArraySet<>();
166
Ruben Brunk98576cf2016-03-07 18:54:28 -0800167 // These are the components that are enabled by default as VR mode listener services.
168 final ArraySet<ComponentName> mDefaultVrComponents = new ArraySet<>();
169
Christopher Tate494df792016-05-10 17:05:38 -0700170 // These are the permitted backup transport service components
171 final ArraySet<ComponentName> mBackupTransportWhitelist = new ArraySet<>();
172
Ryan Mitchell4fd8e6f2019-10-07 16:31:34 -0700173 // These are packages mapped to maps of component class name to default enabled state.
174 final ArrayMap<String, ArrayMap<String, Boolean>> mPackageComponentEnabledState =
175 new ArrayMap<>();
176
Mathew Inwood4693a752018-02-20 16:04:25 +0000177 // Package names that are exempted from private API blacklisting
178 final ArraySet<String> mHiddenApiPackageWhitelist = new ArraySet<>();
179
goneileb31cd42018-02-28 15:22:08 -0800180 // The list of carrier applications which should be disabled until used.
181 // This function suppresses update notifications for these pre-installed apps.
182 // In SubscriptionInfoUpdater, the listed applications are disabled until used when all of the
183 // following conditions are met.
184 // 1. Not currently carrier-privileged according to the inserted SIM
185 // 2. Pre-installed
186 // 3. In the default state (enabled but not explicitly)
187 // And SubscriptionInfoUpdater undoes this and marks the app enabled when a SIM is inserted
188 // that marks the app as carrier privileged. It also grants the app default permissions
189 // for Phone and Location. As such, apps MUST only ever be added to this list if they
190 // obtain user consent to access their location through other means.
191 final ArraySet<String> mDisabledUntilUsedPreinstalledCarrierApps = new ArraySet<>();
192
Jeff Davidson24b9d962016-07-21 12:35:10 -0700193 // These are the packages of carrier-associated apps which should be disabled until used until
194 // a SIM is inserted which grants carrier privileges to that carrier app.
195 final ArrayMap<String, List<String>> mDisabledUntilUsedPreinstalledCarrierAssociatedApps =
196 new ArrayMap<>();
197
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800198 final ArrayMap<String, ArraySet<String>> mPrivAppPermissions = new ArrayMap<>();
Todd Kennedy74629e32017-08-15 14:48:07 -0700199 final ArrayMap<String, ArraySet<String>> mPrivAppDenyPermissions = new ArrayMap<>();
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800200
Jiyong Park002fdbd2017-02-13 20:50:31 +0900201 final ArrayMap<String, ArraySet<String>> mVendorPrivAppPermissions = new ArrayMap<>();
202 final ArrayMap<String, ArraySet<String>> mVendorPrivAppDenyPermissions = new ArrayMap<>();
203
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900204 final ArrayMap<String, ArraySet<String>> mProductPrivAppPermissions = new ArrayMap<>();
205 final ArrayMap<String, ArraySet<String>> mProductPrivAppDenyPermissions = new ArrayMap<>();
206
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900207 final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppPermissions = new ArrayMap<>();
208 final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppDenyPermissions = new ArrayMap<>();
Dario Freni2bef1762018-06-01 14:02:08 +0100209
Svet Ganov087dce22017-09-07 15:42:16 -0700210 final ArrayMap<String, ArrayMap<String, Boolean>> mOemPermissions = new ArrayMap<>();
211
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800212 // Allowed associations between applications. If there are any entries
213 // for an app, those are the only associations allowed; otherwise, all associations
214 // are allowed. Allowing an association from app A to app B means app A can not
215 // associate with any other apps, but does not limit what apps B can associate with.
216 final ArrayMap<String, ArraySet<String>> mAllowedAssociations = new ArrayMap<>();
217
Nikita Ioffe07964b42019-02-28 21:35:02 +0000218 private final ArraySet<String> mBugreportWhitelistedPackages = new ArraySet<>();
219
Bookatz04d7ae52019-08-05 14:07:12 -0700220 // Map of packagesNames to userTypes. Stored temporarily until cleared by UserManagerService().
221 private ArrayMap<String, Set<String>> mPackageToUserTypeWhitelist = new ArrayMap<>();
222 private ArrayMap<String, Set<String>> mPackageToUserTypeBlacklist = new ArrayMap<>();
223
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700224 public static SystemConfig getInstance() {
Anthony Hughde787d42019-08-22 15:35:48 -0700225 if (!isSystemProcess()) {
226 Slog.wtf(TAG, "SystemConfig is being accessed by a process other than "
227 + "system_server.");
228 }
229
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700230 synchronized (SystemConfig.class) {
231 if (sInstance == null) {
232 sInstance = new SystemConfig();
233 }
234 return sInstance;
235 }
236 }
237
238 public int[] getGlobalGids() {
239 return mGlobalGids;
240 }
241
Jeff Sharkey9f837a92014-10-24 12:07:24 -0700242 public SparseArray<ArraySet<String>> getSystemPermissions() {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700243 return mSystemPermissions;
244 }
245
Zimuzocc2932f2018-10-29 16:04:41 +0000246 public ArrayList<SplitPermissionInfo> getSplitPermissions() {
247 return mSplitPermissions;
248 }
249
Ben Lin71c16d72018-12-06 18:34:51 -0800250 public ArrayMap<String, SharedLibraryEntry> getSharedLibraries() {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700251 return mSharedLibraries;
252 }
253
Jeff Sharkey9f837a92014-10-24 12:07:24 -0700254 public ArrayMap<String, FeatureInfo> getAvailableFeatures() {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700255 return mAvailableFeatures;
256 }
257
258 public ArrayMap<String, PermissionEntry> getPermissions() {
259 return mPermissions;
260 }
261
Christopher Tate42a386b2016-11-07 12:21:21 -0800262 public ArraySet<String> getAllowImplicitBroadcasts() {
263 return mAllowImplicitBroadcasts;
264 }
265
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700266 public ArraySet<String> getAllowInPowerSaveExceptIdle() {
267 return mAllowInPowerSaveExceptIdle;
268 }
269
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700270 public ArraySet<String> getAllowInPowerSave() {
271 return mAllowInPowerSave;
272 }
273
Felipe Lemea9505cc2016-02-26 10:28:41 -0800274 public ArraySet<String> getAllowInDataUsageSave() {
275 return mAllowInDataUsageSave;
276 }
277
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800278 public ArraySet<String> getAllowUnthrottledLocation() {
279 return mAllowUnthrottledLocation;
280 }
281
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800282 public ArraySet<String> getAllowIgnoreLocationSettings() {
283 return mAllowIgnoreLocationSettings;
284 }
285
Christopher Tate01e18642015-07-07 18:10:38 -0700286 public ArraySet<String> getLinkedApps() {
287 return mLinkedApps;
288 }
289
Fyodor Kupolov7db5af12015-07-31 16:50:27 -0700290 public ArraySet<String> getSystemUserWhitelistedApps() {
291 return mSystemUserWhitelistedApps;
292 }
293
294 public ArraySet<String> getSystemUserBlacklistedApps() {
295 return mSystemUserBlacklistedApps;
296 }
297
Mathew Inwood4693a752018-02-20 16:04:25 +0000298 public ArraySet<String> getHiddenApiWhitelistedApps() {
299 return mHiddenApiPackageWhitelist;
300 }
301
Ruben Brunk98576cf2016-03-07 18:54:28 -0800302 public ArraySet<ComponentName> getDefaultVrComponents() {
303 return mDefaultVrComponents;
304 }
305
Christopher Tate494df792016-05-10 17:05:38 -0700306 public ArraySet<ComponentName> getBackupTransportWhitelist() {
307 return mBackupTransportWhitelist;
308 }
309
Ryan Mitchell4fd8e6f2019-10-07 16:31:34 -0700310 public ArrayMap<String, Boolean> getComponentsEnabledStates(String packageName) {
311 return mPackageComponentEnabledState.get(packageName);
312 }
313
goneileb31cd42018-02-28 15:22:08 -0800314 public ArraySet<String> getDisabledUntilUsedPreinstalledCarrierApps() {
315 return mDisabledUntilUsedPreinstalledCarrierApps;
316 }
317
Jeff Davidson24b9d962016-07-21 12:35:10 -0700318 public ArrayMap<String, List<String>> getDisabledUntilUsedPreinstalledCarrierAssociatedApps() {
319 return mDisabledUntilUsedPreinstalledCarrierAssociatedApps;
320 }
321
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800322 public ArraySet<String> getPrivAppPermissions(String packageName) {
323 return mPrivAppPermissions.get(packageName);
324 }
325
Todd Kennedy74629e32017-08-15 14:48:07 -0700326 public ArraySet<String> getPrivAppDenyPermissions(String packageName) {
327 return mPrivAppDenyPermissions.get(packageName);
328 }
329
Jiyong Park002fdbd2017-02-13 20:50:31 +0900330 public ArraySet<String> getVendorPrivAppPermissions(String packageName) {
331 return mVendorPrivAppPermissions.get(packageName);
332 }
333
334 public ArraySet<String> getVendorPrivAppDenyPermissions(String packageName) {
335 return mVendorPrivAppDenyPermissions.get(packageName);
336 }
337
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900338 public ArraySet<String> getProductPrivAppPermissions(String packageName) {
339 return mProductPrivAppPermissions.get(packageName);
340 }
341
342 public ArraySet<String> getProductPrivAppDenyPermissions(String packageName) {
343 return mProductPrivAppDenyPermissions.get(packageName);
344 }
345
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900346 /**
347 * Read from "permission" tags in /system_ext/etc/permissions/*.xml
348 * @return Set of privileged permissions that are explicitly granted.
349 */
350 public ArraySet<String> getSystemExtPrivAppPermissions(String packageName) {
351 return mSystemExtPrivAppPermissions.get(packageName);
Dario Freni2bef1762018-06-01 14:02:08 +0100352 }
353
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900354 /**
355 * Read from "deny-permission" tags in /system_ext/etc/permissions/*.xml
356 * @return Set of privileged permissions that are explicitly denied.
357 */
358 public ArraySet<String> getSystemExtPrivAppDenyPermissions(String packageName) {
359 return mSystemExtPrivAppDenyPermissions.get(packageName);
Dario Freni2bef1762018-06-01 14:02:08 +0100360 }
361
Svet Ganov087dce22017-09-07 15:42:16 -0700362 public Map<String, Boolean> getOemPermissions(String packageName) {
363 final Map<String, Boolean> oemPermissions = mOemPermissions.get(packageName);
364 if (oemPermissions != null) {
365 return oemPermissions;
366 }
367 return Collections.emptyMap();
368 }
369
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800370 public ArrayMap<String, ArraySet<String>> getAllowedAssociations() {
371 return mAllowedAssociations;
372 }
373
Nikita Ioffe07964b42019-02-28 21:35:02 +0000374 public ArraySet<String> getBugreportWhitelistedPackages() {
375 return mBugreportWhitelistedPackages;
376 }
377
Bookatz04d7ae52019-08-05 14:07:12 -0700378 /**
379 * Gets map of packagesNames to userTypes, dictating on which user types each package should be
380 * initially installed, and then removes this map from SystemConfig.
381 * Called by UserManagerService when it is constructed.
382 */
383 public ArrayMap<String, Set<String>> getAndClearPackageToUserTypeWhitelist() {
384 ArrayMap<String, Set<String>> r = mPackageToUserTypeWhitelist;
385 mPackageToUserTypeWhitelist = new ArrayMap<>(0);
386 return r;
387 }
388
389 /**
390 * Gets map of packagesNames to userTypes, dictating on which user types each package should NOT
391 * be initially installed, even if they are whitelisted, and then removes this map from
392 * SystemConfig.
393 * Called by UserManagerService when it is constructed.
394 */
395 public ArrayMap<String, Set<String>> getAndClearPackageToUserTypeBlacklist() {
396 ArrayMap<String, Set<String>> r = mPackageToUserTypeBlacklist;
397 mPackageToUserTypeBlacklist = new ArrayMap<>(0);
398 return r;
399 }
400
401 /**
402 * Only use for testing. Do NOT use in production code.
403 * @param readPermissions false to create an empty SystemConfig; true to read the permissions.
404 */
405 @VisibleForTesting
406 protected SystemConfig(boolean readPermissions) {
407 if (readPermissions) {
408 Slog.w(TAG, "Constructing a test SystemConfig");
409 readAllPermissions();
410 } else {
411 Slog.w(TAG, "Constructing an empty test SystemConfig");
412 }
413 }
414
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700415 SystemConfig() {
Felipe Leme3eb78092019-10-22 09:22:20 -0700416 TimingsTraceLog log = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
417 log.traceBegin("readAllPermissions");
418 try {
419 readAllPermissions();
420 } finally {
421 log.traceEnd();
422 }
Bookatz04d7ae52019-08-05 14:07:12 -0700423 }
424
425 private void readAllPermissions() {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700426 // Read configuration from system
427 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800428 Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL);
Svet Ganov087dce22017-09-07 15:42:16 -0700429
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700430 // Read configuration from the old permissions dir
431 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800432 Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);
Svet Ganov087dce22017-09-07 15:42:16 -0700433
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800434 // Vendors are only allowed to customize these
435 int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS
436 | ALLOW_ASSOCIATIONS;
Jiyong Parkfad99442018-03-12 10:39:07 +0900437 if (Build.VERSION.FIRST_SDK_INT <= Build.VERSION_CODES.O_MR1) {
438 // For backward compatibility
439 vendorPermissionFlag |= (ALLOW_PERMISSIONS | ALLOW_APP_CONFIGS);
440 }
Jaekyun Seoke3b6bf12017-02-16 13:48:30 +0900441 readPermissions(Environment.buildPath(
442 Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
443 readPermissions(Environment.buildPath(
444 Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag);
Svet Ganov087dce22017-09-07 15:42:16 -0700445
Jiyong Park090c6b12017-12-28 12:03:28 +0900446 // Allow ODM to customize system configs as much as Vendor, because /odm is another
447 // vendor partition other than /vendor.
448 int odmPermissionFlag = vendorPermissionFlag;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700449 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800450 Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700451 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800452 Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);
Svet Ganov087dce22017-09-07 15:42:16 -0700453
Steven Morelandd7827fd2018-12-03 10:27:01 -0800454 String skuProperty = SystemProperties.get(SKU_PROPERTY, "");
455 if (!skuProperty.isEmpty()) {
456 String skuDir = "sku_" + skuProperty;
457
458 readPermissions(Environment.buildPath(
459 Environment.getOdmDirectory(), "etc", "sysconfig", skuDir), odmPermissionFlag);
460 readPermissions(Environment.buildPath(
461 Environment.getOdmDirectory(), "etc", "permissions", skuDir),
462 odmPermissionFlag);
463 }
464
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800465 // Allow OEM to customize these
466 int oemPermissionFlag = ALLOW_FEATURES | ALLOW_OEM_PERMISSIONS | ALLOW_ASSOCIATIONS;
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800467 readPermissions(Environment.buildPath(
Svet Ganov087dce22017-09-07 15:42:16 -0700468 Environment.getOemDirectory(), "etc", "sysconfig"), oemPermissionFlag);
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800469 readPermissions(Environment.buildPath(
Svet Ganov087dce22017-09-07 15:42:16 -0700470 Environment.getOemDirectory(), "etc", "permissions"), oemPermissionFlag);
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900471
Hung-ying Tyan38cd31c2018-09-26 15:05:07 +0800472 // Allow Product to customize all system configs
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900473 readPermissions(Environment.buildPath(
Hung-ying Tyan38cd31c2018-09-26 15:05:07 +0800474 Environment.getProductDirectory(), "etc", "sysconfig"), ALLOW_ALL);
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900475 readPermissions(Environment.buildPath(
Hung-ying Tyan38cd31c2018-09-26 15:05:07 +0800476 Environment.getProductDirectory(), "etc", "permissions"), ALLOW_ALL);
Dario Freni2bef1762018-06-01 14:02:08 +0100477
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900478 // Allow /system_ext to customize all system configs
Dario Freni2bef1762018-06-01 14:02:08 +0100479 readPermissions(Environment.buildPath(
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900480 Environment.getSystemExtDirectory(), "etc", "sysconfig"), ALLOW_ALL);
Dario Freni2bef1762018-06-01 14:02:08 +0100481 readPermissions(Environment.buildPath(
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900482 Environment.getSystemExtDirectory(), "etc", "permissions"), ALLOW_ALL);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700483 }
484
Bookatz04d7ae52019-08-05 14:07:12 -0700485 @VisibleForTesting
486 public void readPermissions(File libraryDir, int permissionFlag) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700487 // Read permissions from given directory.
488 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800489 if (permissionFlag == ALLOW_ALL) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700490 Slog.w(TAG, "No directory " + libraryDir + ", skipping");
491 }
492 return;
493 }
494 if (!libraryDir.canRead()) {
495 Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
496 return;
497 }
498
499 // Iterate over the files in the directory and scan .xml files
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800500 File platformFile = null;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700501 for (File f : libraryDir.listFiles()) {
Steven Morelandd7827fd2018-12-03 10:27:01 -0800502 if (!f.isFile()) {
503 continue;
504 }
505
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700506 // We'll read platform.xml last
507 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800508 platformFile = f;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700509 continue;
510 }
511
512 if (!f.getPath().endsWith(".xml")) {
513 Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
514 continue;
515 }
516 if (!f.canRead()) {
517 Slog.w(TAG, "Permissions library file " + f + " cannot be read");
518 continue;
519 }
520
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800521 readPermissionsFromXml(f, permissionFlag);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700522 }
523
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800524 // Read platform permissions last so it will take precedence
525 if (platformFile != null) {
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800526 readPermissionsFromXml(platformFile, permissionFlag);
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800527 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700528 }
529
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800530 private void logNotAllowedInPartition(String name, File permFile, XmlPullParser parser) {
531 Slog.w(TAG, "<" + name + "> not allowed in partition of "
532 + permFile + " at " + parser.getPositionDescription());
533 }
534
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800535 private void readPermissionsFromXml(File permFile, int permissionFlag) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700536 FileReader permReader = null;
537 try {
538 permReader = new FileReader(permFile);
539 } catch (FileNotFoundException e) {
540 Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
541 return;
542 }
Felipe Leme1fbe9b52019-10-21 14:20:08 -0700543 Slog.i(TAG, "Reading permissions from " + permFile);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700544
Dianne Hackbornc0e4aaa2014-11-14 10:55:50 -0800545 final boolean lowRam = ActivityManager.isLowRamDeviceStatic();
546
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700547 try {
548 XmlPullParser parser = Xml.newPullParser();
549 parser.setInput(permReader);
550
551 int type;
552 while ((type=parser.next()) != parser.START_TAG
553 && type != parser.END_DOCUMENT) {
554 ;
555 }
556
557 if (type != parser.START_TAG) {
558 throw new XmlPullParserException("No start tag found");
559 }
560
561 if (!parser.getName().equals("permissions") && !parser.getName().equals("config")) {
Dianne Hackbornb3d4cb32015-01-09 09:54:06 -0800562 throw new XmlPullParserException("Unexpected start tag in " + permFile
563 + ": found " + parser.getName() + ", expected 'permissions' or 'config'");
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700564 }
565
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800566 final boolean allowAll = permissionFlag == ALLOW_ALL;
567 final boolean allowLibs = (permissionFlag & ALLOW_LIBS) != 0;
568 final boolean allowFeatures = (permissionFlag & ALLOW_FEATURES) != 0;
569 final boolean allowPermissions = (permissionFlag & ALLOW_PERMISSIONS) != 0;
570 final boolean allowAppConfigs = (permissionFlag & ALLOW_APP_CONFIGS) != 0;
571 final boolean allowPrivappPermissions = (permissionFlag & ALLOW_PRIVAPP_PERMISSIONS)
572 != 0;
573 final boolean allowOemPermissions = (permissionFlag & ALLOW_OEM_PERMISSIONS) != 0;
574 final boolean allowApiWhitelisting = (permissionFlag & ALLOW_HIDDENAPI_WHITELISTING)
575 != 0;
576 final boolean allowAssociations = (permissionFlag & ALLOW_ASSOCIATIONS) != 0;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700577 while (true) {
578 XmlUtils.nextElement(parser);
579 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
580 break;
581 }
582
583 String name = parser.getName();
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800584 if (name == null) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700585 XmlUtils.skipCurrentTag(parser);
586 continue;
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800587 }
588 switch (name) {
589 case "group": {
590 if (allowAll) {
591 String gidStr = parser.getAttributeValue(null, "gid");
592 if (gidStr != null) {
593 int gid = android.os.Process.getGidForName(gidStr);
594 mGlobalGids = appendInt(mGlobalGids, gid);
595 } else {
596 Slog.w(TAG, "<" + name + "> without gid in " + permFile + " at "
goneileb31cd42018-02-28 15:22:08 -0800597 + parser.getPositionDescription());
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800598 }
599 } else {
600 logNotAllowedInPartition(name, permFile, parser);
601 }
602 XmlUtils.skipCurrentTag(parser);
603 } break;
604 case "permission": {
605 if (allowPermissions) {
606 String perm = parser.getAttributeValue(null, "name");
607 if (perm == null) {
608 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
609 + parser.getPositionDescription());
610 XmlUtils.skipCurrentTag(parser);
611 break;
612 }
613 perm = perm.intern();
614 readPermission(parser, perm);
615 } else {
616 logNotAllowedInPartition(name, permFile, parser);
617 XmlUtils.skipCurrentTag(parser);
618 }
619 } break;
620 case "assign-permission": {
621 if (allowPermissions) {
622 String perm = parser.getAttributeValue(null, "name");
623 if (perm == null) {
624 Slog.w(TAG, "<" + name + "> without name in " + permFile
625 + " at " + parser.getPositionDescription());
626 XmlUtils.skipCurrentTag(parser);
627 break;
628 }
629 String uidStr = parser.getAttributeValue(null, "uid");
630 if (uidStr == null) {
631 Slog.w(TAG, "<" + name + "> without uid in " + permFile
632 + " at " + parser.getPositionDescription());
633 XmlUtils.skipCurrentTag(parser);
634 break;
635 }
636 int uid = Process.getUidForName(uidStr);
637 if (uid < 0) {
638 Slog.w(TAG, "<" + name + "> with unknown uid \""
639 + uidStr + " in " + permFile + " at "
640 + parser.getPositionDescription());
641 XmlUtils.skipCurrentTag(parser);
642 break;
643 }
644 perm = perm.intern();
645 ArraySet<String> perms = mSystemPermissions.get(uid);
646 if (perms == null) {
647 perms = new ArraySet<String>();
648 mSystemPermissions.put(uid, perms);
649 }
650 perms.add(perm);
651 } else {
652 logNotAllowedInPartition(name, permFile, parser);
653 }
654 XmlUtils.skipCurrentTag(parser);
655 } break;
656 case "split-permission": {
657 if (allowPermissions) {
658 readSplitPermission(parser, permFile);
659 } else {
660 logNotAllowedInPartition(name, permFile, parser);
661 XmlUtils.skipCurrentTag(parser);
662 }
663 } break;
664 case "library": {
665 if (allowLibs) {
666 String lname = parser.getAttributeValue(null, "name");
667 String lfile = parser.getAttributeValue(null, "file");
668 String ldependency = parser.getAttributeValue(null, "dependency");
669 if (lname == null) {
670 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
671 + parser.getPositionDescription());
672 } else if (lfile == null) {
673 Slog.w(TAG, "<" + name + "> without file in " + permFile + " at "
674 + parser.getPositionDescription());
675 } else {
676 //Log.i(TAG, "Got library " + lname + " in " + lfile);
677 SharedLibraryEntry entry = new SharedLibraryEntry(lname, lfile,
678 ldependency == null ? new String[0] : ldependency.split(":"));
679 mSharedLibraries.put(lname, entry);
680 }
681 } else {
682 logNotAllowedInPartition(name, permFile, parser);
683 }
684 XmlUtils.skipCurrentTag(parser);
685 } break;
686 case "feature": {
687 if (allowFeatures) {
688 String fname = parser.getAttributeValue(null, "name");
689 int fversion = XmlUtils.readIntAttribute(parser, "version", 0);
690 boolean allowed;
691 if (!lowRam) {
692 allowed = true;
693 } else {
694 String notLowRam = parser.getAttributeValue(null, "notLowRam");
695 allowed = !"true".equals(notLowRam);
696 }
697 if (fname == null) {
698 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
699 + parser.getPositionDescription());
700 } else if (allowed) {
701 addFeature(fname, fversion);
702 }
703 } else {
704 logNotAllowedInPartition(name, permFile, parser);
705 }
706 XmlUtils.skipCurrentTag(parser);
707 } break;
708 case "unavailable-feature": {
709 if (allowFeatures) {
710 String fname = parser.getAttributeValue(null, "name");
711 if (fname == null) {
712 Slog.w(TAG, "<" + name + "> without name in " + permFile
713 + " at " + parser.getPositionDescription());
714 } else {
715 mUnavailableFeatures.add(fname);
716 }
717 } else {
718 logNotAllowedInPartition(name, permFile, parser);
719 }
720 XmlUtils.skipCurrentTag(parser);
721 } break;
722 case "allow-in-power-save-except-idle": {
723 if (allowAll) {
724 String pkgname = parser.getAttributeValue(null, "package");
725 if (pkgname == null) {
726 Slog.w(TAG, "<" + name + "> without package in "
727 + permFile + " at " + parser.getPositionDescription());
728 } else {
729 mAllowInPowerSaveExceptIdle.add(pkgname);
730 }
731 } else {
732 logNotAllowedInPartition(name, permFile, parser);
733 }
734 XmlUtils.skipCurrentTag(parser);
735 } break;
736 case "allow-in-power-save": {
737 if (allowAll) {
738 String pkgname = parser.getAttributeValue(null, "package");
739 if (pkgname == null) {
740 Slog.w(TAG, "<" + name + "> without package in "
741 + permFile + " at " + parser.getPositionDescription());
742 } else {
743 mAllowInPowerSave.add(pkgname);
744 }
745 } else {
746 logNotAllowedInPartition(name, permFile, parser);
747 }
748 XmlUtils.skipCurrentTag(parser);
749 } break;
750 case "allow-in-data-usage-save": {
751 if (allowAll) {
752 String pkgname = parser.getAttributeValue(null, "package");
753 if (pkgname == null) {
754 Slog.w(TAG, "<" + name + "> without package in "
755 + permFile + " at " + parser.getPositionDescription());
756 } else {
757 mAllowInDataUsageSave.add(pkgname);
758 }
759 } else {
760 logNotAllowedInPartition(name, permFile, parser);
761 }
762 XmlUtils.skipCurrentTag(parser);
763 } break;
764 case "allow-unthrottled-location": {
765 if (allowAll) {
766 String pkgname = parser.getAttributeValue(null, "package");
767 if (pkgname == null) {
768 Slog.w(TAG, "<" + name + "> without package in "
769 + permFile + " at " + parser.getPositionDescription());
770 } else {
771 mAllowUnthrottledLocation.add(pkgname);
772 }
773 } else {
774 logNotAllowedInPartition(name, permFile, parser);
775 }
776 XmlUtils.skipCurrentTag(parser);
777 } break;
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800778 case "allow-ignore-location-settings": {
779 if (allowAll) {
780 String pkgname = parser.getAttributeValue(null, "package");
781 if (pkgname == null) {
782 Slog.w(TAG, "<" + name + "> without package in "
783 + permFile + " at " + parser.getPositionDescription());
784 } else {
785 mAllowIgnoreLocationSettings.add(pkgname);
786 }
787 } else {
788 logNotAllowedInPartition(name, permFile, parser);
789 }
790 XmlUtils.skipCurrentTag(parser);
791 } break;
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800792 case "allow-implicit-broadcast": {
793 if (allowAll) {
794 String action = parser.getAttributeValue(null, "action");
795 if (action == null) {
796 Slog.w(TAG, "<" + name + "> without action in "
797 + permFile + " at " + parser.getPositionDescription());
798 } else {
799 mAllowImplicitBroadcasts.add(action);
800 }
801 } else {
802 logNotAllowedInPartition(name, permFile, parser);
803 }
804 XmlUtils.skipCurrentTag(parser);
805 } break;
806 case "app-link": {
807 if (allowAppConfigs) {
808 String pkgname = parser.getAttributeValue(null, "package");
809 if (pkgname == null) {
810 Slog.w(TAG, "<" + name + "> without package in " + permFile
811 + " at " + parser.getPositionDescription());
812 } else {
813 mLinkedApps.add(pkgname);
814 }
815 } else {
816 logNotAllowedInPartition(name, permFile, parser);
817 }
818 XmlUtils.skipCurrentTag(parser);
819 } break;
820 case "system-user-whitelisted-app": {
821 if (allowAppConfigs) {
822 String pkgname = parser.getAttributeValue(null, "package");
823 if (pkgname == null) {
824 Slog.w(TAG, "<" + name + "> without package in "
825 + permFile + " at " + parser.getPositionDescription());
826 } else {
827 mSystemUserWhitelistedApps.add(pkgname);
828 }
829 } else {
830 logNotAllowedInPartition(name, permFile, parser);
831 }
832 XmlUtils.skipCurrentTag(parser);
833 } break;
834 case "system-user-blacklisted-app": {
835 if (allowAppConfigs) {
836 String pkgname = parser.getAttributeValue(null, "package");
837 if (pkgname == null) {
838 Slog.w(TAG, "<" + name + "> without package in "
839 + permFile + " at " + parser.getPositionDescription());
840 } else {
841 mSystemUserBlacklistedApps.add(pkgname);
842 }
843 } else {
844 logNotAllowedInPartition(name, permFile, parser);
845 }
846 XmlUtils.skipCurrentTag(parser);
847 } break;
848 case "default-enabled-vr-app": {
849 if (allowAppConfigs) {
850 String pkgname = parser.getAttributeValue(null, "package");
851 String clsname = parser.getAttributeValue(null, "class");
852 if (pkgname == null) {
853 Slog.w(TAG, "<" + name + "> without package in "
854 + permFile + " at " + parser.getPositionDescription());
855 } else if (clsname == null) {
856 Slog.w(TAG, "<" + name + "> without class in "
857 + permFile + " at " + parser.getPositionDescription());
858 } else {
859 mDefaultVrComponents.add(new ComponentName(pkgname, clsname));
860 }
861 } else {
862 logNotAllowedInPartition(name, permFile, parser);
863 }
864 XmlUtils.skipCurrentTag(parser);
865 } break;
Ryan Mitchell4fd8e6f2019-10-07 16:31:34 -0700866 case "component-override": {
Ryan Mitchell61a30322019-10-30 08:52:43 -0700867 readComponentOverrides(parser, permFile);
Ryan Mitchell4fd8e6f2019-10-07 16:31:34 -0700868 XmlUtils.skipCurrentTag(parser);
869 } break;
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800870 case "backup-transport-whitelisted-service": {
871 if (allowFeatures) {
872 String serviceName = parser.getAttributeValue(null, "service");
873 if (serviceName == null) {
874 Slog.w(TAG, "<" + name + "> without service in "
875 + permFile + " at " + parser.getPositionDescription());
876 } else {
877 ComponentName cn = ComponentName.unflattenFromString(serviceName);
878 if (cn == null) {
879 Slog.w(TAG, "<" + name + "> with invalid service name "
880 + serviceName + " in " + permFile
881 + " at " + parser.getPositionDescription());
882 } else {
883 mBackupTransportWhitelist.add(cn);
884 }
885 }
886 } else {
887 logNotAllowedInPartition(name, permFile, parser);
888 }
889 XmlUtils.skipCurrentTag(parser);
890 } break;
891 case "disabled-until-used-preinstalled-carrier-associated-app": {
892 if (allowAppConfigs) {
893 String pkgname = parser.getAttributeValue(null, "package");
894 String carrierPkgname = parser.getAttributeValue(null,
895 "carrierAppPackage");
896 if (pkgname == null || carrierPkgname == null) {
897 Slog.w(TAG, "<" + name
898 + "> without package or carrierAppPackage in " + permFile
899 + " at " + parser.getPositionDescription());
900 } else {
901 List<String> associatedPkgs =
902 mDisabledUntilUsedPreinstalledCarrierAssociatedApps.get(
903 carrierPkgname);
904 if (associatedPkgs == null) {
905 associatedPkgs = new ArrayList<>();
906 mDisabledUntilUsedPreinstalledCarrierAssociatedApps.put(
907 carrierPkgname, associatedPkgs);
908 }
909 associatedPkgs.add(pkgname);
910 }
911 } else {
912 logNotAllowedInPartition(name, permFile, parser);
913 }
914 XmlUtils.skipCurrentTag(parser);
915 } break;
916 case "disabled-until-used-preinstalled-carrier-app": {
917 if (allowAppConfigs) {
918 String pkgname = parser.getAttributeValue(null, "package");
919 if (pkgname == null) {
920 Slog.w(TAG,
921 "<" + name + "> without "
922 + "package in " + permFile + " at "
923 + parser.getPositionDescription());
924 } else {
925 mDisabledUntilUsedPreinstalledCarrierApps.add(pkgname);
926 }
927 } else {
928 logNotAllowedInPartition(name, permFile, parser);
929 }
930 XmlUtils.skipCurrentTag(parser);
931 } break;
932 case "privapp-permissions": {
933 if (allowPrivappPermissions) {
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900934 // privapp permissions from system, vendor, product and system_ext
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800935 // partitions are stored separately. This is to prevent xml files in
936 // the vendor partition from granting permissions to priv apps in the
937 // system partition and vice versa.
938 boolean vendor = permFile.toPath().startsWith(
939 Environment.getVendorDirectory().toPath() + "/")
940 || permFile.toPath().startsWith(
941 Environment.getOdmDirectory().toPath() + "/");
942 boolean product = permFile.toPath().startsWith(
943 Environment.getProductDirectory().toPath() + "/");
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900944 boolean systemExt = permFile.toPath().startsWith(
945 Environment.getSystemExtDirectory().toPath() + "/");
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800946 if (vendor) {
947 readPrivAppPermissions(parser, mVendorPrivAppPermissions,
948 mVendorPrivAppDenyPermissions);
949 } else if (product) {
950 readPrivAppPermissions(parser, mProductPrivAppPermissions,
951 mProductPrivAppDenyPermissions);
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900952 } else if (systemExt) {
953 readPrivAppPermissions(parser, mSystemExtPrivAppPermissions,
954 mSystemExtPrivAppDenyPermissions);
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800955 } else {
956 readPrivAppPermissions(parser, mPrivAppPermissions,
957 mPrivAppDenyPermissions);
958 }
959 } else {
960 logNotAllowedInPartition(name, permFile, parser);
961 XmlUtils.skipCurrentTag(parser);
962 }
963 } break;
964 case "oem-permissions": {
965 if (allowOemPermissions) {
966 readOemPermissions(parser);
967 } else {
968 logNotAllowedInPartition(name, permFile, parser);
969 XmlUtils.skipCurrentTag(parser);
970 }
971 } break;
972 case "hidden-api-whitelisted-app": {
973 if (allowApiWhitelisting) {
974 String pkgname = parser.getAttributeValue(null, "package");
975 if (pkgname == null) {
976 Slog.w(TAG, "<" + name + "> without package in "
977 + permFile + " at " + parser.getPositionDescription());
978 } else {
979 mHiddenApiPackageWhitelist.add(pkgname);
980 }
981 } else {
982 logNotAllowedInPartition(name, permFile, parser);
983 }
984 XmlUtils.skipCurrentTag(parser);
985 } break;
986 case "allow-association": {
987 if (allowAssociations) {
988 String target = parser.getAttributeValue(null, "target");
989 if (target == null) {
990 Slog.w(TAG, "<" + name + "> without target in " + permFile
991 + " at " + parser.getPositionDescription());
992 XmlUtils.skipCurrentTag(parser);
993 break;
994 }
995 String allowed = parser.getAttributeValue(null, "allowed");
996 if (allowed == null) {
997 Slog.w(TAG, "<" + name + "> without allowed in " + permFile
998 + " at " + parser.getPositionDescription());
999 XmlUtils.skipCurrentTag(parser);
1000 break;
1001 }
1002 target = target.intern();
1003 allowed = allowed.intern();
1004 ArraySet<String> associations = mAllowedAssociations.get(target);
1005 if (associations == null) {
1006 associations = new ArraySet<>();
1007 mAllowedAssociations.put(target, associations);
1008 }
1009 Slog.i(TAG, "Adding association: " + target + " <- " + allowed);
1010 associations.add(allowed);
1011 } else {
1012 logNotAllowedInPartition(name, permFile, parser);
1013 }
1014 XmlUtils.skipCurrentTag(parser);
1015 } break;
Nikita Ioffe07964b42019-02-28 21:35:02 +00001016 case "bugreport-whitelisted": {
1017 String pkgname = parser.getAttributeValue(null, "package");
1018 if (pkgname == null) {
1019 Slog.w(TAG, "<" + name + "> without package in " + permFile
1020 + " at " + parser.getPositionDescription());
1021 } else {
1022 mBugreportWhitelistedPackages.add(pkgname);
1023 }
Nikita Ioffe08146ef2019-03-13 17:04:21 +00001024 XmlUtils.skipCurrentTag(parser);
Nikita Ioffe07964b42019-02-28 21:35:02 +00001025 } break;
Bookatz04d7ae52019-08-05 14:07:12 -07001026 case "install-in-user-type": {
1027 // NB: We allow any directory permission to declare install-in-user-type.
1028 readInstallInUserType(parser,
1029 mPackageToUserTypeWhitelist, mPackageToUserTypeBlacklist);
1030 } break;
Dianne Hackborn769b2e72018-12-05 08:51:20 -08001031 default: {
1032 Slog.w(TAG, "Tag " + name + " is unknown in "
1033 + permFile + " at " + parser.getPositionDescription());
1034 XmlUtils.skipCurrentTag(parser);
1035 } break;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001036 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001037 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001038 } catch (XmlPullParserException e) {
Jeff Sharkey1c4ae802014-12-19 11:08:55 -08001039 Slog.w(TAG, "Got exception parsing permissions.", e);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001040 } catch (IOException e) {
Jeff Sharkey1c4ae802014-12-19 11:08:55 -08001041 Slog.w(TAG, "Got exception parsing permissions.", e);
1042 } finally {
1043 IoUtils.closeQuietly(permReader);
1044 }
1045
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -07001046 // Some devices can be field-converted to FBE, so offer to splice in
1047 // those features if not already defined by the static config
Paul Lawrence20be5d62016-02-26 13:51:17 -08001048 if (StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkey115d2c12016-02-15 17:25:57 -07001049 addFeature(PackageManager.FEATURE_FILE_BASED_ENCRYPTION, 0);
1050 addFeature(PackageManager.FEATURE_SECURELY_REMOVES_USERS, 0);
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -07001051 }
1052
Jeff Sharkey8eb783b2018-01-04 16:46:48 -07001053 // Help legacy devices that may not have updated their static config
1054 if (StorageManager.hasAdoptable()) {
1055 addFeature(PackageManager.FEATURE_ADOPTABLE_STORAGE, 0);
1056 }
1057
Dianne Hackborn2a103f12017-08-08 15:50:31 -07001058 if (ActivityManager.isLowRamDeviceStatic()) {
1059 addFeature(PackageManager.FEATURE_RAM_LOW, 0);
1060 } else {
1061 addFeature(PackageManager.FEATURE_RAM_NORMAL, 0);
1062 }
1063
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -07001064 for (String featureName : mUnavailableFeatures) {
1065 removeFeature(featureName);
1066 }
1067 }
1068
Jeff Sharkey115d2c12016-02-15 17:25:57 -07001069 private void addFeature(String name, int version) {
1070 FeatureInfo fi = mAvailableFeatures.get(name);
1071 if (fi == null) {
1072 fi = new FeatureInfo();
1073 fi.name = name;
1074 fi.version = version;
1075 mAvailableFeatures.put(name, fi);
1076 } else {
1077 fi.version = Math.max(fi.version, version);
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -07001078 }
1079 }
1080
Jeff Sharkey115d2c12016-02-15 17:25:57 -07001081 private void removeFeature(String name) {
1082 if (mAvailableFeatures.remove(name) != null) {
1083 Slog.d(TAG, "Removed unavailable feature " + name);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001084 }
1085 }
1086
1087 void readPermission(XmlPullParser parser, String name)
1088 throws IOException, XmlPullParserException {
Jeff Sharkey00f39042015-03-23 16:51:22 -07001089 if (mPermissions.containsKey(name)) {
1090 throw new IllegalStateException("Duplicate permission definition for " + name);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001091 }
Jeff Sharkey00f39042015-03-23 16:51:22 -07001092
1093 final boolean perUser = XmlUtils.readBooleanAttribute(parser, "perUser", false);
1094 final PermissionEntry perm = new PermissionEntry(name, perUser);
1095 mPermissions.put(name, perm);
1096
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001097 int outerDepth = parser.getDepth();
1098 int type;
1099 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1100 && (type != XmlPullParser.END_TAG
1101 || parser.getDepth() > outerDepth)) {
1102 if (type == XmlPullParser.END_TAG
1103 || type == XmlPullParser.TEXT) {
1104 continue;
1105 }
1106
1107 String tagName = parser.getName();
1108 if ("group".equals(tagName)) {
1109 String gidStr = parser.getAttributeValue(null, "gid");
1110 if (gidStr != null) {
1111 int gid = Process.getGidForName(gidStr);
1112 perm.gids = appendInt(perm.gids, gid);
1113 } else {
1114 Slog.w(TAG, "<group> without gid at "
1115 + parser.getPositionDescription());
1116 }
1117 }
1118 XmlUtils.skipCurrentTag(parser);
1119 }
1120 }
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001121
Jiyong Park002fdbd2017-02-13 20:50:31 +09001122 private void readPrivAppPermissions(XmlPullParser parser,
1123 ArrayMap<String, ArraySet<String>> grantMap,
1124 ArrayMap<String, ArraySet<String>> denyMap)
1125 throws IOException, XmlPullParserException {
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001126 String packageName = parser.getAttributeValue(null, "package");
1127 if (TextUtils.isEmpty(packageName)) {
1128 Slog.w(TAG, "package is required for <privapp-permissions> in "
1129 + parser.getPositionDescription());
1130 return;
1131 }
1132
Jiyong Park002fdbd2017-02-13 20:50:31 +09001133 ArraySet<String> permissions = grantMap.get(packageName);
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001134 if (permissions == null) {
1135 permissions = new ArraySet<>();
1136 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09001137 ArraySet<String> denyPermissions = denyMap.get(packageName);
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001138 int depth = parser.getDepth();
1139 while (XmlUtils.nextElementWithin(parser, depth)) {
1140 String name = parser.getName();
1141 if ("permission".equals(name)) {
1142 String permName = parser.getAttributeValue(null, "name");
1143 if (TextUtils.isEmpty(permName)) {
1144 Slog.w(TAG, "name is required for <permission> in "
1145 + parser.getPositionDescription());
1146 continue;
1147 }
1148 permissions.add(permName);
Todd Kennedy74629e32017-08-15 14:48:07 -07001149 } else if ("deny-permission".equals(name)) {
1150 String permName = parser.getAttributeValue(null, "name");
1151 if (TextUtils.isEmpty(permName)) {
1152 Slog.w(TAG, "name is required for <deny-permission> in "
1153 + parser.getPositionDescription());
1154 continue;
1155 }
1156 if (denyPermissions == null) {
1157 denyPermissions = new ArraySet<>();
1158 }
1159 denyPermissions.add(permName);
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001160 }
1161 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09001162 grantMap.put(packageName, permissions);
Todd Kennedy74629e32017-08-15 14:48:07 -07001163 if (denyPermissions != null) {
Jiyong Park002fdbd2017-02-13 20:50:31 +09001164 denyMap.put(packageName, denyPermissions);
Todd Kennedy74629e32017-08-15 14:48:07 -07001165 }
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001166 }
Svet Ganov087dce22017-09-07 15:42:16 -07001167
Bookatz04d7ae52019-08-05 14:07:12 -07001168 private void readInstallInUserType(XmlPullParser parser,
1169 Map<String, Set<String>> doInstallMap,
1170 Map<String, Set<String>> nonInstallMap)
1171 throws IOException, XmlPullParserException {
1172 final String packageName = parser.getAttributeValue(null, "package");
1173 if (TextUtils.isEmpty(packageName)) {
1174 Slog.w(TAG, "package is required for <install-in-user-type> in "
1175 + parser.getPositionDescription());
1176 return;
1177 }
1178
1179 Set<String> userTypesYes = doInstallMap.get(packageName);
1180 Set<String> userTypesNo = nonInstallMap.get(packageName);
1181 final int depth = parser.getDepth();
1182 while (XmlUtils.nextElementWithin(parser, depth)) {
1183 final String name = parser.getName();
1184 if ("install-in".equals(name)) {
1185 final String userType = parser.getAttributeValue(null, "user-type");
1186 if (TextUtils.isEmpty(userType)) {
1187 Slog.w(TAG, "user-type is required for <install-in-user-type> in "
1188 + parser.getPositionDescription());
1189 continue;
1190 }
1191 if (userTypesYes == null) {
1192 userTypesYes = new ArraySet<>();
1193 doInstallMap.put(packageName, userTypesYes);
1194 }
1195 userTypesYes.add(userType);
1196 } else if ("do-not-install-in".equals(name)) {
1197 final String userType = parser.getAttributeValue(null, "user-type");
1198 if (TextUtils.isEmpty(userType)) {
1199 Slog.w(TAG, "user-type is required for <install-in-user-type> in "
1200 + parser.getPositionDescription());
1201 continue;
1202 }
1203 if (userTypesNo == null) {
1204 userTypesNo = new ArraySet<>();
1205 nonInstallMap.put(packageName, userTypesNo);
1206 }
1207 userTypesNo.add(userType);
1208 } else {
1209 Slog.w(TAG, "unrecognized tag in <install-in-user-type> in "
1210 + parser.getPositionDescription());
1211 }
1212 }
1213 }
1214
Svet Ganov087dce22017-09-07 15:42:16 -07001215 void readOemPermissions(XmlPullParser parser) throws IOException, XmlPullParserException {
1216 final String packageName = parser.getAttributeValue(null, "package");
1217 if (TextUtils.isEmpty(packageName)) {
1218 Slog.w(TAG, "package is required for <oem-permissions> in "
1219 + parser.getPositionDescription());
1220 return;
1221 }
1222
1223 ArrayMap<String, Boolean> permissions = mOemPermissions.get(packageName);
1224 if (permissions == null) {
1225 permissions = new ArrayMap<>();
1226 }
1227 final int depth = parser.getDepth();
1228 while (XmlUtils.nextElementWithin(parser, depth)) {
1229 final String name = parser.getName();
1230 if ("permission".equals(name)) {
1231 final String permName = parser.getAttributeValue(null, "name");
1232 if (TextUtils.isEmpty(permName)) {
1233 Slog.w(TAG, "name is required for <permission> in "
1234 + parser.getPositionDescription());
1235 continue;
1236 }
1237 permissions.put(permName, Boolean.TRUE);
1238 } else if ("deny-permission".equals(name)) {
1239 String permName = parser.getAttributeValue(null, "name");
1240 if (TextUtils.isEmpty(permName)) {
1241 Slog.w(TAG, "name is required for <deny-permission> in "
1242 + parser.getPositionDescription());
1243 continue;
1244 }
1245 permissions.put(permName, Boolean.FALSE);
1246 }
1247 }
1248 mOemPermissions.put(packageName, permissions);
1249 }
Zimuzocc2932f2018-10-29 16:04:41 +00001250
1251 private void readSplitPermission(XmlPullParser parser, File permFile)
1252 throws IOException, XmlPullParserException {
1253 String splitPerm = parser.getAttributeValue(null, "name");
1254 if (splitPerm == null) {
1255 Slog.w(TAG, "<split-permission> without name in " + permFile + " at "
1256 + parser.getPositionDescription());
1257 XmlUtils.skipCurrentTag(parser);
1258 return;
1259 }
1260 String targetSdkStr = parser.getAttributeValue(null, "targetSdk");
1261 int targetSdk = Build.VERSION_CODES.CUR_DEVELOPMENT + 1;
1262 if (!TextUtils.isEmpty(targetSdkStr)) {
1263 try {
1264 targetSdk = Integer.parseInt(targetSdkStr);
1265 } catch (NumberFormatException e) {
1266 Slog.w(TAG, "<split-permission> targetSdk not an integer in " + permFile + " at "
1267 + parser.getPositionDescription());
1268 XmlUtils.skipCurrentTag(parser);
1269 return;
1270 }
1271 }
1272 final int depth = parser.getDepth();
1273 List<String> newPermissions = new ArrayList<>();
1274 while (XmlUtils.nextElementWithin(parser, depth)) {
1275 String name = parser.getName();
1276 if ("new-permission".equals(name)) {
1277 final String newName = parser.getAttributeValue(null, "name");
1278 if (TextUtils.isEmpty(newName)) {
1279 Slog.w(TAG, "name is required for <new-permission> in "
1280 + parser.getPositionDescription());
1281 continue;
1282 }
1283 newPermissions.add(newName);
1284 } else {
1285 XmlUtils.skipCurrentTag(parser);
1286 }
1287 }
1288 if (!newPermissions.isEmpty()) {
1289 mSplitPermissions.add(new SplitPermissionInfo(splitPerm, newPermissions, targetSdk));
1290 }
1291 }
Anthony Hughde787d42019-08-22 15:35:48 -07001292
Ryan Mitchell4fd8e6f2019-10-07 16:31:34 -07001293 private void readComponentOverrides(XmlPullParser parser, File permFile)
1294 throws IOException, XmlPullParserException {
1295 String pkgname = parser.getAttributeValue(null, "package");
1296 if (pkgname == null) {
1297 Slog.w(TAG, "<component-override> without package in "
1298 + permFile + " at " + parser.getPositionDescription());
1299 return;
1300 }
1301
1302 pkgname = pkgname.intern();
1303
1304 final int depth = parser.getDepth();
1305 while (XmlUtils.nextElementWithin(parser, depth)) {
1306 String name = parser.getName();
1307 if ("component".equals(name)) {
1308 String clsname = parser.getAttributeValue(null, "class");
1309 String enabled = parser.getAttributeValue(null, "enabled");
1310 if (clsname == null) {
1311 Slog.w(TAG, "<component> without class in "
1312 + permFile + " at " + parser.getPositionDescription());
1313 return;
1314 } else if (enabled == null) {
1315 Slog.w(TAG, "<component> without enabled in "
1316 + permFile + " at " + parser.getPositionDescription());
1317 return;
1318 }
1319
1320 if (clsname.startsWith(".")) {
1321 clsname = pkgname + clsname;
1322 }
1323
1324 clsname = clsname.intern();
1325
1326 ArrayMap<String, Boolean> componentEnabledStates =
1327 mPackageComponentEnabledState.get(pkgname);
1328 if (componentEnabledStates == null) {
1329 componentEnabledStates = new ArrayMap<>();
1330 mPackageComponentEnabledState.put(pkgname,
1331 componentEnabledStates);
1332 }
1333
1334 componentEnabledStates.put(clsname, !"false".equals(enabled));
1335 } else {
1336 XmlUtils.skipCurrentTag(parser);
1337 }
1338 }
1339 }
1340
Anthony Hughde787d42019-08-22 15:35:48 -07001341 private static boolean isSystemProcess() {
1342 return Process.myUid() == Process.SYSTEM_UID;
1343 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001344}