blob: 49a73ee7790fd5897982054e14f3d65678738f3d [file] [log] [blame]
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -070019import static com.android.internal.util.ArrayUtils.appendInt;
20
Winsond9d17362019-10-02 12:41:29 -070021import android.annotation.NonNull;
Dianne Hackbornc0e4aaa2014-11-14 10:55:50 -080022import android.app.ActivityManager;
Ruben Brunk98576cf2016-03-07 18:54:28 -080023import android.content.ComponentName;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070024import android.content.pm.FeatureInfo;
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -070025import android.content.pm.PackageManager;
Jiyong Parkfad99442018-03-12 10:39:07 +090026import android.os.Build;
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -070027import android.os.Environment;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070028import android.os.Process;
Steven Morelandd7827fd2018-12-03 10:27:01 -080029import android.os.SystemProperties;
Felipe Leme3eb78092019-10-22 09:22:20 -070030import android.os.Trace;
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -070031import android.os.storage.StorageManager;
Zimuzocc2932f2018-10-29 16:04:41 +000032import android.permission.PermissionManager.SplitPermissionInfo;
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -080033import android.text.TextUtils;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070034import android.util.ArrayMap;
35import android.util.ArraySet;
36import android.util.Slog;
37import android.util.SparseArray;
Felipe Leme3eb78092019-10-22 09:22:20 -070038import android.util.TimingsTraceLog;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070039import android.util.Xml;
Jeff Sharkey1c4ae802014-12-19 11:08:55 -080040
Bookatz04d7ae52019-08-05 14:07:12 -070041import com.android.internal.annotations.VisibleForTesting;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070042import com.android.internal.util.XmlUtils;
Jeff Sharkey1c4ae802014-12-19 11:08:55 -080043
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -070044import libcore.io.IoUtils;
45
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070046import org.xmlpull.v1.XmlPullParser;
47import org.xmlpull.v1.XmlPullParserException;
48
49import java.io.File;
50import java.io.FileNotFoundException;
51import java.io.FileReader;
52import java.io.IOException;
Jeff Davidson24b9d962016-07-21 12:35:10 -070053import java.util.ArrayList;
Svet Ganov087dce22017-09-07 15:42:16 -070054import java.util.Collections;
Jeff Davidson24b9d962016-07-21 12:35:10 -070055import java.util.List;
Svet Ganov087dce22017-09-07 15:42:16 -070056import java.util.Map;
Bookatz04d7ae52019-08-05 14:07:12 -070057import java.util.Set;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070058
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070059/**
60 * Loads global system configuration info.
Anthony Hughde787d42019-08-22 15:35:48 -070061 * Note: Initializing this class hits the disk and is slow. This class should generally only be
62 * accessed by the system_server process.
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070063 */
64public class SystemConfig {
65 static final String TAG = "SystemConfig";
66
67 static SystemConfig sInstance;
68
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +080069 // permission flag, determines which types of configuration are allowed to be read
70 private static final int ALLOW_FEATURES = 0x01;
71 private static final int ALLOW_LIBS = 0x02;
72 private static final int ALLOW_PERMISSIONS = 0x04;
73 private static final int ALLOW_APP_CONFIGS = 0x08;
Jaekyun Seoke3b6bf12017-02-16 13:48:30 +090074 private static final int ALLOW_PRIVAPP_PERMISSIONS = 0x10;
Svet Ganov087dce22017-09-07 15:42:16 -070075 private static final int ALLOW_OEM_PERMISSIONS = 0x20;
Mathew Inwood4693a752018-02-20 16:04:25 +000076 private static final int ALLOW_HIDDENAPI_WHITELISTING = 0x40;
Dianne Hackborn769b2e72018-12-05 08:51:20 -080077 private static final int ALLOW_ASSOCIATIONS = 0x80;
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +080078 private static final int ALLOW_ALL = ~0;
79
Steven Morelandd7827fd2018-12-03 10:27:01 -080080 // property for runtime configuration differentiation
81 private static final String SKU_PROPERTY = "ro.boot.product.hardware.sku";
82
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070083 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
84 int[] mGlobalGids;
85
86 // These are the built-in uid -> permission mappings that were read from the
87 // system configuration files.
Jeff Sharkey9f837a92014-10-24 12:07:24 -070088 final SparseArray<ArraySet<String>> mSystemPermissions = new SparseArray<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070089
Zimuzocc2932f2018-10-29 16:04:41 +000090 final ArrayList<SplitPermissionInfo> mSplitPermissions = new ArrayList<>();
91
Ben Lin71c16d72018-12-06 18:34:51 -080092 public static final class SharedLibraryEntry {
93 public final String name;
94 public final String filename;
95 public final String[] dependencies;
96
97 SharedLibraryEntry(String name, String filename, String[] dependencies) {
98 this.name = name;
99 this.filename = filename;
100 this.dependencies = dependencies;
101 }
102 }
103
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700104 // These are the built-in shared libraries that were read from the
Ben Lin71c16d72018-12-06 18:34:51 -0800105 // system configuration files. Keys are the library names; values are
106 // the individual entries that contain information such as filename
107 // and dependencies.
108 final ArrayMap<String, SharedLibraryEntry> mSharedLibraries = new ArrayMap<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700109
110 // These are the features this devices supports that were read from the
111 // system configuration files.
Jeff Sharkey9f837a92014-10-24 12:07:24 -0700112 final ArrayMap<String, FeatureInfo> mAvailableFeatures = new ArrayMap<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700113
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800114 // These are the features which this device doesn't support; the OEM
115 // partition uses these to opt-out of features from the system image.
116 final ArraySet<String> mUnavailableFeatures = new ArraySet<>();
117
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700118 public static final class PermissionEntry {
119 public final String name;
120 public int[] gids;
Jeff Sharkey00f39042015-03-23 16:51:22 -0700121 public boolean perUser;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700122
Jeff Sharkey00f39042015-03-23 16:51:22 -0700123 PermissionEntry(String name, boolean perUser) {
124 this.name = name;
125 this.perUser = perUser;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700126 }
127 }
128
129 // These are the permission -> gid mappings that were read from the
130 // system configuration files.
Dianne Hackbornbb8aa5a2014-09-17 13:20:38 -0700131 final ArrayMap<String, PermissionEntry> mPermissions = new ArrayMap<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700132
133 // These are the packages that are white-listed to be able to run in the
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700134 // background while in power save mode (but not whitelisted from device idle modes),
135 // as read from the configuration files.
136 final ArraySet<String> mAllowInPowerSaveExceptIdle = new ArraySet<>();
137
138 // These are the packages that are white-listed to be able to run in the
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700139 // background while in power save mode, as read from the configuration files.
Dianne Hackbornbb8aa5a2014-09-17 13:20:38 -0700140 final ArraySet<String> mAllowInPowerSave = new ArraySet<>();
141
Felipe Lemea9505cc2016-02-26 10:28:41 -0800142 // These are the packages that are white-listed to be able to run in the
143 // background while in data-usage save mode, as read from the configuration files.
144 final ArraySet<String> mAllowInDataUsageSave = new ArraySet<>();
145
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800146 // These are the packages that are white-listed to be able to run background location
147 // without throttling, as read from the configuration files.
148 final ArraySet<String> mAllowUnthrottledLocation = new ArraySet<>();
149
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800150 // These are the packages that are white-listed to be able to retrieve location even when user
151 // location settings are off, for emergency purposes, as read from the configuration files.
152 final ArraySet<String> mAllowIgnoreLocationSettings = new ArraySet<>();
153
Christopher Tate42a386b2016-11-07 12:21:21 -0800154 // These are the action strings of broadcasts which are whitelisted to
155 // be delivered anonymously even to apps which target O+.
156 final ArraySet<String> mAllowImplicitBroadcasts = new ArraySet<>();
157
Christopher Tate01e18642015-07-07 18:10:38 -0700158 // These are the package names of apps which should be in the 'always'
159 // URL-handling state upon factory reset.
160 final ArraySet<String> mLinkedApps = new ArraySet<>();
161
Fyodor Kupolov7db5af12015-07-31 16:50:27 -0700162 // These are the packages that are whitelisted to be able to run as system user
163 final ArraySet<String> mSystemUserWhitelistedApps = new ArraySet<>();
164
165 // These are the packages that should not run under system user
166 final ArraySet<String> mSystemUserBlacklistedApps = new ArraySet<>();
167
Ruben Brunk98576cf2016-03-07 18:54:28 -0800168 // These are the components that are enabled by default as VR mode listener services.
169 final ArraySet<ComponentName> mDefaultVrComponents = new ArraySet<>();
170
Christopher Tate494df792016-05-10 17:05:38 -0700171 // These are the permitted backup transport service components
172 final ArraySet<ComponentName> mBackupTransportWhitelist = new ArraySet<>();
173
Ryan Mitchell4fd8e6f2019-10-07 16:31:34 -0700174 // These are packages mapped to maps of component class name to default enabled state.
175 final ArrayMap<String, ArrayMap<String, Boolean>> mPackageComponentEnabledState =
176 new ArrayMap<>();
177
Mathew Inwood4693a752018-02-20 16:04:25 +0000178 // Package names that are exempted from private API blacklisting
179 final ArraySet<String> mHiddenApiPackageWhitelist = new ArraySet<>();
180
goneileb31cd42018-02-28 15:22:08 -0800181 // The list of carrier applications which should be disabled until used.
182 // This function suppresses update notifications for these pre-installed apps.
183 // In SubscriptionInfoUpdater, the listed applications are disabled until used when all of the
184 // following conditions are met.
185 // 1. Not currently carrier-privileged according to the inserted SIM
186 // 2. Pre-installed
187 // 3. In the default state (enabled but not explicitly)
188 // And SubscriptionInfoUpdater undoes this and marks the app enabled when a SIM is inserted
189 // that marks the app as carrier privileged. It also grants the app default permissions
190 // for Phone and Location. As such, apps MUST only ever be added to this list if they
191 // obtain user consent to access their location through other means.
192 final ArraySet<String> mDisabledUntilUsedPreinstalledCarrierApps = new ArraySet<>();
193
Jeff Davidson24b9d962016-07-21 12:35:10 -0700194 // These are the packages of carrier-associated apps which should be disabled until used until
195 // a SIM is inserted which grants carrier privileges to that carrier app.
196 final ArrayMap<String, List<String>> mDisabledUntilUsedPreinstalledCarrierAssociatedApps =
197 new ArrayMap<>();
198
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800199 final ArrayMap<String, ArraySet<String>> mPrivAppPermissions = new ArrayMap<>();
Todd Kennedy74629e32017-08-15 14:48:07 -0700200 final ArrayMap<String, ArraySet<String>> mPrivAppDenyPermissions = new ArrayMap<>();
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800201
Jiyong Park002fdbd2017-02-13 20:50:31 +0900202 final ArrayMap<String, ArraySet<String>> mVendorPrivAppPermissions = new ArrayMap<>();
203 final ArrayMap<String, ArraySet<String>> mVendorPrivAppDenyPermissions = new ArrayMap<>();
204
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900205 final ArrayMap<String, ArraySet<String>> mProductPrivAppPermissions = new ArrayMap<>();
206 final ArrayMap<String, ArraySet<String>> mProductPrivAppDenyPermissions = new ArrayMap<>();
207
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900208 final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppPermissions = new ArrayMap<>();
209 final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppDenyPermissions = new ArrayMap<>();
Dario Freni2bef1762018-06-01 14:02:08 +0100210
Svet Ganov087dce22017-09-07 15:42:16 -0700211 final ArrayMap<String, ArrayMap<String, Boolean>> mOemPermissions = new ArrayMap<>();
212
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800213 // Allowed associations between applications. If there are any entries
214 // for an app, those are the only associations allowed; otherwise, all associations
215 // are allowed. Allowing an association from app A to app B means app A can not
216 // associate with any other apps, but does not limit what apps B can associate with.
217 final ArrayMap<String, ArraySet<String>> mAllowedAssociations = new ArrayMap<>();
218
Nikita Ioffe07964b42019-02-28 21:35:02 +0000219 private final ArraySet<String> mBugreportWhitelistedPackages = new ArraySet<>();
220
Bookatz04d7ae52019-08-05 14:07:12 -0700221 // Map of packagesNames to userTypes. Stored temporarily until cleared by UserManagerService().
222 private ArrayMap<String, Set<String>> mPackageToUserTypeWhitelist = new ArrayMap<>();
223 private ArrayMap<String, Set<String>> mPackageToUserTypeBlacklist = new ArrayMap<>();
224
Winsond9d17362019-10-02 12:41:29 -0700225 /**
226 * Map of system pre-defined, uniquely named actors; keys are namespace,
227 * value maps actor name to package name.
228 */
229 private ArrayMap<String, ArrayMap<String, String>> mNamedActors = null;
230
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700231 public static SystemConfig getInstance() {
Anthony Hughde787d42019-08-22 15:35:48 -0700232 if (!isSystemProcess()) {
233 Slog.wtf(TAG, "SystemConfig is being accessed by a process other than "
234 + "system_server.");
235 }
236
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700237 synchronized (SystemConfig.class) {
238 if (sInstance == null) {
239 sInstance = new SystemConfig();
240 }
241 return sInstance;
242 }
243 }
244
245 public int[] getGlobalGids() {
246 return mGlobalGids;
247 }
248
Jeff Sharkey9f837a92014-10-24 12:07:24 -0700249 public SparseArray<ArraySet<String>> getSystemPermissions() {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700250 return mSystemPermissions;
251 }
252
Zimuzocc2932f2018-10-29 16:04:41 +0000253 public ArrayList<SplitPermissionInfo> getSplitPermissions() {
254 return mSplitPermissions;
255 }
256
Ben Lin71c16d72018-12-06 18:34:51 -0800257 public ArrayMap<String, SharedLibraryEntry> getSharedLibraries() {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700258 return mSharedLibraries;
259 }
260
Jeff Sharkey9f837a92014-10-24 12:07:24 -0700261 public ArrayMap<String, FeatureInfo> getAvailableFeatures() {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700262 return mAvailableFeatures;
263 }
264
265 public ArrayMap<String, PermissionEntry> getPermissions() {
266 return mPermissions;
267 }
268
Christopher Tate42a386b2016-11-07 12:21:21 -0800269 public ArraySet<String> getAllowImplicitBroadcasts() {
270 return mAllowImplicitBroadcasts;
271 }
272
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700273 public ArraySet<String> getAllowInPowerSaveExceptIdle() {
274 return mAllowInPowerSaveExceptIdle;
275 }
276
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700277 public ArraySet<String> getAllowInPowerSave() {
278 return mAllowInPowerSave;
279 }
280
Felipe Lemea9505cc2016-02-26 10:28:41 -0800281 public ArraySet<String> getAllowInDataUsageSave() {
282 return mAllowInDataUsageSave;
283 }
284
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800285 public ArraySet<String> getAllowUnthrottledLocation() {
286 return mAllowUnthrottledLocation;
287 }
288
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800289 public ArraySet<String> getAllowIgnoreLocationSettings() {
290 return mAllowIgnoreLocationSettings;
291 }
292
Christopher Tate01e18642015-07-07 18:10:38 -0700293 public ArraySet<String> getLinkedApps() {
294 return mLinkedApps;
295 }
296
Fyodor Kupolov7db5af12015-07-31 16:50:27 -0700297 public ArraySet<String> getSystemUserWhitelistedApps() {
298 return mSystemUserWhitelistedApps;
299 }
300
301 public ArraySet<String> getSystemUserBlacklistedApps() {
302 return mSystemUserBlacklistedApps;
303 }
304
Mathew Inwood4693a752018-02-20 16:04:25 +0000305 public ArraySet<String> getHiddenApiWhitelistedApps() {
306 return mHiddenApiPackageWhitelist;
307 }
308
Ruben Brunk98576cf2016-03-07 18:54:28 -0800309 public ArraySet<ComponentName> getDefaultVrComponents() {
310 return mDefaultVrComponents;
311 }
312
Christopher Tate494df792016-05-10 17:05:38 -0700313 public ArraySet<ComponentName> getBackupTransportWhitelist() {
314 return mBackupTransportWhitelist;
315 }
316
Ryan Mitchell4fd8e6f2019-10-07 16:31:34 -0700317 public ArrayMap<String, Boolean> getComponentsEnabledStates(String packageName) {
318 return mPackageComponentEnabledState.get(packageName);
319 }
320
goneileb31cd42018-02-28 15:22:08 -0800321 public ArraySet<String> getDisabledUntilUsedPreinstalledCarrierApps() {
322 return mDisabledUntilUsedPreinstalledCarrierApps;
323 }
324
Jeff Davidson24b9d962016-07-21 12:35:10 -0700325 public ArrayMap<String, List<String>> getDisabledUntilUsedPreinstalledCarrierAssociatedApps() {
326 return mDisabledUntilUsedPreinstalledCarrierAssociatedApps;
327 }
328
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800329 public ArraySet<String> getPrivAppPermissions(String packageName) {
330 return mPrivAppPermissions.get(packageName);
331 }
332
Todd Kennedy74629e32017-08-15 14:48:07 -0700333 public ArraySet<String> getPrivAppDenyPermissions(String packageName) {
334 return mPrivAppDenyPermissions.get(packageName);
335 }
336
Jiyong Park002fdbd2017-02-13 20:50:31 +0900337 public ArraySet<String> getVendorPrivAppPermissions(String packageName) {
338 return mVendorPrivAppPermissions.get(packageName);
339 }
340
341 public ArraySet<String> getVendorPrivAppDenyPermissions(String packageName) {
342 return mVendorPrivAppDenyPermissions.get(packageName);
343 }
344
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900345 public ArraySet<String> getProductPrivAppPermissions(String packageName) {
346 return mProductPrivAppPermissions.get(packageName);
347 }
348
349 public ArraySet<String> getProductPrivAppDenyPermissions(String packageName) {
350 return mProductPrivAppDenyPermissions.get(packageName);
351 }
352
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900353 /**
354 * Read from "permission" tags in /system_ext/etc/permissions/*.xml
355 * @return Set of privileged permissions that are explicitly granted.
356 */
357 public ArraySet<String> getSystemExtPrivAppPermissions(String packageName) {
358 return mSystemExtPrivAppPermissions.get(packageName);
Dario Freni2bef1762018-06-01 14:02:08 +0100359 }
360
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900361 /**
362 * Read from "deny-permission" tags in /system_ext/etc/permissions/*.xml
363 * @return Set of privileged permissions that are explicitly denied.
364 */
365 public ArraySet<String> getSystemExtPrivAppDenyPermissions(String packageName) {
366 return mSystemExtPrivAppDenyPermissions.get(packageName);
Dario Freni2bef1762018-06-01 14:02:08 +0100367 }
368
Svet Ganov087dce22017-09-07 15:42:16 -0700369 public Map<String, Boolean> getOemPermissions(String packageName) {
370 final Map<String, Boolean> oemPermissions = mOemPermissions.get(packageName);
371 if (oemPermissions != null) {
372 return oemPermissions;
373 }
374 return Collections.emptyMap();
375 }
376
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800377 public ArrayMap<String, ArraySet<String>> getAllowedAssociations() {
378 return mAllowedAssociations;
379 }
380
Nikita Ioffe07964b42019-02-28 21:35:02 +0000381 public ArraySet<String> getBugreportWhitelistedPackages() {
382 return mBugreportWhitelistedPackages;
383 }
384
Bookatz04d7ae52019-08-05 14:07:12 -0700385 /**
386 * Gets map of packagesNames to userTypes, dictating on which user types each package should be
387 * initially installed, and then removes this map from SystemConfig.
388 * Called by UserManagerService when it is constructed.
389 */
390 public ArrayMap<String, Set<String>> getAndClearPackageToUserTypeWhitelist() {
391 ArrayMap<String, Set<String>> r = mPackageToUserTypeWhitelist;
392 mPackageToUserTypeWhitelist = new ArrayMap<>(0);
393 return r;
394 }
395
396 /**
397 * Gets map of packagesNames to userTypes, dictating on which user types each package should NOT
398 * be initially installed, even if they are whitelisted, and then removes this map from
399 * SystemConfig.
400 * Called by UserManagerService when it is constructed.
401 */
402 public ArrayMap<String, Set<String>> getAndClearPackageToUserTypeBlacklist() {
403 ArrayMap<String, Set<String>> r = mPackageToUserTypeBlacklist;
404 mPackageToUserTypeBlacklist = new ArrayMap<>(0);
405 return r;
406 }
407
Winsond9d17362019-10-02 12:41:29 -0700408 @NonNull
409 public Map<String, ? extends Map<String, String>> getNamedActors() {
410 return mNamedActors != null ? mNamedActors : Collections.emptyMap();
411 }
412
Bookatz04d7ae52019-08-05 14:07:12 -0700413 /**
414 * Only use for testing. Do NOT use in production code.
415 * @param readPermissions false to create an empty SystemConfig; true to read the permissions.
416 */
417 @VisibleForTesting
Winsond9d17362019-10-02 12:41:29 -0700418 public SystemConfig(boolean readPermissions) {
Bookatz04d7ae52019-08-05 14:07:12 -0700419 if (readPermissions) {
420 Slog.w(TAG, "Constructing a test SystemConfig");
421 readAllPermissions();
422 } else {
423 Slog.w(TAG, "Constructing an empty test SystemConfig");
424 }
425 }
426
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700427 SystemConfig() {
Felipe Leme3eb78092019-10-22 09:22:20 -0700428 TimingsTraceLog log = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
429 log.traceBegin("readAllPermissions");
430 try {
431 readAllPermissions();
432 } finally {
433 log.traceEnd();
434 }
Bookatz04d7ae52019-08-05 14:07:12 -0700435 }
436
437 private void readAllPermissions() {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700438 // Read configuration from system
439 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800440 Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL);
Svet Ganov087dce22017-09-07 15:42:16 -0700441
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700442 // Read configuration from the old permissions dir
443 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800444 Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);
Svet Ganov087dce22017-09-07 15:42:16 -0700445
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800446 // Vendors are only allowed to customize these
447 int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS
448 | ALLOW_ASSOCIATIONS;
Jiyong Parkfad99442018-03-12 10:39:07 +0900449 if (Build.VERSION.FIRST_SDK_INT <= Build.VERSION_CODES.O_MR1) {
450 // For backward compatibility
451 vendorPermissionFlag |= (ALLOW_PERMISSIONS | ALLOW_APP_CONFIGS);
452 }
Jaekyun Seoke3b6bf12017-02-16 13:48:30 +0900453 readPermissions(Environment.buildPath(
454 Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
455 readPermissions(Environment.buildPath(
456 Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag);
Svet Ganov087dce22017-09-07 15:42:16 -0700457
Jiyong Park090c6b12017-12-28 12:03:28 +0900458 // Allow ODM to customize system configs as much as Vendor, because /odm is another
459 // vendor partition other than /vendor.
460 int odmPermissionFlag = vendorPermissionFlag;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700461 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800462 Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700463 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800464 Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);
Svet Ganov087dce22017-09-07 15:42:16 -0700465
Steven Morelandd7827fd2018-12-03 10:27:01 -0800466 String skuProperty = SystemProperties.get(SKU_PROPERTY, "");
467 if (!skuProperty.isEmpty()) {
468 String skuDir = "sku_" + skuProperty;
469
470 readPermissions(Environment.buildPath(
471 Environment.getOdmDirectory(), "etc", "sysconfig", skuDir), odmPermissionFlag);
472 readPermissions(Environment.buildPath(
473 Environment.getOdmDirectory(), "etc", "permissions", skuDir),
474 odmPermissionFlag);
475 }
476
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800477 // Allow OEM to customize these
478 int oemPermissionFlag = ALLOW_FEATURES | ALLOW_OEM_PERMISSIONS | ALLOW_ASSOCIATIONS;
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800479 readPermissions(Environment.buildPath(
Svet Ganov087dce22017-09-07 15:42:16 -0700480 Environment.getOemDirectory(), "etc", "sysconfig"), oemPermissionFlag);
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800481 readPermissions(Environment.buildPath(
Svet Ganov087dce22017-09-07 15:42:16 -0700482 Environment.getOemDirectory(), "etc", "permissions"), oemPermissionFlag);
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900483
Hung-ying Tyan38cd31c2018-09-26 15:05:07 +0800484 // Allow Product to customize all system configs
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900485 readPermissions(Environment.buildPath(
Hung-ying Tyan38cd31c2018-09-26 15:05:07 +0800486 Environment.getProductDirectory(), "etc", "sysconfig"), ALLOW_ALL);
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900487 readPermissions(Environment.buildPath(
Hung-ying Tyan38cd31c2018-09-26 15:05:07 +0800488 Environment.getProductDirectory(), "etc", "permissions"), ALLOW_ALL);
Dario Freni2bef1762018-06-01 14:02:08 +0100489
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900490 // Allow /system_ext to customize all system configs
Dario Freni2bef1762018-06-01 14:02:08 +0100491 readPermissions(Environment.buildPath(
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900492 Environment.getSystemExtDirectory(), "etc", "sysconfig"), ALLOW_ALL);
Dario Freni2bef1762018-06-01 14:02:08 +0100493 readPermissions(Environment.buildPath(
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900494 Environment.getSystemExtDirectory(), "etc", "permissions"), ALLOW_ALL);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700495 }
496
Bookatz04d7ae52019-08-05 14:07:12 -0700497 @VisibleForTesting
498 public void readPermissions(File libraryDir, int permissionFlag) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700499 // Read permissions from given directory.
500 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800501 if (permissionFlag == ALLOW_ALL) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700502 Slog.w(TAG, "No directory " + libraryDir + ", skipping");
503 }
504 return;
505 }
506 if (!libraryDir.canRead()) {
507 Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
508 return;
509 }
510
511 // Iterate over the files in the directory and scan .xml files
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800512 File platformFile = null;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700513 for (File f : libraryDir.listFiles()) {
Steven Morelandd7827fd2018-12-03 10:27:01 -0800514 if (!f.isFile()) {
515 continue;
516 }
517
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700518 // We'll read platform.xml last
519 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800520 platformFile = f;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700521 continue;
522 }
523
524 if (!f.getPath().endsWith(".xml")) {
525 Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
526 continue;
527 }
528 if (!f.canRead()) {
529 Slog.w(TAG, "Permissions library file " + f + " cannot be read");
530 continue;
531 }
532
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800533 readPermissionsFromXml(f, permissionFlag);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700534 }
535
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800536 // Read platform permissions last so it will take precedence
537 if (platformFile != null) {
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800538 readPermissionsFromXml(platformFile, permissionFlag);
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800539 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700540 }
541
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800542 private void logNotAllowedInPartition(String name, File permFile, XmlPullParser parser) {
543 Slog.w(TAG, "<" + name + "> not allowed in partition of "
544 + permFile + " at " + parser.getPositionDescription());
545 }
546
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800547 private void readPermissionsFromXml(File permFile, int permissionFlag) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700548 FileReader permReader = null;
549 try {
550 permReader = new FileReader(permFile);
551 } catch (FileNotFoundException e) {
552 Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
553 return;
554 }
Felipe Leme1fbe9b52019-10-21 14:20:08 -0700555 Slog.i(TAG, "Reading permissions from " + permFile);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700556
Dianne Hackbornc0e4aaa2014-11-14 10:55:50 -0800557 final boolean lowRam = ActivityManager.isLowRamDeviceStatic();
558
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700559 try {
560 XmlPullParser parser = Xml.newPullParser();
561 parser.setInput(permReader);
562
563 int type;
564 while ((type=parser.next()) != parser.START_TAG
565 && type != parser.END_DOCUMENT) {
566 ;
567 }
568
569 if (type != parser.START_TAG) {
570 throw new XmlPullParserException("No start tag found");
571 }
572
573 if (!parser.getName().equals("permissions") && !parser.getName().equals("config")) {
Dianne Hackbornb3d4cb32015-01-09 09:54:06 -0800574 throw new XmlPullParserException("Unexpected start tag in " + permFile
575 + ": found " + parser.getName() + ", expected 'permissions' or 'config'");
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700576 }
577
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800578 final boolean allowAll = permissionFlag == ALLOW_ALL;
579 final boolean allowLibs = (permissionFlag & ALLOW_LIBS) != 0;
580 final boolean allowFeatures = (permissionFlag & ALLOW_FEATURES) != 0;
581 final boolean allowPermissions = (permissionFlag & ALLOW_PERMISSIONS) != 0;
582 final boolean allowAppConfigs = (permissionFlag & ALLOW_APP_CONFIGS) != 0;
583 final boolean allowPrivappPermissions = (permissionFlag & ALLOW_PRIVAPP_PERMISSIONS)
584 != 0;
585 final boolean allowOemPermissions = (permissionFlag & ALLOW_OEM_PERMISSIONS) != 0;
586 final boolean allowApiWhitelisting = (permissionFlag & ALLOW_HIDDENAPI_WHITELISTING)
587 != 0;
588 final boolean allowAssociations = (permissionFlag & ALLOW_ASSOCIATIONS) != 0;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700589 while (true) {
590 XmlUtils.nextElement(parser);
591 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
592 break;
593 }
594
595 String name = parser.getName();
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800596 if (name == null) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700597 XmlUtils.skipCurrentTag(parser);
598 continue;
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800599 }
600 switch (name) {
601 case "group": {
602 if (allowAll) {
603 String gidStr = parser.getAttributeValue(null, "gid");
604 if (gidStr != null) {
605 int gid = android.os.Process.getGidForName(gidStr);
606 mGlobalGids = appendInt(mGlobalGids, gid);
607 } else {
608 Slog.w(TAG, "<" + name + "> without gid in " + permFile + " at "
goneileb31cd42018-02-28 15:22:08 -0800609 + parser.getPositionDescription());
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800610 }
611 } else {
612 logNotAllowedInPartition(name, permFile, parser);
613 }
614 XmlUtils.skipCurrentTag(parser);
615 } break;
616 case "permission": {
617 if (allowPermissions) {
618 String perm = parser.getAttributeValue(null, "name");
619 if (perm == null) {
620 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
621 + parser.getPositionDescription());
622 XmlUtils.skipCurrentTag(parser);
623 break;
624 }
625 perm = perm.intern();
626 readPermission(parser, perm);
627 } else {
628 logNotAllowedInPartition(name, permFile, parser);
629 XmlUtils.skipCurrentTag(parser);
630 }
631 } break;
632 case "assign-permission": {
633 if (allowPermissions) {
634 String perm = parser.getAttributeValue(null, "name");
635 if (perm == null) {
636 Slog.w(TAG, "<" + name + "> without name in " + permFile
637 + " at " + parser.getPositionDescription());
638 XmlUtils.skipCurrentTag(parser);
639 break;
640 }
641 String uidStr = parser.getAttributeValue(null, "uid");
642 if (uidStr == null) {
643 Slog.w(TAG, "<" + name + "> without uid in " + permFile
644 + " at " + parser.getPositionDescription());
645 XmlUtils.skipCurrentTag(parser);
646 break;
647 }
648 int uid = Process.getUidForName(uidStr);
649 if (uid < 0) {
650 Slog.w(TAG, "<" + name + "> with unknown uid \""
651 + uidStr + " in " + permFile + " at "
652 + parser.getPositionDescription());
653 XmlUtils.skipCurrentTag(parser);
654 break;
655 }
656 perm = perm.intern();
657 ArraySet<String> perms = mSystemPermissions.get(uid);
658 if (perms == null) {
659 perms = new ArraySet<String>();
660 mSystemPermissions.put(uid, perms);
661 }
662 perms.add(perm);
663 } else {
664 logNotAllowedInPartition(name, permFile, parser);
665 }
666 XmlUtils.skipCurrentTag(parser);
667 } break;
668 case "split-permission": {
669 if (allowPermissions) {
670 readSplitPermission(parser, permFile);
671 } else {
672 logNotAllowedInPartition(name, permFile, parser);
673 XmlUtils.skipCurrentTag(parser);
674 }
675 } break;
676 case "library": {
677 if (allowLibs) {
678 String lname = parser.getAttributeValue(null, "name");
679 String lfile = parser.getAttributeValue(null, "file");
680 String ldependency = parser.getAttributeValue(null, "dependency");
681 if (lname == null) {
682 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
683 + parser.getPositionDescription());
684 } else if (lfile == null) {
685 Slog.w(TAG, "<" + name + "> without file in " + permFile + " at "
686 + parser.getPositionDescription());
687 } else {
688 //Log.i(TAG, "Got library " + lname + " in " + lfile);
689 SharedLibraryEntry entry = new SharedLibraryEntry(lname, lfile,
690 ldependency == null ? new String[0] : ldependency.split(":"));
691 mSharedLibraries.put(lname, entry);
692 }
693 } else {
694 logNotAllowedInPartition(name, permFile, parser);
695 }
696 XmlUtils.skipCurrentTag(parser);
697 } break;
698 case "feature": {
699 if (allowFeatures) {
700 String fname = parser.getAttributeValue(null, "name");
701 int fversion = XmlUtils.readIntAttribute(parser, "version", 0);
702 boolean allowed;
703 if (!lowRam) {
704 allowed = true;
705 } else {
706 String notLowRam = parser.getAttributeValue(null, "notLowRam");
707 allowed = !"true".equals(notLowRam);
708 }
709 if (fname == null) {
710 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
711 + parser.getPositionDescription());
712 } else if (allowed) {
713 addFeature(fname, fversion);
714 }
715 } else {
716 logNotAllowedInPartition(name, permFile, parser);
717 }
718 XmlUtils.skipCurrentTag(parser);
719 } break;
720 case "unavailable-feature": {
721 if (allowFeatures) {
722 String fname = parser.getAttributeValue(null, "name");
723 if (fname == null) {
724 Slog.w(TAG, "<" + name + "> without name in " + permFile
725 + " at " + parser.getPositionDescription());
726 } else {
727 mUnavailableFeatures.add(fname);
728 }
729 } else {
730 logNotAllowedInPartition(name, permFile, parser);
731 }
732 XmlUtils.skipCurrentTag(parser);
733 } break;
734 case "allow-in-power-save-except-idle": {
735 if (allowAll) {
736 String pkgname = parser.getAttributeValue(null, "package");
737 if (pkgname == null) {
738 Slog.w(TAG, "<" + name + "> without package in "
739 + permFile + " at " + parser.getPositionDescription());
740 } else {
741 mAllowInPowerSaveExceptIdle.add(pkgname);
742 }
743 } else {
744 logNotAllowedInPartition(name, permFile, parser);
745 }
746 XmlUtils.skipCurrentTag(parser);
747 } break;
748 case "allow-in-power-save": {
749 if (allowAll) {
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 mAllowInPowerSave.add(pkgname);
756 }
757 } else {
758 logNotAllowedInPartition(name, permFile, parser);
759 }
760 XmlUtils.skipCurrentTag(parser);
761 } break;
762 case "allow-in-data-usage-save": {
763 if (allowAll) {
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 mAllowInDataUsageSave.add(pkgname);
770 }
771 } else {
772 logNotAllowedInPartition(name, permFile, parser);
773 }
774 XmlUtils.skipCurrentTag(parser);
775 } break;
776 case "allow-unthrottled-location": {
777 if (allowAll) {
778 String pkgname = parser.getAttributeValue(null, "package");
779 if (pkgname == null) {
780 Slog.w(TAG, "<" + name + "> without package in "
781 + permFile + " at " + parser.getPositionDescription());
782 } else {
783 mAllowUnthrottledLocation.add(pkgname);
784 }
785 } else {
786 logNotAllowedInPartition(name, permFile, parser);
787 }
788 XmlUtils.skipCurrentTag(parser);
789 } break;
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800790 case "allow-ignore-location-settings": {
791 if (allowAll) {
792 String pkgname = parser.getAttributeValue(null, "package");
793 if (pkgname == null) {
794 Slog.w(TAG, "<" + name + "> without package in "
795 + permFile + " at " + parser.getPositionDescription());
796 } else {
797 mAllowIgnoreLocationSettings.add(pkgname);
798 }
799 } else {
800 logNotAllowedInPartition(name, permFile, parser);
801 }
802 XmlUtils.skipCurrentTag(parser);
803 } break;
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800804 case "allow-implicit-broadcast": {
805 if (allowAll) {
806 String action = parser.getAttributeValue(null, "action");
807 if (action == null) {
808 Slog.w(TAG, "<" + name + "> without action in "
809 + permFile + " at " + parser.getPositionDescription());
810 } else {
811 mAllowImplicitBroadcasts.add(action);
812 }
813 } else {
814 logNotAllowedInPartition(name, permFile, parser);
815 }
816 XmlUtils.skipCurrentTag(parser);
817 } break;
818 case "app-link": {
819 if (allowAppConfigs) {
820 String pkgname = parser.getAttributeValue(null, "package");
821 if (pkgname == null) {
822 Slog.w(TAG, "<" + name + "> without package in " + permFile
823 + " at " + parser.getPositionDescription());
824 } else {
825 mLinkedApps.add(pkgname);
826 }
827 } else {
828 logNotAllowedInPartition(name, permFile, parser);
829 }
830 XmlUtils.skipCurrentTag(parser);
831 } break;
832 case "system-user-whitelisted-app": {
833 if (allowAppConfigs) {
834 String pkgname = parser.getAttributeValue(null, "package");
835 if (pkgname == null) {
836 Slog.w(TAG, "<" + name + "> without package in "
837 + permFile + " at " + parser.getPositionDescription());
838 } else {
839 mSystemUserWhitelistedApps.add(pkgname);
840 }
841 } else {
842 logNotAllowedInPartition(name, permFile, parser);
843 }
844 XmlUtils.skipCurrentTag(parser);
845 } break;
846 case "system-user-blacklisted-app": {
847 if (allowAppConfigs) {
848 String pkgname = parser.getAttributeValue(null, "package");
849 if (pkgname == null) {
850 Slog.w(TAG, "<" + name + "> without package in "
851 + permFile + " at " + parser.getPositionDescription());
852 } else {
853 mSystemUserBlacklistedApps.add(pkgname);
854 }
855 } else {
856 logNotAllowedInPartition(name, permFile, parser);
857 }
858 XmlUtils.skipCurrentTag(parser);
859 } break;
860 case "default-enabled-vr-app": {
861 if (allowAppConfigs) {
862 String pkgname = parser.getAttributeValue(null, "package");
863 String clsname = parser.getAttributeValue(null, "class");
864 if (pkgname == null) {
865 Slog.w(TAG, "<" + name + "> without package in "
866 + permFile + " at " + parser.getPositionDescription());
867 } else if (clsname == null) {
868 Slog.w(TAG, "<" + name + "> without class in "
869 + permFile + " at " + parser.getPositionDescription());
870 } else {
871 mDefaultVrComponents.add(new ComponentName(pkgname, clsname));
872 }
873 } else {
874 logNotAllowedInPartition(name, permFile, parser);
875 }
876 XmlUtils.skipCurrentTag(parser);
877 } break;
Ryan Mitchell4fd8e6f2019-10-07 16:31:34 -0700878 case "component-override": {
Ryan Mitchell61a30322019-10-30 08:52:43 -0700879 readComponentOverrides(parser, permFile);
Ryan Mitchell4fd8e6f2019-10-07 16:31:34 -0700880 XmlUtils.skipCurrentTag(parser);
881 } break;
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800882 case "backup-transport-whitelisted-service": {
883 if (allowFeatures) {
884 String serviceName = parser.getAttributeValue(null, "service");
885 if (serviceName == null) {
886 Slog.w(TAG, "<" + name + "> without service in "
887 + permFile + " at " + parser.getPositionDescription());
888 } else {
889 ComponentName cn = ComponentName.unflattenFromString(serviceName);
890 if (cn == null) {
891 Slog.w(TAG, "<" + name + "> with invalid service name "
892 + serviceName + " in " + permFile
893 + " at " + parser.getPositionDescription());
894 } else {
895 mBackupTransportWhitelist.add(cn);
896 }
897 }
898 } else {
899 logNotAllowedInPartition(name, permFile, parser);
900 }
901 XmlUtils.skipCurrentTag(parser);
902 } break;
903 case "disabled-until-used-preinstalled-carrier-associated-app": {
904 if (allowAppConfigs) {
905 String pkgname = parser.getAttributeValue(null, "package");
906 String carrierPkgname = parser.getAttributeValue(null,
907 "carrierAppPackage");
908 if (pkgname == null || carrierPkgname == null) {
909 Slog.w(TAG, "<" + name
910 + "> without package or carrierAppPackage in " + permFile
911 + " at " + parser.getPositionDescription());
912 } else {
913 List<String> associatedPkgs =
914 mDisabledUntilUsedPreinstalledCarrierAssociatedApps.get(
915 carrierPkgname);
916 if (associatedPkgs == null) {
917 associatedPkgs = new ArrayList<>();
918 mDisabledUntilUsedPreinstalledCarrierAssociatedApps.put(
919 carrierPkgname, associatedPkgs);
920 }
921 associatedPkgs.add(pkgname);
922 }
923 } else {
924 logNotAllowedInPartition(name, permFile, parser);
925 }
926 XmlUtils.skipCurrentTag(parser);
927 } break;
928 case "disabled-until-used-preinstalled-carrier-app": {
929 if (allowAppConfigs) {
930 String pkgname = parser.getAttributeValue(null, "package");
931 if (pkgname == null) {
932 Slog.w(TAG,
933 "<" + name + "> without "
934 + "package in " + permFile + " at "
935 + parser.getPositionDescription());
936 } else {
937 mDisabledUntilUsedPreinstalledCarrierApps.add(pkgname);
938 }
939 } else {
940 logNotAllowedInPartition(name, permFile, parser);
941 }
942 XmlUtils.skipCurrentTag(parser);
943 } break;
944 case "privapp-permissions": {
945 if (allowPrivappPermissions) {
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900946 // privapp permissions from system, vendor, product and system_ext
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800947 // partitions are stored separately. This is to prevent xml files in
948 // the vendor partition from granting permissions to priv apps in the
949 // system partition and vice versa.
950 boolean vendor = permFile.toPath().startsWith(
951 Environment.getVendorDirectory().toPath() + "/")
952 || permFile.toPath().startsWith(
953 Environment.getOdmDirectory().toPath() + "/");
954 boolean product = permFile.toPath().startsWith(
955 Environment.getProductDirectory().toPath() + "/");
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900956 boolean systemExt = permFile.toPath().startsWith(
957 Environment.getSystemExtDirectory().toPath() + "/");
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800958 if (vendor) {
959 readPrivAppPermissions(parser, mVendorPrivAppPermissions,
960 mVendorPrivAppDenyPermissions);
961 } else if (product) {
962 readPrivAppPermissions(parser, mProductPrivAppPermissions,
963 mProductPrivAppDenyPermissions);
Jeongik Cha9ec059a2019-07-04 21:12:06 +0900964 } else if (systemExt) {
965 readPrivAppPermissions(parser, mSystemExtPrivAppPermissions,
966 mSystemExtPrivAppDenyPermissions);
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800967 } else {
968 readPrivAppPermissions(parser, mPrivAppPermissions,
969 mPrivAppDenyPermissions);
970 }
971 } else {
972 logNotAllowedInPartition(name, permFile, parser);
973 XmlUtils.skipCurrentTag(parser);
974 }
975 } break;
976 case "oem-permissions": {
977 if (allowOemPermissions) {
978 readOemPermissions(parser);
979 } else {
980 logNotAllowedInPartition(name, permFile, parser);
981 XmlUtils.skipCurrentTag(parser);
982 }
983 } break;
984 case "hidden-api-whitelisted-app": {
985 if (allowApiWhitelisting) {
986 String pkgname = parser.getAttributeValue(null, "package");
987 if (pkgname == null) {
988 Slog.w(TAG, "<" + name + "> without package in "
989 + permFile + " at " + parser.getPositionDescription());
990 } else {
991 mHiddenApiPackageWhitelist.add(pkgname);
992 }
993 } else {
994 logNotAllowedInPartition(name, permFile, parser);
995 }
996 XmlUtils.skipCurrentTag(parser);
997 } break;
998 case "allow-association": {
999 if (allowAssociations) {
1000 String target = parser.getAttributeValue(null, "target");
1001 if (target == null) {
1002 Slog.w(TAG, "<" + name + "> without target in " + permFile
1003 + " at " + parser.getPositionDescription());
1004 XmlUtils.skipCurrentTag(parser);
1005 break;
1006 }
1007 String allowed = parser.getAttributeValue(null, "allowed");
1008 if (allowed == null) {
1009 Slog.w(TAG, "<" + name + "> without allowed in " + permFile
1010 + " at " + parser.getPositionDescription());
1011 XmlUtils.skipCurrentTag(parser);
1012 break;
1013 }
1014 target = target.intern();
1015 allowed = allowed.intern();
1016 ArraySet<String> associations = mAllowedAssociations.get(target);
1017 if (associations == null) {
1018 associations = new ArraySet<>();
1019 mAllowedAssociations.put(target, associations);
1020 }
1021 Slog.i(TAG, "Adding association: " + target + " <- " + allowed);
1022 associations.add(allowed);
1023 } else {
1024 logNotAllowedInPartition(name, permFile, parser);
1025 }
1026 XmlUtils.skipCurrentTag(parser);
1027 } break;
Nikita Ioffe07964b42019-02-28 21:35:02 +00001028 case "bugreport-whitelisted": {
1029 String pkgname = parser.getAttributeValue(null, "package");
1030 if (pkgname == null) {
1031 Slog.w(TAG, "<" + name + "> without package in " + permFile
1032 + " at " + parser.getPositionDescription());
1033 } else {
1034 mBugreportWhitelistedPackages.add(pkgname);
1035 }
Nikita Ioffe08146ef2019-03-13 17:04:21 +00001036 XmlUtils.skipCurrentTag(parser);
Nikita Ioffe07964b42019-02-28 21:35:02 +00001037 } break;
Bookatz04d7ae52019-08-05 14:07:12 -07001038 case "install-in-user-type": {
1039 // NB: We allow any directory permission to declare install-in-user-type.
1040 readInstallInUserType(parser,
1041 mPackageToUserTypeWhitelist, mPackageToUserTypeBlacklist);
1042 } break;
Winsond9d17362019-10-02 12:41:29 -07001043 case "named-actor": {
1044 String namespace = TextUtils.safeIntern(
1045 parser.getAttributeValue(null, "namespace"));
1046 String actorName = parser.getAttributeValue(null, "name");
1047 String pkgName = TextUtils.safeIntern(
1048 parser.getAttributeValue(null, "package"));
1049 if (TextUtils.isEmpty(namespace)) {
1050 Slog.wtf(TAG, "<" + name + "> without namespace in " + permFile
1051 + " at " + parser.getPositionDescription());
1052 } else if (TextUtils.isEmpty(actorName)) {
1053 Slog.wtf(TAG, "<" + name + "> without actor name in " + permFile
1054 + " at " + parser.getPositionDescription());
1055 } else if (TextUtils.isEmpty(pkgName)) {
1056 Slog.wtf(TAG, "<" + name + "> without package name in " + permFile
1057 + " at " + parser.getPositionDescription());
1058 } else if ("android".equalsIgnoreCase(namespace)) {
1059 throw new IllegalStateException("Defining " + actorName + " as "
1060 + pkgName + " for the android namespace is not allowed");
1061 } else {
1062 if (mNamedActors == null) {
1063 mNamedActors = new ArrayMap<>();
1064 }
1065
1066 ArrayMap<String, String> nameToPkgMap = mNamedActors.get(namespace);
1067 if (nameToPkgMap == null) {
1068 nameToPkgMap = new ArrayMap<>();
1069 mNamedActors.put(namespace, nameToPkgMap);
1070 } else if (nameToPkgMap.containsKey(actorName)) {
1071 String existing = nameToPkgMap.get(actorName);
1072 throw new IllegalStateException("Duplicate actor definition for "
1073 + namespace + "/" + actorName
1074 + "; defined as both " + existing + " and " + pkgName);
1075 }
1076
1077 nameToPkgMap.put(actorName, pkgName);
1078 }
1079 XmlUtils.skipCurrentTag(parser);
1080 } break;
Dianne Hackborn769b2e72018-12-05 08:51:20 -08001081 default: {
1082 Slog.w(TAG, "Tag " + name + " is unknown in "
1083 + permFile + " at " + parser.getPositionDescription());
1084 XmlUtils.skipCurrentTag(parser);
1085 } break;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001086 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001087 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001088 } catch (XmlPullParserException e) {
Jeff Sharkey1c4ae802014-12-19 11:08:55 -08001089 Slog.w(TAG, "Got exception parsing permissions.", e);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001090 } catch (IOException e) {
Jeff Sharkey1c4ae802014-12-19 11:08:55 -08001091 Slog.w(TAG, "Got exception parsing permissions.", e);
1092 } finally {
1093 IoUtils.closeQuietly(permReader);
1094 }
1095
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -07001096 // Some devices can be field-converted to FBE, so offer to splice in
1097 // those features if not already defined by the static config
Paul Lawrence20be5d62016-02-26 13:51:17 -08001098 if (StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkey115d2c12016-02-15 17:25:57 -07001099 addFeature(PackageManager.FEATURE_FILE_BASED_ENCRYPTION, 0);
1100 addFeature(PackageManager.FEATURE_SECURELY_REMOVES_USERS, 0);
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -07001101 }
1102
Jeff Sharkey8eb783b2018-01-04 16:46:48 -07001103 // Help legacy devices that may not have updated their static config
1104 if (StorageManager.hasAdoptable()) {
1105 addFeature(PackageManager.FEATURE_ADOPTABLE_STORAGE, 0);
1106 }
1107
Dianne Hackborn2a103f12017-08-08 15:50:31 -07001108 if (ActivityManager.isLowRamDeviceStatic()) {
1109 addFeature(PackageManager.FEATURE_RAM_LOW, 0);
1110 } else {
1111 addFeature(PackageManager.FEATURE_RAM_NORMAL, 0);
1112 }
1113
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -07001114 for (String featureName : mUnavailableFeatures) {
1115 removeFeature(featureName);
1116 }
1117 }
1118
Jeff Sharkey115d2c12016-02-15 17:25:57 -07001119 private void addFeature(String name, int version) {
1120 FeatureInfo fi = mAvailableFeatures.get(name);
1121 if (fi == null) {
1122 fi = new FeatureInfo();
1123 fi.name = name;
1124 fi.version = version;
1125 mAvailableFeatures.put(name, fi);
1126 } else {
1127 fi.version = Math.max(fi.version, version);
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -07001128 }
1129 }
1130
Jeff Sharkey115d2c12016-02-15 17:25:57 -07001131 private void removeFeature(String name) {
1132 if (mAvailableFeatures.remove(name) != null) {
1133 Slog.d(TAG, "Removed unavailable feature " + name);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001134 }
1135 }
1136
1137 void readPermission(XmlPullParser parser, String name)
1138 throws IOException, XmlPullParserException {
Jeff Sharkey00f39042015-03-23 16:51:22 -07001139 if (mPermissions.containsKey(name)) {
1140 throw new IllegalStateException("Duplicate permission definition for " + name);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001141 }
Jeff Sharkey00f39042015-03-23 16:51:22 -07001142
1143 final boolean perUser = XmlUtils.readBooleanAttribute(parser, "perUser", false);
1144 final PermissionEntry perm = new PermissionEntry(name, perUser);
1145 mPermissions.put(name, perm);
1146
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001147 int outerDepth = parser.getDepth();
1148 int type;
1149 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1150 && (type != XmlPullParser.END_TAG
1151 || parser.getDepth() > outerDepth)) {
1152 if (type == XmlPullParser.END_TAG
1153 || type == XmlPullParser.TEXT) {
1154 continue;
1155 }
1156
1157 String tagName = parser.getName();
1158 if ("group".equals(tagName)) {
1159 String gidStr = parser.getAttributeValue(null, "gid");
1160 if (gidStr != null) {
1161 int gid = Process.getGidForName(gidStr);
1162 perm.gids = appendInt(perm.gids, gid);
1163 } else {
1164 Slog.w(TAG, "<group> without gid at "
1165 + parser.getPositionDescription());
1166 }
1167 }
1168 XmlUtils.skipCurrentTag(parser);
1169 }
1170 }
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001171
Jiyong Park002fdbd2017-02-13 20:50:31 +09001172 private void readPrivAppPermissions(XmlPullParser parser,
1173 ArrayMap<String, ArraySet<String>> grantMap,
1174 ArrayMap<String, ArraySet<String>> denyMap)
1175 throws IOException, XmlPullParserException {
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001176 String packageName = parser.getAttributeValue(null, "package");
1177 if (TextUtils.isEmpty(packageName)) {
1178 Slog.w(TAG, "package is required for <privapp-permissions> in "
1179 + parser.getPositionDescription());
1180 return;
1181 }
1182
Jiyong Park002fdbd2017-02-13 20:50:31 +09001183 ArraySet<String> permissions = grantMap.get(packageName);
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001184 if (permissions == null) {
1185 permissions = new ArraySet<>();
1186 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09001187 ArraySet<String> denyPermissions = denyMap.get(packageName);
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001188 int depth = parser.getDepth();
1189 while (XmlUtils.nextElementWithin(parser, depth)) {
1190 String name = parser.getName();
1191 if ("permission".equals(name)) {
1192 String permName = parser.getAttributeValue(null, "name");
1193 if (TextUtils.isEmpty(permName)) {
1194 Slog.w(TAG, "name is required for <permission> in "
1195 + parser.getPositionDescription());
1196 continue;
1197 }
1198 permissions.add(permName);
Todd Kennedy74629e32017-08-15 14:48:07 -07001199 } else if ("deny-permission".equals(name)) {
1200 String permName = parser.getAttributeValue(null, "name");
1201 if (TextUtils.isEmpty(permName)) {
1202 Slog.w(TAG, "name is required for <deny-permission> in "
1203 + parser.getPositionDescription());
1204 continue;
1205 }
1206 if (denyPermissions == null) {
1207 denyPermissions = new ArraySet<>();
1208 }
1209 denyPermissions.add(permName);
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001210 }
1211 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09001212 grantMap.put(packageName, permissions);
Todd Kennedy74629e32017-08-15 14:48:07 -07001213 if (denyPermissions != null) {
Jiyong Park002fdbd2017-02-13 20:50:31 +09001214 denyMap.put(packageName, denyPermissions);
Todd Kennedy74629e32017-08-15 14:48:07 -07001215 }
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001216 }
Svet Ganov087dce22017-09-07 15:42:16 -07001217
Bookatz04d7ae52019-08-05 14:07:12 -07001218 private void readInstallInUserType(XmlPullParser parser,
1219 Map<String, Set<String>> doInstallMap,
1220 Map<String, Set<String>> nonInstallMap)
1221 throws IOException, XmlPullParserException {
1222 final String packageName = parser.getAttributeValue(null, "package");
1223 if (TextUtils.isEmpty(packageName)) {
1224 Slog.w(TAG, "package is required for <install-in-user-type> in "
1225 + parser.getPositionDescription());
1226 return;
1227 }
1228
1229 Set<String> userTypesYes = doInstallMap.get(packageName);
1230 Set<String> userTypesNo = nonInstallMap.get(packageName);
1231 final int depth = parser.getDepth();
1232 while (XmlUtils.nextElementWithin(parser, depth)) {
1233 final String name = parser.getName();
1234 if ("install-in".equals(name)) {
1235 final String userType = parser.getAttributeValue(null, "user-type");
1236 if (TextUtils.isEmpty(userType)) {
1237 Slog.w(TAG, "user-type is required for <install-in-user-type> in "
1238 + parser.getPositionDescription());
1239 continue;
1240 }
1241 if (userTypesYes == null) {
1242 userTypesYes = new ArraySet<>();
1243 doInstallMap.put(packageName, userTypesYes);
1244 }
1245 userTypesYes.add(userType);
1246 } else if ("do-not-install-in".equals(name)) {
1247 final String userType = parser.getAttributeValue(null, "user-type");
1248 if (TextUtils.isEmpty(userType)) {
1249 Slog.w(TAG, "user-type is required for <install-in-user-type> in "
1250 + parser.getPositionDescription());
1251 continue;
1252 }
1253 if (userTypesNo == null) {
1254 userTypesNo = new ArraySet<>();
1255 nonInstallMap.put(packageName, userTypesNo);
1256 }
1257 userTypesNo.add(userType);
1258 } else {
1259 Slog.w(TAG, "unrecognized tag in <install-in-user-type> in "
1260 + parser.getPositionDescription());
1261 }
1262 }
1263 }
1264
Svet Ganov087dce22017-09-07 15:42:16 -07001265 void readOemPermissions(XmlPullParser parser) throws IOException, XmlPullParserException {
1266 final String packageName = parser.getAttributeValue(null, "package");
1267 if (TextUtils.isEmpty(packageName)) {
1268 Slog.w(TAG, "package is required for <oem-permissions> in "
1269 + parser.getPositionDescription());
1270 return;
1271 }
1272
1273 ArrayMap<String, Boolean> permissions = mOemPermissions.get(packageName);
1274 if (permissions == null) {
1275 permissions = new ArrayMap<>();
1276 }
1277 final int depth = parser.getDepth();
1278 while (XmlUtils.nextElementWithin(parser, depth)) {
1279 final String name = parser.getName();
1280 if ("permission".equals(name)) {
1281 final String permName = parser.getAttributeValue(null, "name");
1282 if (TextUtils.isEmpty(permName)) {
1283 Slog.w(TAG, "name is required for <permission> in "
1284 + parser.getPositionDescription());
1285 continue;
1286 }
1287 permissions.put(permName, Boolean.TRUE);
1288 } else if ("deny-permission".equals(name)) {
1289 String permName = parser.getAttributeValue(null, "name");
1290 if (TextUtils.isEmpty(permName)) {
1291 Slog.w(TAG, "name is required for <deny-permission> in "
1292 + parser.getPositionDescription());
1293 continue;
1294 }
1295 permissions.put(permName, Boolean.FALSE);
1296 }
1297 }
1298 mOemPermissions.put(packageName, permissions);
1299 }
Zimuzocc2932f2018-10-29 16:04:41 +00001300
1301 private void readSplitPermission(XmlPullParser parser, File permFile)
1302 throws IOException, XmlPullParserException {
1303 String splitPerm = parser.getAttributeValue(null, "name");
1304 if (splitPerm == null) {
1305 Slog.w(TAG, "<split-permission> without name in " + permFile + " at "
1306 + parser.getPositionDescription());
1307 XmlUtils.skipCurrentTag(parser);
1308 return;
1309 }
1310 String targetSdkStr = parser.getAttributeValue(null, "targetSdk");
1311 int targetSdk = Build.VERSION_CODES.CUR_DEVELOPMENT + 1;
1312 if (!TextUtils.isEmpty(targetSdkStr)) {
1313 try {
1314 targetSdk = Integer.parseInt(targetSdkStr);
1315 } catch (NumberFormatException e) {
1316 Slog.w(TAG, "<split-permission> targetSdk not an integer in " + permFile + " at "
1317 + parser.getPositionDescription());
1318 XmlUtils.skipCurrentTag(parser);
1319 return;
1320 }
1321 }
1322 final int depth = parser.getDepth();
1323 List<String> newPermissions = new ArrayList<>();
1324 while (XmlUtils.nextElementWithin(parser, depth)) {
1325 String name = parser.getName();
1326 if ("new-permission".equals(name)) {
1327 final String newName = parser.getAttributeValue(null, "name");
1328 if (TextUtils.isEmpty(newName)) {
1329 Slog.w(TAG, "name is required for <new-permission> in "
1330 + parser.getPositionDescription());
1331 continue;
1332 }
1333 newPermissions.add(newName);
1334 } else {
1335 XmlUtils.skipCurrentTag(parser);
1336 }
1337 }
1338 if (!newPermissions.isEmpty()) {
1339 mSplitPermissions.add(new SplitPermissionInfo(splitPerm, newPermissions, targetSdk));
1340 }
1341 }
Anthony Hughde787d42019-08-22 15:35:48 -07001342
Ryan Mitchell4fd8e6f2019-10-07 16:31:34 -07001343 private void readComponentOverrides(XmlPullParser parser, File permFile)
1344 throws IOException, XmlPullParserException {
1345 String pkgname = parser.getAttributeValue(null, "package");
1346 if (pkgname == null) {
1347 Slog.w(TAG, "<component-override> without package in "
1348 + permFile + " at " + parser.getPositionDescription());
1349 return;
1350 }
1351
1352 pkgname = pkgname.intern();
1353
1354 final int depth = parser.getDepth();
1355 while (XmlUtils.nextElementWithin(parser, depth)) {
1356 String name = parser.getName();
1357 if ("component".equals(name)) {
1358 String clsname = parser.getAttributeValue(null, "class");
1359 String enabled = parser.getAttributeValue(null, "enabled");
1360 if (clsname == null) {
1361 Slog.w(TAG, "<component> without class in "
1362 + permFile + " at " + parser.getPositionDescription());
1363 return;
1364 } else if (enabled == null) {
1365 Slog.w(TAG, "<component> without enabled in "
1366 + permFile + " at " + parser.getPositionDescription());
1367 return;
1368 }
1369
1370 if (clsname.startsWith(".")) {
1371 clsname = pkgname + clsname;
1372 }
1373
1374 clsname = clsname.intern();
1375
1376 ArrayMap<String, Boolean> componentEnabledStates =
1377 mPackageComponentEnabledState.get(pkgname);
1378 if (componentEnabledStates == null) {
1379 componentEnabledStates = new ArrayMap<>();
1380 mPackageComponentEnabledState.put(pkgname,
1381 componentEnabledStates);
1382 }
1383
1384 componentEnabledStates.put(clsname, !"false".equals(enabled));
1385 } else {
1386 XmlUtils.skipCurrentTag(parser);
1387 }
1388 }
1389 }
1390
Anthony Hughde787d42019-08-22 15:35:48 -07001391 private static boolean isSystemProcess() {
1392 return Process.myUid() == Process.SYSTEM_UID;
1393 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001394}