blob: 7cd3e95c6499c140d793fbef740c80dbb4fb87ed [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;
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -070029import android.os.storage.StorageManager;
Zimuzocc2932f2018-10-29 16:04:41 +000030import android.permission.PermissionManager.SplitPermissionInfo;
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -080031import android.text.TextUtils;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070032import android.util.ArrayMap;
33import android.util.ArraySet;
34import android.util.Slog;
35import android.util.SparseArray;
36import android.util.Xml;
Jeff Sharkey1c4ae802014-12-19 11:08:55 -080037
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070038import com.android.internal.util.XmlUtils;
Jeff Sharkey1c4ae802014-12-19 11:08:55 -080039
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -070040import libcore.io.IoUtils;
41
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070042import org.xmlpull.v1.XmlPullParser;
43import org.xmlpull.v1.XmlPullParserException;
44
45import java.io.File;
46import java.io.FileNotFoundException;
47import java.io.FileReader;
48import java.io.IOException;
Jeff Davidson24b9d962016-07-21 12:35:10 -070049import java.util.ArrayList;
Svet Ganov087dce22017-09-07 15:42:16 -070050import java.util.Collections;
Jeff Davidson24b9d962016-07-21 12:35:10 -070051import java.util.List;
Svet Ganov087dce22017-09-07 15:42:16 -070052import java.util.Map;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070053
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070054/**
55 * Loads global system configuration info.
Anthony Hugh6f5eadc2019-08-22 15:35:48 -070056 * Note: Initializing this class hits the disk and is slow. This class should generally only be
57 * accessed by the system_server process.
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070058 */
59public class SystemConfig {
60 static final String TAG = "SystemConfig";
61
62 static SystemConfig sInstance;
63
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +080064 // permission flag, determines which types of configuration are allowed to be read
65 private static final int ALLOW_FEATURES = 0x01;
66 private static final int ALLOW_LIBS = 0x02;
67 private static final int ALLOW_PERMISSIONS = 0x04;
68 private static final int ALLOW_APP_CONFIGS = 0x08;
Jaekyun Seoke3b6bf12017-02-16 13:48:30 +090069 private static final int ALLOW_PRIVAPP_PERMISSIONS = 0x10;
Svet Ganov087dce22017-09-07 15:42:16 -070070 private static final int ALLOW_OEM_PERMISSIONS = 0x20;
Mathew Inwood4693a752018-02-20 16:04:25 +000071 private static final int ALLOW_HIDDENAPI_WHITELISTING = 0x40;
Dianne Hackborn769b2e72018-12-05 08:51:20 -080072 private static final int ALLOW_ASSOCIATIONS = 0x80;
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +080073 private static final int ALLOW_ALL = ~0;
74
Steven Morelandd7827fd2018-12-03 10:27:01 -080075 // property for runtime configuration differentiation
76 private static final String SKU_PROPERTY = "ro.boot.product.hardware.sku";
77
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070078 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
79 int[] mGlobalGids;
80
81 // These are the built-in uid -> permission mappings that were read from the
82 // system configuration files.
Jeff Sharkey9f837a92014-10-24 12:07:24 -070083 final SparseArray<ArraySet<String>> mSystemPermissions = new SparseArray<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070084
Zimuzocc2932f2018-10-29 16:04:41 +000085 final ArrayList<SplitPermissionInfo> mSplitPermissions = new ArrayList<>();
86
Ben Lin71c16d72018-12-06 18:34:51 -080087 public static final class SharedLibraryEntry {
88 public final String name;
89 public final String filename;
90 public final String[] dependencies;
91
92 SharedLibraryEntry(String name, String filename, String[] dependencies) {
93 this.name = name;
94 this.filename = filename;
95 this.dependencies = dependencies;
96 }
97 }
98
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070099 // These are the built-in shared libraries that were read from the
Ben Lin71c16d72018-12-06 18:34:51 -0800100 // system configuration files. Keys are the library names; values are
101 // the individual entries that contain information such as filename
102 // and dependencies.
103 final ArrayMap<String, SharedLibraryEntry> mSharedLibraries = new ArrayMap<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700104
105 // These are the features this devices supports that were read from the
106 // system configuration files.
Jeff Sharkey9f837a92014-10-24 12:07:24 -0700107 final ArrayMap<String, FeatureInfo> mAvailableFeatures = new ArrayMap<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700108
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800109 // These are the features which this device doesn't support; the OEM
110 // partition uses these to opt-out of features from the system image.
111 final ArraySet<String> mUnavailableFeatures = new ArraySet<>();
112
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700113 public static final class PermissionEntry {
114 public final String name;
115 public int[] gids;
Jeff Sharkey00f39042015-03-23 16:51:22 -0700116 public boolean perUser;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700117
Jeff Sharkey00f39042015-03-23 16:51:22 -0700118 PermissionEntry(String name, boolean perUser) {
119 this.name = name;
120 this.perUser = perUser;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700121 }
122 }
123
124 // These are the permission -> gid mappings that were read from the
125 // system configuration files.
Dianne Hackbornbb8aa5a2014-09-17 13:20:38 -0700126 final ArrayMap<String, PermissionEntry> mPermissions = new ArrayMap<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700127
128 // These are the packages that are white-listed to be able to run in the
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700129 // background while in power save mode (but not whitelisted from device idle modes),
130 // as read from the configuration files.
131 final ArraySet<String> mAllowInPowerSaveExceptIdle = new ArraySet<>();
132
133 // These are the packages that are white-listed to be able to run in the
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700134 // background while in power save mode, as read from the configuration files.
Dianne Hackbornbb8aa5a2014-09-17 13:20:38 -0700135 final ArraySet<String> mAllowInPowerSave = new ArraySet<>();
136
Felipe Lemea9505cc2016-02-26 10:28:41 -0800137 // These are the packages that are white-listed to be able to run in the
138 // background while in data-usage save mode, as read from the configuration files.
139 final ArraySet<String> mAllowInDataUsageSave = new ArraySet<>();
140
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800141 // These are the packages that are white-listed to be able to run background location
142 // without throttling, as read from the configuration files.
143 final ArraySet<String> mAllowUnthrottledLocation = new ArraySet<>();
144
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800145 // These are the packages that are white-listed to be able to retrieve location even when user
146 // location settings are off, for emergency purposes, as read from the configuration files.
147 final ArraySet<String> mAllowIgnoreLocationSettings = new ArraySet<>();
148
Christopher Tate42a386b2016-11-07 12:21:21 -0800149 // These are the action strings of broadcasts which are whitelisted to
150 // be delivered anonymously even to apps which target O+.
151 final ArraySet<String> mAllowImplicitBroadcasts = new ArraySet<>();
152
Christopher Tate01e18642015-07-07 18:10:38 -0700153 // These are the package names of apps which should be in the 'always'
154 // URL-handling state upon factory reset.
155 final ArraySet<String> mLinkedApps = new ArraySet<>();
156
Fyodor Kupolov7db5af12015-07-31 16:50:27 -0700157 // These are the packages that are whitelisted to be able to run as system user
158 final ArraySet<String> mSystemUserWhitelistedApps = new ArraySet<>();
159
160 // These are the packages that should not run under system user
161 final ArraySet<String> mSystemUserBlacklistedApps = new ArraySet<>();
162
Ruben Brunk98576cf2016-03-07 18:54:28 -0800163 // These are the components that are enabled by default as VR mode listener services.
164 final ArraySet<ComponentName> mDefaultVrComponents = new ArraySet<>();
165
Christopher Tate494df792016-05-10 17:05:38 -0700166 // These are the permitted backup transport service components
167 final ArraySet<ComponentName> mBackupTransportWhitelist = new ArraySet<>();
168
Mathew Inwood4693a752018-02-20 16:04:25 +0000169 // Package names that are exempted from private API blacklisting
170 final ArraySet<String> mHiddenApiPackageWhitelist = new ArraySet<>();
171
goneileb31cd42018-02-28 15:22:08 -0800172 // The list of carrier applications which should be disabled until used.
173 // This function suppresses update notifications for these pre-installed apps.
174 // In SubscriptionInfoUpdater, the listed applications are disabled until used when all of the
175 // following conditions are met.
176 // 1. Not currently carrier-privileged according to the inserted SIM
177 // 2. Pre-installed
178 // 3. In the default state (enabled but not explicitly)
179 // And SubscriptionInfoUpdater undoes this and marks the app enabled when a SIM is inserted
180 // that marks the app as carrier privileged. It also grants the app default permissions
181 // for Phone and Location. As such, apps MUST only ever be added to this list if they
182 // obtain user consent to access their location through other means.
183 final ArraySet<String> mDisabledUntilUsedPreinstalledCarrierApps = new ArraySet<>();
184
Jeff Davidson24b9d962016-07-21 12:35:10 -0700185 // These are the packages of carrier-associated apps which should be disabled until used until
186 // a SIM is inserted which grants carrier privileges to that carrier app.
187 final ArrayMap<String, List<String>> mDisabledUntilUsedPreinstalledCarrierAssociatedApps =
188 new ArrayMap<>();
189
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800190 final ArrayMap<String, ArraySet<String>> mPrivAppPermissions = new ArrayMap<>();
Todd Kennedy74629e32017-08-15 14:48:07 -0700191 final ArrayMap<String, ArraySet<String>> mPrivAppDenyPermissions = new ArrayMap<>();
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800192
Jiyong Park002fdbd2017-02-13 20:50:31 +0900193 final ArrayMap<String, ArraySet<String>> mVendorPrivAppPermissions = new ArrayMap<>();
194 final ArrayMap<String, ArraySet<String>> mVendorPrivAppDenyPermissions = new ArrayMap<>();
195
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900196 final ArrayMap<String, ArraySet<String>> mProductPrivAppPermissions = new ArrayMap<>();
197 final ArrayMap<String, ArraySet<String>> mProductPrivAppDenyPermissions = new ArrayMap<>();
198
Jeongik Chaf6629832019-07-04 21:12:06 +0900199 final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppPermissions = new ArrayMap<>();
200 final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppDenyPermissions = new ArrayMap<>();
Dario Freni2bef1762018-06-01 14:02:08 +0100201
Svet Ganov087dce22017-09-07 15:42:16 -0700202 final ArrayMap<String, ArrayMap<String, Boolean>> mOemPermissions = new ArrayMap<>();
203
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800204 // Allowed associations between applications. If there are any entries
205 // for an app, those are the only associations allowed; otherwise, all associations
206 // are allowed. Allowing an association from app A to app B means app A can not
207 // associate with any other apps, but does not limit what apps B can associate with.
208 final ArrayMap<String, ArraySet<String>> mAllowedAssociations = new ArrayMap<>();
209
Nikita Ioffe07964b42019-02-28 21:35:02 +0000210 private final ArraySet<String> mBugreportWhitelistedPackages = new ArraySet<>();
211
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700212 public static SystemConfig getInstance() {
Anthony Hugh6f5eadc2019-08-22 15:35:48 -0700213 if (!isSystemProcess()) {
214 Slog.wtf(TAG, "SystemConfig is being accessed by a process other than "
215 + "system_server.");
216 }
217
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700218 synchronized (SystemConfig.class) {
219 if (sInstance == null) {
220 sInstance = new SystemConfig();
221 }
222 return sInstance;
223 }
224 }
225
226 public int[] getGlobalGids() {
227 return mGlobalGids;
228 }
229
Jeff Sharkey9f837a92014-10-24 12:07:24 -0700230 public SparseArray<ArraySet<String>> getSystemPermissions() {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700231 return mSystemPermissions;
232 }
233
Zimuzocc2932f2018-10-29 16:04:41 +0000234 public ArrayList<SplitPermissionInfo> getSplitPermissions() {
235 return mSplitPermissions;
236 }
237
Ben Lin71c16d72018-12-06 18:34:51 -0800238 public ArrayMap<String, SharedLibraryEntry> getSharedLibraries() {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700239 return mSharedLibraries;
240 }
241
Jeff Sharkey9f837a92014-10-24 12:07:24 -0700242 public ArrayMap<String, FeatureInfo> getAvailableFeatures() {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700243 return mAvailableFeatures;
244 }
245
246 public ArrayMap<String, PermissionEntry> getPermissions() {
247 return mPermissions;
248 }
249
Christopher Tate42a386b2016-11-07 12:21:21 -0800250 public ArraySet<String> getAllowImplicitBroadcasts() {
251 return mAllowImplicitBroadcasts;
252 }
253
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700254 public ArraySet<String> getAllowInPowerSaveExceptIdle() {
255 return mAllowInPowerSaveExceptIdle;
256 }
257
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700258 public ArraySet<String> getAllowInPowerSave() {
259 return mAllowInPowerSave;
260 }
261
Felipe Lemea9505cc2016-02-26 10:28:41 -0800262 public ArraySet<String> getAllowInDataUsageSave() {
263 return mAllowInDataUsageSave;
264 }
265
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800266 public ArraySet<String> getAllowUnthrottledLocation() {
267 return mAllowUnthrottledLocation;
268 }
269
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800270 public ArraySet<String> getAllowIgnoreLocationSettings() {
271 return mAllowIgnoreLocationSettings;
272 }
273
Christopher Tate01e18642015-07-07 18:10:38 -0700274 public ArraySet<String> getLinkedApps() {
275 return mLinkedApps;
276 }
277
Fyodor Kupolov7db5af12015-07-31 16:50:27 -0700278 public ArraySet<String> getSystemUserWhitelistedApps() {
279 return mSystemUserWhitelistedApps;
280 }
281
282 public ArraySet<String> getSystemUserBlacklistedApps() {
283 return mSystemUserBlacklistedApps;
284 }
285
Mathew Inwood4693a752018-02-20 16:04:25 +0000286 public ArraySet<String> getHiddenApiWhitelistedApps() {
287 return mHiddenApiPackageWhitelist;
288 }
289
Ruben Brunk98576cf2016-03-07 18:54:28 -0800290 public ArraySet<ComponentName> getDefaultVrComponents() {
291 return mDefaultVrComponents;
292 }
293
Christopher Tate494df792016-05-10 17:05:38 -0700294 public ArraySet<ComponentName> getBackupTransportWhitelist() {
295 return mBackupTransportWhitelist;
296 }
297
goneileb31cd42018-02-28 15:22:08 -0800298 public ArraySet<String> getDisabledUntilUsedPreinstalledCarrierApps() {
299 return mDisabledUntilUsedPreinstalledCarrierApps;
300 }
301
Jeff Davidson24b9d962016-07-21 12:35:10 -0700302 public ArrayMap<String, List<String>> getDisabledUntilUsedPreinstalledCarrierAssociatedApps() {
303 return mDisabledUntilUsedPreinstalledCarrierAssociatedApps;
304 }
305
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800306 public ArraySet<String> getPrivAppPermissions(String packageName) {
307 return mPrivAppPermissions.get(packageName);
308 }
309
Todd Kennedy74629e32017-08-15 14:48:07 -0700310 public ArraySet<String> getPrivAppDenyPermissions(String packageName) {
311 return mPrivAppDenyPermissions.get(packageName);
312 }
313
Jiyong Park002fdbd2017-02-13 20:50:31 +0900314 public ArraySet<String> getVendorPrivAppPermissions(String packageName) {
315 return mVendorPrivAppPermissions.get(packageName);
316 }
317
318 public ArraySet<String> getVendorPrivAppDenyPermissions(String packageName) {
319 return mVendorPrivAppDenyPermissions.get(packageName);
320 }
321
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900322 public ArraySet<String> getProductPrivAppPermissions(String packageName) {
323 return mProductPrivAppPermissions.get(packageName);
324 }
325
326 public ArraySet<String> getProductPrivAppDenyPermissions(String packageName) {
327 return mProductPrivAppDenyPermissions.get(packageName);
328 }
329
Jeongik Chaf6629832019-07-04 21:12:06 +0900330 /**
331 * Read from "permission" tags in /system_ext/etc/permissions/*.xml
332 * @return Set of privileged permissions that are explicitly granted.
333 */
334 public ArraySet<String> getSystemExtPrivAppPermissions(String packageName) {
335 return mSystemExtPrivAppPermissions.get(packageName);
Dario Freni2bef1762018-06-01 14:02:08 +0100336 }
337
Jeongik Chaf6629832019-07-04 21:12:06 +0900338 /**
339 * Read from "deny-permission" tags in /system_ext/etc/permissions/*.xml
340 * @return Set of privileged permissions that are explicitly denied.
341 */
342 public ArraySet<String> getSystemExtPrivAppDenyPermissions(String packageName) {
343 return mSystemExtPrivAppDenyPermissions.get(packageName);
Dario Freni2bef1762018-06-01 14:02:08 +0100344 }
345
Svet Ganov087dce22017-09-07 15:42:16 -0700346 public Map<String, Boolean> getOemPermissions(String packageName) {
347 final Map<String, Boolean> oemPermissions = mOemPermissions.get(packageName);
348 if (oemPermissions != null) {
349 return oemPermissions;
350 }
351 return Collections.emptyMap();
352 }
353
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800354 public ArrayMap<String, ArraySet<String>> getAllowedAssociations() {
355 return mAllowedAssociations;
356 }
357
Nikita Ioffe07964b42019-02-28 21:35:02 +0000358 public ArraySet<String> getBugreportWhitelistedPackages() {
359 return mBugreportWhitelistedPackages;
360 }
361
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700362 SystemConfig() {
363 // Read configuration from system
364 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800365 Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL);
Svet Ganov087dce22017-09-07 15:42:16 -0700366
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700367 // Read configuration from the old permissions dir
368 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800369 Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);
Svet Ganov087dce22017-09-07 15:42:16 -0700370
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800371 // Vendors are only allowed to customize these
372 int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS
373 | ALLOW_ASSOCIATIONS;
Jiyong Parkfad99442018-03-12 10:39:07 +0900374 if (Build.VERSION.FIRST_SDK_INT <= Build.VERSION_CODES.O_MR1) {
375 // For backward compatibility
376 vendorPermissionFlag |= (ALLOW_PERMISSIONS | ALLOW_APP_CONFIGS);
377 }
Jaekyun Seoke3b6bf12017-02-16 13:48:30 +0900378 readPermissions(Environment.buildPath(
379 Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
380 readPermissions(Environment.buildPath(
381 Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag);
Svet Ganov087dce22017-09-07 15:42:16 -0700382
Jiyong Park090c6b12017-12-28 12:03:28 +0900383 // Allow ODM to customize system configs as much as Vendor, because /odm is another
384 // vendor partition other than /vendor.
385 int odmPermissionFlag = vendorPermissionFlag;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700386 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800387 Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700388 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800389 Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);
Svet Ganov087dce22017-09-07 15:42:16 -0700390
Steven Morelandd7827fd2018-12-03 10:27:01 -0800391 String skuProperty = SystemProperties.get(SKU_PROPERTY, "");
392 if (!skuProperty.isEmpty()) {
393 String skuDir = "sku_" + skuProperty;
394
395 readPermissions(Environment.buildPath(
396 Environment.getOdmDirectory(), "etc", "sysconfig", skuDir), odmPermissionFlag);
397 readPermissions(Environment.buildPath(
398 Environment.getOdmDirectory(), "etc", "permissions", skuDir),
399 odmPermissionFlag);
400 }
401
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800402 // Allow OEM to customize these
403 int oemPermissionFlag = ALLOW_FEATURES | ALLOW_OEM_PERMISSIONS | ALLOW_ASSOCIATIONS;
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800404 readPermissions(Environment.buildPath(
Svet Ganov087dce22017-09-07 15:42:16 -0700405 Environment.getOemDirectory(), "etc", "sysconfig"), oemPermissionFlag);
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800406 readPermissions(Environment.buildPath(
Svet Ganov087dce22017-09-07 15:42:16 -0700407 Environment.getOemDirectory(), "etc", "permissions"), oemPermissionFlag);
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900408
Hung-ying Tyan38cd31c2018-09-26 15:05:07 +0800409 // Allow Product to customize all system configs
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900410 readPermissions(Environment.buildPath(
Hung-ying Tyan38cd31c2018-09-26 15:05:07 +0800411 Environment.getProductDirectory(), "etc", "sysconfig"), ALLOW_ALL);
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900412 readPermissions(Environment.buildPath(
Hung-ying Tyan38cd31c2018-09-26 15:05:07 +0800413 Environment.getProductDirectory(), "etc", "permissions"), ALLOW_ALL);
Dario Freni2bef1762018-06-01 14:02:08 +0100414
Jeongik Chaf6629832019-07-04 21:12:06 +0900415 // Allow /system_ext to customize all system configs
Dario Freni2bef1762018-06-01 14:02:08 +0100416 readPermissions(Environment.buildPath(
Jeongik Chaf6629832019-07-04 21:12:06 +0900417 Environment.getSystemExtDirectory(), "etc", "sysconfig"), ALLOW_ALL);
Dario Freni2bef1762018-06-01 14:02:08 +0100418 readPermissions(Environment.buildPath(
Jeongik Chaf6629832019-07-04 21:12:06 +0900419 Environment.getSystemExtDirectory(), "etc", "permissions"), ALLOW_ALL);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700420 }
421
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800422 void readPermissions(File libraryDir, int permissionFlag) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700423 // Read permissions from given directory.
424 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800425 if (permissionFlag == ALLOW_ALL) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700426 Slog.w(TAG, "No directory " + libraryDir + ", skipping");
427 }
428 return;
429 }
430 if (!libraryDir.canRead()) {
431 Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
432 return;
433 }
434
435 // Iterate over the files in the directory and scan .xml files
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800436 File platformFile = null;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700437 for (File f : libraryDir.listFiles()) {
Steven Morelandd7827fd2018-12-03 10:27:01 -0800438 if (!f.isFile()) {
439 continue;
440 }
441
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700442 // We'll read platform.xml last
443 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800444 platformFile = f;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700445 continue;
446 }
447
448 if (!f.getPath().endsWith(".xml")) {
449 Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
450 continue;
451 }
452 if (!f.canRead()) {
453 Slog.w(TAG, "Permissions library file " + f + " cannot be read");
454 continue;
455 }
456
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800457 readPermissionsFromXml(f, permissionFlag);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700458 }
459
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800460 // Read platform permissions last so it will take precedence
461 if (platformFile != null) {
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800462 readPermissionsFromXml(platformFile, permissionFlag);
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800463 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700464 }
465
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800466 private void logNotAllowedInPartition(String name, File permFile, XmlPullParser parser) {
467 Slog.w(TAG, "<" + name + "> not allowed in partition of "
468 + permFile + " at " + parser.getPositionDescription());
469 }
470
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800471 private void readPermissionsFromXml(File permFile, int permissionFlag) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700472 FileReader permReader = null;
473 try {
474 permReader = new FileReader(permFile);
475 } catch (FileNotFoundException e) {
476 Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
477 return;
478 }
479
Dianne Hackbornc0e4aaa2014-11-14 10:55:50 -0800480 final boolean lowRam = ActivityManager.isLowRamDeviceStatic();
481
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700482 try {
483 XmlPullParser parser = Xml.newPullParser();
484 parser.setInput(permReader);
485
486 int type;
487 while ((type=parser.next()) != parser.START_TAG
488 && type != parser.END_DOCUMENT) {
489 ;
490 }
491
492 if (type != parser.START_TAG) {
493 throw new XmlPullParserException("No start tag found");
494 }
495
496 if (!parser.getName().equals("permissions") && !parser.getName().equals("config")) {
Dianne Hackbornb3d4cb32015-01-09 09:54:06 -0800497 throw new XmlPullParserException("Unexpected start tag in " + permFile
498 + ": found " + parser.getName() + ", expected 'permissions' or 'config'");
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700499 }
500
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800501 final boolean allowAll = permissionFlag == ALLOW_ALL;
502 final boolean allowLibs = (permissionFlag & ALLOW_LIBS) != 0;
503 final boolean allowFeatures = (permissionFlag & ALLOW_FEATURES) != 0;
504 final boolean allowPermissions = (permissionFlag & ALLOW_PERMISSIONS) != 0;
505 final boolean allowAppConfigs = (permissionFlag & ALLOW_APP_CONFIGS) != 0;
506 final boolean allowPrivappPermissions = (permissionFlag & ALLOW_PRIVAPP_PERMISSIONS)
507 != 0;
508 final boolean allowOemPermissions = (permissionFlag & ALLOW_OEM_PERMISSIONS) != 0;
509 final boolean allowApiWhitelisting = (permissionFlag & ALLOW_HIDDENAPI_WHITELISTING)
510 != 0;
511 final boolean allowAssociations = (permissionFlag & ALLOW_ASSOCIATIONS) != 0;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700512 while (true) {
513 XmlUtils.nextElement(parser);
514 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
515 break;
516 }
517
518 String name = parser.getName();
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800519 if (name == null) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700520 XmlUtils.skipCurrentTag(parser);
521 continue;
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800522 }
523 switch (name) {
524 case "group": {
525 if (allowAll) {
526 String gidStr = parser.getAttributeValue(null, "gid");
527 if (gidStr != null) {
528 int gid = android.os.Process.getGidForName(gidStr);
529 mGlobalGids = appendInt(mGlobalGids, gid);
530 } else {
531 Slog.w(TAG, "<" + name + "> without gid in " + permFile + " at "
goneileb31cd42018-02-28 15:22:08 -0800532 + parser.getPositionDescription());
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800533 }
534 } else {
535 logNotAllowedInPartition(name, permFile, parser);
536 }
537 XmlUtils.skipCurrentTag(parser);
538 } break;
539 case "permission": {
540 if (allowPermissions) {
541 String perm = parser.getAttributeValue(null, "name");
542 if (perm == null) {
543 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
544 + parser.getPositionDescription());
545 XmlUtils.skipCurrentTag(parser);
546 break;
547 }
548 perm = perm.intern();
549 readPermission(parser, perm);
550 } else {
551 logNotAllowedInPartition(name, permFile, parser);
552 XmlUtils.skipCurrentTag(parser);
553 }
554 } break;
555 case "assign-permission": {
556 if (allowPermissions) {
557 String perm = parser.getAttributeValue(null, "name");
558 if (perm == null) {
559 Slog.w(TAG, "<" + name + "> without name in " + permFile
560 + " at " + parser.getPositionDescription());
561 XmlUtils.skipCurrentTag(parser);
562 break;
563 }
564 String uidStr = parser.getAttributeValue(null, "uid");
565 if (uidStr == null) {
566 Slog.w(TAG, "<" + name + "> without uid in " + permFile
567 + " at " + parser.getPositionDescription());
568 XmlUtils.skipCurrentTag(parser);
569 break;
570 }
571 int uid = Process.getUidForName(uidStr);
572 if (uid < 0) {
573 Slog.w(TAG, "<" + name + "> with unknown uid \""
574 + uidStr + " in " + permFile + " at "
575 + parser.getPositionDescription());
576 XmlUtils.skipCurrentTag(parser);
577 break;
578 }
579 perm = perm.intern();
580 ArraySet<String> perms = mSystemPermissions.get(uid);
581 if (perms == null) {
582 perms = new ArraySet<String>();
583 mSystemPermissions.put(uid, perms);
584 }
585 perms.add(perm);
586 } else {
587 logNotAllowedInPartition(name, permFile, parser);
588 }
589 XmlUtils.skipCurrentTag(parser);
590 } break;
591 case "split-permission": {
592 if (allowPermissions) {
593 readSplitPermission(parser, permFile);
594 } else {
595 logNotAllowedInPartition(name, permFile, parser);
596 XmlUtils.skipCurrentTag(parser);
597 }
598 } break;
599 case "library": {
600 if (allowLibs) {
601 String lname = parser.getAttributeValue(null, "name");
602 String lfile = parser.getAttributeValue(null, "file");
603 String ldependency = parser.getAttributeValue(null, "dependency");
604 if (lname == null) {
605 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
606 + parser.getPositionDescription());
607 } else if (lfile == null) {
608 Slog.w(TAG, "<" + name + "> without file in " + permFile + " at "
609 + parser.getPositionDescription());
610 } else {
611 //Log.i(TAG, "Got library " + lname + " in " + lfile);
612 SharedLibraryEntry entry = new SharedLibraryEntry(lname, lfile,
613 ldependency == null ? new String[0] : ldependency.split(":"));
614 mSharedLibraries.put(lname, entry);
615 }
616 } else {
617 logNotAllowedInPartition(name, permFile, parser);
618 }
619 XmlUtils.skipCurrentTag(parser);
620 } break;
621 case "feature": {
622 if (allowFeatures) {
623 String fname = parser.getAttributeValue(null, "name");
624 int fversion = XmlUtils.readIntAttribute(parser, "version", 0);
625 boolean allowed;
626 if (!lowRam) {
627 allowed = true;
628 } else {
629 String notLowRam = parser.getAttributeValue(null, "notLowRam");
630 allowed = !"true".equals(notLowRam);
631 }
632 if (fname == null) {
633 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
634 + parser.getPositionDescription());
635 } else if (allowed) {
636 addFeature(fname, fversion);
637 }
638 } else {
639 logNotAllowedInPartition(name, permFile, parser);
640 }
641 XmlUtils.skipCurrentTag(parser);
642 } break;
643 case "unavailable-feature": {
644 if (allowFeatures) {
645 String fname = parser.getAttributeValue(null, "name");
646 if (fname == null) {
647 Slog.w(TAG, "<" + name + "> without name in " + permFile
648 + " at " + parser.getPositionDescription());
649 } else {
650 mUnavailableFeatures.add(fname);
651 }
652 } else {
653 logNotAllowedInPartition(name, permFile, parser);
654 }
655 XmlUtils.skipCurrentTag(parser);
656 } break;
657 case "allow-in-power-save-except-idle": {
658 if (allowAll) {
659 String pkgname = parser.getAttributeValue(null, "package");
660 if (pkgname == null) {
661 Slog.w(TAG, "<" + name + "> without package in "
662 + permFile + " at " + parser.getPositionDescription());
663 } else {
664 mAllowInPowerSaveExceptIdle.add(pkgname);
665 }
666 } else {
667 logNotAllowedInPartition(name, permFile, parser);
668 }
669 XmlUtils.skipCurrentTag(parser);
670 } break;
671 case "allow-in-power-save": {
672 if (allowAll) {
673 String pkgname = parser.getAttributeValue(null, "package");
674 if (pkgname == null) {
675 Slog.w(TAG, "<" + name + "> without package in "
676 + permFile + " at " + parser.getPositionDescription());
677 } else {
678 mAllowInPowerSave.add(pkgname);
679 }
680 } else {
681 logNotAllowedInPartition(name, permFile, parser);
682 }
683 XmlUtils.skipCurrentTag(parser);
684 } break;
685 case "allow-in-data-usage-save": {
686 if (allowAll) {
687 String pkgname = parser.getAttributeValue(null, "package");
688 if (pkgname == null) {
689 Slog.w(TAG, "<" + name + "> without package in "
690 + permFile + " at " + parser.getPositionDescription());
691 } else {
692 mAllowInDataUsageSave.add(pkgname);
693 }
694 } else {
695 logNotAllowedInPartition(name, permFile, parser);
696 }
697 XmlUtils.skipCurrentTag(parser);
698 } break;
699 case "allow-unthrottled-location": {
700 if (allowAll) {
701 String pkgname = parser.getAttributeValue(null, "package");
702 if (pkgname == null) {
703 Slog.w(TAG, "<" + name + "> without package in "
704 + permFile + " at " + parser.getPositionDescription());
705 } else {
706 mAllowUnthrottledLocation.add(pkgname);
707 }
708 } else {
709 logNotAllowedInPartition(name, permFile, parser);
710 }
711 XmlUtils.skipCurrentTag(parser);
712 } break;
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800713 case "allow-ignore-location-settings": {
714 if (allowAll) {
715 String pkgname = parser.getAttributeValue(null, "package");
716 if (pkgname == null) {
717 Slog.w(TAG, "<" + name + "> without package in "
718 + permFile + " at " + parser.getPositionDescription());
719 } else {
720 mAllowIgnoreLocationSettings.add(pkgname);
721 }
722 } else {
723 logNotAllowedInPartition(name, permFile, parser);
724 }
725 XmlUtils.skipCurrentTag(parser);
726 } break;
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800727 case "allow-implicit-broadcast": {
728 if (allowAll) {
729 String action = parser.getAttributeValue(null, "action");
730 if (action == null) {
731 Slog.w(TAG, "<" + name + "> without action in "
732 + permFile + " at " + parser.getPositionDescription());
733 } else {
734 mAllowImplicitBroadcasts.add(action);
735 }
736 } else {
737 logNotAllowedInPartition(name, permFile, parser);
738 }
739 XmlUtils.skipCurrentTag(parser);
740 } break;
741 case "app-link": {
742 if (allowAppConfigs) {
743 String pkgname = parser.getAttributeValue(null, "package");
744 if (pkgname == null) {
745 Slog.w(TAG, "<" + name + "> without package in " + permFile
746 + " at " + parser.getPositionDescription());
747 } else {
748 mLinkedApps.add(pkgname);
749 }
750 } else {
751 logNotAllowedInPartition(name, permFile, parser);
752 }
753 XmlUtils.skipCurrentTag(parser);
754 } break;
755 case "system-user-whitelisted-app": {
756 if (allowAppConfigs) {
757 String pkgname = parser.getAttributeValue(null, "package");
758 if (pkgname == null) {
759 Slog.w(TAG, "<" + name + "> without package in "
760 + permFile + " at " + parser.getPositionDescription());
761 } else {
762 mSystemUserWhitelistedApps.add(pkgname);
763 }
764 } else {
765 logNotAllowedInPartition(name, permFile, parser);
766 }
767 XmlUtils.skipCurrentTag(parser);
768 } break;
769 case "system-user-blacklisted-app": {
770 if (allowAppConfigs) {
771 String pkgname = parser.getAttributeValue(null, "package");
772 if (pkgname == null) {
773 Slog.w(TAG, "<" + name + "> without package in "
774 + permFile + " at " + parser.getPositionDescription());
775 } else {
776 mSystemUserBlacklistedApps.add(pkgname);
777 }
778 } else {
779 logNotAllowedInPartition(name, permFile, parser);
780 }
781 XmlUtils.skipCurrentTag(parser);
782 } break;
783 case "default-enabled-vr-app": {
784 if (allowAppConfigs) {
785 String pkgname = parser.getAttributeValue(null, "package");
786 String clsname = parser.getAttributeValue(null, "class");
787 if (pkgname == null) {
788 Slog.w(TAG, "<" + name + "> without package in "
789 + permFile + " at " + parser.getPositionDescription());
790 } else if (clsname == null) {
791 Slog.w(TAG, "<" + name + "> without class in "
792 + permFile + " at " + parser.getPositionDescription());
793 } else {
794 mDefaultVrComponents.add(new ComponentName(pkgname, clsname));
795 }
796 } else {
797 logNotAllowedInPartition(name, permFile, parser);
798 }
799 XmlUtils.skipCurrentTag(parser);
800 } break;
801 case "backup-transport-whitelisted-service": {
802 if (allowFeatures) {
803 String serviceName = parser.getAttributeValue(null, "service");
804 if (serviceName == null) {
805 Slog.w(TAG, "<" + name + "> without service in "
806 + permFile + " at " + parser.getPositionDescription());
807 } else {
808 ComponentName cn = ComponentName.unflattenFromString(serviceName);
809 if (cn == null) {
810 Slog.w(TAG, "<" + name + "> with invalid service name "
811 + serviceName + " in " + permFile
812 + " at " + parser.getPositionDescription());
813 } else {
814 mBackupTransportWhitelist.add(cn);
815 }
816 }
817 } else {
818 logNotAllowedInPartition(name, permFile, parser);
819 }
820 XmlUtils.skipCurrentTag(parser);
821 } break;
822 case "disabled-until-used-preinstalled-carrier-associated-app": {
823 if (allowAppConfigs) {
824 String pkgname = parser.getAttributeValue(null, "package");
825 String carrierPkgname = parser.getAttributeValue(null,
826 "carrierAppPackage");
827 if (pkgname == null || carrierPkgname == null) {
828 Slog.w(TAG, "<" + name
829 + "> without package or carrierAppPackage in " + permFile
830 + " at " + parser.getPositionDescription());
831 } else {
832 List<String> associatedPkgs =
833 mDisabledUntilUsedPreinstalledCarrierAssociatedApps.get(
834 carrierPkgname);
835 if (associatedPkgs == null) {
836 associatedPkgs = new ArrayList<>();
837 mDisabledUntilUsedPreinstalledCarrierAssociatedApps.put(
838 carrierPkgname, associatedPkgs);
839 }
840 associatedPkgs.add(pkgname);
841 }
842 } else {
843 logNotAllowedInPartition(name, permFile, parser);
844 }
845 XmlUtils.skipCurrentTag(parser);
846 } break;
847 case "disabled-until-used-preinstalled-carrier-app": {
848 if (allowAppConfigs) {
849 String pkgname = parser.getAttributeValue(null, "package");
850 if (pkgname == null) {
851 Slog.w(TAG,
852 "<" + name + "> without "
853 + "package in " + permFile + " at "
854 + parser.getPositionDescription());
855 } else {
856 mDisabledUntilUsedPreinstalledCarrierApps.add(pkgname);
857 }
858 } else {
859 logNotAllowedInPartition(name, permFile, parser);
860 }
861 XmlUtils.skipCurrentTag(parser);
862 } break;
863 case "privapp-permissions": {
864 if (allowPrivappPermissions) {
Jeongik Chaf6629832019-07-04 21:12:06 +0900865 // privapp permissions from system, vendor, product and system_ext
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800866 // partitions are stored separately. This is to prevent xml files in
867 // the vendor partition from granting permissions to priv apps in the
868 // system partition and vice versa.
869 boolean vendor = permFile.toPath().startsWith(
870 Environment.getVendorDirectory().toPath() + "/")
871 || permFile.toPath().startsWith(
872 Environment.getOdmDirectory().toPath() + "/");
873 boolean product = permFile.toPath().startsWith(
874 Environment.getProductDirectory().toPath() + "/");
Jeongik Chaf6629832019-07-04 21:12:06 +0900875 boolean systemExt = permFile.toPath().startsWith(
876 Environment.getSystemExtDirectory().toPath() + "/");
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800877 if (vendor) {
878 readPrivAppPermissions(parser, mVendorPrivAppPermissions,
879 mVendorPrivAppDenyPermissions);
880 } else if (product) {
881 readPrivAppPermissions(parser, mProductPrivAppPermissions,
882 mProductPrivAppDenyPermissions);
Jeongik Chaf6629832019-07-04 21:12:06 +0900883 } else if (systemExt) {
884 readPrivAppPermissions(parser, mSystemExtPrivAppPermissions,
885 mSystemExtPrivAppDenyPermissions);
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800886 } else {
887 readPrivAppPermissions(parser, mPrivAppPermissions,
888 mPrivAppDenyPermissions);
889 }
890 } else {
891 logNotAllowedInPartition(name, permFile, parser);
892 XmlUtils.skipCurrentTag(parser);
893 }
894 } break;
895 case "oem-permissions": {
896 if (allowOemPermissions) {
897 readOemPermissions(parser);
898 } else {
899 logNotAllowedInPartition(name, permFile, parser);
900 XmlUtils.skipCurrentTag(parser);
901 }
902 } break;
903 case "hidden-api-whitelisted-app": {
904 if (allowApiWhitelisting) {
905 String pkgname = parser.getAttributeValue(null, "package");
906 if (pkgname == null) {
907 Slog.w(TAG, "<" + name + "> without package in "
908 + permFile + " at " + parser.getPositionDescription());
909 } else {
910 mHiddenApiPackageWhitelist.add(pkgname);
911 }
912 } else {
913 logNotAllowedInPartition(name, permFile, parser);
914 }
915 XmlUtils.skipCurrentTag(parser);
916 } break;
917 case "allow-association": {
918 if (allowAssociations) {
919 String target = parser.getAttributeValue(null, "target");
920 if (target == null) {
921 Slog.w(TAG, "<" + name + "> without target in " + permFile
922 + " at " + parser.getPositionDescription());
923 XmlUtils.skipCurrentTag(parser);
924 break;
925 }
926 String allowed = parser.getAttributeValue(null, "allowed");
927 if (allowed == null) {
928 Slog.w(TAG, "<" + name + "> without allowed in " + permFile
929 + " at " + parser.getPositionDescription());
930 XmlUtils.skipCurrentTag(parser);
931 break;
932 }
933 target = target.intern();
934 allowed = allowed.intern();
935 ArraySet<String> associations = mAllowedAssociations.get(target);
936 if (associations == null) {
937 associations = new ArraySet<>();
938 mAllowedAssociations.put(target, associations);
939 }
940 Slog.i(TAG, "Adding association: " + target + " <- " + allowed);
941 associations.add(allowed);
942 } else {
943 logNotAllowedInPartition(name, permFile, parser);
944 }
945 XmlUtils.skipCurrentTag(parser);
946 } break;
Nikita Ioffe07964b42019-02-28 21:35:02 +0000947 case "bugreport-whitelisted": {
948 String pkgname = parser.getAttributeValue(null, "package");
949 if (pkgname == null) {
950 Slog.w(TAG, "<" + name + "> without package in " + permFile
951 + " at " + parser.getPositionDescription());
952 } else {
953 mBugreportWhitelistedPackages.add(pkgname);
954 }
Nikita Ioffe08146ef2019-03-13 17:04:21 +0000955 XmlUtils.skipCurrentTag(parser);
Nikita Ioffe07964b42019-02-28 21:35:02 +0000956 } break;
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800957 default: {
958 Slog.w(TAG, "Tag " + name + " is unknown in "
959 + permFile + " at " + parser.getPositionDescription());
960 XmlUtils.skipCurrentTag(parser);
961 } break;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700962 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700963 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700964 } catch (XmlPullParserException e) {
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800965 Slog.w(TAG, "Got exception parsing permissions.", e);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700966 } catch (IOException e) {
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800967 Slog.w(TAG, "Got exception parsing permissions.", e);
968 } finally {
969 IoUtils.closeQuietly(permReader);
970 }
971
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -0700972 // Some devices can be field-converted to FBE, so offer to splice in
973 // those features if not already defined by the static config
Paul Lawrence20be5d62016-02-26 13:51:17 -0800974 if (StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700975 addFeature(PackageManager.FEATURE_FILE_BASED_ENCRYPTION, 0);
976 addFeature(PackageManager.FEATURE_SECURELY_REMOVES_USERS, 0);
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -0700977 }
978
Jeff Sharkey8eb783b2018-01-04 16:46:48 -0700979 // Help legacy devices that may not have updated their static config
980 if (StorageManager.hasAdoptable()) {
981 addFeature(PackageManager.FEATURE_ADOPTABLE_STORAGE, 0);
982 }
983
Dianne Hackborn2a103f12017-08-08 15:50:31 -0700984 if (ActivityManager.isLowRamDeviceStatic()) {
985 addFeature(PackageManager.FEATURE_RAM_LOW, 0);
986 } else {
987 addFeature(PackageManager.FEATURE_RAM_NORMAL, 0);
988 }
989
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -0700990 for (String featureName : mUnavailableFeatures) {
991 removeFeature(featureName);
992 }
993 }
994
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700995 private void addFeature(String name, int version) {
996 FeatureInfo fi = mAvailableFeatures.get(name);
997 if (fi == null) {
998 fi = new FeatureInfo();
999 fi.name = name;
1000 fi.version = version;
1001 mAvailableFeatures.put(name, fi);
1002 } else {
1003 fi.version = Math.max(fi.version, version);
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -07001004 }
1005 }
1006
Jeff Sharkey115d2c12016-02-15 17:25:57 -07001007 private void removeFeature(String name) {
1008 if (mAvailableFeatures.remove(name) != null) {
1009 Slog.d(TAG, "Removed unavailable feature " + name);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001010 }
1011 }
1012
1013 void readPermission(XmlPullParser parser, String name)
1014 throws IOException, XmlPullParserException {
Jeff Sharkey00f39042015-03-23 16:51:22 -07001015 if (mPermissions.containsKey(name)) {
1016 throw new IllegalStateException("Duplicate permission definition for " + name);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001017 }
Jeff Sharkey00f39042015-03-23 16:51:22 -07001018
1019 final boolean perUser = XmlUtils.readBooleanAttribute(parser, "perUser", false);
1020 final PermissionEntry perm = new PermissionEntry(name, perUser);
1021 mPermissions.put(name, perm);
1022
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001023 int outerDepth = parser.getDepth();
1024 int type;
1025 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1026 && (type != XmlPullParser.END_TAG
1027 || parser.getDepth() > outerDepth)) {
1028 if (type == XmlPullParser.END_TAG
1029 || type == XmlPullParser.TEXT) {
1030 continue;
1031 }
1032
1033 String tagName = parser.getName();
1034 if ("group".equals(tagName)) {
1035 String gidStr = parser.getAttributeValue(null, "gid");
1036 if (gidStr != null) {
1037 int gid = Process.getGidForName(gidStr);
1038 perm.gids = appendInt(perm.gids, gid);
1039 } else {
1040 Slog.w(TAG, "<group> without gid at "
1041 + parser.getPositionDescription());
1042 }
1043 }
1044 XmlUtils.skipCurrentTag(parser);
1045 }
1046 }
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001047
Jiyong Park002fdbd2017-02-13 20:50:31 +09001048 private void readPrivAppPermissions(XmlPullParser parser,
1049 ArrayMap<String, ArraySet<String>> grantMap,
1050 ArrayMap<String, ArraySet<String>> denyMap)
1051 throws IOException, XmlPullParserException {
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001052 String packageName = parser.getAttributeValue(null, "package");
1053 if (TextUtils.isEmpty(packageName)) {
1054 Slog.w(TAG, "package is required for <privapp-permissions> in "
1055 + parser.getPositionDescription());
1056 return;
1057 }
1058
Jiyong Park002fdbd2017-02-13 20:50:31 +09001059 ArraySet<String> permissions = grantMap.get(packageName);
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001060 if (permissions == null) {
1061 permissions = new ArraySet<>();
1062 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09001063 ArraySet<String> denyPermissions = denyMap.get(packageName);
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001064 int depth = parser.getDepth();
1065 while (XmlUtils.nextElementWithin(parser, depth)) {
1066 String name = parser.getName();
1067 if ("permission".equals(name)) {
1068 String permName = parser.getAttributeValue(null, "name");
1069 if (TextUtils.isEmpty(permName)) {
1070 Slog.w(TAG, "name is required for <permission> in "
1071 + parser.getPositionDescription());
1072 continue;
1073 }
1074 permissions.add(permName);
Todd Kennedy74629e32017-08-15 14:48:07 -07001075 } else if ("deny-permission".equals(name)) {
1076 String permName = parser.getAttributeValue(null, "name");
1077 if (TextUtils.isEmpty(permName)) {
1078 Slog.w(TAG, "name is required for <deny-permission> in "
1079 + parser.getPositionDescription());
1080 continue;
1081 }
1082 if (denyPermissions == null) {
1083 denyPermissions = new ArraySet<>();
1084 }
1085 denyPermissions.add(permName);
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001086 }
1087 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09001088 grantMap.put(packageName, permissions);
Todd Kennedy74629e32017-08-15 14:48:07 -07001089 if (denyPermissions != null) {
Jiyong Park002fdbd2017-02-13 20:50:31 +09001090 denyMap.put(packageName, denyPermissions);
Todd Kennedy74629e32017-08-15 14:48:07 -07001091 }
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001092 }
Svet Ganov087dce22017-09-07 15:42:16 -07001093
1094 void readOemPermissions(XmlPullParser parser) throws IOException, XmlPullParserException {
1095 final String packageName = parser.getAttributeValue(null, "package");
1096 if (TextUtils.isEmpty(packageName)) {
1097 Slog.w(TAG, "package is required for <oem-permissions> in "
1098 + parser.getPositionDescription());
1099 return;
1100 }
1101
1102 ArrayMap<String, Boolean> permissions = mOemPermissions.get(packageName);
1103 if (permissions == null) {
1104 permissions = new ArrayMap<>();
1105 }
1106 final int depth = parser.getDepth();
1107 while (XmlUtils.nextElementWithin(parser, depth)) {
1108 final String name = parser.getName();
1109 if ("permission".equals(name)) {
1110 final String permName = parser.getAttributeValue(null, "name");
1111 if (TextUtils.isEmpty(permName)) {
1112 Slog.w(TAG, "name is required for <permission> in "
1113 + parser.getPositionDescription());
1114 continue;
1115 }
1116 permissions.put(permName, Boolean.TRUE);
1117 } else if ("deny-permission".equals(name)) {
1118 String permName = parser.getAttributeValue(null, "name");
1119 if (TextUtils.isEmpty(permName)) {
1120 Slog.w(TAG, "name is required for <deny-permission> in "
1121 + parser.getPositionDescription());
1122 continue;
1123 }
1124 permissions.put(permName, Boolean.FALSE);
1125 }
1126 }
1127 mOemPermissions.put(packageName, permissions);
1128 }
Zimuzocc2932f2018-10-29 16:04:41 +00001129
1130 private void readSplitPermission(XmlPullParser parser, File permFile)
1131 throws IOException, XmlPullParserException {
1132 String splitPerm = parser.getAttributeValue(null, "name");
1133 if (splitPerm == null) {
1134 Slog.w(TAG, "<split-permission> without name in " + permFile + " at "
1135 + parser.getPositionDescription());
1136 XmlUtils.skipCurrentTag(parser);
1137 return;
1138 }
1139 String targetSdkStr = parser.getAttributeValue(null, "targetSdk");
1140 int targetSdk = Build.VERSION_CODES.CUR_DEVELOPMENT + 1;
1141 if (!TextUtils.isEmpty(targetSdkStr)) {
1142 try {
1143 targetSdk = Integer.parseInt(targetSdkStr);
1144 } catch (NumberFormatException e) {
1145 Slog.w(TAG, "<split-permission> targetSdk not an integer in " + permFile + " at "
1146 + parser.getPositionDescription());
1147 XmlUtils.skipCurrentTag(parser);
1148 return;
1149 }
1150 }
1151 final int depth = parser.getDepth();
1152 List<String> newPermissions = new ArrayList<>();
1153 while (XmlUtils.nextElementWithin(parser, depth)) {
1154 String name = parser.getName();
1155 if ("new-permission".equals(name)) {
1156 final String newName = parser.getAttributeValue(null, "name");
1157 if (TextUtils.isEmpty(newName)) {
1158 Slog.w(TAG, "name is required for <new-permission> in "
1159 + parser.getPositionDescription());
1160 continue;
1161 }
1162 newPermissions.add(newName);
1163 } else {
1164 XmlUtils.skipCurrentTag(parser);
1165 }
1166 }
1167 if (!newPermissions.isEmpty()) {
1168 mSplitPermissions.add(new SplitPermissionInfo(splitPerm, newPermissions, targetSdk));
1169 }
1170 }
Anthony Hugh6f5eadc2019-08-22 15:35:48 -07001171
1172 private static boolean isSystemProcess() {
1173 return Process.myUid() == Process.SYSTEM_UID;
1174 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001175}