blob: 958bb18192fb5ac97d69fa3d34fdf051ea5d518a [file] [log] [blame]
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -070019import static com.android.internal.util.ArrayUtils.appendInt;
20
Dianne Hackbornc0e4aaa2014-11-14 10:55:50 -080021import android.app.ActivityManager;
Ruben Brunk98576cf2016-03-07 18:54:28 -080022import android.content.ComponentName;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070023import android.content.pm.FeatureInfo;
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -070024import android.content.pm.PackageManager;
Jiyong Parkfad99442018-03-12 10:39:07 +090025import android.os.Build;
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -070026import android.os.Environment;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070027import android.os.Process;
Steven Morelandd7827fd2018-12-03 10:27:01 -080028import android.os.SystemProperties;
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -070029import android.os.storage.StorageManager;
Zimuzocc2932f2018-10-29 16:04:41 +000030import android.permission.PermissionManager.SplitPermissionInfo;
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -080031import android.text.TextUtils;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070032import android.util.ArrayMap;
33import android.util.ArraySet;
34import android.util.Slog;
35import android.util.SparseArray;
36import android.util.Xml;
Jeff Sharkey1c4ae802014-12-19 11:08:55 -080037
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070038import com.android.internal.util.XmlUtils;
Jeff Sharkey1c4ae802014-12-19 11:08:55 -080039
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -070040import libcore.io.IoUtils;
41
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070042import org.xmlpull.v1.XmlPullParser;
43import org.xmlpull.v1.XmlPullParserException;
44
45import java.io.File;
46import java.io.FileNotFoundException;
47import java.io.FileReader;
48import java.io.IOException;
Jeff Davidson24b9d962016-07-21 12:35:10 -070049import java.util.ArrayList;
Svet Ganov087dce22017-09-07 15:42:16 -070050import java.util.Collections;
Jeff Davidson24b9d962016-07-21 12:35:10 -070051import java.util.List;
Svet Ganov087dce22017-09-07 15:42:16 -070052import java.util.Map;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070053
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070054/**
55 * Loads global system configuration info.
56 */
57public class SystemConfig {
58 static final String TAG = "SystemConfig";
59
60 static SystemConfig sInstance;
61
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +080062 // permission flag, determines which types of configuration are allowed to be read
63 private static final int ALLOW_FEATURES = 0x01;
64 private static final int ALLOW_LIBS = 0x02;
65 private static final int ALLOW_PERMISSIONS = 0x04;
66 private static final int ALLOW_APP_CONFIGS = 0x08;
Jaekyun Seoke3b6bf12017-02-16 13:48:30 +090067 private static final int ALLOW_PRIVAPP_PERMISSIONS = 0x10;
Svet Ganov087dce22017-09-07 15:42:16 -070068 private static final int ALLOW_OEM_PERMISSIONS = 0x20;
Mathew Inwood4693a752018-02-20 16:04:25 +000069 private static final int ALLOW_HIDDENAPI_WHITELISTING = 0x40;
Dianne Hackborn769b2e72018-12-05 08:51:20 -080070 private static final int ALLOW_ASSOCIATIONS = 0x80;
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +080071 private static final int ALLOW_ALL = ~0;
72
Steven Morelandd7827fd2018-12-03 10:27:01 -080073 // property for runtime configuration differentiation
74 private static final String SKU_PROPERTY = "ro.boot.product.hardware.sku";
75
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070076 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
77 int[] mGlobalGids;
78
79 // These are the built-in uid -> permission mappings that were read from the
80 // system configuration files.
Jeff Sharkey9f837a92014-10-24 12:07:24 -070081 final SparseArray<ArraySet<String>> mSystemPermissions = new SparseArray<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070082
Zimuzocc2932f2018-10-29 16:04:41 +000083 final ArrayList<SplitPermissionInfo> mSplitPermissions = new ArrayList<>();
84
Ben Lin71c16d72018-12-06 18:34:51 -080085 public static final class SharedLibraryEntry {
86 public final String name;
87 public final String filename;
88 public final String[] dependencies;
89
90 SharedLibraryEntry(String name, String filename, String[] dependencies) {
91 this.name = name;
92 this.filename = filename;
93 this.dependencies = dependencies;
94 }
95 }
96
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070097 // These are the built-in shared libraries that were read from the
Ben Lin71c16d72018-12-06 18:34:51 -080098 // system configuration files. Keys are the library names; values are
99 // the individual entries that contain information such as filename
100 // and dependencies.
101 final ArrayMap<String, SharedLibraryEntry> mSharedLibraries = new ArrayMap<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700102
103 // These are the features this devices supports that were read from the
104 // system configuration files.
Jeff Sharkey9f837a92014-10-24 12:07:24 -0700105 final ArrayMap<String, FeatureInfo> mAvailableFeatures = new ArrayMap<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700106
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800107 // These are the features which this device doesn't support; the OEM
108 // partition uses these to opt-out of features from the system image.
109 final ArraySet<String> mUnavailableFeatures = new ArraySet<>();
110
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700111 public static final class PermissionEntry {
112 public final String name;
113 public int[] gids;
Jeff Sharkey00f39042015-03-23 16:51:22 -0700114 public boolean perUser;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700115
Jeff Sharkey00f39042015-03-23 16:51:22 -0700116 PermissionEntry(String name, boolean perUser) {
117 this.name = name;
118 this.perUser = perUser;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700119 }
120 }
121
122 // These are the permission -> gid mappings that were read from the
123 // system configuration files.
Dianne Hackbornbb8aa5a2014-09-17 13:20:38 -0700124 final ArrayMap<String, PermissionEntry> mPermissions = new ArrayMap<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700125
126 // These are the packages that are white-listed to be able to run in the
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700127 // background while in power save mode (but not whitelisted from device idle modes),
128 // as read from the configuration files.
129 final ArraySet<String> mAllowInPowerSaveExceptIdle = new ArraySet<>();
130
131 // These are the packages that are white-listed to be able to run in the
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700132 // background while in power save mode, as read from the configuration files.
Dianne Hackbornbb8aa5a2014-09-17 13:20:38 -0700133 final ArraySet<String> mAllowInPowerSave = new ArraySet<>();
134
Felipe Lemea9505cc2016-02-26 10:28:41 -0800135 // These are the packages that are white-listed to be able to run in the
136 // background while in data-usage save mode, as read from the configuration files.
137 final ArraySet<String> mAllowInDataUsageSave = new ArraySet<>();
138
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800139 // These are the packages that are white-listed to be able to run background location
140 // without throttling, as read from the configuration files.
141 final ArraySet<String> mAllowUnthrottledLocation = new ArraySet<>();
142
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800143 // These are the packages that are white-listed to be able to retrieve location even when user
144 // location settings are off, for emergency purposes, as read from the configuration files.
145 final ArraySet<String> mAllowIgnoreLocationSettings = new ArraySet<>();
146
Christopher Tate42a386b2016-11-07 12:21:21 -0800147 // These are the action strings of broadcasts which are whitelisted to
148 // be delivered anonymously even to apps which target O+.
149 final ArraySet<String> mAllowImplicitBroadcasts = new ArraySet<>();
150
Christopher Tate01e18642015-07-07 18:10:38 -0700151 // These are the package names of apps which should be in the 'always'
152 // URL-handling state upon factory reset.
153 final ArraySet<String> mLinkedApps = new ArraySet<>();
154
Fyodor Kupolov7db5af12015-07-31 16:50:27 -0700155 // These are the packages that are whitelisted to be able to run as system user
156 final ArraySet<String> mSystemUserWhitelistedApps = new ArraySet<>();
157
158 // These are the packages that should not run under system user
159 final ArraySet<String> mSystemUserBlacklistedApps = new ArraySet<>();
160
Ruben Brunk98576cf2016-03-07 18:54:28 -0800161 // These are the components that are enabled by default as VR mode listener services.
162 final ArraySet<ComponentName> mDefaultVrComponents = new ArraySet<>();
163
Christopher Tate494df792016-05-10 17:05:38 -0700164 // These are the permitted backup transport service components
165 final ArraySet<ComponentName> mBackupTransportWhitelist = new ArraySet<>();
166
Mathew Inwood4693a752018-02-20 16:04:25 +0000167 // Package names that are exempted from private API blacklisting
168 final ArraySet<String> mHiddenApiPackageWhitelist = new ArraySet<>();
169
goneileb31cd42018-02-28 15:22:08 -0800170 // The list of carrier applications which should be disabled until used.
171 // This function suppresses update notifications for these pre-installed apps.
172 // In SubscriptionInfoUpdater, the listed applications are disabled until used when all of the
173 // following conditions are met.
174 // 1. Not currently carrier-privileged according to the inserted SIM
175 // 2. Pre-installed
176 // 3. In the default state (enabled but not explicitly)
177 // And SubscriptionInfoUpdater undoes this and marks the app enabled when a SIM is inserted
178 // that marks the app as carrier privileged. It also grants the app default permissions
179 // for Phone and Location. As such, apps MUST only ever be added to this list if they
180 // obtain user consent to access their location through other means.
181 final ArraySet<String> mDisabledUntilUsedPreinstalledCarrierApps = new ArraySet<>();
182
Jeff Davidson24b9d962016-07-21 12:35:10 -0700183 // These are the packages of carrier-associated apps which should be disabled until used until
184 // a SIM is inserted which grants carrier privileges to that carrier app.
185 final ArrayMap<String, List<String>> mDisabledUntilUsedPreinstalledCarrierAssociatedApps =
186 new ArrayMap<>();
187
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800188 final ArrayMap<String, ArraySet<String>> mPrivAppPermissions = new ArrayMap<>();
Todd Kennedy74629e32017-08-15 14:48:07 -0700189 final ArrayMap<String, ArraySet<String>> mPrivAppDenyPermissions = new ArrayMap<>();
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800190
Jiyong Park002fdbd2017-02-13 20:50:31 +0900191 final ArrayMap<String, ArraySet<String>> mVendorPrivAppPermissions = new ArrayMap<>();
192 final ArrayMap<String, ArraySet<String>> mVendorPrivAppDenyPermissions = new ArrayMap<>();
193
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900194 final ArrayMap<String, ArraySet<String>> mProductPrivAppPermissions = new ArrayMap<>();
195 final ArrayMap<String, ArraySet<String>> mProductPrivAppDenyPermissions = new ArrayMap<>();
196
Dario Freni2bef1762018-06-01 14:02:08 +0100197 final ArrayMap<String, ArraySet<String>> mProductServicesPrivAppPermissions = new ArrayMap<>();
198 final ArrayMap<String, ArraySet<String>> mProductServicesPrivAppDenyPermissions =
199 new ArrayMap<>();
200
Svet Ganov087dce22017-09-07 15:42:16 -0700201 final ArrayMap<String, ArrayMap<String, Boolean>> mOemPermissions = new ArrayMap<>();
202
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800203 // Allowed associations between applications. If there are any entries
204 // for an app, those are the only associations allowed; otherwise, all associations
205 // are allowed. Allowing an association from app A to app B means app A can not
206 // associate with any other apps, but does not limit what apps B can associate with.
207 final ArrayMap<String, ArraySet<String>> mAllowedAssociations = new ArrayMap<>();
208
Nikita Ioffe07964b42019-02-28 21:35:02 +0000209 private final ArraySet<String> mBugreportWhitelistedPackages = new ArraySet<>();
210
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700211 public static SystemConfig getInstance() {
212 synchronized (SystemConfig.class) {
213 if (sInstance == null) {
214 sInstance = new SystemConfig();
215 }
216 return sInstance;
217 }
218 }
219
220 public int[] getGlobalGids() {
221 return mGlobalGids;
222 }
223
Jeff Sharkey9f837a92014-10-24 12:07:24 -0700224 public SparseArray<ArraySet<String>> getSystemPermissions() {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700225 return mSystemPermissions;
226 }
227
Zimuzocc2932f2018-10-29 16:04:41 +0000228 public ArrayList<SplitPermissionInfo> getSplitPermissions() {
229 return mSplitPermissions;
230 }
231
Ben Lin71c16d72018-12-06 18:34:51 -0800232 public ArrayMap<String, SharedLibraryEntry> getSharedLibraries() {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700233 return mSharedLibraries;
234 }
235
Jeff Sharkey9f837a92014-10-24 12:07:24 -0700236 public ArrayMap<String, FeatureInfo> getAvailableFeatures() {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700237 return mAvailableFeatures;
238 }
239
240 public ArrayMap<String, PermissionEntry> getPermissions() {
241 return mPermissions;
242 }
243
Christopher Tate42a386b2016-11-07 12:21:21 -0800244 public ArraySet<String> getAllowImplicitBroadcasts() {
245 return mAllowImplicitBroadcasts;
246 }
247
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700248 public ArraySet<String> getAllowInPowerSaveExceptIdle() {
249 return mAllowInPowerSaveExceptIdle;
250 }
251
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700252 public ArraySet<String> getAllowInPowerSave() {
253 return mAllowInPowerSave;
254 }
255
Felipe Lemea9505cc2016-02-26 10:28:41 -0800256 public ArraySet<String> getAllowInDataUsageSave() {
257 return mAllowInDataUsageSave;
258 }
259
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800260 public ArraySet<String> getAllowUnthrottledLocation() {
261 return mAllowUnthrottledLocation;
262 }
263
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800264 public ArraySet<String> getAllowIgnoreLocationSettings() {
265 return mAllowIgnoreLocationSettings;
266 }
267
Christopher Tate01e18642015-07-07 18:10:38 -0700268 public ArraySet<String> getLinkedApps() {
269 return mLinkedApps;
270 }
271
Fyodor Kupolov7db5af12015-07-31 16:50:27 -0700272 public ArraySet<String> getSystemUserWhitelistedApps() {
273 return mSystemUserWhitelistedApps;
274 }
275
276 public ArraySet<String> getSystemUserBlacklistedApps() {
277 return mSystemUserBlacklistedApps;
278 }
279
Mathew Inwood4693a752018-02-20 16:04:25 +0000280 public ArraySet<String> getHiddenApiWhitelistedApps() {
281 return mHiddenApiPackageWhitelist;
282 }
283
Ruben Brunk98576cf2016-03-07 18:54:28 -0800284 public ArraySet<ComponentName> getDefaultVrComponents() {
285 return mDefaultVrComponents;
286 }
287
Christopher Tate494df792016-05-10 17:05:38 -0700288 public ArraySet<ComponentName> getBackupTransportWhitelist() {
289 return mBackupTransportWhitelist;
290 }
291
goneileb31cd42018-02-28 15:22:08 -0800292 public ArraySet<String> getDisabledUntilUsedPreinstalledCarrierApps() {
293 return mDisabledUntilUsedPreinstalledCarrierApps;
294 }
295
Jeff Davidson24b9d962016-07-21 12:35:10 -0700296 public ArrayMap<String, List<String>> getDisabledUntilUsedPreinstalledCarrierAssociatedApps() {
297 return mDisabledUntilUsedPreinstalledCarrierAssociatedApps;
298 }
299
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800300 public ArraySet<String> getPrivAppPermissions(String packageName) {
301 return mPrivAppPermissions.get(packageName);
302 }
303
Todd Kennedy74629e32017-08-15 14:48:07 -0700304 public ArraySet<String> getPrivAppDenyPermissions(String packageName) {
305 return mPrivAppDenyPermissions.get(packageName);
306 }
307
Jiyong Park002fdbd2017-02-13 20:50:31 +0900308 public ArraySet<String> getVendorPrivAppPermissions(String packageName) {
309 return mVendorPrivAppPermissions.get(packageName);
310 }
311
312 public ArraySet<String> getVendorPrivAppDenyPermissions(String packageName) {
313 return mVendorPrivAppDenyPermissions.get(packageName);
314 }
315
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900316 public ArraySet<String> getProductPrivAppPermissions(String packageName) {
317 return mProductPrivAppPermissions.get(packageName);
318 }
319
320 public ArraySet<String> getProductPrivAppDenyPermissions(String packageName) {
321 return mProductPrivAppDenyPermissions.get(packageName);
322 }
323
Dario Freni2bef1762018-06-01 14:02:08 +0100324 public ArraySet<String> getProductServicesPrivAppPermissions(String packageName) {
325 return mProductServicesPrivAppPermissions.get(packageName);
326 }
327
328 public ArraySet<String> getProductServicesPrivAppDenyPermissions(String packageName) {
329 return mProductServicesPrivAppDenyPermissions.get(packageName);
330 }
331
Svet Ganov087dce22017-09-07 15:42:16 -0700332 public Map<String, Boolean> getOemPermissions(String packageName) {
333 final Map<String, Boolean> oemPermissions = mOemPermissions.get(packageName);
334 if (oemPermissions != null) {
335 return oemPermissions;
336 }
337 return Collections.emptyMap();
338 }
339
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800340 public ArrayMap<String, ArraySet<String>> getAllowedAssociations() {
341 return mAllowedAssociations;
342 }
343
Nikita Ioffe07964b42019-02-28 21:35:02 +0000344 public ArraySet<String> getBugreportWhitelistedPackages() {
345 return mBugreportWhitelistedPackages;
346 }
347
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700348 SystemConfig() {
349 // Read configuration from system
350 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800351 Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL);
Svet Ganov087dce22017-09-07 15:42:16 -0700352
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700353 // Read configuration from the old permissions dir
354 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800355 Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);
Svet Ganov087dce22017-09-07 15:42:16 -0700356
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800357 // Vendors are only allowed to customize these
358 int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS
359 | ALLOW_ASSOCIATIONS;
Jiyong Parkfad99442018-03-12 10:39:07 +0900360 if (Build.VERSION.FIRST_SDK_INT <= Build.VERSION_CODES.O_MR1) {
361 // For backward compatibility
362 vendorPermissionFlag |= (ALLOW_PERMISSIONS | ALLOW_APP_CONFIGS);
363 }
Jaekyun Seoke3b6bf12017-02-16 13:48:30 +0900364 readPermissions(Environment.buildPath(
365 Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
366 readPermissions(Environment.buildPath(
367 Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag);
Svet Ganov087dce22017-09-07 15:42:16 -0700368
Jiyong Park090c6b12017-12-28 12:03:28 +0900369 // Allow ODM to customize system configs as much as Vendor, because /odm is another
370 // vendor partition other than /vendor.
371 int odmPermissionFlag = vendorPermissionFlag;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700372 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800373 Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700374 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800375 Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);
Svet Ganov087dce22017-09-07 15:42:16 -0700376
Steven Morelandd7827fd2018-12-03 10:27:01 -0800377 String skuProperty = SystemProperties.get(SKU_PROPERTY, "");
378 if (!skuProperty.isEmpty()) {
379 String skuDir = "sku_" + skuProperty;
380
381 readPermissions(Environment.buildPath(
382 Environment.getOdmDirectory(), "etc", "sysconfig", skuDir), odmPermissionFlag);
383 readPermissions(Environment.buildPath(
384 Environment.getOdmDirectory(), "etc", "permissions", skuDir),
385 odmPermissionFlag);
386 }
387
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800388 // Allow OEM to customize these
389 int oemPermissionFlag = ALLOW_FEATURES | ALLOW_OEM_PERMISSIONS | ALLOW_ASSOCIATIONS;
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800390 readPermissions(Environment.buildPath(
Svet Ganov087dce22017-09-07 15:42:16 -0700391 Environment.getOemDirectory(), "etc", "sysconfig"), oemPermissionFlag);
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800392 readPermissions(Environment.buildPath(
Svet Ganov087dce22017-09-07 15:42:16 -0700393 Environment.getOemDirectory(), "etc", "permissions"), oemPermissionFlag);
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900394
Hung-ying Tyan38cd31c2018-09-26 15:05:07 +0800395 // Allow Product to customize all system configs
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900396 readPermissions(Environment.buildPath(
Hung-ying Tyan38cd31c2018-09-26 15:05:07 +0800397 Environment.getProductDirectory(), "etc", "sysconfig"), ALLOW_ALL);
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900398 readPermissions(Environment.buildPath(
Hung-ying Tyan38cd31c2018-09-26 15:05:07 +0800399 Environment.getProductDirectory(), "etc", "permissions"), ALLOW_ALL);
Dario Freni2bef1762018-06-01 14:02:08 +0100400
Hung-ying Tyan01ab8772018-09-27 15:22:07 +0800401 // Allow /product_services to customize all system configs
Dario Freni2bef1762018-06-01 14:02:08 +0100402 readPermissions(Environment.buildPath(
Hung-ying Tyan01ab8772018-09-27 15:22:07 +0800403 Environment.getProductServicesDirectory(), "etc", "sysconfig"), ALLOW_ALL);
Dario Freni2bef1762018-06-01 14:02:08 +0100404 readPermissions(Environment.buildPath(
Hung-ying Tyan01ab8772018-09-27 15:22:07 +0800405 Environment.getProductServicesDirectory(), "etc", "permissions"), ALLOW_ALL);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700406 }
407
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800408 void readPermissions(File libraryDir, int permissionFlag) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700409 // Read permissions from given directory.
410 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800411 if (permissionFlag == ALLOW_ALL) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700412 Slog.w(TAG, "No directory " + libraryDir + ", skipping");
413 }
414 return;
415 }
416 if (!libraryDir.canRead()) {
417 Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
418 return;
419 }
420
421 // Iterate over the files in the directory and scan .xml files
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800422 File platformFile = null;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700423 for (File f : libraryDir.listFiles()) {
Steven Morelandd7827fd2018-12-03 10:27:01 -0800424 if (!f.isFile()) {
425 continue;
426 }
427
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700428 // We'll read platform.xml last
429 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800430 platformFile = f;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700431 continue;
432 }
433
434 if (!f.getPath().endsWith(".xml")) {
435 Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
436 continue;
437 }
438 if (!f.canRead()) {
439 Slog.w(TAG, "Permissions library file " + f + " cannot be read");
440 continue;
441 }
442
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800443 readPermissionsFromXml(f, permissionFlag);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700444 }
445
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800446 // Read platform permissions last so it will take precedence
447 if (platformFile != null) {
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800448 readPermissionsFromXml(platformFile, permissionFlag);
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800449 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700450 }
451
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800452 private void logNotAllowedInPartition(String name, File permFile, XmlPullParser parser) {
453 Slog.w(TAG, "<" + name + "> not allowed in partition of "
454 + permFile + " at " + parser.getPositionDescription());
455 }
456
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800457 private void readPermissionsFromXml(File permFile, int permissionFlag) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700458 FileReader permReader = null;
459 try {
460 permReader = new FileReader(permFile);
461 } catch (FileNotFoundException e) {
462 Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
463 return;
464 }
465
Dianne Hackbornc0e4aaa2014-11-14 10:55:50 -0800466 final boolean lowRam = ActivityManager.isLowRamDeviceStatic();
467
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700468 try {
469 XmlPullParser parser = Xml.newPullParser();
470 parser.setInput(permReader);
471
472 int type;
473 while ((type=parser.next()) != parser.START_TAG
474 && type != parser.END_DOCUMENT) {
475 ;
476 }
477
478 if (type != parser.START_TAG) {
479 throw new XmlPullParserException("No start tag found");
480 }
481
482 if (!parser.getName().equals("permissions") && !parser.getName().equals("config")) {
Dianne Hackbornb3d4cb32015-01-09 09:54:06 -0800483 throw new XmlPullParserException("Unexpected start tag in " + permFile
484 + ": found " + parser.getName() + ", expected 'permissions' or 'config'");
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700485 }
486
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800487 final boolean allowAll = permissionFlag == ALLOW_ALL;
488 final boolean allowLibs = (permissionFlag & ALLOW_LIBS) != 0;
489 final boolean allowFeatures = (permissionFlag & ALLOW_FEATURES) != 0;
490 final boolean allowPermissions = (permissionFlag & ALLOW_PERMISSIONS) != 0;
491 final boolean allowAppConfigs = (permissionFlag & ALLOW_APP_CONFIGS) != 0;
492 final boolean allowPrivappPermissions = (permissionFlag & ALLOW_PRIVAPP_PERMISSIONS)
493 != 0;
494 final boolean allowOemPermissions = (permissionFlag & ALLOW_OEM_PERMISSIONS) != 0;
495 final boolean allowApiWhitelisting = (permissionFlag & ALLOW_HIDDENAPI_WHITELISTING)
496 != 0;
497 final boolean allowAssociations = (permissionFlag & ALLOW_ASSOCIATIONS) != 0;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700498 while (true) {
499 XmlUtils.nextElement(parser);
500 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
501 break;
502 }
503
504 String name = parser.getName();
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800505 if (name == null) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700506 XmlUtils.skipCurrentTag(parser);
507 continue;
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800508 }
509 switch (name) {
510 case "group": {
511 if (allowAll) {
512 String gidStr = parser.getAttributeValue(null, "gid");
513 if (gidStr != null) {
514 int gid = android.os.Process.getGidForName(gidStr);
515 mGlobalGids = appendInt(mGlobalGids, gid);
516 } else {
517 Slog.w(TAG, "<" + name + "> without gid in " + permFile + " at "
goneileb31cd42018-02-28 15:22:08 -0800518 + parser.getPositionDescription());
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800519 }
520 } else {
521 logNotAllowedInPartition(name, permFile, parser);
522 }
523 XmlUtils.skipCurrentTag(parser);
524 } break;
525 case "permission": {
526 if (allowPermissions) {
527 String perm = parser.getAttributeValue(null, "name");
528 if (perm == null) {
529 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
530 + parser.getPositionDescription());
531 XmlUtils.skipCurrentTag(parser);
532 break;
533 }
534 perm = perm.intern();
535 readPermission(parser, perm);
536 } else {
537 logNotAllowedInPartition(name, permFile, parser);
538 XmlUtils.skipCurrentTag(parser);
539 }
540 } break;
541 case "assign-permission": {
542 if (allowPermissions) {
543 String perm = parser.getAttributeValue(null, "name");
544 if (perm == null) {
545 Slog.w(TAG, "<" + name + "> without name in " + permFile
546 + " at " + parser.getPositionDescription());
547 XmlUtils.skipCurrentTag(parser);
548 break;
549 }
550 String uidStr = parser.getAttributeValue(null, "uid");
551 if (uidStr == null) {
552 Slog.w(TAG, "<" + name + "> without uid in " + permFile
553 + " at " + parser.getPositionDescription());
554 XmlUtils.skipCurrentTag(parser);
555 break;
556 }
557 int uid = Process.getUidForName(uidStr);
558 if (uid < 0) {
559 Slog.w(TAG, "<" + name + "> with unknown uid \""
560 + uidStr + " in " + permFile + " at "
561 + parser.getPositionDescription());
562 XmlUtils.skipCurrentTag(parser);
563 break;
564 }
565 perm = perm.intern();
566 ArraySet<String> perms = mSystemPermissions.get(uid);
567 if (perms == null) {
568 perms = new ArraySet<String>();
569 mSystemPermissions.put(uid, perms);
570 }
571 perms.add(perm);
572 } else {
573 logNotAllowedInPartition(name, permFile, parser);
574 }
575 XmlUtils.skipCurrentTag(parser);
576 } break;
577 case "split-permission": {
578 if (allowPermissions) {
579 readSplitPermission(parser, permFile);
580 } else {
581 logNotAllowedInPartition(name, permFile, parser);
582 XmlUtils.skipCurrentTag(parser);
583 }
584 } break;
585 case "library": {
586 if (allowLibs) {
587 String lname = parser.getAttributeValue(null, "name");
588 String lfile = parser.getAttributeValue(null, "file");
589 String ldependency = parser.getAttributeValue(null, "dependency");
590 if (lname == null) {
591 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
592 + parser.getPositionDescription());
593 } else if (lfile == null) {
594 Slog.w(TAG, "<" + name + "> without file in " + permFile + " at "
595 + parser.getPositionDescription());
596 } else {
597 //Log.i(TAG, "Got library " + lname + " in " + lfile);
598 SharedLibraryEntry entry = new SharedLibraryEntry(lname, lfile,
599 ldependency == null ? new String[0] : ldependency.split(":"));
600 mSharedLibraries.put(lname, entry);
601 }
602 } else {
603 logNotAllowedInPartition(name, permFile, parser);
604 }
605 XmlUtils.skipCurrentTag(parser);
606 } break;
607 case "feature": {
608 if (allowFeatures) {
609 String fname = parser.getAttributeValue(null, "name");
610 int fversion = XmlUtils.readIntAttribute(parser, "version", 0);
611 boolean allowed;
612 if (!lowRam) {
613 allowed = true;
614 } else {
615 String notLowRam = parser.getAttributeValue(null, "notLowRam");
616 allowed = !"true".equals(notLowRam);
617 }
618 if (fname == null) {
619 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
620 + parser.getPositionDescription());
621 } else if (allowed) {
622 addFeature(fname, fversion);
623 }
624 } else {
625 logNotAllowedInPartition(name, permFile, parser);
626 }
627 XmlUtils.skipCurrentTag(parser);
628 } break;
629 case "unavailable-feature": {
630 if (allowFeatures) {
631 String fname = parser.getAttributeValue(null, "name");
632 if (fname == null) {
633 Slog.w(TAG, "<" + name + "> without name in " + permFile
634 + " at " + parser.getPositionDescription());
635 } else {
636 mUnavailableFeatures.add(fname);
637 }
638 } else {
639 logNotAllowedInPartition(name, permFile, parser);
640 }
641 XmlUtils.skipCurrentTag(parser);
642 } break;
643 case "allow-in-power-save-except-idle": {
644 if (allowAll) {
645 String pkgname = parser.getAttributeValue(null, "package");
646 if (pkgname == null) {
647 Slog.w(TAG, "<" + name + "> without package in "
648 + permFile + " at " + parser.getPositionDescription());
649 } else {
650 mAllowInPowerSaveExceptIdle.add(pkgname);
651 }
652 } else {
653 logNotAllowedInPartition(name, permFile, parser);
654 }
655 XmlUtils.skipCurrentTag(parser);
656 } break;
657 case "allow-in-power-save": {
658 if (allowAll) {
659 String pkgname = parser.getAttributeValue(null, "package");
660 if (pkgname == null) {
661 Slog.w(TAG, "<" + name + "> without package in "
662 + permFile + " at " + parser.getPositionDescription());
663 } else {
664 mAllowInPowerSave.add(pkgname);
665 }
666 } else {
667 logNotAllowedInPartition(name, permFile, parser);
668 }
669 XmlUtils.skipCurrentTag(parser);
670 } break;
671 case "allow-in-data-usage-save": {
672 if (allowAll) {
673 String pkgname = parser.getAttributeValue(null, "package");
674 if (pkgname == null) {
675 Slog.w(TAG, "<" + name + "> without package in "
676 + permFile + " at " + parser.getPositionDescription());
677 } else {
678 mAllowInDataUsageSave.add(pkgname);
679 }
680 } else {
681 logNotAllowedInPartition(name, permFile, parser);
682 }
683 XmlUtils.skipCurrentTag(parser);
684 } break;
685 case "allow-unthrottled-location": {
686 if (allowAll) {
687 String pkgname = parser.getAttributeValue(null, "package");
688 if (pkgname == null) {
689 Slog.w(TAG, "<" + name + "> without package in "
690 + permFile + " at " + parser.getPositionDescription());
691 } else {
692 mAllowUnthrottledLocation.add(pkgname);
693 }
694 } else {
695 logNotAllowedInPartition(name, permFile, parser);
696 }
697 XmlUtils.skipCurrentTag(parser);
698 } break;
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800699 case "allow-ignore-location-settings": {
700 if (allowAll) {
701 String pkgname = parser.getAttributeValue(null, "package");
702 if (pkgname == null) {
703 Slog.w(TAG, "<" + name + "> without package in "
704 + permFile + " at " + parser.getPositionDescription());
705 } else {
706 mAllowIgnoreLocationSettings.add(pkgname);
707 }
708 } else {
709 logNotAllowedInPartition(name, permFile, parser);
710 }
711 XmlUtils.skipCurrentTag(parser);
712 } break;
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800713 case "allow-implicit-broadcast": {
714 if (allowAll) {
715 String action = parser.getAttributeValue(null, "action");
716 if (action == null) {
717 Slog.w(TAG, "<" + name + "> without action in "
718 + permFile + " at " + parser.getPositionDescription());
719 } else {
720 mAllowImplicitBroadcasts.add(action);
721 }
722 } else {
723 logNotAllowedInPartition(name, permFile, parser);
724 }
725 XmlUtils.skipCurrentTag(parser);
726 } break;
727 case "app-link": {
728 if (allowAppConfigs) {
729 String pkgname = parser.getAttributeValue(null, "package");
730 if (pkgname == null) {
731 Slog.w(TAG, "<" + name + "> without package in " + permFile
732 + " at " + parser.getPositionDescription());
733 } else {
734 mLinkedApps.add(pkgname);
735 }
736 } else {
737 logNotAllowedInPartition(name, permFile, parser);
738 }
739 XmlUtils.skipCurrentTag(parser);
740 } break;
741 case "system-user-whitelisted-app": {
742 if (allowAppConfigs) {
743 String pkgname = parser.getAttributeValue(null, "package");
744 if (pkgname == null) {
745 Slog.w(TAG, "<" + name + "> without package in "
746 + permFile + " at " + parser.getPositionDescription());
747 } else {
748 mSystemUserWhitelistedApps.add(pkgname);
749 }
750 } else {
751 logNotAllowedInPartition(name, permFile, parser);
752 }
753 XmlUtils.skipCurrentTag(parser);
754 } break;
755 case "system-user-blacklisted-app": {
756 if (allowAppConfigs) {
757 String pkgname = parser.getAttributeValue(null, "package");
758 if (pkgname == null) {
759 Slog.w(TAG, "<" + name + "> without package in "
760 + permFile + " at " + parser.getPositionDescription());
761 } else {
762 mSystemUserBlacklistedApps.add(pkgname);
763 }
764 } else {
765 logNotAllowedInPartition(name, permFile, parser);
766 }
767 XmlUtils.skipCurrentTag(parser);
768 } break;
769 case "default-enabled-vr-app": {
770 if (allowAppConfigs) {
771 String pkgname = parser.getAttributeValue(null, "package");
772 String clsname = parser.getAttributeValue(null, "class");
773 if (pkgname == null) {
774 Slog.w(TAG, "<" + name + "> without package in "
775 + permFile + " at " + parser.getPositionDescription());
776 } else if (clsname == null) {
777 Slog.w(TAG, "<" + name + "> without class in "
778 + permFile + " at " + parser.getPositionDescription());
779 } else {
780 mDefaultVrComponents.add(new ComponentName(pkgname, clsname));
781 }
782 } else {
783 logNotAllowedInPartition(name, permFile, parser);
784 }
785 XmlUtils.skipCurrentTag(parser);
786 } break;
787 case "backup-transport-whitelisted-service": {
788 if (allowFeatures) {
789 String serviceName = parser.getAttributeValue(null, "service");
790 if (serviceName == null) {
791 Slog.w(TAG, "<" + name + "> without service in "
792 + permFile + " at " + parser.getPositionDescription());
793 } else {
794 ComponentName cn = ComponentName.unflattenFromString(serviceName);
795 if (cn == null) {
796 Slog.w(TAG, "<" + name + "> with invalid service name "
797 + serviceName + " in " + permFile
798 + " at " + parser.getPositionDescription());
799 } else {
800 mBackupTransportWhitelist.add(cn);
801 }
802 }
803 } else {
804 logNotAllowedInPartition(name, permFile, parser);
805 }
806 XmlUtils.skipCurrentTag(parser);
807 } break;
808 case "disabled-until-used-preinstalled-carrier-associated-app": {
809 if (allowAppConfigs) {
810 String pkgname = parser.getAttributeValue(null, "package");
811 String carrierPkgname = parser.getAttributeValue(null,
812 "carrierAppPackage");
813 if (pkgname == null || carrierPkgname == null) {
814 Slog.w(TAG, "<" + name
815 + "> without package or carrierAppPackage in " + permFile
816 + " at " + parser.getPositionDescription());
817 } else {
818 List<String> associatedPkgs =
819 mDisabledUntilUsedPreinstalledCarrierAssociatedApps.get(
820 carrierPkgname);
821 if (associatedPkgs == null) {
822 associatedPkgs = new ArrayList<>();
823 mDisabledUntilUsedPreinstalledCarrierAssociatedApps.put(
824 carrierPkgname, associatedPkgs);
825 }
826 associatedPkgs.add(pkgname);
827 }
828 } else {
829 logNotAllowedInPartition(name, permFile, parser);
830 }
831 XmlUtils.skipCurrentTag(parser);
832 } break;
833 case "disabled-until-used-preinstalled-carrier-app": {
834 if (allowAppConfigs) {
835 String pkgname = parser.getAttributeValue(null, "package");
836 if (pkgname == null) {
837 Slog.w(TAG,
838 "<" + name + "> without "
839 + "package in " + permFile + " at "
840 + parser.getPositionDescription());
841 } else {
842 mDisabledUntilUsedPreinstalledCarrierApps.add(pkgname);
843 }
844 } else {
845 logNotAllowedInPartition(name, permFile, parser);
846 }
847 XmlUtils.skipCurrentTag(parser);
848 } break;
849 case "privapp-permissions": {
850 if (allowPrivappPermissions) {
851 // privapp permissions from system, vendor, product and product_services
852 // partitions are stored separately. This is to prevent xml files in
853 // the vendor partition from granting permissions to priv apps in the
854 // system partition and vice versa.
855 boolean vendor = permFile.toPath().startsWith(
856 Environment.getVendorDirectory().toPath() + "/")
857 || permFile.toPath().startsWith(
858 Environment.getOdmDirectory().toPath() + "/");
859 boolean product = permFile.toPath().startsWith(
860 Environment.getProductDirectory().toPath() + "/");
861 boolean productServices = permFile.toPath().startsWith(
862 Environment.getProductServicesDirectory().toPath() + "/");
863 if (vendor) {
864 readPrivAppPermissions(parser, mVendorPrivAppPermissions,
865 mVendorPrivAppDenyPermissions);
866 } else if (product) {
867 readPrivAppPermissions(parser, mProductPrivAppPermissions,
868 mProductPrivAppDenyPermissions);
869 } else if (productServices) {
870 readPrivAppPermissions(parser, mProductServicesPrivAppPermissions,
871 mProductServicesPrivAppDenyPermissions);
872 } else {
873 readPrivAppPermissions(parser, mPrivAppPermissions,
874 mPrivAppDenyPermissions);
875 }
876 } else {
877 logNotAllowedInPartition(name, permFile, parser);
878 XmlUtils.skipCurrentTag(parser);
879 }
880 } break;
881 case "oem-permissions": {
882 if (allowOemPermissions) {
883 readOemPermissions(parser);
884 } else {
885 logNotAllowedInPartition(name, permFile, parser);
886 XmlUtils.skipCurrentTag(parser);
887 }
888 } break;
889 case "hidden-api-whitelisted-app": {
890 if (allowApiWhitelisting) {
891 String pkgname = parser.getAttributeValue(null, "package");
892 if (pkgname == null) {
893 Slog.w(TAG, "<" + name + "> without package in "
894 + permFile + " at " + parser.getPositionDescription());
895 } else {
896 mHiddenApiPackageWhitelist.add(pkgname);
897 }
898 } else {
899 logNotAllowedInPartition(name, permFile, parser);
900 }
901 XmlUtils.skipCurrentTag(parser);
902 } break;
903 case "allow-association": {
904 if (allowAssociations) {
905 String target = parser.getAttributeValue(null, "target");
906 if (target == null) {
907 Slog.w(TAG, "<" + name + "> without target in " + permFile
908 + " at " + parser.getPositionDescription());
909 XmlUtils.skipCurrentTag(parser);
910 break;
911 }
912 String allowed = parser.getAttributeValue(null, "allowed");
913 if (allowed == null) {
914 Slog.w(TAG, "<" + name + "> without allowed in " + permFile
915 + " at " + parser.getPositionDescription());
916 XmlUtils.skipCurrentTag(parser);
917 break;
918 }
919 target = target.intern();
920 allowed = allowed.intern();
921 ArraySet<String> associations = mAllowedAssociations.get(target);
922 if (associations == null) {
923 associations = new ArraySet<>();
924 mAllowedAssociations.put(target, associations);
925 }
926 Slog.i(TAG, "Adding association: " + target + " <- " + allowed);
927 associations.add(allowed);
928 } else {
929 logNotAllowedInPartition(name, permFile, parser);
930 }
931 XmlUtils.skipCurrentTag(parser);
932 } break;
Nikita Ioffe07964b42019-02-28 21:35:02 +0000933 case "bugreport-whitelisted": {
934 String pkgname = parser.getAttributeValue(null, "package");
935 if (pkgname == null) {
936 Slog.w(TAG, "<" + name + "> without package in " + permFile
937 + " at " + parser.getPositionDescription());
938 } else {
939 mBugreportWhitelistedPackages.add(pkgname);
940 }
941 } break;
Dianne Hackborn769b2e72018-12-05 08:51:20 -0800942 default: {
943 Slog.w(TAG, "Tag " + name + " is unknown in "
944 + permFile + " at " + parser.getPositionDescription());
945 XmlUtils.skipCurrentTag(parser);
946 } break;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700947 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700948 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700949 } catch (XmlPullParserException e) {
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800950 Slog.w(TAG, "Got exception parsing permissions.", e);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700951 } catch (IOException e) {
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800952 Slog.w(TAG, "Got exception parsing permissions.", e);
953 } finally {
954 IoUtils.closeQuietly(permReader);
955 }
956
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -0700957 // Some devices can be field-converted to FBE, so offer to splice in
958 // those features if not already defined by the static config
Paul Lawrence20be5d62016-02-26 13:51:17 -0800959 if (StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700960 addFeature(PackageManager.FEATURE_FILE_BASED_ENCRYPTION, 0);
961 addFeature(PackageManager.FEATURE_SECURELY_REMOVES_USERS, 0);
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -0700962 }
963
Jeff Sharkey8eb783b2018-01-04 16:46:48 -0700964 // Help legacy devices that may not have updated their static config
965 if (StorageManager.hasAdoptable()) {
966 addFeature(PackageManager.FEATURE_ADOPTABLE_STORAGE, 0);
967 }
968
Dianne Hackborn2a103f12017-08-08 15:50:31 -0700969 if (ActivityManager.isLowRamDeviceStatic()) {
970 addFeature(PackageManager.FEATURE_RAM_LOW, 0);
971 } else {
972 addFeature(PackageManager.FEATURE_RAM_NORMAL, 0);
973 }
974
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -0700975 for (String featureName : mUnavailableFeatures) {
976 removeFeature(featureName);
977 }
978 }
979
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700980 private void addFeature(String name, int version) {
981 FeatureInfo fi = mAvailableFeatures.get(name);
982 if (fi == null) {
983 fi = new FeatureInfo();
984 fi.name = name;
985 fi.version = version;
986 mAvailableFeatures.put(name, fi);
987 } else {
988 fi.version = Math.max(fi.version, version);
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -0700989 }
990 }
991
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700992 private void removeFeature(String name) {
993 if (mAvailableFeatures.remove(name) != null) {
994 Slog.d(TAG, "Removed unavailable feature " + name);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700995 }
996 }
997
998 void readPermission(XmlPullParser parser, String name)
999 throws IOException, XmlPullParserException {
Jeff Sharkey00f39042015-03-23 16:51:22 -07001000 if (mPermissions.containsKey(name)) {
1001 throw new IllegalStateException("Duplicate permission definition for " + name);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001002 }
Jeff Sharkey00f39042015-03-23 16:51:22 -07001003
1004 final boolean perUser = XmlUtils.readBooleanAttribute(parser, "perUser", false);
1005 final PermissionEntry perm = new PermissionEntry(name, perUser);
1006 mPermissions.put(name, perm);
1007
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001008 int outerDepth = parser.getDepth();
1009 int type;
1010 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1011 && (type != XmlPullParser.END_TAG
1012 || parser.getDepth() > outerDepth)) {
1013 if (type == XmlPullParser.END_TAG
1014 || type == XmlPullParser.TEXT) {
1015 continue;
1016 }
1017
1018 String tagName = parser.getName();
1019 if ("group".equals(tagName)) {
1020 String gidStr = parser.getAttributeValue(null, "gid");
1021 if (gidStr != null) {
1022 int gid = Process.getGidForName(gidStr);
1023 perm.gids = appendInt(perm.gids, gid);
1024 } else {
1025 Slog.w(TAG, "<group> without gid at "
1026 + parser.getPositionDescription());
1027 }
1028 }
1029 XmlUtils.skipCurrentTag(parser);
1030 }
1031 }
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001032
Jiyong Park002fdbd2017-02-13 20:50:31 +09001033 private void readPrivAppPermissions(XmlPullParser parser,
1034 ArrayMap<String, ArraySet<String>> grantMap,
1035 ArrayMap<String, ArraySet<String>> denyMap)
1036 throws IOException, XmlPullParserException {
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001037 String packageName = parser.getAttributeValue(null, "package");
1038 if (TextUtils.isEmpty(packageName)) {
1039 Slog.w(TAG, "package is required for <privapp-permissions> in "
1040 + parser.getPositionDescription());
1041 return;
1042 }
1043
Jiyong Park002fdbd2017-02-13 20:50:31 +09001044 ArraySet<String> permissions = grantMap.get(packageName);
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001045 if (permissions == null) {
1046 permissions = new ArraySet<>();
1047 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09001048 ArraySet<String> denyPermissions = denyMap.get(packageName);
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001049 int depth = parser.getDepth();
1050 while (XmlUtils.nextElementWithin(parser, depth)) {
1051 String name = parser.getName();
1052 if ("permission".equals(name)) {
1053 String permName = parser.getAttributeValue(null, "name");
1054 if (TextUtils.isEmpty(permName)) {
1055 Slog.w(TAG, "name is required for <permission> in "
1056 + parser.getPositionDescription());
1057 continue;
1058 }
1059 permissions.add(permName);
Todd Kennedy74629e32017-08-15 14:48:07 -07001060 } else if ("deny-permission".equals(name)) {
1061 String permName = parser.getAttributeValue(null, "name");
1062 if (TextUtils.isEmpty(permName)) {
1063 Slog.w(TAG, "name is required for <deny-permission> in "
1064 + parser.getPositionDescription());
1065 continue;
1066 }
1067 if (denyPermissions == null) {
1068 denyPermissions = new ArraySet<>();
1069 }
1070 denyPermissions.add(permName);
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001071 }
1072 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09001073 grantMap.put(packageName, permissions);
Todd Kennedy74629e32017-08-15 14:48:07 -07001074 if (denyPermissions != null) {
Jiyong Park002fdbd2017-02-13 20:50:31 +09001075 denyMap.put(packageName, denyPermissions);
Todd Kennedy74629e32017-08-15 14:48:07 -07001076 }
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -08001077 }
Svet Ganov087dce22017-09-07 15:42:16 -07001078
1079 void readOemPermissions(XmlPullParser parser) throws IOException, XmlPullParserException {
1080 final String packageName = parser.getAttributeValue(null, "package");
1081 if (TextUtils.isEmpty(packageName)) {
1082 Slog.w(TAG, "package is required for <oem-permissions> in "
1083 + parser.getPositionDescription());
1084 return;
1085 }
1086
1087 ArrayMap<String, Boolean> permissions = mOemPermissions.get(packageName);
1088 if (permissions == null) {
1089 permissions = new ArrayMap<>();
1090 }
1091 final int depth = parser.getDepth();
1092 while (XmlUtils.nextElementWithin(parser, depth)) {
1093 final String name = parser.getName();
1094 if ("permission".equals(name)) {
1095 final String permName = parser.getAttributeValue(null, "name");
1096 if (TextUtils.isEmpty(permName)) {
1097 Slog.w(TAG, "name is required for <permission> in "
1098 + parser.getPositionDescription());
1099 continue;
1100 }
1101 permissions.put(permName, Boolean.TRUE);
1102 } else if ("deny-permission".equals(name)) {
1103 String permName = parser.getAttributeValue(null, "name");
1104 if (TextUtils.isEmpty(permName)) {
1105 Slog.w(TAG, "name is required for <deny-permission> in "
1106 + parser.getPositionDescription());
1107 continue;
1108 }
1109 permissions.put(permName, Boolean.FALSE);
1110 }
1111 }
1112 mOemPermissions.put(packageName, permissions);
1113 }
Zimuzocc2932f2018-10-29 16:04:41 +00001114
1115 private void readSplitPermission(XmlPullParser parser, File permFile)
1116 throws IOException, XmlPullParserException {
1117 String splitPerm = parser.getAttributeValue(null, "name");
1118 if (splitPerm == null) {
1119 Slog.w(TAG, "<split-permission> without name in " + permFile + " at "
1120 + parser.getPositionDescription());
1121 XmlUtils.skipCurrentTag(parser);
1122 return;
1123 }
1124 String targetSdkStr = parser.getAttributeValue(null, "targetSdk");
1125 int targetSdk = Build.VERSION_CODES.CUR_DEVELOPMENT + 1;
1126 if (!TextUtils.isEmpty(targetSdkStr)) {
1127 try {
1128 targetSdk = Integer.parseInt(targetSdkStr);
1129 } catch (NumberFormatException e) {
1130 Slog.w(TAG, "<split-permission> targetSdk not an integer in " + permFile + " at "
1131 + parser.getPositionDescription());
1132 XmlUtils.skipCurrentTag(parser);
1133 return;
1134 }
1135 }
1136 final int depth = parser.getDepth();
1137 List<String> newPermissions = new ArrayList<>();
1138 while (XmlUtils.nextElementWithin(parser, depth)) {
1139 String name = parser.getName();
1140 if ("new-permission".equals(name)) {
1141 final String newName = parser.getAttributeValue(null, "name");
1142 if (TextUtils.isEmpty(newName)) {
1143 Slog.w(TAG, "name is required for <new-permission> in "
1144 + parser.getPositionDescription());
1145 continue;
1146 }
1147 newPermissions.add(newName);
1148 } else {
1149 XmlUtils.skipCurrentTag(parser);
1150 }
1151 }
Jeff Sharkey9787a9452018-11-18 17:53:02 -07001152 // If the storage model feature flag is disabled, we need to fiddle
1153 // around with permission definitions to return us to pre-Q behavior.
1154 // STOPSHIP(b/112545973): remove once feature enabled by default
Jeff Sharkey10ec9d82018-11-28 14:52:45 -07001155 if (!StorageManager.hasIsolatedStorage()) {
Jeff Sharkey9787a9452018-11-18 17:53:02 -07001156 if (newPermissions.contains(android.Manifest.permission.READ_MEDIA_AUDIO) ||
1157 newPermissions.contains(android.Manifest.permission.READ_MEDIA_VIDEO) ||
1158 newPermissions.contains(android.Manifest.permission.READ_MEDIA_IMAGES)) {
1159 return;
1160 }
1161 }
Zimuzocc2932f2018-10-29 16:04:41 +00001162 if (!newPermissions.isEmpty()) {
1163 mSplitPermissions.add(new SplitPermissionInfo(splitPerm, newPermissions, targetSdk));
1164 }
1165 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -07001166}