blob: 364278d1a09e058e1943853371999503316c8883 [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.
56 */
57public class SystemConfig {
58 static final String TAG = "SystemConfig";
59
60 static SystemConfig sInstance;
61
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +080062 // permission flag, determines which types of configuration are allowed to be read
63 private static final int ALLOW_FEATURES = 0x01;
64 private static final int ALLOW_LIBS = 0x02;
65 private static final int ALLOW_PERMISSIONS = 0x04;
66 private static final int ALLOW_APP_CONFIGS = 0x08;
Jaekyun Seoke3b6bf12017-02-16 13:48:30 +090067 private static final int ALLOW_PRIVAPP_PERMISSIONS = 0x10;
Svet Ganov087dce22017-09-07 15:42:16 -070068 private static final int ALLOW_OEM_PERMISSIONS = 0x20;
Mathew Inwood4693a752018-02-20 16:04:25 +000069 private static final int ALLOW_HIDDENAPI_WHITELISTING = 0x40;
Dianne Hackborn769b2e72018-12-05 08:51:20 -080070 private static final int ALLOW_ASSOCIATIONS = 0x80;
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +080071 private static final int ALLOW_ALL = ~0;
72
Steven Morelandd7827fd2018-12-03 10:27:01 -080073 // property for runtime configuration differentiation
74 private static final String SKU_PROPERTY = "ro.boot.product.hardware.sku";
75
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070076 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
77 int[] mGlobalGids;
78
79 // These are the built-in uid -> permission mappings that were read from the
80 // system configuration files.
Jeff Sharkey9f837a92014-10-24 12:07:24 -070081 final SparseArray<ArraySet<String>> mSystemPermissions = new SparseArray<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070082
Zimuzocc2932f2018-10-29 16:04:41 +000083 final ArrayList<SplitPermissionInfo> mSplitPermissions = new ArrayList<>();
84
Ben Lin71c16d72018-12-06 18:34:51 -080085 public static final class SharedLibraryEntry {
86 public final String name;
87 public final String filename;
88 public final String[] dependencies;
89
90 SharedLibraryEntry(String name, String filename, String[] dependencies) {
91 this.name = name;
92 this.filename = filename;
93 this.dependencies = dependencies;
94 }
95 }
96
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070097 // These are the built-in shared libraries that were read from the
Ben Lin71c16d72018-12-06 18:34:51 -080098 // system configuration files. Keys are the library names; values are
99 // the individual entries that contain information such as filename
100 // and dependencies.
101 final ArrayMap<String, SharedLibraryEntry> mSharedLibraries = new ArrayMap<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700102
103 // These are the features this devices supports that were read from the
104 // system configuration files.
Jeff Sharkey9f837a92014-10-24 12:07:24 -0700105 final ArrayMap<String, FeatureInfo> mAvailableFeatures = new ArrayMap<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700106
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800107 // These are the features which this device doesn't support; the OEM
108 // partition uses these to opt-out of features from the system image.
109 final ArraySet<String> mUnavailableFeatures = new ArraySet<>();
110
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700111 public static final class PermissionEntry {
112 public final String name;
113 public int[] gids;
Jeff Sharkey00f39042015-03-23 16:51:22 -0700114 public boolean perUser;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700115
Jeff Sharkey00f39042015-03-23 16:51:22 -0700116 PermissionEntry(String name, boolean perUser) {
117 this.name = name;
118 this.perUser = perUser;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700119 }
120 }
121
122 // These are the permission -> gid mappings that were read from the
123 // system configuration files.
Dianne Hackbornbb8aa5a2014-09-17 13:20:38 -0700124 final ArrayMap<String, PermissionEntry> mPermissions = new ArrayMap<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700125
126 // These are the packages that are white-listed to be able to run in the
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700127 // background while in power save mode (but not whitelisted from device idle modes),
128 // as read from the configuration files.
129 final ArraySet<String> mAllowInPowerSaveExceptIdle = new ArraySet<>();
130
131 // These are the packages that are white-listed to be able to run in the
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700132 // background while in power save mode, as read from the configuration files.
Dianne Hackbornbb8aa5a2014-09-17 13:20:38 -0700133 final ArraySet<String> mAllowInPowerSave = new ArraySet<>();
134
Felipe Lemea9505cc2016-02-26 10:28:41 -0800135 // These are the packages that are white-listed to be able to run in the
136 // background while in data-usage save mode, as read from the configuration files.
137 final ArraySet<String> mAllowInDataUsageSave = new ArraySet<>();
138
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800139 // These are the packages that are white-listed to be able to run background location
140 // without throttling, as read from the configuration files.
141 final ArraySet<String> mAllowUnthrottledLocation = new ArraySet<>();
142
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800143 // These are the packages that are white-listed to be able to retrieve location even when user
144 // location settings are off, for emergency purposes, as read from the configuration files.
145 final ArraySet<String> mAllowIgnoreLocationSettings = new ArraySet<>();
146
Christopher Tate42a386b2016-11-07 12:21:21 -0800147 // These are the action strings of broadcasts which are whitelisted to
148 // be delivered anonymously even to apps which target O+.
149 final ArraySet<String> mAllowImplicitBroadcasts = new ArraySet<>();
150
Christopher Tate01e18642015-07-07 18:10:38 -0700151 // These are the package names of apps which should be in the 'always'
152 // URL-handling state upon factory reset.
153 final ArraySet<String> mLinkedApps = new ArraySet<>();
154
Fyodor Kupolov7db5af12015-07-31 16:50:27 -0700155 // These are the packages that are whitelisted to be able to run as system user
156 final ArraySet<String> mSystemUserWhitelistedApps = new ArraySet<>();
157
158 // These are the packages that should not run under system user
159 final ArraySet<String> mSystemUserBlacklistedApps = new ArraySet<>();
160
Ruben Brunk98576cf2016-03-07 18:54:28 -0800161 // These are the components that are enabled by default as VR mode listener services.
162 final ArraySet<ComponentName> mDefaultVrComponents = new ArraySet<>();
163
Christopher Tate494df792016-05-10 17:05:38 -0700164 // These are the permitted backup transport service components
165 final ArraySet<ComponentName> mBackupTransportWhitelist = new ArraySet<>();
166
Mathew Inwood4693a752018-02-20 16:04:25 +0000167 // Package names that are exempted from private API blacklisting
168 final ArraySet<String> mHiddenApiPackageWhitelist = new ArraySet<>();
169
goneileb31cd42018-02-28 15:22:08 -0800170 // The list of carrier applications which should be disabled until used.
171 // This function suppresses update notifications for these pre-installed apps.
172 // In SubscriptionInfoUpdater, the listed applications are disabled until used when all of the
173 // following conditions are met.
174 // 1. Not currently carrier-privileged according to the inserted SIM
175 // 2. Pre-installed
176 // 3. In the default state (enabled but not explicitly)
177 // And SubscriptionInfoUpdater undoes this and marks the app enabled when a SIM is inserted
178 // that marks the app as carrier privileged. It also grants the app default permissions
179 // for Phone and Location. As such, apps MUST only ever be added to this list if they
180 // obtain user consent to access their location through other means.
181 final ArraySet<String> mDisabledUntilUsedPreinstalledCarrierApps = new ArraySet<>();
182
Jeff Davidson24b9d962016-07-21 12:35:10 -0700183 // These are the packages of carrier-associated apps which should be disabled until used until
184 // a SIM is inserted which grants carrier privileges to that carrier app.
185 final ArrayMap<String, List<String>> mDisabledUntilUsedPreinstalledCarrierAssociatedApps =
186 new ArrayMap<>();
187
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800188 final ArrayMap<String, ArraySet<String>> mPrivAppPermissions = new ArrayMap<>();
Todd Kennedy74629e32017-08-15 14:48:07 -0700189 final ArrayMap<String, ArraySet<String>> mPrivAppDenyPermissions = new ArrayMap<>();
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800190
Jiyong Park002fdbd2017-02-13 20:50:31 +0900191 final ArrayMap<String, ArraySet<String>> mVendorPrivAppPermissions = new ArrayMap<>();
192 final ArrayMap<String, ArraySet<String>> mVendorPrivAppDenyPermissions = new ArrayMap<>();
193
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900194 final ArrayMap<String, ArraySet<String>> mProductPrivAppPermissions = new ArrayMap<>();
195 final ArrayMap<String, ArraySet<String>> mProductPrivAppDenyPermissions = new ArrayMap<>();
196
Jeongik Chaf6629832019-07-04 21:12:06 +0900197 final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppPermissions = new ArrayMap<>();
198 final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppDenyPermissions = new ArrayMap<>();
Dario Freni2bef1762018-06-01 14:02:08 +0100199
Svet Ganov087dce22017-09-07 15:42:16 -0700200 final ArrayMap<String, ArrayMap<String, Boolean>> mOemPermissions = new ArrayMap<>();
201
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800202 // Allowed associations between applications. If there are any entries
203 // for an app, those are the only associations allowed; otherwise, all associations
204 // are allowed. Allowing an association from app A to app B means app A can not
205 // associate with any other apps, but does not limit what apps B can associate with.
206 final ArrayMap<String, ArraySet<String>> mAllowedAssociations = new ArrayMap<>();
207
Nikita Ioffe07964b42019-02-28 21:35:02 +0000208 private final ArraySet<String> mBugreportWhitelistedPackages = new ArraySet<>();
209
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700210 public static SystemConfig getInstance() {
211 synchronized (SystemConfig.class) {
212 if (sInstance == null) {
213 sInstance = new SystemConfig();
214 }
215 return sInstance;
216 }
217 }
218
219 public int[] getGlobalGids() {
220 return mGlobalGids;
221 }
222
Jeff Sharkey9f837a92014-10-24 12:07:24 -0700223 public SparseArray<ArraySet<String>> getSystemPermissions() {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700224 return mSystemPermissions;
225 }
226
Zimuzocc2932f2018-10-29 16:04:41 +0000227 public ArrayList<SplitPermissionInfo> getSplitPermissions() {
228 return mSplitPermissions;
229 }
230
Ben Lin71c16d72018-12-06 18:34:51 -0800231 public ArrayMap<String, SharedLibraryEntry> getSharedLibraries() {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700232 return mSharedLibraries;
233 }
234
Jeff Sharkey9f837a92014-10-24 12:07:24 -0700235 public ArrayMap<String, FeatureInfo> getAvailableFeatures() {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700236 return mAvailableFeatures;
237 }
238
239 public ArrayMap<String, PermissionEntry> getPermissions() {
240 return mPermissions;
241 }
242
Christopher Tate42a386b2016-11-07 12:21:21 -0800243 public ArraySet<String> getAllowImplicitBroadcasts() {
244 return mAllowImplicitBroadcasts;
245 }
246
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700247 public ArraySet<String> getAllowInPowerSaveExceptIdle() {
248 return mAllowInPowerSaveExceptIdle;
249 }
250
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700251 public ArraySet<String> getAllowInPowerSave() {
252 return mAllowInPowerSave;
253 }
254
Felipe Lemea9505cc2016-02-26 10:28:41 -0800255 public ArraySet<String> getAllowInDataUsageSave() {
256 return mAllowInDataUsageSave;
257 }
258
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800259 public ArraySet<String> getAllowUnthrottledLocation() {
260 return mAllowUnthrottledLocation;
261 }
262
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800263 public ArraySet<String> getAllowIgnoreLocationSettings() {
264 return mAllowIgnoreLocationSettings;
265 }
266
Christopher Tate01e18642015-07-07 18:10:38 -0700267 public ArraySet<String> getLinkedApps() {
268 return mLinkedApps;
269 }
270
Fyodor Kupolov7db5af12015-07-31 16:50:27 -0700271 public ArraySet<String> getSystemUserWhitelistedApps() {
272 return mSystemUserWhitelistedApps;
273 }
274
275 public ArraySet<String> getSystemUserBlacklistedApps() {
276 return mSystemUserBlacklistedApps;
277 }
278
Mathew Inwood4693a752018-02-20 16:04:25 +0000279 public ArraySet<String> getHiddenApiWhitelistedApps() {
280 return mHiddenApiPackageWhitelist;
281 }
282
Ruben Brunk98576cf2016-03-07 18:54:28 -0800283 public ArraySet<ComponentName> getDefaultVrComponents() {
284 return mDefaultVrComponents;
285 }
286
Christopher Tate494df792016-05-10 17:05:38 -0700287 public ArraySet<ComponentName> getBackupTransportWhitelist() {
288 return mBackupTransportWhitelist;
289 }
290
goneileb31cd42018-02-28 15:22:08 -0800291 public ArraySet<String> getDisabledUntilUsedPreinstalledCarrierApps() {
292 return mDisabledUntilUsedPreinstalledCarrierApps;
293 }
294
Jeff Davidson24b9d962016-07-21 12:35:10 -0700295 public ArrayMap<String, List<String>> getDisabledUntilUsedPreinstalledCarrierAssociatedApps() {
296 return mDisabledUntilUsedPreinstalledCarrierAssociatedApps;
297 }
298
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800299 public ArraySet<String> getPrivAppPermissions(String packageName) {
300 return mPrivAppPermissions.get(packageName);
301 }
302
Todd Kennedy74629e32017-08-15 14:48:07 -0700303 public ArraySet<String> getPrivAppDenyPermissions(String packageName) {
304 return mPrivAppDenyPermissions.get(packageName);
305 }
306
Jiyong Park002fdbd2017-02-13 20:50:31 +0900307 public ArraySet<String> getVendorPrivAppPermissions(String packageName) {
308 return mVendorPrivAppPermissions.get(packageName);
309 }
310
311 public ArraySet<String> getVendorPrivAppDenyPermissions(String packageName) {
312 return mVendorPrivAppDenyPermissions.get(packageName);
313 }
314
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900315 public ArraySet<String> getProductPrivAppPermissions(String packageName) {
316 return mProductPrivAppPermissions.get(packageName);
317 }
318
319 public ArraySet<String> getProductPrivAppDenyPermissions(String packageName) {
320 return mProductPrivAppDenyPermissions.get(packageName);
321 }
322
Jeongik Chaf6629832019-07-04 21:12:06 +0900323 /**
324 * Read from "permission" tags in /system_ext/etc/permissions/*.xml
325 * @return Set of privileged permissions that are explicitly granted.
326 */
327 public ArraySet<String> getSystemExtPrivAppPermissions(String packageName) {
328 return mSystemExtPrivAppPermissions.get(packageName);
Dario Freni2bef1762018-06-01 14:02:08 +0100329 }
330
Jeongik Chaf6629832019-07-04 21:12:06 +0900331 /**
332 * Read from "deny-permission" tags in /system_ext/etc/permissions/*.xml
333 * @return Set of privileged permissions that are explicitly denied.
334 */
335 public ArraySet<String> getSystemExtPrivAppDenyPermissions(String packageName) {
336 return mSystemExtPrivAppDenyPermissions.get(packageName);
Dario Freni2bef1762018-06-01 14:02:08 +0100337 }
338
Svet Ganov087dce22017-09-07 15:42:16 -0700339 public Map<String, Boolean> getOemPermissions(String packageName) {
340 final Map<String, Boolean> oemPermissions = mOemPermissions.get(packageName);
341 if (oemPermissions != null) {
342 return oemPermissions;
343 }
344 return Collections.emptyMap();
345 }
346
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800347 public ArrayMap<String, ArraySet<String>> getAllowedAssociations() {
348 return mAllowedAssociations;
349 }
350
Nikita Ioffe07964b42019-02-28 21:35:02 +0000351 public ArraySet<String> getBugreportWhitelistedPackages() {
352 return mBugreportWhitelistedPackages;
353 }
354
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700355 SystemConfig() {
356 // Read configuration from system
357 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800358 Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL);
Svet Ganov087dce22017-09-07 15:42:16 -0700359
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700360 // Read configuration from the old permissions dir
361 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800362 Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);
Svet Ganov087dce22017-09-07 15:42:16 -0700363
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800364 // Vendors are only allowed to customize these
365 int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS
366 | ALLOW_ASSOCIATIONS;
Jiyong Parkfad99442018-03-12 10:39:07 +0900367 if (Build.VERSION.FIRST_SDK_INT <= Build.VERSION_CODES.O_MR1) {
368 // For backward compatibility
369 vendorPermissionFlag |= (ALLOW_PERMISSIONS | ALLOW_APP_CONFIGS);
370 }
Jaekyun Seoke3b6bf12017-02-16 13:48:30 +0900371 readPermissions(Environment.buildPath(
372 Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
373 readPermissions(Environment.buildPath(
374 Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag);
Svet Ganov087dce22017-09-07 15:42:16 -0700375
Jiyong Park090c6b12017-12-28 12:03:28 +0900376 // Allow ODM to customize system configs as much as Vendor, because /odm is another
377 // vendor partition other than /vendor.
378 int odmPermissionFlag = vendorPermissionFlag;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700379 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800380 Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700381 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800382 Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);
Svet Ganov087dce22017-09-07 15:42:16 -0700383
Steven Morelandd7827fd2018-12-03 10:27:01 -0800384 String skuProperty = SystemProperties.get(SKU_PROPERTY, "");
385 if (!skuProperty.isEmpty()) {
386 String skuDir = "sku_" + skuProperty;
387
388 readPermissions(Environment.buildPath(
389 Environment.getOdmDirectory(), "etc", "sysconfig", skuDir), odmPermissionFlag);
390 readPermissions(Environment.buildPath(
391 Environment.getOdmDirectory(), "etc", "permissions", skuDir),
392 odmPermissionFlag);
393 }
394
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800395 // Allow OEM to customize these
396 int oemPermissionFlag = ALLOW_FEATURES | ALLOW_OEM_PERMISSIONS | ALLOW_ASSOCIATIONS;
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800397 readPermissions(Environment.buildPath(
Svet Ganov087dce22017-09-07 15:42:16 -0700398 Environment.getOemDirectory(), "etc", "sysconfig"), oemPermissionFlag);
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800399 readPermissions(Environment.buildPath(
Svet Ganov087dce22017-09-07 15:42:16 -0700400 Environment.getOemDirectory(), "etc", "permissions"), oemPermissionFlag);
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900401
Hung-ying Tyan38cd31c2018-09-26 15:05:07 +0800402 // Allow Product to customize all system configs
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900403 readPermissions(Environment.buildPath(
Hung-ying Tyan38cd31c2018-09-26 15:05:07 +0800404 Environment.getProductDirectory(), "etc", "sysconfig"), ALLOW_ALL);
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900405 readPermissions(Environment.buildPath(
Hung-ying Tyan38cd31c2018-09-26 15:05:07 +0800406 Environment.getProductDirectory(), "etc", "permissions"), ALLOW_ALL);
Dario Freni2bef1762018-06-01 14:02:08 +0100407
Jeongik Chaf6629832019-07-04 21:12:06 +0900408 // Allow /system_ext to customize all system configs
Dario Freni2bef1762018-06-01 14:02:08 +0100409 readPermissions(Environment.buildPath(
Jeongik Chaf6629832019-07-04 21:12:06 +0900410 Environment.getSystemExtDirectory(), "etc", "sysconfig"), ALLOW_ALL);
Dario Freni2bef1762018-06-01 14:02:08 +0100411 readPermissions(Environment.buildPath(
Jeongik Chaf6629832019-07-04 21:12:06 +0900412 Environment.getSystemExtDirectory(), "etc", "permissions"), ALLOW_ALL);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700413 }
414
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800415 void readPermissions(File libraryDir, int permissionFlag) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700416 // Read permissions from given directory.
417 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800418 if (permissionFlag == ALLOW_ALL) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700419 Slog.w(TAG, "No directory " + libraryDir + ", skipping");
420 }
421 return;
422 }
423 if (!libraryDir.canRead()) {
424 Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
425 return;
426 }
427
428 // Iterate over the files in the directory and scan .xml files
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800429 File platformFile = null;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700430 for (File f : libraryDir.listFiles()) {
Steven Morelandd7827fd2018-12-03 10:27:01 -0800431 if (!f.isFile()) {
432 continue;
433 }
434
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700435 // We'll read platform.xml last
436 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800437 platformFile = f;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700438 continue;
439 }
440
441 if (!f.getPath().endsWith(".xml")) {
442 Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
443 continue;
444 }
445 if (!f.canRead()) {
446 Slog.w(TAG, "Permissions library file " + f + " cannot be read");
447 continue;
448 }
449
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800450 readPermissionsFromXml(f, permissionFlag);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700451 }
452
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800453 // Read platform permissions last so it will take precedence
454 if (platformFile != null) {
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800455 readPermissionsFromXml(platformFile, permissionFlag);
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800456 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700457 }
458
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800459 private void logNotAllowedInPartition(String name, File permFile, XmlPullParser parser) {
460 Slog.w(TAG, "<" + name + "> not allowed in partition of "
461 + permFile + " at " + parser.getPositionDescription());
462 }
463
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800464 private void readPermissionsFromXml(File permFile, int permissionFlag) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700465 FileReader permReader = null;
466 try {
467 permReader = new FileReader(permFile);
468 } catch (FileNotFoundException e) {
469 Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
470 return;
471 }
472
Dianne Hackbornc0e4aaa2014-11-14 10:55:50 -0800473 final boolean lowRam = ActivityManager.isLowRamDeviceStatic();
474
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700475 try {
476 XmlPullParser parser = Xml.newPullParser();
477 parser.setInput(permReader);
478
479 int type;
480 while ((type=parser.next()) != parser.START_TAG
481 && type != parser.END_DOCUMENT) {
482 ;
483 }
484
485 if (type != parser.START_TAG) {
486 throw new XmlPullParserException("No start tag found");
487 }
488
489 if (!parser.getName().equals("permissions") && !parser.getName().equals("config")) {
Dianne Hackbornb3d4cb32015-01-09 09:54:06 -0800490 throw new XmlPullParserException("Unexpected start tag in " + permFile
491 + ": found " + parser.getName() + ", expected 'permissions' or 'config'");
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700492 }
493
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800494 final boolean allowAll = permissionFlag == ALLOW_ALL;
495 final boolean allowLibs = (permissionFlag & ALLOW_LIBS) != 0;
496 final boolean allowFeatures = (permissionFlag & ALLOW_FEATURES) != 0;
497 final boolean allowPermissions = (permissionFlag & ALLOW_PERMISSIONS) != 0;
498 final boolean allowAppConfigs = (permissionFlag & ALLOW_APP_CONFIGS) != 0;
499 final boolean allowPrivappPermissions = (permissionFlag & ALLOW_PRIVAPP_PERMISSIONS)
500 != 0;
501 final boolean allowOemPermissions = (permissionFlag & ALLOW_OEM_PERMISSIONS) != 0;
502 final boolean allowApiWhitelisting = (permissionFlag & ALLOW_HIDDENAPI_WHITELISTING)
503 != 0;
504 final boolean allowAssociations = (permissionFlag & ALLOW_ASSOCIATIONS) != 0;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700505 while (true) {
506 XmlUtils.nextElement(parser);
507 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
508 break;
509 }
510
511 String name = parser.getName();
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800512 if (name == null) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700513 XmlUtils.skipCurrentTag(parser);
514 continue;
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800515 }
516 switch (name) {
517 case "group": {
518 if (allowAll) {
519 String gidStr = parser.getAttributeValue(null, "gid");
520 if (gidStr != null) {
521 int gid = android.os.Process.getGidForName(gidStr);
522 mGlobalGids = appendInt(mGlobalGids, gid);
523 } else {
524 Slog.w(TAG, "<" + name + "> without gid in " + permFile + " at "
goneileb31cd42018-02-28 15:22:08 -0800525 + parser.getPositionDescription());
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800526 }
527 } else {
528 logNotAllowedInPartition(name, permFile, parser);
529 }
530 XmlUtils.skipCurrentTag(parser);
531 } break;
532 case "permission": {
533 if (allowPermissions) {
534 String perm = parser.getAttributeValue(null, "name");
535 if (perm == null) {
536 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
537 + parser.getPositionDescription());
538 XmlUtils.skipCurrentTag(parser);
539 break;
540 }
541 perm = perm.intern();
542 readPermission(parser, perm);
543 } else {
544 logNotAllowedInPartition(name, permFile, parser);
545 XmlUtils.skipCurrentTag(parser);
546 }
547 } break;
548 case "assign-permission": {
549 if (allowPermissions) {
550 String perm = parser.getAttributeValue(null, "name");
551 if (perm == null) {
552 Slog.w(TAG, "<" + name + "> without name in " + permFile
553 + " at " + parser.getPositionDescription());
554 XmlUtils.skipCurrentTag(parser);
555 break;
556 }
557 String uidStr = parser.getAttributeValue(null, "uid");
558 if (uidStr == null) {
559 Slog.w(TAG, "<" + name + "> without uid in " + permFile
560 + " at " + parser.getPositionDescription());
561 XmlUtils.skipCurrentTag(parser);
562 break;
563 }
564 int uid = Process.getUidForName(uidStr);
565 if (uid < 0) {
566 Slog.w(TAG, "<" + name + "> with unknown uid \""
567 + uidStr + " in " + permFile + " at "
568 + parser.getPositionDescription());
569 XmlUtils.skipCurrentTag(parser);
570 break;
571 }
572 perm = perm.intern();
573 ArraySet<String> perms = mSystemPermissions.get(uid);
574 if (perms == null) {
575 perms = new ArraySet<String>();
576 mSystemPermissions.put(uid, perms);
577 }
578 perms.add(perm);
579 } else {
580 logNotAllowedInPartition(name, permFile, parser);
581 }
582 XmlUtils.skipCurrentTag(parser);
583 } break;
584 case "split-permission": {
585 if (allowPermissions) {
586 readSplitPermission(parser, permFile);
587 } else {
588 logNotAllowedInPartition(name, permFile, parser);
589 XmlUtils.skipCurrentTag(parser);
590 }
591 } break;
592 case "library": {
593 if (allowLibs) {
594 String lname = parser.getAttributeValue(null, "name");
595 String lfile = parser.getAttributeValue(null, "file");
596 String ldependency = parser.getAttributeValue(null, "dependency");
597 if (lname == null) {
598 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
599 + parser.getPositionDescription());
600 } else if (lfile == null) {
601 Slog.w(TAG, "<" + name + "> without file in " + permFile + " at "
602 + parser.getPositionDescription());
603 } else {
604 //Log.i(TAG, "Got library " + lname + " in " + lfile);
605 SharedLibraryEntry entry = new SharedLibraryEntry(lname, lfile,
606 ldependency == null ? new String[0] : ldependency.split(":"));
607 mSharedLibraries.put(lname, entry);
608 }
609 } else {
610 logNotAllowedInPartition(name, permFile, parser);
611 }
612 XmlUtils.skipCurrentTag(parser);
613 } break;
614 case "feature": {
615 if (allowFeatures) {
616 String fname = parser.getAttributeValue(null, "name");
617 int fversion = XmlUtils.readIntAttribute(parser, "version", 0);
618 boolean allowed;
619 if (!lowRam) {
620 allowed = true;
621 } else {
622 String notLowRam = parser.getAttributeValue(null, "notLowRam");
623 allowed = !"true".equals(notLowRam);
624 }
625 if (fname == null) {
626 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
627 + parser.getPositionDescription());
628 } else if (allowed) {
629 addFeature(fname, fversion);
630 }
631 } else {
632 logNotAllowedInPartition(name, permFile, parser);
633 }
634 XmlUtils.skipCurrentTag(parser);
635 } break;
636 case "unavailable-feature": {
637 if (allowFeatures) {
638 String fname = parser.getAttributeValue(null, "name");
639 if (fname == null) {
640 Slog.w(TAG, "<" + name + "> without name in " + permFile
641 + " at " + parser.getPositionDescription());
642 } else {
643 mUnavailableFeatures.add(fname);
644 }
645 } else {
646 logNotAllowedInPartition(name, permFile, parser);
647 }
648 XmlUtils.skipCurrentTag(parser);
649 } break;
650 case "allow-in-power-save-except-idle": {
651 if (allowAll) {
652 String pkgname = parser.getAttributeValue(null, "package");
653 if (pkgname == null) {
654 Slog.w(TAG, "<" + name + "> without package in "
655 + permFile + " at " + parser.getPositionDescription());
656 } else {
657 mAllowInPowerSaveExceptIdle.add(pkgname);
658 }
659 } else {
660 logNotAllowedInPartition(name, permFile, parser);
661 }
662 XmlUtils.skipCurrentTag(parser);
663 } break;
664 case "allow-in-power-save": {
665 if (allowAll) {
666 String pkgname = parser.getAttributeValue(null, "package");
667 if (pkgname == null) {
668 Slog.w(TAG, "<" + name + "> without package in "
669 + permFile + " at " + parser.getPositionDescription());
670 } else {
671 mAllowInPowerSave.add(pkgname);
672 }
673 } else {
674 logNotAllowedInPartition(name, permFile, parser);
675 }
676 XmlUtils.skipCurrentTag(parser);
677 } break;
678 case "allow-in-data-usage-save": {
679 if (allowAll) {
680 String pkgname = parser.getAttributeValue(null, "package");
681 if (pkgname == null) {
682 Slog.w(TAG, "<" + name + "> without package in "
683 + permFile + " at " + parser.getPositionDescription());
684 } else {
685 mAllowInDataUsageSave.add(pkgname);
686 }
687 } else {
688 logNotAllowedInPartition(name, permFile, parser);
689 }
690 XmlUtils.skipCurrentTag(parser);
691 } break;
692 case "allow-unthrottled-location": {
693 if (allowAll) {
694 String pkgname = parser.getAttributeValue(null, "package");
695 if (pkgname == null) {
696 Slog.w(TAG, "<" + name + "> without package in "
697 + permFile + " at " + parser.getPositionDescription());
698 } else {
699 mAllowUnthrottledLocation.add(pkgname);
700 }
701 } else {
702 logNotAllowedInPartition(name, permFile, parser);
703 }
704 XmlUtils.skipCurrentTag(parser);
705 } break;
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800706 case "allow-ignore-location-settings": {
707 if (allowAll) {
708 String pkgname = parser.getAttributeValue(null, "package");
709 if (pkgname == null) {
710 Slog.w(TAG, "<" + name + "> without package in "
711 + permFile + " at " + parser.getPositionDescription());
712 } else {
713 mAllowIgnoreLocationSettings.add(pkgname);
714 }
715 } else {
716 logNotAllowedInPartition(name, permFile, parser);
717 }
718 XmlUtils.skipCurrentTag(parser);
719 } break;
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800720 case "allow-implicit-broadcast": {
721 if (allowAll) {
722 String action = parser.getAttributeValue(null, "action");
723 if (action == null) {
724 Slog.w(TAG, "<" + name + "> without action in "
725 + permFile + " at " + parser.getPositionDescription());
726 } else {
727 mAllowImplicitBroadcasts.add(action);
728 }
729 } else {
730 logNotAllowedInPartition(name, permFile, parser);
731 }
732 XmlUtils.skipCurrentTag(parser);
733 } break;
734 case "app-link": {
735 if (allowAppConfigs) {
736 String pkgname = parser.getAttributeValue(null, "package");
737 if (pkgname == null) {
738 Slog.w(TAG, "<" + name + "> without package in " + permFile
739 + " at " + parser.getPositionDescription());
740 } else {
741 mLinkedApps.add(pkgname);
742 }
743 } else {
744 logNotAllowedInPartition(name, permFile, parser);
745 }
746 XmlUtils.skipCurrentTag(parser);
747 } break;
748 case "system-user-whitelisted-app": {
749 if (allowAppConfigs) {
750 String pkgname = parser.getAttributeValue(null, "package");
751 if (pkgname == null) {
752 Slog.w(TAG, "<" + name + "> without package in "
753 + permFile + " at " + parser.getPositionDescription());
754 } else {
755 mSystemUserWhitelistedApps.add(pkgname);
756 }
757 } else {
758 logNotAllowedInPartition(name, permFile, parser);
759 }
760 XmlUtils.skipCurrentTag(parser);
761 } break;
762 case "system-user-blacklisted-app": {
763 if (allowAppConfigs) {
764 String pkgname = parser.getAttributeValue(null, "package");
765 if (pkgname == null) {
766 Slog.w(TAG, "<" + name + "> without package in "
767 + permFile + " at " + parser.getPositionDescription());
768 } else {
769 mSystemUserBlacklistedApps.add(pkgname);
770 }
771 } else {
772 logNotAllowedInPartition(name, permFile, parser);
773 }
774 XmlUtils.skipCurrentTag(parser);
775 } break;
776 case "default-enabled-vr-app": {
777 if (allowAppConfigs) {
778 String pkgname = parser.getAttributeValue(null, "package");
779 String clsname = parser.getAttributeValue(null, "class");
780 if (pkgname == null) {
781 Slog.w(TAG, "<" + name + "> without package in "
782 + permFile + " at " + parser.getPositionDescription());
783 } else if (clsname == null) {
784 Slog.w(TAG, "<" + name + "> without class in "
785 + permFile + " at " + parser.getPositionDescription());
786 } else {
787 mDefaultVrComponents.add(new ComponentName(pkgname, clsname));
788 }
789 } else {
790 logNotAllowedInPartition(name, permFile, parser);
791 }
792 XmlUtils.skipCurrentTag(parser);
793 } break;
794 case "backup-transport-whitelisted-service": {
795 if (allowFeatures) {
796 String serviceName = parser.getAttributeValue(null, "service");
797 if (serviceName == null) {
798 Slog.w(TAG, "<" + name + "> without service in "
799 + permFile + " at " + parser.getPositionDescription());
800 } else {
801 ComponentName cn = ComponentName.unflattenFromString(serviceName);
802 if (cn == null) {
803 Slog.w(TAG, "<" + name + "> with invalid service name "
804 + serviceName + " in " + permFile
805 + " at " + parser.getPositionDescription());
806 } else {
807 mBackupTransportWhitelist.add(cn);
808 }
809 }
810 } else {
811 logNotAllowedInPartition(name, permFile, parser);
812 }
813 XmlUtils.skipCurrentTag(parser);
814 } break;
815 case "disabled-until-used-preinstalled-carrier-associated-app": {
816 if (allowAppConfigs) {
817 String pkgname = parser.getAttributeValue(null, "package");
818 String carrierPkgname = parser.getAttributeValue(null,
819 "carrierAppPackage");
820 if (pkgname == null || carrierPkgname == null) {
821 Slog.w(TAG, "<" + name
822 + "> without package or carrierAppPackage in " + permFile
823 + " at " + parser.getPositionDescription());
824 } else {
825 List<String> associatedPkgs =
826 mDisabledUntilUsedPreinstalledCarrierAssociatedApps.get(
827 carrierPkgname);
828 if (associatedPkgs == null) {
829 associatedPkgs = new ArrayList<>();
830 mDisabledUntilUsedPreinstalledCarrierAssociatedApps.put(
831 carrierPkgname, associatedPkgs);
832 }
833 associatedPkgs.add(pkgname);
834 }
835 } else {
836 logNotAllowedInPartition(name, permFile, parser);
837 }
838 XmlUtils.skipCurrentTag(parser);
839 } break;
840 case "disabled-until-used-preinstalled-carrier-app": {
841 if (allowAppConfigs) {
842 String pkgname = parser.getAttributeValue(null, "package");
843 if (pkgname == null) {
844 Slog.w(TAG,
845 "<" + name + "> without "
846 + "package in " + permFile + " at "
847 + parser.getPositionDescription());
848 } else {
849 mDisabledUntilUsedPreinstalledCarrierApps.add(pkgname);
850 }
851 } else {
852 logNotAllowedInPartition(name, permFile, parser);
853 }
854 XmlUtils.skipCurrentTag(parser);
855 } break;
856 case "privapp-permissions": {
857 if (allowPrivappPermissions) {
Jeongik Chaf6629832019-07-04 21:12:06 +0900858 // privapp permissions from system, vendor, product and system_ext
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800859 // partitions are stored separately. This is to prevent xml files in
860 // the vendor partition from granting permissions to priv apps in the
861 // system partition and vice versa.
862 boolean vendor = permFile.toPath().startsWith(
863 Environment.getVendorDirectory().toPath() + "/")
864 || permFile.toPath().startsWith(
865 Environment.getOdmDirectory().toPath() + "/");
866 boolean product = permFile.toPath().startsWith(
867 Environment.getProductDirectory().toPath() + "/");
Jeongik Chaf6629832019-07-04 21:12:06 +0900868 boolean systemExt = permFile.toPath().startsWith(
869 Environment.getSystemExtDirectory().toPath() + "/");
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800870 if (vendor) {
871 readPrivAppPermissions(parser, mVendorPrivAppPermissions,
872 mVendorPrivAppDenyPermissions);
873 } else if (product) {
874 readPrivAppPermissions(parser, mProductPrivAppPermissions,
875 mProductPrivAppDenyPermissions);
Jeongik Chaf6629832019-07-04 21:12:06 +0900876 } else if (systemExt) {
877 readPrivAppPermissions(parser, mSystemExtPrivAppPermissions,
878 mSystemExtPrivAppDenyPermissions);
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800879 } else {
880 readPrivAppPermissions(parser, mPrivAppPermissions,
881 mPrivAppDenyPermissions);
882 }
883 } else {
884 logNotAllowedInPartition(name, permFile, parser);
885 XmlUtils.skipCurrentTag(parser);
886 }
887 } break;
888 case "oem-permissions": {
889 if (allowOemPermissions) {
890 readOemPermissions(parser);
891 } else {
892 logNotAllowedInPartition(name, permFile, parser);
893 XmlUtils.skipCurrentTag(parser);
894 }
895 } break;
896 case "hidden-api-whitelisted-app": {
897 if (allowApiWhitelisting) {
898 String pkgname = parser.getAttributeValue(null, "package");
899 if (pkgname == null) {
900 Slog.w(TAG, "<" + name + "> without package in "
901 + permFile + " at " + parser.getPositionDescription());
902 } else {
903 mHiddenApiPackageWhitelist.add(pkgname);
904 }
905 } else {
906 logNotAllowedInPartition(name, permFile, parser);
907 }
908 XmlUtils.skipCurrentTag(parser);
909 } break;
910 case "allow-association": {
911 if (allowAssociations) {
912 String target = parser.getAttributeValue(null, "target");
913 if (target == null) {
914 Slog.w(TAG, "<" + name + "> without target in " + permFile
915 + " at " + parser.getPositionDescription());
916 XmlUtils.skipCurrentTag(parser);
917 break;
918 }
919 String allowed = parser.getAttributeValue(null, "allowed");
920 if (allowed == null) {
921 Slog.w(TAG, "<" + name + "> without allowed in " + permFile
922 + " at " + parser.getPositionDescription());
923 XmlUtils.skipCurrentTag(parser);
924 break;
925 }
926 target = target.intern();
927 allowed = allowed.intern();
928 ArraySet<String> associations = mAllowedAssociations.get(target);
929 if (associations == null) {
930 associations = new ArraySet<>();
931 mAllowedAssociations.put(target, associations);
932 }
933 Slog.i(TAG, "Adding association: " + target + " <- " + allowed);
934 associations.add(allowed);
935 } else {
936 logNotAllowedInPartition(name, permFile, parser);
937 }
938 XmlUtils.skipCurrentTag(parser);
939 } break;
Nikita Ioffe07964b42019-02-28 21:35:02 +0000940 case "bugreport-whitelisted": {
941 String pkgname = parser.getAttributeValue(null, "package");
942 if (pkgname == null) {
943 Slog.w(TAG, "<" + name + "> without package in " + permFile
944 + " at " + parser.getPositionDescription());
945 } else {
946 mBugreportWhitelistedPackages.add(pkgname);
947 }
Nikita Ioffe08146ef2019-03-13 17:04:21 +0000948 XmlUtils.skipCurrentTag(parser);
Nikita Ioffe07964b42019-02-28 21:35:02 +0000949 } break;
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800950 default: {
951 Slog.w(TAG, "Tag " + name + " is unknown in "
952 + permFile + " at " + parser.getPositionDescription());
953 XmlUtils.skipCurrentTag(parser);
954 } break;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700955 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700956 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700957 } catch (XmlPullParserException e) {
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800958 Slog.w(TAG, "Got exception parsing permissions.", e);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700959 } catch (IOException e) {
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800960 Slog.w(TAG, "Got exception parsing permissions.", e);
961 } finally {
962 IoUtils.closeQuietly(permReader);
963 }
964
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -0700965 // Some devices can be field-converted to FBE, so offer to splice in
966 // those features if not already defined by the static config
Paul Lawrence20be5d62016-02-26 13:51:17 -0800967 if (StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700968 addFeature(PackageManager.FEATURE_FILE_BASED_ENCRYPTION, 0);
969 addFeature(PackageManager.FEATURE_SECURELY_REMOVES_USERS, 0);
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -0700970 }
971
Jeff Sharkey8eb783b2018-01-04 16:46:48 -0700972 // Help legacy devices that may not have updated their static config
973 if (StorageManager.hasAdoptable()) {
974 addFeature(PackageManager.FEATURE_ADOPTABLE_STORAGE, 0);
975 }
976
Dianne Hackborn2a103f12017-08-08 15:50:31 -0700977 if (ActivityManager.isLowRamDeviceStatic()) {
978 addFeature(PackageManager.FEATURE_RAM_LOW, 0);
979 } else {
980 addFeature(PackageManager.FEATURE_RAM_NORMAL, 0);
981 }
982
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -0700983 for (String featureName : mUnavailableFeatures) {
984 removeFeature(featureName);
985 }
986 }
987
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700988 private void addFeature(String name, int version) {
989 FeatureInfo fi = mAvailableFeatures.get(name);
990 if (fi == null) {
991 fi = new FeatureInfo();
992 fi.name = name;
993 fi.version = version;
994 mAvailableFeatures.put(name, fi);
995 } else {
996 fi.version = Math.max(fi.version, version);
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -0700997 }
998 }
999
Jeff Sharkey115d2c12016-02-15 17:25:57 -07001000 private void removeFeature(String name) {
1001 if (mAvailableFeatures.remove(name) != null) {
1002 Slog.d(TAG, "Removed unavailable feature " + name);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001003 }
1004 }
1005
1006 void readPermission(XmlPullParser parser, String name)
1007 throws IOException, XmlPullParserException {
Jeff Sharkey00f39042015-03-23 16:51:22 -07001008 if (mPermissions.containsKey(name)) {
1009 throw new IllegalStateException("Duplicate permission definition for " + name);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001010 }
Jeff Sharkey00f39042015-03-23 16:51:22 -07001011
1012 final boolean perUser = XmlUtils.readBooleanAttribute(parser, "perUser", false);
1013 final PermissionEntry perm = new PermissionEntry(name, perUser);
1014 mPermissions.put(name, perm);
1015
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001016 int outerDepth = parser.getDepth();
1017 int type;
1018 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1019 && (type != XmlPullParser.END_TAG
1020 || parser.getDepth() > outerDepth)) {
1021 if (type == XmlPullParser.END_TAG
1022 || type == XmlPullParser.TEXT) {
1023 continue;
1024 }
1025
1026 String tagName = parser.getName();
1027 if ("group".equals(tagName)) {
1028 String gidStr = parser.getAttributeValue(null, "gid");
1029 if (gidStr != null) {
1030 int gid = Process.getGidForName(gidStr);
1031 perm.gids = appendInt(perm.gids, gid);
1032 } else {
1033 Slog.w(TAG, "<group> without gid at "
1034 + parser.getPositionDescription());
1035 }
1036 }
1037 XmlUtils.skipCurrentTag(parser);
1038 }
1039 }
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001040
Jiyong Park002fdbd2017-02-13 20:50:31 +09001041 private void readPrivAppPermissions(XmlPullParser parser,
1042 ArrayMap<String, ArraySet<String>> grantMap,
1043 ArrayMap<String, ArraySet<String>> denyMap)
1044 throws IOException, XmlPullParserException {
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001045 String packageName = parser.getAttributeValue(null, "package");
1046 if (TextUtils.isEmpty(packageName)) {
1047 Slog.w(TAG, "package is required for <privapp-permissions> in "
1048 + parser.getPositionDescription());
1049 return;
1050 }
1051
Jiyong Park002fdbd2017-02-13 20:50:31 +09001052 ArraySet<String> permissions = grantMap.get(packageName);
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001053 if (permissions == null) {
1054 permissions = new ArraySet<>();
1055 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09001056 ArraySet<String> denyPermissions = denyMap.get(packageName);
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001057 int depth = parser.getDepth();
1058 while (XmlUtils.nextElementWithin(parser, depth)) {
1059 String name = parser.getName();
1060 if ("permission".equals(name)) {
1061 String permName = parser.getAttributeValue(null, "name");
1062 if (TextUtils.isEmpty(permName)) {
1063 Slog.w(TAG, "name is required for <permission> in "
1064 + parser.getPositionDescription());
1065 continue;
1066 }
1067 permissions.add(permName);
Todd Kennedy74629e32017-08-15 14:48:07 -07001068 } else if ("deny-permission".equals(name)) {
1069 String permName = parser.getAttributeValue(null, "name");
1070 if (TextUtils.isEmpty(permName)) {
1071 Slog.w(TAG, "name is required for <deny-permission> in "
1072 + parser.getPositionDescription());
1073 continue;
1074 }
1075 if (denyPermissions == null) {
1076 denyPermissions = new ArraySet<>();
1077 }
1078 denyPermissions.add(permName);
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001079 }
1080 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09001081 grantMap.put(packageName, permissions);
Todd Kennedy74629e32017-08-15 14:48:07 -07001082 if (denyPermissions != null) {
Jiyong Park002fdbd2017-02-13 20:50:31 +09001083 denyMap.put(packageName, denyPermissions);
Todd Kennedy74629e32017-08-15 14:48:07 -07001084 }
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001085 }
Svet Ganov087dce22017-09-07 15:42:16 -07001086
1087 void readOemPermissions(XmlPullParser parser) throws IOException, XmlPullParserException {
1088 final String packageName = parser.getAttributeValue(null, "package");
1089 if (TextUtils.isEmpty(packageName)) {
1090 Slog.w(TAG, "package is required for <oem-permissions> in "
1091 + parser.getPositionDescription());
1092 return;
1093 }
1094
1095 ArrayMap<String, Boolean> permissions = mOemPermissions.get(packageName);
1096 if (permissions == null) {
1097 permissions = new ArrayMap<>();
1098 }
1099 final int depth = parser.getDepth();
1100 while (XmlUtils.nextElementWithin(parser, depth)) {
1101 final String name = parser.getName();
1102 if ("permission".equals(name)) {
1103 final String permName = parser.getAttributeValue(null, "name");
1104 if (TextUtils.isEmpty(permName)) {
1105 Slog.w(TAG, "name is required for <permission> in "
1106 + parser.getPositionDescription());
1107 continue;
1108 }
1109 permissions.put(permName, Boolean.TRUE);
1110 } else if ("deny-permission".equals(name)) {
1111 String permName = parser.getAttributeValue(null, "name");
1112 if (TextUtils.isEmpty(permName)) {
1113 Slog.w(TAG, "name is required for <deny-permission> in "
1114 + parser.getPositionDescription());
1115 continue;
1116 }
1117 permissions.put(permName, Boolean.FALSE);
1118 }
1119 }
1120 mOemPermissions.put(packageName, permissions);
1121 }
Zimuzocc2932f2018-10-29 16:04:41 +00001122
1123 private void readSplitPermission(XmlPullParser parser, File permFile)
1124 throws IOException, XmlPullParserException {
1125 String splitPerm = parser.getAttributeValue(null, "name");
1126 if (splitPerm == null) {
1127 Slog.w(TAG, "<split-permission> without name in " + permFile + " at "
1128 + parser.getPositionDescription());
1129 XmlUtils.skipCurrentTag(parser);
1130 return;
1131 }
1132 String targetSdkStr = parser.getAttributeValue(null, "targetSdk");
1133 int targetSdk = Build.VERSION_CODES.CUR_DEVELOPMENT + 1;
1134 if (!TextUtils.isEmpty(targetSdkStr)) {
1135 try {
1136 targetSdk = Integer.parseInt(targetSdkStr);
1137 } catch (NumberFormatException e) {
1138 Slog.w(TAG, "<split-permission> targetSdk not an integer in " + permFile + " at "
1139 + parser.getPositionDescription());
1140 XmlUtils.skipCurrentTag(parser);
1141 return;
1142 }
1143 }
1144 final int depth = parser.getDepth();
1145 List<String> newPermissions = new ArrayList<>();
1146 while (XmlUtils.nextElementWithin(parser, depth)) {
1147 String name = parser.getName();
1148 if ("new-permission".equals(name)) {
1149 final String newName = parser.getAttributeValue(null, "name");
1150 if (TextUtils.isEmpty(newName)) {
1151 Slog.w(TAG, "name is required for <new-permission> in "
1152 + parser.getPositionDescription());
1153 continue;
1154 }
1155 newPermissions.add(newName);
1156 } else {
1157 XmlUtils.skipCurrentTag(parser);
1158 }
1159 }
1160 if (!newPermissions.isEmpty()) {
1161 mSplitPermissions.add(new SplitPermissionInfo(splitPerm, newPermissions, targetSdk));
1162 }
1163 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001164}