blob: 697825dcefd7b0ef7c2f80721d0f23becde926a2 [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
Bookatz04d7ae52019-08-05 14:07:12 -070038import com.android.internal.annotations.VisibleForTesting;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070039import com.android.internal.util.XmlUtils;
Jeff Sharkey1c4ae802014-12-19 11:08:55 -080040
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -070041import libcore.io.IoUtils;
42
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070043import org.xmlpull.v1.XmlPullParser;
44import org.xmlpull.v1.XmlPullParserException;
45
46import java.io.File;
47import java.io.FileNotFoundException;
48import java.io.FileReader;
49import java.io.IOException;
Jeff Davidson24b9d962016-07-21 12:35:10 -070050import java.util.ArrayList;
Svet Ganov087dce22017-09-07 15:42:16 -070051import java.util.Collections;
Jeff Davidson24b9d962016-07-21 12:35:10 -070052import java.util.List;
Svet Ganov087dce22017-09-07 15:42:16 -070053import java.util.Map;
Bookatz04d7ae52019-08-05 14:07:12 -070054import java.util.Set;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070055
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070056/**
57 * Loads global system configuration info.
Anthony Hughde787d42019-08-22 15:35:48 -070058 * Note: Initializing this class hits the disk and is slow. This class should generally only be
59 * accessed by the system_server process.
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070060 */
61public class SystemConfig {
62 static final String TAG = "SystemConfig";
63
64 static SystemConfig sInstance;
65
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +080066 // permission flag, determines which types of configuration are allowed to be read
67 private static final int ALLOW_FEATURES = 0x01;
68 private static final int ALLOW_LIBS = 0x02;
69 private static final int ALLOW_PERMISSIONS = 0x04;
70 private static final int ALLOW_APP_CONFIGS = 0x08;
Jaekyun Seoke3b6bf12017-02-16 13:48:30 +090071 private static final int ALLOW_PRIVAPP_PERMISSIONS = 0x10;
Svet Ganov087dce22017-09-07 15:42:16 -070072 private static final int ALLOW_OEM_PERMISSIONS = 0x20;
Mathew Inwood4693a752018-02-20 16:04:25 +000073 private static final int ALLOW_HIDDENAPI_WHITELISTING = 0x40;
Dianne Hackborn769b2e72018-12-05 08:51:20 -080074 private static final int ALLOW_ASSOCIATIONS = 0x80;
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +080075 private static final int ALLOW_ALL = ~0;
76
Steven Morelandd7827fd2018-12-03 10:27:01 -080077 // property for runtime configuration differentiation
78 private static final String SKU_PROPERTY = "ro.boot.product.hardware.sku";
79
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070080 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
81 int[] mGlobalGids;
82
83 // These are the built-in uid -> permission mappings that were read from the
84 // system configuration files.
Jeff Sharkey9f837a92014-10-24 12:07:24 -070085 final SparseArray<ArraySet<String>> mSystemPermissions = new SparseArray<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070086
Zimuzocc2932f2018-10-29 16:04:41 +000087 final ArrayList<SplitPermissionInfo> mSplitPermissions = new ArrayList<>();
88
Ben Lin71c16d72018-12-06 18:34:51 -080089 public static final class SharedLibraryEntry {
90 public final String name;
91 public final String filename;
92 public final String[] dependencies;
93
94 SharedLibraryEntry(String name, String filename, String[] dependencies) {
95 this.name = name;
96 this.filename = filename;
97 this.dependencies = dependencies;
98 }
99 }
100
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700101 // These are the built-in shared libraries that were read from the
Ben Lin71c16d72018-12-06 18:34:51 -0800102 // system configuration files. Keys are the library names; values are
103 // the individual entries that contain information such as filename
104 // and dependencies.
105 final ArrayMap<String, SharedLibraryEntry> mSharedLibraries = new ArrayMap<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700106
107 // These are the features this devices supports that were read from the
108 // system configuration files.
Jeff Sharkey9f837a92014-10-24 12:07:24 -0700109 final ArrayMap<String, FeatureInfo> mAvailableFeatures = new ArrayMap<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700110
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800111 // These are the features which this device doesn't support; the OEM
112 // partition uses these to opt-out of features from the system image.
113 final ArraySet<String> mUnavailableFeatures = new ArraySet<>();
114
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700115 public static final class PermissionEntry {
116 public final String name;
117 public int[] gids;
Jeff Sharkey00f39042015-03-23 16:51:22 -0700118 public boolean perUser;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700119
Jeff Sharkey00f39042015-03-23 16:51:22 -0700120 PermissionEntry(String name, boolean perUser) {
121 this.name = name;
122 this.perUser = perUser;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700123 }
124 }
125
126 // These are the permission -> gid mappings that were read from the
127 // system configuration files.
Dianne Hackbornbb8aa5a2014-09-17 13:20:38 -0700128 final ArrayMap<String, PermissionEntry> mPermissions = new ArrayMap<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700129
130 // These are the packages that are white-listed to be able to run in the
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700131 // background while in power save mode (but not whitelisted from device idle modes),
132 // as read from the configuration files.
133 final ArraySet<String> mAllowInPowerSaveExceptIdle = new ArraySet<>();
134
135 // These are the packages that are white-listed to be able to run in the
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700136 // background while in power save mode, as read from the configuration files.
Dianne Hackbornbb8aa5a2014-09-17 13:20:38 -0700137 final ArraySet<String> mAllowInPowerSave = new ArraySet<>();
138
Felipe Lemea9505cc2016-02-26 10:28:41 -0800139 // These are the packages that are white-listed to be able to run in the
140 // background while in data-usage save mode, as read from the configuration files.
141 final ArraySet<String> mAllowInDataUsageSave = new ArraySet<>();
142
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800143 // These are the packages that are white-listed to be able to run background location
144 // without throttling, as read from the configuration files.
145 final ArraySet<String> mAllowUnthrottledLocation = new ArraySet<>();
146
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800147 // These are the packages that are white-listed to be able to retrieve location even when user
148 // location settings are off, for emergency purposes, as read from the configuration files.
149 final ArraySet<String> mAllowIgnoreLocationSettings = new ArraySet<>();
150
Christopher Tate42a386b2016-11-07 12:21:21 -0800151 // These are the action strings of broadcasts which are whitelisted to
152 // be delivered anonymously even to apps which target O+.
153 final ArraySet<String> mAllowImplicitBroadcasts = new ArraySet<>();
154
Christopher Tate01e18642015-07-07 18:10:38 -0700155 // These are the package names of apps which should be in the 'always'
156 // URL-handling state upon factory reset.
157 final ArraySet<String> mLinkedApps = new ArraySet<>();
158
Fyodor Kupolov7db5af12015-07-31 16:50:27 -0700159 // These are the packages that are whitelisted to be able to run as system user
160 final ArraySet<String> mSystemUserWhitelistedApps = new ArraySet<>();
161
162 // These are the packages that should not run under system user
163 final ArraySet<String> mSystemUserBlacklistedApps = new ArraySet<>();
164
Ruben Brunk98576cf2016-03-07 18:54:28 -0800165 // These are the components that are enabled by default as VR mode listener services.
166 final ArraySet<ComponentName> mDefaultVrComponents = new ArraySet<>();
167
Christopher Tate494df792016-05-10 17:05:38 -0700168 // These are the permitted backup transport service components
169 final ArraySet<ComponentName> mBackupTransportWhitelist = new ArraySet<>();
170
Mathew Inwood4693a752018-02-20 16:04:25 +0000171 // Package names that are exempted from private API blacklisting
172 final ArraySet<String> mHiddenApiPackageWhitelist = new ArraySet<>();
173
goneileb31cd42018-02-28 15:22:08 -0800174 // The list of carrier applications which should be disabled until used.
175 // This function suppresses update notifications for these pre-installed apps.
176 // In SubscriptionInfoUpdater, the listed applications are disabled until used when all of the
177 // following conditions are met.
178 // 1. Not currently carrier-privileged according to the inserted SIM
179 // 2. Pre-installed
180 // 3. In the default state (enabled but not explicitly)
181 // And SubscriptionInfoUpdater undoes this and marks the app enabled when a SIM is inserted
182 // that marks the app as carrier privileged. It also grants the app default permissions
183 // for Phone and Location. As such, apps MUST only ever be added to this list if they
184 // obtain user consent to access their location through other means.
185 final ArraySet<String> mDisabledUntilUsedPreinstalledCarrierApps = new ArraySet<>();
186
Jeff Davidson24b9d962016-07-21 12:35:10 -0700187 // These are the packages of carrier-associated apps which should be disabled until used until
188 // a SIM is inserted which grants carrier privileges to that carrier app.
189 final ArrayMap<String, List<String>> mDisabledUntilUsedPreinstalledCarrierAssociatedApps =
190 new ArrayMap<>();
191
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800192 final ArrayMap<String, ArraySet<String>> mPrivAppPermissions = new ArrayMap<>();
Todd Kennedy74629e32017-08-15 14:48:07 -0700193 final ArrayMap<String, ArraySet<String>> mPrivAppDenyPermissions = new ArrayMap<>();
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800194
Jiyong Park002fdbd2017-02-13 20:50:31 +0900195 final ArrayMap<String, ArraySet<String>> mVendorPrivAppPermissions = new ArrayMap<>();
196 final ArrayMap<String, ArraySet<String>> mVendorPrivAppDenyPermissions = new ArrayMap<>();
197
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900198 final ArrayMap<String, ArraySet<String>> mProductPrivAppPermissions = new ArrayMap<>();
199 final ArrayMap<String, ArraySet<String>> mProductPrivAppDenyPermissions = new ArrayMap<>();
200
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900201 final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppPermissions = new ArrayMap<>();
202 final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppDenyPermissions = new ArrayMap<>();
Dario Freni2bef1762018-06-01 14:02:08 +0100203
Svet Ganov087dce22017-09-07 15:42:16 -0700204 final ArrayMap<String, ArrayMap<String, Boolean>> mOemPermissions = new ArrayMap<>();
205
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800206 // Allowed associations between applications. If there are any entries
207 // for an app, those are the only associations allowed; otherwise, all associations
208 // are allowed. Allowing an association from app A to app B means app A can not
209 // associate with any other apps, but does not limit what apps B can associate with.
210 final ArrayMap<String, ArraySet<String>> mAllowedAssociations = new ArrayMap<>();
211
Nikita Ioffe07964b42019-02-28 21:35:02 +0000212 private final ArraySet<String> mBugreportWhitelistedPackages = new ArraySet<>();
213
Bookatz04d7ae52019-08-05 14:07:12 -0700214 // Map of packagesNames to userTypes. Stored temporarily until cleared by UserManagerService().
215 private ArrayMap<String, Set<String>> mPackageToUserTypeWhitelist = new ArrayMap<>();
216 private ArrayMap<String, Set<String>> mPackageToUserTypeBlacklist = new ArrayMap<>();
217
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700218 public static SystemConfig getInstance() {
Anthony Hughde787d42019-08-22 15:35:48 -0700219 if (!isSystemProcess()) {
220 Slog.wtf(TAG, "SystemConfig is being accessed by a process other than "
221 + "system_server.");
222 }
223
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700224 synchronized (SystemConfig.class) {
225 if (sInstance == null) {
226 sInstance = new SystemConfig();
227 }
228 return sInstance;
229 }
230 }
231
232 public int[] getGlobalGids() {
233 return mGlobalGids;
234 }
235
Jeff Sharkey9f837a92014-10-24 12:07:24 -0700236 public SparseArray<ArraySet<String>> getSystemPermissions() {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700237 return mSystemPermissions;
238 }
239
Zimuzocc2932f2018-10-29 16:04:41 +0000240 public ArrayList<SplitPermissionInfo> getSplitPermissions() {
241 return mSplitPermissions;
242 }
243
Ben Lin71c16d72018-12-06 18:34:51 -0800244 public ArrayMap<String, SharedLibraryEntry> getSharedLibraries() {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700245 return mSharedLibraries;
246 }
247
Jeff Sharkey9f837a92014-10-24 12:07:24 -0700248 public ArrayMap<String, FeatureInfo> getAvailableFeatures() {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700249 return mAvailableFeatures;
250 }
251
252 public ArrayMap<String, PermissionEntry> getPermissions() {
253 return mPermissions;
254 }
255
Christopher Tate42a386b2016-11-07 12:21:21 -0800256 public ArraySet<String> getAllowImplicitBroadcasts() {
257 return mAllowImplicitBroadcasts;
258 }
259
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700260 public ArraySet<String> getAllowInPowerSaveExceptIdle() {
261 return mAllowInPowerSaveExceptIdle;
262 }
263
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700264 public ArraySet<String> getAllowInPowerSave() {
265 return mAllowInPowerSave;
266 }
267
Felipe Lemea9505cc2016-02-26 10:28:41 -0800268 public ArraySet<String> getAllowInDataUsageSave() {
269 return mAllowInDataUsageSave;
270 }
271
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800272 public ArraySet<String> getAllowUnthrottledLocation() {
273 return mAllowUnthrottledLocation;
274 }
275
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800276 public ArraySet<String> getAllowIgnoreLocationSettings() {
277 return mAllowIgnoreLocationSettings;
278 }
279
Christopher Tate01e18642015-07-07 18:10:38 -0700280 public ArraySet<String> getLinkedApps() {
281 return mLinkedApps;
282 }
283
Fyodor Kupolov7db5af12015-07-31 16:50:27 -0700284 public ArraySet<String> getSystemUserWhitelistedApps() {
285 return mSystemUserWhitelistedApps;
286 }
287
288 public ArraySet<String> getSystemUserBlacklistedApps() {
289 return mSystemUserBlacklistedApps;
290 }
291
Mathew Inwood4693a752018-02-20 16:04:25 +0000292 public ArraySet<String> getHiddenApiWhitelistedApps() {
293 return mHiddenApiPackageWhitelist;
294 }
295
Ruben Brunk98576cf2016-03-07 18:54:28 -0800296 public ArraySet<ComponentName> getDefaultVrComponents() {
297 return mDefaultVrComponents;
298 }
299
Christopher Tate494df792016-05-10 17:05:38 -0700300 public ArraySet<ComponentName> getBackupTransportWhitelist() {
301 return mBackupTransportWhitelist;
302 }
303
goneileb31cd42018-02-28 15:22:08 -0800304 public ArraySet<String> getDisabledUntilUsedPreinstalledCarrierApps() {
305 return mDisabledUntilUsedPreinstalledCarrierApps;
306 }
307
Jeff Davidson24b9d962016-07-21 12:35:10 -0700308 public ArrayMap<String, List<String>> getDisabledUntilUsedPreinstalledCarrierAssociatedApps() {
309 return mDisabledUntilUsedPreinstalledCarrierAssociatedApps;
310 }
311
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800312 public ArraySet<String> getPrivAppPermissions(String packageName) {
313 return mPrivAppPermissions.get(packageName);
314 }
315
Todd Kennedy74629e32017-08-15 14:48:07 -0700316 public ArraySet<String> getPrivAppDenyPermissions(String packageName) {
317 return mPrivAppDenyPermissions.get(packageName);
318 }
319
Jiyong Park002fdbd2017-02-13 20:50:31 +0900320 public ArraySet<String> getVendorPrivAppPermissions(String packageName) {
321 return mVendorPrivAppPermissions.get(packageName);
322 }
323
324 public ArraySet<String> getVendorPrivAppDenyPermissions(String packageName) {
325 return mVendorPrivAppDenyPermissions.get(packageName);
326 }
327
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900328 public ArraySet<String> getProductPrivAppPermissions(String packageName) {
329 return mProductPrivAppPermissions.get(packageName);
330 }
331
332 public ArraySet<String> getProductPrivAppDenyPermissions(String packageName) {
333 return mProductPrivAppDenyPermissions.get(packageName);
334 }
335
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900336 /**
337 * Read from "permission" tags in /system_ext/etc/permissions/*.xml
338 * @return Set of privileged permissions that are explicitly granted.
339 */
340 public ArraySet<String> getSystemExtPrivAppPermissions(String packageName) {
341 return mSystemExtPrivAppPermissions.get(packageName);
Dario Freni2bef1762018-06-01 14:02:08 +0100342 }
343
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900344 /**
345 * Read from "deny-permission" tags in /system_ext/etc/permissions/*.xml
346 * @return Set of privileged permissions that are explicitly denied.
347 */
348 public ArraySet<String> getSystemExtPrivAppDenyPermissions(String packageName) {
349 return mSystemExtPrivAppDenyPermissions.get(packageName);
Dario Freni2bef1762018-06-01 14:02:08 +0100350 }
351
Svet Ganov087dce22017-09-07 15:42:16 -0700352 public Map<String, Boolean> getOemPermissions(String packageName) {
353 final Map<String, Boolean> oemPermissions = mOemPermissions.get(packageName);
354 if (oemPermissions != null) {
355 return oemPermissions;
356 }
357 return Collections.emptyMap();
358 }
359
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800360 public ArrayMap<String, ArraySet<String>> getAllowedAssociations() {
361 return mAllowedAssociations;
362 }
363
Nikita Ioffe07964b42019-02-28 21:35:02 +0000364 public ArraySet<String> getBugreportWhitelistedPackages() {
365 return mBugreportWhitelistedPackages;
366 }
367
Bookatz04d7ae52019-08-05 14:07:12 -0700368 /**
369 * Gets map of packagesNames to userTypes, dictating on which user types each package should be
370 * initially installed, and then removes this map from SystemConfig.
371 * Called by UserManagerService when it is constructed.
372 */
373 public ArrayMap<String, Set<String>> getAndClearPackageToUserTypeWhitelist() {
374 ArrayMap<String, Set<String>> r = mPackageToUserTypeWhitelist;
375 mPackageToUserTypeWhitelist = new ArrayMap<>(0);
376 return r;
377 }
378
379 /**
380 * Gets map of packagesNames to userTypes, dictating on which user types each package should NOT
381 * be initially installed, even if they are whitelisted, and then removes this map from
382 * SystemConfig.
383 * Called by UserManagerService when it is constructed.
384 */
385 public ArrayMap<String, Set<String>> getAndClearPackageToUserTypeBlacklist() {
386 ArrayMap<String, Set<String>> r = mPackageToUserTypeBlacklist;
387 mPackageToUserTypeBlacklist = new ArrayMap<>(0);
388 return r;
389 }
390
391 /**
392 * Only use for testing. Do NOT use in production code.
393 * @param readPermissions false to create an empty SystemConfig; true to read the permissions.
394 */
395 @VisibleForTesting
396 protected SystemConfig(boolean readPermissions) {
397 if (readPermissions) {
398 Slog.w(TAG, "Constructing a test SystemConfig");
399 readAllPermissions();
400 } else {
401 Slog.w(TAG, "Constructing an empty test SystemConfig");
402 }
403 }
404
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700405 SystemConfig() {
Bookatz04d7ae52019-08-05 14:07:12 -0700406 readAllPermissions();
407 }
408
409 private void readAllPermissions() {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700410 // Read configuration from system
411 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800412 Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL);
Svet Ganov087dce22017-09-07 15:42:16 -0700413
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700414 // Read configuration from the old permissions dir
415 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800416 Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);
Svet Ganov087dce22017-09-07 15:42:16 -0700417
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800418 // Vendors are only allowed to customize these
419 int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS
420 | ALLOW_ASSOCIATIONS;
Jiyong Parkfad99442018-03-12 10:39:07 +0900421 if (Build.VERSION.FIRST_SDK_INT <= Build.VERSION_CODES.O_MR1) {
422 // For backward compatibility
423 vendorPermissionFlag |= (ALLOW_PERMISSIONS | ALLOW_APP_CONFIGS);
424 }
Jaekyun Seoke3b6bf12017-02-16 13:48:30 +0900425 readPermissions(Environment.buildPath(
426 Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
427 readPermissions(Environment.buildPath(
428 Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag);
Svet Ganov087dce22017-09-07 15:42:16 -0700429
Jiyong Park090c6b12017-12-28 12:03:28 +0900430 // Allow ODM to customize system configs as much as Vendor, because /odm is another
431 // vendor partition other than /vendor.
432 int odmPermissionFlag = vendorPermissionFlag;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700433 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800434 Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700435 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800436 Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);
Svet Ganov087dce22017-09-07 15:42:16 -0700437
Steven Morelandd7827fd2018-12-03 10:27:01 -0800438 String skuProperty = SystemProperties.get(SKU_PROPERTY, "");
439 if (!skuProperty.isEmpty()) {
440 String skuDir = "sku_" + skuProperty;
441
442 readPermissions(Environment.buildPath(
443 Environment.getOdmDirectory(), "etc", "sysconfig", skuDir), odmPermissionFlag);
444 readPermissions(Environment.buildPath(
445 Environment.getOdmDirectory(), "etc", "permissions", skuDir),
446 odmPermissionFlag);
447 }
448
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800449 // Allow OEM to customize these
450 int oemPermissionFlag = ALLOW_FEATURES | ALLOW_OEM_PERMISSIONS | ALLOW_ASSOCIATIONS;
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800451 readPermissions(Environment.buildPath(
Svet Ganov087dce22017-09-07 15:42:16 -0700452 Environment.getOemDirectory(), "etc", "sysconfig"), oemPermissionFlag);
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800453 readPermissions(Environment.buildPath(
Svet Ganov087dce22017-09-07 15:42:16 -0700454 Environment.getOemDirectory(), "etc", "permissions"), oemPermissionFlag);
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900455
Hung-ying Tyan38cd31c2018-09-26 15:05:07 +0800456 // Allow Product to customize all system configs
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900457 readPermissions(Environment.buildPath(
Hung-ying Tyan38cd31c2018-09-26 15:05:07 +0800458 Environment.getProductDirectory(), "etc", "sysconfig"), ALLOW_ALL);
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900459 readPermissions(Environment.buildPath(
Hung-ying Tyan38cd31c2018-09-26 15:05:07 +0800460 Environment.getProductDirectory(), "etc", "permissions"), ALLOW_ALL);
Dario Freni2bef1762018-06-01 14:02:08 +0100461
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900462 // Allow /system_ext to customize all system configs
Dario Freni2bef1762018-06-01 14:02:08 +0100463 readPermissions(Environment.buildPath(
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900464 Environment.getSystemExtDirectory(), "etc", "sysconfig"), ALLOW_ALL);
Dario Freni2bef1762018-06-01 14:02:08 +0100465 readPermissions(Environment.buildPath(
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900466 Environment.getSystemExtDirectory(), "etc", "permissions"), ALLOW_ALL);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700467 }
468
Bookatz04d7ae52019-08-05 14:07:12 -0700469 @VisibleForTesting
470 public void readPermissions(File libraryDir, int permissionFlag) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700471 // Read permissions from given directory.
472 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800473 if (permissionFlag == ALLOW_ALL) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700474 Slog.w(TAG, "No directory " + libraryDir + ", skipping");
475 }
476 return;
477 }
478 if (!libraryDir.canRead()) {
479 Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
480 return;
481 }
482
483 // Iterate over the files in the directory and scan .xml files
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800484 File platformFile = null;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700485 for (File f : libraryDir.listFiles()) {
Steven Morelandd7827fd2018-12-03 10:27:01 -0800486 if (!f.isFile()) {
487 continue;
488 }
489
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700490 // We'll read platform.xml last
491 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800492 platformFile = f;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700493 continue;
494 }
495
496 if (!f.getPath().endsWith(".xml")) {
497 Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
498 continue;
499 }
500 if (!f.canRead()) {
501 Slog.w(TAG, "Permissions library file " + f + " cannot be read");
502 continue;
503 }
504
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800505 readPermissionsFromXml(f, permissionFlag);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700506 }
507
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800508 // Read platform permissions last so it will take precedence
509 if (platformFile != null) {
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800510 readPermissionsFromXml(platformFile, permissionFlag);
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800511 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700512 }
513
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800514 private void logNotAllowedInPartition(String name, File permFile, XmlPullParser parser) {
515 Slog.w(TAG, "<" + name + "> not allowed in partition of "
516 + permFile + " at " + parser.getPositionDescription());
517 }
518
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800519 private void readPermissionsFromXml(File permFile, int permissionFlag) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700520 FileReader permReader = null;
521 try {
522 permReader = new FileReader(permFile);
523 } catch (FileNotFoundException e) {
524 Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
525 return;
526 }
527
Dianne Hackbornc0e4aaa2014-11-14 10:55:50 -0800528 final boolean lowRam = ActivityManager.isLowRamDeviceStatic();
529
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700530 try {
531 XmlPullParser parser = Xml.newPullParser();
532 parser.setInput(permReader);
533
534 int type;
535 while ((type=parser.next()) != parser.START_TAG
536 && type != parser.END_DOCUMENT) {
537 ;
538 }
539
540 if (type != parser.START_TAG) {
541 throw new XmlPullParserException("No start tag found");
542 }
543
544 if (!parser.getName().equals("permissions") && !parser.getName().equals("config")) {
Dianne Hackbornb3d4cb32015-01-09 09:54:06 -0800545 throw new XmlPullParserException("Unexpected start tag in " + permFile
546 + ": found " + parser.getName() + ", expected 'permissions' or 'config'");
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700547 }
548
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800549 final boolean allowAll = permissionFlag == ALLOW_ALL;
550 final boolean allowLibs = (permissionFlag & ALLOW_LIBS) != 0;
551 final boolean allowFeatures = (permissionFlag & ALLOW_FEATURES) != 0;
552 final boolean allowPermissions = (permissionFlag & ALLOW_PERMISSIONS) != 0;
553 final boolean allowAppConfigs = (permissionFlag & ALLOW_APP_CONFIGS) != 0;
554 final boolean allowPrivappPermissions = (permissionFlag & ALLOW_PRIVAPP_PERMISSIONS)
555 != 0;
556 final boolean allowOemPermissions = (permissionFlag & ALLOW_OEM_PERMISSIONS) != 0;
557 final boolean allowApiWhitelisting = (permissionFlag & ALLOW_HIDDENAPI_WHITELISTING)
558 != 0;
559 final boolean allowAssociations = (permissionFlag & ALLOW_ASSOCIATIONS) != 0;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700560 while (true) {
561 XmlUtils.nextElement(parser);
562 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
563 break;
564 }
565
566 String name = parser.getName();
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800567 if (name == null) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700568 XmlUtils.skipCurrentTag(parser);
569 continue;
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800570 }
571 switch (name) {
572 case "group": {
573 if (allowAll) {
574 String gidStr = parser.getAttributeValue(null, "gid");
575 if (gidStr != null) {
576 int gid = android.os.Process.getGidForName(gidStr);
577 mGlobalGids = appendInt(mGlobalGids, gid);
578 } else {
579 Slog.w(TAG, "<" + name + "> without gid in " + permFile + " at "
goneileb31cd42018-02-28 15:22:08 -0800580 + parser.getPositionDescription());
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800581 }
582 } else {
583 logNotAllowedInPartition(name, permFile, parser);
584 }
585 XmlUtils.skipCurrentTag(parser);
586 } break;
587 case "permission": {
588 if (allowPermissions) {
589 String perm = parser.getAttributeValue(null, "name");
590 if (perm == null) {
591 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
592 + parser.getPositionDescription());
593 XmlUtils.skipCurrentTag(parser);
594 break;
595 }
596 perm = perm.intern();
597 readPermission(parser, perm);
598 } else {
599 logNotAllowedInPartition(name, permFile, parser);
600 XmlUtils.skipCurrentTag(parser);
601 }
602 } break;
603 case "assign-permission": {
604 if (allowPermissions) {
605 String perm = parser.getAttributeValue(null, "name");
606 if (perm == null) {
607 Slog.w(TAG, "<" + name + "> without name in " + permFile
608 + " at " + parser.getPositionDescription());
609 XmlUtils.skipCurrentTag(parser);
610 break;
611 }
612 String uidStr = parser.getAttributeValue(null, "uid");
613 if (uidStr == null) {
614 Slog.w(TAG, "<" + name + "> without uid in " + permFile
615 + " at " + parser.getPositionDescription());
616 XmlUtils.skipCurrentTag(parser);
617 break;
618 }
619 int uid = Process.getUidForName(uidStr);
620 if (uid < 0) {
621 Slog.w(TAG, "<" + name + "> with unknown uid \""
622 + uidStr + " in " + permFile + " at "
623 + parser.getPositionDescription());
624 XmlUtils.skipCurrentTag(parser);
625 break;
626 }
627 perm = perm.intern();
628 ArraySet<String> perms = mSystemPermissions.get(uid);
629 if (perms == null) {
630 perms = new ArraySet<String>();
631 mSystemPermissions.put(uid, perms);
632 }
633 perms.add(perm);
634 } else {
635 logNotAllowedInPartition(name, permFile, parser);
636 }
637 XmlUtils.skipCurrentTag(parser);
638 } break;
639 case "split-permission": {
640 if (allowPermissions) {
641 readSplitPermission(parser, permFile);
642 } else {
643 logNotAllowedInPartition(name, permFile, parser);
644 XmlUtils.skipCurrentTag(parser);
645 }
646 } break;
647 case "library": {
648 if (allowLibs) {
649 String lname = parser.getAttributeValue(null, "name");
650 String lfile = parser.getAttributeValue(null, "file");
651 String ldependency = parser.getAttributeValue(null, "dependency");
652 if (lname == null) {
653 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
654 + parser.getPositionDescription());
655 } else if (lfile == null) {
656 Slog.w(TAG, "<" + name + "> without file in " + permFile + " at "
657 + parser.getPositionDescription());
658 } else {
659 //Log.i(TAG, "Got library " + lname + " in " + lfile);
660 SharedLibraryEntry entry = new SharedLibraryEntry(lname, lfile,
661 ldependency == null ? new String[0] : ldependency.split(":"));
662 mSharedLibraries.put(lname, entry);
663 }
664 } else {
665 logNotAllowedInPartition(name, permFile, parser);
666 }
667 XmlUtils.skipCurrentTag(parser);
668 } break;
669 case "feature": {
670 if (allowFeatures) {
671 String fname = parser.getAttributeValue(null, "name");
672 int fversion = XmlUtils.readIntAttribute(parser, "version", 0);
673 boolean allowed;
674 if (!lowRam) {
675 allowed = true;
676 } else {
677 String notLowRam = parser.getAttributeValue(null, "notLowRam");
678 allowed = !"true".equals(notLowRam);
679 }
680 if (fname == null) {
681 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
682 + parser.getPositionDescription());
683 } else if (allowed) {
684 addFeature(fname, fversion);
685 }
686 } else {
687 logNotAllowedInPartition(name, permFile, parser);
688 }
689 XmlUtils.skipCurrentTag(parser);
690 } break;
691 case "unavailable-feature": {
692 if (allowFeatures) {
693 String fname = parser.getAttributeValue(null, "name");
694 if (fname == null) {
695 Slog.w(TAG, "<" + name + "> without name in " + permFile
696 + " at " + parser.getPositionDescription());
697 } else {
698 mUnavailableFeatures.add(fname);
699 }
700 } else {
701 logNotAllowedInPartition(name, permFile, parser);
702 }
703 XmlUtils.skipCurrentTag(parser);
704 } break;
705 case "allow-in-power-save-except-idle": {
706 if (allowAll) {
707 String pkgname = parser.getAttributeValue(null, "package");
708 if (pkgname == null) {
709 Slog.w(TAG, "<" + name + "> without package in "
710 + permFile + " at " + parser.getPositionDescription());
711 } else {
712 mAllowInPowerSaveExceptIdle.add(pkgname);
713 }
714 } else {
715 logNotAllowedInPartition(name, permFile, parser);
716 }
717 XmlUtils.skipCurrentTag(parser);
718 } break;
719 case "allow-in-power-save": {
720 if (allowAll) {
721 String pkgname = parser.getAttributeValue(null, "package");
722 if (pkgname == null) {
723 Slog.w(TAG, "<" + name + "> without package in "
724 + permFile + " at " + parser.getPositionDescription());
725 } else {
726 mAllowInPowerSave.add(pkgname);
727 }
728 } else {
729 logNotAllowedInPartition(name, permFile, parser);
730 }
731 XmlUtils.skipCurrentTag(parser);
732 } break;
733 case "allow-in-data-usage-save": {
734 if (allowAll) {
735 String pkgname = parser.getAttributeValue(null, "package");
736 if (pkgname == null) {
737 Slog.w(TAG, "<" + name + "> without package in "
738 + permFile + " at " + parser.getPositionDescription());
739 } else {
740 mAllowInDataUsageSave.add(pkgname);
741 }
742 } else {
743 logNotAllowedInPartition(name, permFile, parser);
744 }
745 XmlUtils.skipCurrentTag(parser);
746 } break;
747 case "allow-unthrottled-location": {
748 if (allowAll) {
749 String pkgname = parser.getAttributeValue(null, "package");
750 if (pkgname == null) {
751 Slog.w(TAG, "<" + name + "> without package in "
752 + permFile + " at " + parser.getPositionDescription());
753 } else {
754 mAllowUnthrottledLocation.add(pkgname);
755 }
756 } else {
757 logNotAllowedInPartition(name, permFile, parser);
758 }
759 XmlUtils.skipCurrentTag(parser);
760 } break;
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800761 case "allow-ignore-location-settings": {
762 if (allowAll) {
763 String pkgname = parser.getAttributeValue(null, "package");
764 if (pkgname == null) {
765 Slog.w(TAG, "<" + name + "> without package in "
766 + permFile + " at " + parser.getPositionDescription());
767 } else {
768 mAllowIgnoreLocationSettings.add(pkgname);
769 }
770 } else {
771 logNotAllowedInPartition(name, permFile, parser);
772 }
773 XmlUtils.skipCurrentTag(parser);
774 } break;
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800775 case "allow-implicit-broadcast": {
776 if (allowAll) {
777 String action = parser.getAttributeValue(null, "action");
778 if (action == null) {
779 Slog.w(TAG, "<" + name + "> without action in "
780 + permFile + " at " + parser.getPositionDescription());
781 } else {
782 mAllowImplicitBroadcasts.add(action);
783 }
784 } else {
785 logNotAllowedInPartition(name, permFile, parser);
786 }
787 XmlUtils.skipCurrentTag(parser);
788 } break;
789 case "app-link": {
790 if (allowAppConfigs) {
791 String pkgname = parser.getAttributeValue(null, "package");
792 if (pkgname == null) {
793 Slog.w(TAG, "<" + name + "> without package in " + permFile
794 + " at " + parser.getPositionDescription());
795 } else {
796 mLinkedApps.add(pkgname);
797 }
798 } else {
799 logNotAllowedInPartition(name, permFile, parser);
800 }
801 XmlUtils.skipCurrentTag(parser);
802 } break;
803 case "system-user-whitelisted-app": {
804 if (allowAppConfigs) {
805 String pkgname = parser.getAttributeValue(null, "package");
806 if (pkgname == null) {
807 Slog.w(TAG, "<" + name + "> without package in "
808 + permFile + " at " + parser.getPositionDescription());
809 } else {
810 mSystemUserWhitelistedApps.add(pkgname);
811 }
812 } else {
813 logNotAllowedInPartition(name, permFile, parser);
814 }
815 XmlUtils.skipCurrentTag(parser);
816 } break;
817 case "system-user-blacklisted-app": {
818 if (allowAppConfigs) {
819 String pkgname = parser.getAttributeValue(null, "package");
820 if (pkgname == null) {
821 Slog.w(TAG, "<" + name + "> without package in "
822 + permFile + " at " + parser.getPositionDescription());
823 } else {
824 mSystemUserBlacklistedApps.add(pkgname);
825 }
826 } else {
827 logNotAllowedInPartition(name, permFile, parser);
828 }
829 XmlUtils.skipCurrentTag(parser);
830 } break;
831 case "default-enabled-vr-app": {
832 if (allowAppConfigs) {
833 String pkgname = parser.getAttributeValue(null, "package");
834 String clsname = parser.getAttributeValue(null, "class");
835 if (pkgname == null) {
836 Slog.w(TAG, "<" + name + "> without package in "
837 + permFile + " at " + parser.getPositionDescription());
838 } else if (clsname == null) {
839 Slog.w(TAG, "<" + name + "> without class in "
840 + permFile + " at " + parser.getPositionDescription());
841 } else {
842 mDefaultVrComponents.add(new ComponentName(pkgname, clsname));
843 }
844 } else {
845 logNotAllowedInPartition(name, permFile, parser);
846 }
847 XmlUtils.skipCurrentTag(parser);
848 } break;
849 case "backup-transport-whitelisted-service": {
850 if (allowFeatures) {
851 String serviceName = parser.getAttributeValue(null, "service");
852 if (serviceName == null) {
853 Slog.w(TAG, "<" + name + "> without service in "
854 + permFile + " at " + parser.getPositionDescription());
855 } else {
856 ComponentName cn = ComponentName.unflattenFromString(serviceName);
857 if (cn == null) {
858 Slog.w(TAG, "<" + name + "> with invalid service name "
859 + serviceName + " in " + permFile
860 + " at " + parser.getPositionDescription());
861 } else {
862 mBackupTransportWhitelist.add(cn);
863 }
864 }
865 } else {
866 logNotAllowedInPartition(name, permFile, parser);
867 }
868 XmlUtils.skipCurrentTag(parser);
869 } break;
870 case "disabled-until-used-preinstalled-carrier-associated-app": {
871 if (allowAppConfigs) {
872 String pkgname = parser.getAttributeValue(null, "package");
873 String carrierPkgname = parser.getAttributeValue(null,
874 "carrierAppPackage");
875 if (pkgname == null || carrierPkgname == null) {
876 Slog.w(TAG, "<" + name
877 + "> without package or carrierAppPackage in " + permFile
878 + " at " + parser.getPositionDescription());
879 } else {
880 List<String> associatedPkgs =
881 mDisabledUntilUsedPreinstalledCarrierAssociatedApps.get(
882 carrierPkgname);
883 if (associatedPkgs == null) {
884 associatedPkgs = new ArrayList<>();
885 mDisabledUntilUsedPreinstalledCarrierAssociatedApps.put(
886 carrierPkgname, associatedPkgs);
887 }
888 associatedPkgs.add(pkgname);
889 }
890 } else {
891 logNotAllowedInPartition(name, permFile, parser);
892 }
893 XmlUtils.skipCurrentTag(parser);
894 } break;
895 case "disabled-until-used-preinstalled-carrier-app": {
896 if (allowAppConfigs) {
897 String pkgname = parser.getAttributeValue(null, "package");
898 if (pkgname == null) {
899 Slog.w(TAG,
900 "<" + name + "> without "
901 + "package in " + permFile + " at "
902 + parser.getPositionDescription());
903 } else {
904 mDisabledUntilUsedPreinstalledCarrierApps.add(pkgname);
905 }
906 } else {
907 logNotAllowedInPartition(name, permFile, parser);
908 }
909 XmlUtils.skipCurrentTag(parser);
910 } break;
911 case "privapp-permissions": {
912 if (allowPrivappPermissions) {
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900913 // privapp permissions from system, vendor, product and system_ext
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800914 // partitions are stored separately. This is to prevent xml files in
915 // the vendor partition from granting permissions to priv apps in the
916 // system partition and vice versa.
917 boolean vendor = permFile.toPath().startsWith(
918 Environment.getVendorDirectory().toPath() + "/")
919 || permFile.toPath().startsWith(
920 Environment.getOdmDirectory().toPath() + "/");
921 boolean product = permFile.toPath().startsWith(
922 Environment.getProductDirectory().toPath() + "/");
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900923 boolean systemExt = permFile.toPath().startsWith(
924 Environment.getSystemExtDirectory().toPath() + "/");
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800925 if (vendor) {
926 readPrivAppPermissions(parser, mVendorPrivAppPermissions,
927 mVendorPrivAppDenyPermissions);
928 } else if (product) {
929 readPrivAppPermissions(parser, mProductPrivAppPermissions,
930 mProductPrivAppDenyPermissions);
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900931 } else if (systemExt) {
932 readPrivAppPermissions(parser, mSystemExtPrivAppPermissions,
933 mSystemExtPrivAppDenyPermissions);
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800934 } else {
935 readPrivAppPermissions(parser, mPrivAppPermissions,
936 mPrivAppDenyPermissions);
937 }
938 } else {
939 logNotAllowedInPartition(name, permFile, parser);
940 XmlUtils.skipCurrentTag(parser);
941 }
942 } break;
943 case "oem-permissions": {
944 if (allowOemPermissions) {
945 readOemPermissions(parser);
946 } else {
947 logNotAllowedInPartition(name, permFile, parser);
948 XmlUtils.skipCurrentTag(parser);
949 }
950 } break;
951 case "hidden-api-whitelisted-app": {
952 if (allowApiWhitelisting) {
953 String pkgname = parser.getAttributeValue(null, "package");
954 if (pkgname == null) {
955 Slog.w(TAG, "<" + name + "> without package in "
956 + permFile + " at " + parser.getPositionDescription());
957 } else {
958 mHiddenApiPackageWhitelist.add(pkgname);
959 }
960 } else {
961 logNotAllowedInPartition(name, permFile, parser);
962 }
963 XmlUtils.skipCurrentTag(parser);
964 } break;
965 case "allow-association": {
966 if (allowAssociations) {
967 String target = parser.getAttributeValue(null, "target");
968 if (target == null) {
969 Slog.w(TAG, "<" + name + "> without target in " + permFile
970 + " at " + parser.getPositionDescription());
971 XmlUtils.skipCurrentTag(parser);
972 break;
973 }
974 String allowed = parser.getAttributeValue(null, "allowed");
975 if (allowed == null) {
976 Slog.w(TAG, "<" + name + "> without allowed in " + permFile
977 + " at " + parser.getPositionDescription());
978 XmlUtils.skipCurrentTag(parser);
979 break;
980 }
981 target = target.intern();
982 allowed = allowed.intern();
983 ArraySet<String> associations = mAllowedAssociations.get(target);
984 if (associations == null) {
985 associations = new ArraySet<>();
986 mAllowedAssociations.put(target, associations);
987 }
988 Slog.i(TAG, "Adding association: " + target + " <- " + allowed);
989 associations.add(allowed);
990 } else {
991 logNotAllowedInPartition(name, permFile, parser);
992 }
993 XmlUtils.skipCurrentTag(parser);
994 } break;
Nikita Ioffe07964b42019-02-28 21:35:02 +0000995 case "bugreport-whitelisted": {
996 String pkgname = parser.getAttributeValue(null, "package");
997 if (pkgname == null) {
998 Slog.w(TAG, "<" + name + "> without package in " + permFile
999 + " at " + parser.getPositionDescription());
1000 } else {
1001 mBugreportWhitelistedPackages.add(pkgname);
1002 }
Nikita Ioffe08146ef2019-03-13 17:04:21 +00001003 XmlUtils.skipCurrentTag(parser);
Nikita Ioffe07964b42019-02-28 21:35:02 +00001004 } break;
Bookatz04d7ae52019-08-05 14:07:12 -07001005 case "install-in-user-type": {
1006 // NB: We allow any directory permission to declare install-in-user-type.
1007 readInstallInUserType(parser,
1008 mPackageToUserTypeWhitelist, mPackageToUserTypeBlacklist);
1009 } break;
Dianne Hackborn769b2e72018-12-05 08:51:20 -08001010 default: {
1011 Slog.w(TAG, "Tag " + name + " is unknown in "
1012 + permFile + " at " + parser.getPositionDescription());
1013 XmlUtils.skipCurrentTag(parser);
1014 } break;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001015 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001016 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001017 } catch (XmlPullParserException e) {
Jeff Sharkey1c4ae802014-12-19 11:08:55 -08001018 Slog.w(TAG, "Got exception parsing permissions.", e);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001019 } catch (IOException e) {
Jeff Sharkey1c4ae802014-12-19 11:08:55 -08001020 Slog.w(TAG, "Got exception parsing permissions.", e);
1021 } finally {
1022 IoUtils.closeQuietly(permReader);
1023 }
1024
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -07001025 // Some devices can be field-converted to FBE, so offer to splice in
1026 // those features if not already defined by the static config
Paul Lawrence20be5d62016-02-26 13:51:17 -08001027 if (StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkey115d2c12016-02-15 17:25:57 -07001028 addFeature(PackageManager.FEATURE_FILE_BASED_ENCRYPTION, 0);
1029 addFeature(PackageManager.FEATURE_SECURELY_REMOVES_USERS, 0);
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -07001030 }
1031
Jeff Sharkey8eb783b2018-01-04 16:46:48 -07001032 // Help legacy devices that may not have updated their static config
1033 if (StorageManager.hasAdoptable()) {
1034 addFeature(PackageManager.FEATURE_ADOPTABLE_STORAGE, 0);
1035 }
1036
Dianne Hackborn2a103f12017-08-08 15:50:31 -07001037 if (ActivityManager.isLowRamDeviceStatic()) {
1038 addFeature(PackageManager.FEATURE_RAM_LOW, 0);
1039 } else {
1040 addFeature(PackageManager.FEATURE_RAM_NORMAL, 0);
1041 }
1042
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -07001043 for (String featureName : mUnavailableFeatures) {
1044 removeFeature(featureName);
1045 }
1046 }
1047
Jeff Sharkey115d2c12016-02-15 17:25:57 -07001048 private void addFeature(String name, int version) {
1049 FeatureInfo fi = mAvailableFeatures.get(name);
1050 if (fi == null) {
1051 fi = new FeatureInfo();
1052 fi.name = name;
1053 fi.version = version;
1054 mAvailableFeatures.put(name, fi);
1055 } else {
1056 fi.version = Math.max(fi.version, version);
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -07001057 }
1058 }
1059
Jeff Sharkey115d2c12016-02-15 17:25:57 -07001060 private void removeFeature(String name) {
1061 if (mAvailableFeatures.remove(name) != null) {
1062 Slog.d(TAG, "Removed unavailable feature " + name);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001063 }
1064 }
1065
1066 void readPermission(XmlPullParser parser, String name)
1067 throws IOException, XmlPullParserException {
Jeff Sharkey00f39042015-03-23 16:51:22 -07001068 if (mPermissions.containsKey(name)) {
1069 throw new IllegalStateException("Duplicate permission definition for " + name);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001070 }
Jeff Sharkey00f39042015-03-23 16:51:22 -07001071
1072 final boolean perUser = XmlUtils.readBooleanAttribute(parser, "perUser", false);
1073 final PermissionEntry perm = new PermissionEntry(name, perUser);
1074 mPermissions.put(name, perm);
1075
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001076 int outerDepth = parser.getDepth();
1077 int type;
1078 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1079 && (type != XmlPullParser.END_TAG
1080 || parser.getDepth() > outerDepth)) {
1081 if (type == XmlPullParser.END_TAG
1082 || type == XmlPullParser.TEXT) {
1083 continue;
1084 }
1085
1086 String tagName = parser.getName();
1087 if ("group".equals(tagName)) {
1088 String gidStr = parser.getAttributeValue(null, "gid");
1089 if (gidStr != null) {
1090 int gid = Process.getGidForName(gidStr);
1091 perm.gids = appendInt(perm.gids, gid);
1092 } else {
1093 Slog.w(TAG, "<group> without gid at "
1094 + parser.getPositionDescription());
1095 }
1096 }
1097 XmlUtils.skipCurrentTag(parser);
1098 }
1099 }
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001100
Jiyong Park002fdbd2017-02-13 20:50:31 +09001101 private void readPrivAppPermissions(XmlPullParser parser,
1102 ArrayMap<String, ArraySet<String>> grantMap,
1103 ArrayMap<String, ArraySet<String>> denyMap)
1104 throws IOException, XmlPullParserException {
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001105 String packageName = parser.getAttributeValue(null, "package");
1106 if (TextUtils.isEmpty(packageName)) {
1107 Slog.w(TAG, "package is required for <privapp-permissions> in "
1108 + parser.getPositionDescription());
1109 return;
1110 }
1111
Jiyong Park002fdbd2017-02-13 20:50:31 +09001112 ArraySet<String> permissions = grantMap.get(packageName);
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001113 if (permissions == null) {
1114 permissions = new ArraySet<>();
1115 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09001116 ArraySet<String> denyPermissions = denyMap.get(packageName);
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001117 int depth = parser.getDepth();
1118 while (XmlUtils.nextElementWithin(parser, depth)) {
1119 String name = parser.getName();
1120 if ("permission".equals(name)) {
1121 String permName = parser.getAttributeValue(null, "name");
1122 if (TextUtils.isEmpty(permName)) {
1123 Slog.w(TAG, "name is required for <permission> in "
1124 + parser.getPositionDescription());
1125 continue;
1126 }
1127 permissions.add(permName);
Todd Kennedy74629e32017-08-15 14:48:07 -07001128 } else if ("deny-permission".equals(name)) {
1129 String permName = parser.getAttributeValue(null, "name");
1130 if (TextUtils.isEmpty(permName)) {
1131 Slog.w(TAG, "name is required for <deny-permission> in "
1132 + parser.getPositionDescription());
1133 continue;
1134 }
1135 if (denyPermissions == null) {
1136 denyPermissions = new ArraySet<>();
1137 }
1138 denyPermissions.add(permName);
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001139 }
1140 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09001141 grantMap.put(packageName, permissions);
Todd Kennedy74629e32017-08-15 14:48:07 -07001142 if (denyPermissions != null) {
Jiyong Park002fdbd2017-02-13 20:50:31 +09001143 denyMap.put(packageName, denyPermissions);
Todd Kennedy74629e32017-08-15 14:48:07 -07001144 }
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001145 }
Svet Ganov087dce22017-09-07 15:42:16 -07001146
Bookatz04d7ae52019-08-05 14:07:12 -07001147 private void readInstallInUserType(XmlPullParser parser,
1148 Map<String, Set<String>> doInstallMap,
1149 Map<String, Set<String>> nonInstallMap)
1150 throws IOException, XmlPullParserException {
1151 final String packageName = parser.getAttributeValue(null, "package");
1152 if (TextUtils.isEmpty(packageName)) {
1153 Slog.w(TAG, "package is required for <install-in-user-type> in "
1154 + parser.getPositionDescription());
1155 return;
1156 }
1157
1158 Set<String> userTypesYes = doInstallMap.get(packageName);
1159 Set<String> userTypesNo = nonInstallMap.get(packageName);
1160 final int depth = parser.getDepth();
1161 while (XmlUtils.nextElementWithin(parser, depth)) {
1162 final String name = parser.getName();
1163 if ("install-in".equals(name)) {
1164 final String userType = parser.getAttributeValue(null, "user-type");
1165 if (TextUtils.isEmpty(userType)) {
1166 Slog.w(TAG, "user-type is required for <install-in-user-type> in "
1167 + parser.getPositionDescription());
1168 continue;
1169 }
1170 if (userTypesYes == null) {
1171 userTypesYes = new ArraySet<>();
1172 doInstallMap.put(packageName, userTypesYes);
1173 }
1174 userTypesYes.add(userType);
1175 } else if ("do-not-install-in".equals(name)) {
1176 final String userType = parser.getAttributeValue(null, "user-type");
1177 if (TextUtils.isEmpty(userType)) {
1178 Slog.w(TAG, "user-type is required for <install-in-user-type> in "
1179 + parser.getPositionDescription());
1180 continue;
1181 }
1182 if (userTypesNo == null) {
1183 userTypesNo = new ArraySet<>();
1184 nonInstallMap.put(packageName, userTypesNo);
1185 }
1186 userTypesNo.add(userType);
1187 } else {
1188 Slog.w(TAG, "unrecognized tag in <install-in-user-type> in "
1189 + parser.getPositionDescription());
1190 }
1191 }
1192 }
1193
Svet Ganov087dce22017-09-07 15:42:16 -07001194 void readOemPermissions(XmlPullParser parser) throws IOException, XmlPullParserException {
1195 final String packageName = parser.getAttributeValue(null, "package");
1196 if (TextUtils.isEmpty(packageName)) {
1197 Slog.w(TAG, "package is required for <oem-permissions> in "
1198 + parser.getPositionDescription());
1199 return;
1200 }
1201
1202 ArrayMap<String, Boolean> permissions = mOemPermissions.get(packageName);
1203 if (permissions == null) {
1204 permissions = new ArrayMap<>();
1205 }
1206 final int depth = parser.getDepth();
1207 while (XmlUtils.nextElementWithin(parser, depth)) {
1208 final String name = parser.getName();
1209 if ("permission".equals(name)) {
1210 final String permName = parser.getAttributeValue(null, "name");
1211 if (TextUtils.isEmpty(permName)) {
1212 Slog.w(TAG, "name is required for <permission> in "
1213 + parser.getPositionDescription());
1214 continue;
1215 }
1216 permissions.put(permName, Boolean.TRUE);
1217 } else if ("deny-permission".equals(name)) {
1218 String permName = parser.getAttributeValue(null, "name");
1219 if (TextUtils.isEmpty(permName)) {
1220 Slog.w(TAG, "name is required for <deny-permission> in "
1221 + parser.getPositionDescription());
1222 continue;
1223 }
1224 permissions.put(permName, Boolean.FALSE);
1225 }
1226 }
1227 mOemPermissions.put(packageName, permissions);
1228 }
Zimuzocc2932f2018-10-29 16:04:41 +00001229
1230 private void readSplitPermission(XmlPullParser parser, File permFile)
1231 throws IOException, XmlPullParserException {
1232 String splitPerm = parser.getAttributeValue(null, "name");
1233 if (splitPerm == null) {
1234 Slog.w(TAG, "<split-permission> without name in " + permFile + " at "
1235 + parser.getPositionDescription());
1236 XmlUtils.skipCurrentTag(parser);
1237 return;
1238 }
1239 String targetSdkStr = parser.getAttributeValue(null, "targetSdk");
1240 int targetSdk = Build.VERSION_CODES.CUR_DEVELOPMENT + 1;
1241 if (!TextUtils.isEmpty(targetSdkStr)) {
1242 try {
1243 targetSdk = Integer.parseInt(targetSdkStr);
1244 } catch (NumberFormatException e) {
1245 Slog.w(TAG, "<split-permission> targetSdk not an integer in " + permFile + " at "
1246 + parser.getPositionDescription());
1247 XmlUtils.skipCurrentTag(parser);
1248 return;
1249 }
1250 }
1251 final int depth = parser.getDepth();
1252 List<String> newPermissions = new ArrayList<>();
1253 while (XmlUtils.nextElementWithin(parser, depth)) {
1254 String name = parser.getName();
1255 if ("new-permission".equals(name)) {
1256 final String newName = parser.getAttributeValue(null, "name");
1257 if (TextUtils.isEmpty(newName)) {
1258 Slog.w(TAG, "name is required for <new-permission> in "
1259 + parser.getPositionDescription());
1260 continue;
1261 }
1262 newPermissions.add(newName);
1263 } else {
1264 XmlUtils.skipCurrentTag(parser);
1265 }
1266 }
1267 if (!newPermissions.isEmpty()) {
1268 mSplitPermissions.add(new SplitPermissionInfo(splitPerm, newPermissions, targetSdk));
1269 }
1270 }
Anthony Hughde787d42019-08-22 15:35:48 -07001271
1272 private static boolean isSystemProcess() {
1273 return Process.myUid() == Process.SYSTEM_UID;
1274 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001275}