blob: 111934f9d005c5c9f7f02ee9308e3233a6195cad [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;
25import android.os.Environment;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070026import android.os.Process;
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -070027import android.os.storage.StorageManager;
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -080028import android.text.TextUtils;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070029import android.util.ArrayMap;
30import android.util.ArraySet;
31import android.util.Slog;
32import android.util.SparseArray;
33import android.util.Xml;
Jeff Sharkey1c4ae802014-12-19 11:08:55 -080034
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070035import com.android.internal.util.XmlUtils;
Jeff Sharkey1c4ae802014-12-19 11:08:55 -080036
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -070037import libcore.io.IoUtils;
38
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070039import org.xmlpull.v1.XmlPullParser;
40import org.xmlpull.v1.XmlPullParserException;
41
42import java.io.File;
43import java.io.FileNotFoundException;
44import java.io.FileReader;
45import java.io.IOException;
Jeff Davidson24b9d962016-07-21 12:35:10 -070046import java.util.ArrayList;
Svet Ganov087dce22017-09-07 15:42:16 -070047import java.util.Collections;
Jeff Davidson24b9d962016-07-21 12:35:10 -070048import java.util.List;
Svet Ganov087dce22017-09-07 15:42:16 -070049import java.util.Map;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070050
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070051/**
52 * Loads global system configuration info.
53 */
54public class SystemConfig {
55 static final String TAG = "SystemConfig";
56
57 static SystemConfig sInstance;
58
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +080059 // permission flag, determines which types of configuration are allowed to be read
60 private static final int ALLOW_FEATURES = 0x01;
61 private static final int ALLOW_LIBS = 0x02;
62 private static final int ALLOW_PERMISSIONS = 0x04;
63 private static final int ALLOW_APP_CONFIGS = 0x08;
Jaekyun Seoke3b6bf12017-02-16 13:48:30 +090064 private static final int ALLOW_PRIVAPP_PERMISSIONS = 0x10;
Svet Ganov087dce22017-09-07 15:42:16 -070065 private static final int ALLOW_OEM_PERMISSIONS = 0x20;
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +080066 private static final int ALLOW_ALL = ~0;
67
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070068 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
69 int[] mGlobalGids;
70
71 // These are the built-in uid -> permission mappings that were read from the
72 // system configuration files.
Jeff Sharkey9f837a92014-10-24 12:07:24 -070073 final SparseArray<ArraySet<String>> mSystemPermissions = new SparseArray<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070074
75 // These are the built-in shared libraries that were read from the
76 // system configuration files. Keys are the library names; strings are the
77 // paths to the libraries.
Dianne Hackbornbb8aa5a2014-09-17 13:20:38 -070078 final ArrayMap<String, String> mSharedLibraries = new ArrayMap<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070079
80 // These are the features this devices supports that were read from the
81 // system configuration files.
Jeff Sharkey9f837a92014-10-24 12:07:24 -070082 final ArrayMap<String, FeatureInfo> mAvailableFeatures = new ArrayMap<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070083
Jeff Sharkey1c4ae802014-12-19 11:08:55 -080084 // These are the features which this device doesn't support; the OEM
85 // partition uses these to opt-out of features from the system image.
86 final ArraySet<String> mUnavailableFeatures = new ArraySet<>();
87
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070088 public static final class PermissionEntry {
89 public final String name;
90 public int[] gids;
Jeff Sharkey00f39042015-03-23 16:51:22 -070091 public boolean perUser;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070092
Jeff Sharkey00f39042015-03-23 16:51:22 -070093 PermissionEntry(String name, boolean perUser) {
94 this.name = name;
95 this.perUser = perUser;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070096 }
97 }
98
99 // These are the permission -> gid mappings that were read from the
100 // system configuration files.
Dianne Hackbornbb8aa5a2014-09-17 13:20:38 -0700101 final ArrayMap<String, PermissionEntry> mPermissions = new ArrayMap<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700102
103 // These are the packages that are white-listed to be able to run in the
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700104 // background while in power save mode (but not whitelisted from device idle modes),
105 // as read from the configuration files.
106 final ArraySet<String> mAllowInPowerSaveExceptIdle = new ArraySet<>();
107
108 // These are the packages that are white-listed to be able to run in the
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700109 // background while in power save mode, as read from the configuration files.
Dianne Hackbornbb8aa5a2014-09-17 13:20:38 -0700110 final ArraySet<String> mAllowInPowerSave = new ArraySet<>();
111
Felipe Lemea9505cc2016-02-26 10:28:41 -0800112 // These are the packages that are white-listed to be able to run in the
113 // background while in data-usage save mode, as read from the configuration files.
114 final ArraySet<String> mAllowInDataUsageSave = new ArraySet<>();
115
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800116 // These are the packages that are white-listed to be able to run background location
117 // without throttling, as read from the configuration files.
118 final ArraySet<String> mAllowUnthrottledLocation = new ArraySet<>();
119
Christopher Tate42a386b2016-11-07 12:21:21 -0800120 // These are the action strings of broadcasts which are whitelisted to
121 // be delivered anonymously even to apps which target O+.
122 final ArraySet<String> mAllowImplicitBroadcasts = new ArraySet<>();
123
Christopher Tate01e18642015-07-07 18:10:38 -0700124 // These are the package names of apps which should be in the 'always'
125 // URL-handling state upon factory reset.
126 final ArraySet<String> mLinkedApps = new ArraySet<>();
127
Fyodor Kupolov7db5af12015-07-31 16:50:27 -0700128 // These are the packages that are whitelisted to be able to run as system user
129 final ArraySet<String> mSystemUserWhitelistedApps = new ArraySet<>();
130
131 // These are the packages that should not run under system user
132 final ArraySet<String> mSystemUserBlacklistedApps = new ArraySet<>();
133
Ruben Brunk98576cf2016-03-07 18:54:28 -0800134 // These are the components that are enabled by default as VR mode listener services.
135 final ArraySet<ComponentName> mDefaultVrComponents = new ArraySet<>();
136
Christopher Tate494df792016-05-10 17:05:38 -0700137 // These are the permitted backup transport service components
138 final ArraySet<ComponentName> mBackupTransportWhitelist = new ArraySet<>();
139
Jeff Davidson24b9d962016-07-21 12:35:10 -0700140 // These are the packages of carrier-associated apps which should be disabled until used until
141 // a SIM is inserted which grants carrier privileges to that carrier app.
142 final ArrayMap<String, List<String>> mDisabledUntilUsedPreinstalledCarrierAssociatedApps =
143 new ArrayMap<>();
144
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800145
146 final ArrayMap<String, ArraySet<String>> mPrivAppPermissions = new ArrayMap<>();
Todd Kennedy74629e32017-08-15 14:48:07 -0700147 final ArrayMap<String, ArraySet<String>> mPrivAppDenyPermissions = new ArrayMap<>();
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800148
Jiyong Park002fdbd2017-02-13 20:50:31 +0900149 final ArrayMap<String, ArraySet<String>> mVendorPrivAppPermissions = new ArrayMap<>();
150 final ArrayMap<String, ArraySet<String>> mVendorPrivAppDenyPermissions = new ArrayMap<>();
151
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900152 final ArrayMap<String, ArraySet<String>> mProductPrivAppPermissions = new ArrayMap<>();
153 final ArrayMap<String, ArraySet<String>> mProductPrivAppDenyPermissions = new ArrayMap<>();
154
Svet Ganov087dce22017-09-07 15:42:16 -0700155 final ArrayMap<String, ArrayMap<String, Boolean>> mOemPermissions = new ArrayMap<>();
156
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700157 public static SystemConfig getInstance() {
158 synchronized (SystemConfig.class) {
159 if (sInstance == null) {
160 sInstance = new SystemConfig();
161 }
162 return sInstance;
163 }
164 }
165
166 public int[] getGlobalGids() {
167 return mGlobalGids;
168 }
169
Jeff Sharkey9f837a92014-10-24 12:07:24 -0700170 public SparseArray<ArraySet<String>> getSystemPermissions() {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700171 return mSystemPermissions;
172 }
173
174 public ArrayMap<String, String> getSharedLibraries() {
175 return mSharedLibraries;
176 }
177
Jeff Sharkey9f837a92014-10-24 12:07:24 -0700178 public ArrayMap<String, FeatureInfo> getAvailableFeatures() {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700179 return mAvailableFeatures;
180 }
181
182 public ArrayMap<String, PermissionEntry> getPermissions() {
183 return mPermissions;
184 }
185
Christopher Tate42a386b2016-11-07 12:21:21 -0800186 public ArraySet<String> getAllowImplicitBroadcasts() {
187 return mAllowImplicitBroadcasts;
188 }
189
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700190 public ArraySet<String> getAllowInPowerSaveExceptIdle() {
191 return mAllowInPowerSaveExceptIdle;
192 }
193
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700194 public ArraySet<String> getAllowInPowerSave() {
195 return mAllowInPowerSave;
196 }
197
Felipe Lemea9505cc2016-02-26 10:28:41 -0800198 public ArraySet<String> getAllowInDataUsageSave() {
199 return mAllowInDataUsageSave;
200 }
201
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800202 public ArraySet<String> getAllowUnthrottledLocation() {
203 return mAllowUnthrottledLocation;
204 }
205
Christopher Tate01e18642015-07-07 18:10:38 -0700206 public ArraySet<String> getLinkedApps() {
207 return mLinkedApps;
208 }
209
Fyodor Kupolov7db5af12015-07-31 16:50:27 -0700210 public ArraySet<String> getSystemUserWhitelistedApps() {
211 return mSystemUserWhitelistedApps;
212 }
213
214 public ArraySet<String> getSystemUserBlacklistedApps() {
215 return mSystemUserBlacklistedApps;
216 }
217
Ruben Brunk98576cf2016-03-07 18:54:28 -0800218 public ArraySet<ComponentName> getDefaultVrComponents() {
219 return mDefaultVrComponents;
220 }
221
Christopher Tate494df792016-05-10 17:05:38 -0700222 public ArraySet<ComponentName> getBackupTransportWhitelist() {
223 return mBackupTransportWhitelist;
224 }
225
Jeff Davidson24b9d962016-07-21 12:35:10 -0700226 public ArrayMap<String, List<String>> getDisabledUntilUsedPreinstalledCarrierAssociatedApps() {
227 return mDisabledUntilUsedPreinstalledCarrierAssociatedApps;
228 }
229
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800230 public ArraySet<String> getPrivAppPermissions(String packageName) {
231 return mPrivAppPermissions.get(packageName);
232 }
233
Todd Kennedy74629e32017-08-15 14:48:07 -0700234 public ArraySet<String> getPrivAppDenyPermissions(String packageName) {
235 return mPrivAppDenyPermissions.get(packageName);
236 }
237
Jiyong Park002fdbd2017-02-13 20:50:31 +0900238 public ArraySet<String> getVendorPrivAppPermissions(String packageName) {
239 return mVendorPrivAppPermissions.get(packageName);
240 }
241
242 public ArraySet<String> getVendorPrivAppDenyPermissions(String packageName) {
243 return mVendorPrivAppDenyPermissions.get(packageName);
244 }
245
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900246 public ArraySet<String> getProductPrivAppPermissions(String packageName) {
247 return mProductPrivAppPermissions.get(packageName);
248 }
249
250 public ArraySet<String> getProductPrivAppDenyPermissions(String packageName) {
251 return mProductPrivAppDenyPermissions.get(packageName);
252 }
253
Svet Ganov087dce22017-09-07 15:42:16 -0700254 public Map<String, Boolean> getOemPermissions(String packageName) {
255 final Map<String, Boolean> oemPermissions = mOemPermissions.get(packageName);
256 if (oemPermissions != null) {
257 return oemPermissions;
258 }
259 return Collections.emptyMap();
260 }
261
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700262 SystemConfig() {
263 // Read configuration from system
264 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800265 Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL);
Svet Ganov087dce22017-09-07 15:42:16 -0700266
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700267 // Read configuration from the old permissions dir
268 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800269 Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);
Svet Ganov087dce22017-09-07 15:42:16 -0700270
Jaekyun Seoke3b6bf12017-02-16 13:48:30 +0900271 // Allow Vendor to customize system configs around libs, features, permissions and apps
272 int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS |
Jiyong Park002fdbd2017-02-13 20:50:31 +0900273 ALLOW_APP_CONFIGS | ALLOW_PRIVAPP_PERMISSIONS;
Jaekyun Seoke3b6bf12017-02-16 13:48:30 +0900274 readPermissions(Environment.buildPath(
275 Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
276 readPermissions(Environment.buildPath(
277 Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag);
Svet Ganov087dce22017-09-07 15:42:16 -0700278
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800279 // Allow ODM to customize system configs around libs, features and apps
280 int odmPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_APP_CONFIGS;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700281 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800282 Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700283 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800284 Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);
Svet Ganov087dce22017-09-07 15:42:16 -0700285
286 // Allow OEM to customize features and OEM permissions
287 int oemPermissionFlag = ALLOW_FEATURES | ALLOW_OEM_PERMISSIONS;
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800288 readPermissions(Environment.buildPath(
Svet Ganov087dce22017-09-07 15:42:16 -0700289 Environment.getOemDirectory(), "etc", "sysconfig"), oemPermissionFlag);
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800290 readPermissions(Environment.buildPath(
Svet Ganov087dce22017-09-07 15:42:16 -0700291 Environment.getOemDirectory(), "etc", "permissions"), oemPermissionFlag);
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900292
293 // Allow Product to customize system configs around libs, features, permissions and apps
294 int productPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS |
295 ALLOW_APP_CONFIGS | ALLOW_PRIVAPP_PERMISSIONS;
296 readPermissions(Environment.buildPath(
297 Environment.getProductDirectory(), "etc", "sysconfig"), productPermissionFlag);
298 readPermissions(Environment.buildPath(
299 Environment.getProductDirectory(), "etc", "permissions"), productPermissionFlag);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700300 }
301
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800302 void readPermissions(File libraryDir, int permissionFlag) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700303 // Read permissions from given directory.
304 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800305 if (permissionFlag == ALLOW_ALL) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700306 Slog.w(TAG, "No directory " + libraryDir + ", skipping");
307 }
308 return;
309 }
310 if (!libraryDir.canRead()) {
311 Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
312 return;
313 }
314
315 // Iterate over the files in the directory and scan .xml files
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800316 File platformFile = null;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700317 for (File f : libraryDir.listFiles()) {
318 // We'll read platform.xml last
319 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800320 platformFile = f;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700321 continue;
322 }
323
324 if (!f.getPath().endsWith(".xml")) {
325 Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
326 continue;
327 }
328 if (!f.canRead()) {
329 Slog.w(TAG, "Permissions library file " + f + " cannot be read");
330 continue;
331 }
332
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800333 readPermissionsFromXml(f, permissionFlag);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700334 }
335
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800336 // Read platform permissions last so it will take precedence
337 if (platformFile != null) {
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800338 readPermissionsFromXml(platformFile, permissionFlag);
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800339 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700340 }
341
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800342 private void readPermissionsFromXml(File permFile, int permissionFlag) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700343 FileReader permReader = null;
344 try {
345 permReader = new FileReader(permFile);
346 } catch (FileNotFoundException e) {
347 Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
348 return;
349 }
350
Dianne Hackbornc0e4aaa2014-11-14 10:55:50 -0800351 final boolean lowRam = ActivityManager.isLowRamDeviceStatic();
352
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700353 try {
354 XmlPullParser parser = Xml.newPullParser();
355 parser.setInput(permReader);
356
357 int type;
358 while ((type=parser.next()) != parser.START_TAG
359 && type != parser.END_DOCUMENT) {
360 ;
361 }
362
363 if (type != parser.START_TAG) {
364 throw new XmlPullParserException("No start tag found");
365 }
366
367 if (!parser.getName().equals("permissions") && !parser.getName().equals("config")) {
Dianne Hackbornb3d4cb32015-01-09 09:54:06 -0800368 throw new XmlPullParserException("Unexpected start tag in " + permFile
369 + ": found " + parser.getName() + ", expected 'permissions' or 'config'");
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700370 }
371
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800372 boolean allowAll = permissionFlag == ALLOW_ALL;
373 boolean allowLibs = (permissionFlag & ALLOW_LIBS) != 0;
374 boolean allowFeatures = (permissionFlag & ALLOW_FEATURES) != 0;
375 boolean allowPermissions = (permissionFlag & ALLOW_PERMISSIONS) != 0;
376 boolean allowAppConfigs = (permissionFlag & ALLOW_APP_CONFIGS) != 0;
Jaekyun Seoke3b6bf12017-02-16 13:48:30 +0900377 boolean allowPrivappPermissions = (permissionFlag & ALLOW_PRIVAPP_PERMISSIONS) != 0;
Svet Ganov087dce22017-09-07 15:42:16 -0700378 boolean allowOemPermissions = (permissionFlag & ALLOW_OEM_PERMISSIONS) != 0;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700379 while (true) {
380 XmlUtils.nextElement(parser);
381 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
382 break;
383 }
384
385 String name = parser.getName();
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800386 if ("group".equals(name) && allowAll) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700387 String gidStr = parser.getAttributeValue(null, "gid");
388 if (gidStr != null) {
389 int gid = android.os.Process.getGidForName(gidStr);
390 mGlobalGids = appendInt(mGlobalGids, gid);
391 } else {
Dianne Hackbornb3d4cb32015-01-09 09:54:06 -0800392 Slog.w(TAG, "<group> without gid in " + permFile + " at "
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700393 + parser.getPositionDescription());
394 }
395
396 XmlUtils.skipCurrentTag(parser);
397 continue;
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800398 } else if ("permission".equals(name) && allowPermissions) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700399 String perm = parser.getAttributeValue(null, "name");
400 if (perm == null) {
Dianne Hackbornb3d4cb32015-01-09 09:54:06 -0800401 Slog.w(TAG, "<permission> without name in " + permFile + " at "
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700402 + parser.getPositionDescription());
403 XmlUtils.skipCurrentTag(parser);
404 continue;
405 }
406 perm = perm.intern();
407 readPermission(parser, perm);
408
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800409 } else if ("assign-permission".equals(name) && allowPermissions) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700410 String perm = parser.getAttributeValue(null, "name");
411 if (perm == null) {
Dianne Hackbornb3d4cb32015-01-09 09:54:06 -0800412 Slog.w(TAG, "<assign-permission> without name in " + permFile + " at "
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700413 + parser.getPositionDescription());
414 XmlUtils.skipCurrentTag(parser);
415 continue;
416 }
417 String uidStr = parser.getAttributeValue(null, "uid");
418 if (uidStr == null) {
Dianne Hackbornb3d4cb32015-01-09 09:54:06 -0800419 Slog.w(TAG, "<assign-permission> without uid in " + permFile + " at "
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700420 + parser.getPositionDescription());
421 XmlUtils.skipCurrentTag(parser);
422 continue;
423 }
424 int uid = Process.getUidForName(uidStr);
425 if (uid < 0) {
426 Slog.w(TAG, "<assign-permission> with unknown uid \""
Dianne Hackbornb3d4cb32015-01-09 09:54:06 -0800427 + uidStr + " in " + permFile + " at "
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700428 + parser.getPositionDescription());
429 XmlUtils.skipCurrentTag(parser);
430 continue;
431 }
432 perm = perm.intern();
Jeff Sharkey9f837a92014-10-24 12:07:24 -0700433 ArraySet<String> perms = mSystemPermissions.get(uid);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700434 if (perms == null) {
Jeff Sharkey9f837a92014-10-24 12:07:24 -0700435 perms = new ArraySet<String>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700436 mSystemPermissions.put(uid, perms);
437 }
438 perms.add(perm);
439 XmlUtils.skipCurrentTag(parser);
440
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800441 } else if ("library".equals(name) && allowLibs) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700442 String lname = parser.getAttributeValue(null, "name");
443 String lfile = parser.getAttributeValue(null, "file");
444 if (lname == null) {
Dianne Hackbornb3d4cb32015-01-09 09:54:06 -0800445 Slog.w(TAG, "<library> without name in " + permFile + " at "
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700446 + parser.getPositionDescription());
447 } else if (lfile == null) {
Dianne Hackbornb3d4cb32015-01-09 09:54:06 -0800448 Slog.w(TAG, "<library> without file in " + permFile + " at "
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700449 + parser.getPositionDescription());
450 } else {
451 //Log.i(TAG, "Got library " + lname + " in " + lfile);
452 mSharedLibraries.put(lname, lfile);
453 }
454 XmlUtils.skipCurrentTag(parser);
455 continue;
456
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800457 } else if ("feature".equals(name) && allowFeatures) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700458 String fname = parser.getAttributeValue(null, "name");
Arunesh Mishra4e0bdf32016-02-15 23:50:38 -0800459 int fversion = XmlUtils.readIntAttribute(parser, "version", 0);
Dianne Hackbornc0e4aaa2014-11-14 10:55:50 -0800460 boolean allowed;
461 if (!lowRam) {
462 allowed = true;
463 } else {
464 String notLowRam = parser.getAttributeValue(null, "notLowRam");
465 allowed = !"true".equals(notLowRam);
466 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700467 if (fname == null) {
Dianne Hackbornb3d4cb32015-01-09 09:54:06 -0800468 Slog.w(TAG, "<feature> without name in " + permFile + " at "
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700469 + parser.getPositionDescription());
Dianne Hackbornc0e4aaa2014-11-14 10:55:50 -0800470 } else if (allowed) {
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700471 addFeature(fname, fversion);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700472 }
473 XmlUtils.skipCurrentTag(parser);
474 continue;
475
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800476 } else if ("unavailable-feature".equals(name) && allowFeatures) {
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800477 String fname = parser.getAttributeValue(null, "name");
478 if (fname == null) {
Dianne Hackbornb3d4cb32015-01-09 09:54:06 -0800479 Slog.w(TAG, "<unavailable-feature> without name in " + permFile + " at "
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800480 + parser.getPositionDescription());
481 } else {
482 mUnavailableFeatures.add(fname);
483 }
484 XmlUtils.skipCurrentTag(parser);
485 continue;
486
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800487 } else if ("allow-in-power-save-except-idle".equals(name) && allowAll) {
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700488 String pkgname = parser.getAttributeValue(null, "package");
489 if (pkgname == null) {
490 Slog.w(TAG, "<allow-in-power-save-except-idle> without package in "
491 + permFile + " at " + parser.getPositionDescription());
492 } else {
493 mAllowInPowerSaveExceptIdle.add(pkgname);
494 }
495 XmlUtils.skipCurrentTag(parser);
496 continue;
497
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800498 } else if ("allow-in-power-save".equals(name) && allowAll) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700499 String pkgname = parser.getAttributeValue(null, "package");
500 if (pkgname == null) {
Dianne Hackbornb3d4cb32015-01-09 09:54:06 -0800501 Slog.w(TAG, "<allow-in-power-save> without package in " + permFile + " at "
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700502 + parser.getPositionDescription());
503 } else {
504 mAllowInPowerSave.add(pkgname);
505 }
506 XmlUtils.skipCurrentTag(parser);
507 continue;
508
Felipe Lemea9505cc2016-02-26 10:28:41 -0800509 } else if ("allow-in-data-usage-save".equals(name) && allowAll) {
510 String pkgname = parser.getAttributeValue(null, "package");
511 if (pkgname == null) {
512 Slog.w(TAG, "<allow-in-data-usage-save> without package in " + permFile
513 + " at " + parser.getPositionDescription());
514 } else {
515 mAllowInDataUsageSave.add(pkgname);
516 }
517 XmlUtils.skipCurrentTag(parser);
518 continue;
519
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800520 } else if ("allow-unthrottled-location".equals(name) && allowAll) {
521 String pkgname = parser.getAttributeValue(null, "package");
522 if (pkgname == null) {
523 Slog.w(TAG, "<allow-unthrottled-location> without package in "
524 + permFile + " at " + parser.getPositionDescription());
525 } else {
526 mAllowUnthrottledLocation.add(pkgname);
527 }
528 XmlUtils.skipCurrentTag(parser);
529 continue;
530
Christopher Tate42a386b2016-11-07 12:21:21 -0800531 } else if ("allow-implicit-broadcast".equals(name) && allowAll) {
532 String action = parser.getAttributeValue(null, "action");
533 if (action == null) {
534 Slog.w(TAG, "<allow-implicit-broadcast> without action in " + permFile
535 + " at " + parser.getPositionDescription());
536 } else {
537 mAllowImplicitBroadcasts.add(action);
538 }
539 XmlUtils.skipCurrentTag(parser);
540 continue;
541
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800542 } else if ("app-link".equals(name) && allowAppConfigs) {
Christopher Tate01e18642015-07-07 18:10:38 -0700543 String pkgname = parser.getAttributeValue(null, "package");
544 if (pkgname == null) {
545 Slog.w(TAG, "<app-link> without package in " + permFile + " at "
546 + parser.getPositionDescription());
547 } else {
548 mLinkedApps.add(pkgname);
549 }
550 XmlUtils.skipCurrentTag(parser);
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800551 } else if ("system-user-whitelisted-app".equals(name) && allowAppConfigs) {
Fyodor Kupolov7db5af12015-07-31 16:50:27 -0700552 String pkgname = parser.getAttributeValue(null, "package");
553 if (pkgname == null) {
554 Slog.w(TAG, "<system-user-whitelisted-app> without package in " + permFile
555 + " at " + parser.getPositionDescription());
556 } else {
557 mSystemUserWhitelistedApps.add(pkgname);
558 }
559 XmlUtils.skipCurrentTag(parser);
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800560 } else if ("system-user-blacklisted-app".equals(name) && allowAppConfigs) {
Fyodor Kupolov7db5af12015-07-31 16:50:27 -0700561 String pkgname = parser.getAttributeValue(null, "package");
562 if (pkgname == null) {
563 Slog.w(TAG, "<system-user-blacklisted-app without package in " + permFile
564 + " at " + parser.getPositionDescription());
565 } else {
566 mSystemUserBlacklistedApps.add(pkgname);
567 }
568 XmlUtils.skipCurrentTag(parser);
Ruben Brunk98576cf2016-03-07 18:54:28 -0800569 } else if ("default-enabled-vr-app".equals(name) && allowAppConfigs) {
570 String pkgname = parser.getAttributeValue(null, "package");
571 String clsname = parser.getAttributeValue(null, "class");
572 if (pkgname == null) {
573 Slog.w(TAG, "<default-enabled-vr-app without package in " + permFile
574 + " at " + parser.getPositionDescription());
575 } else if (clsname == null) {
576 Slog.w(TAG, "<default-enabled-vr-app without class in " + permFile
577 + " at " + parser.getPositionDescription());
578 } else {
579 mDefaultVrComponents.add(new ComponentName(pkgname, clsname));
580 }
581 XmlUtils.skipCurrentTag(parser);
Christopher Tate494df792016-05-10 17:05:38 -0700582 } else if ("backup-transport-whitelisted-service".equals(name) && allowFeatures) {
583 String serviceName = parser.getAttributeValue(null, "service");
584 if (serviceName == null) {
585 Slog.w(TAG, "<backup-transport-whitelisted-service> without service in "
586 + permFile + " at " + parser.getPositionDescription());
587 } else {
588 ComponentName cn = ComponentName.unflattenFromString(serviceName);
589 if (cn == null) {
590 Slog.w(TAG,
591 "<backup-transport-whitelisted-service> with invalid service name "
592 + serviceName + " in "+ permFile
593 + " at " + parser.getPositionDescription());
594 } else {
595 mBackupTransportWhitelist.add(cn);
596 }
597 }
598 XmlUtils.skipCurrentTag(parser);
Jeff Davidson24b9d962016-07-21 12:35:10 -0700599 } else if ("disabled-until-used-preinstalled-carrier-associated-app".equals(name)
600 && allowAppConfigs) {
601 String pkgname = parser.getAttributeValue(null, "package");
602 String carrierPkgname = parser.getAttributeValue(null, "carrierAppPackage");
603 if (pkgname == null || carrierPkgname == null) {
604 Slog.w(TAG, "<disabled-until-used-preinstalled-carrier-associated-app"
605 + " without package or carrierAppPackage in " + permFile + " at "
606 + parser.getPositionDescription());
607 } else {
608 List<String> associatedPkgs =
609 mDisabledUntilUsedPreinstalledCarrierAssociatedApps.get(
610 carrierPkgname);
611 if (associatedPkgs == null) {
612 associatedPkgs = new ArrayList<>();
613 mDisabledUntilUsedPreinstalledCarrierAssociatedApps.put(
614 carrierPkgname, associatedPkgs);
615 }
616 associatedPkgs.add(pkgname);
617 }
618 XmlUtils.skipCurrentTag(parser);
Jaekyun Seoke3b6bf12017-02-16 13:48:30 +0900619 } else if ("privapp-permissions".equals(name) && allowPrivappPermissions) {
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900620 // privapp permissions from system, vendor and product partitions are stored
Jiyong Park002fdbd2017-02-13 20:50:31 +0900621 // separately. This is to prevent xml files in the vendor partition from
622 // granting permissions to priv apps in the system partition and vice
623 // versa.
624 boolean vendor = permFile.toPath().startsWith(
625 Environment.getVendorDirectory().toPath());
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900626 boolean product = permFile.toPath().startsWith(
627 Environment.getProductDirectory().toPath());
Jiyong Park002fdbd2017-02-13 20:50:31 +0900628 if (vendor) {
629 readPrivAppPermissions(parser, mVendorPrivAppPermissions,
630 mVendorPrivAppDenyPermissions);
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900631 } else if (product) {
632 readPrivAppPermissions(parser, mProductPrivAppPermissions,
633 mProductPrivAppDenyPermissions);
Jiyong Park002fdbd2017-02-13 20:50:31 +0900634 } else {
635 readPrivAppPermissions(parser, mPrivAppPermissions,
636 mPrivAppDenyPermissions);
637 }
Svet Ganov087dce22017-09-07 15:42:16 -0700638 } else if ("oem-permissions".equals(name) && allowOemPermissions) {
639 readOemPermissions(parser);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700640 } else {
641 XmlUtils.skipCurrentTag(parser);
642 continue;
643 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700644 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700645 } catch (XmlPullParserException e) {
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800646 Slog.w(TAG, "Got exception parsing permissions.", e);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700647 } catch (IOException e) {
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800648 Slog.w(TAG, "Got exception parsing permissions.", e);
649 } finally {
650 IoUtils.closeQuietly(permReader);
651 }
652
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -0700653 // Some devices can be field-converted to FBE, so offer to splice in
654 // those features if not already defined by the static config
Paul Lawrence20be5d62016-02-26 13:51:17 -0800655 if (StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700656 addFeature(PackageManager.FEATURE_FILE_BASED_ENCRYPTION, 0);
657 addFeature(PackageManager.FEATURE_SECURELY_REMOVES_USERS, 0);
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -0700658 }
659
Jeff Sharkey8eb783b2018-01-04 16:46:48 -0700660 // Help legacy devices that may not have updated their static config
661 if (StorageManager.hasAdoptable()) {
662 addFeature(PackageManager.FEATURE_ADOPTABLE_STORAGE, 0);
663 }
664
Dianne Hackborn2a103f12017-08-08 15:50:31 -0700665 if (ActivityManager.isLowRamDeviceStatic()) {
666 addFeature(PackageManager.FEATURE_RAM_LOW, 0);
667 } else {
668 addFeature(PackageManager.FEATURE_RAM_NORMAL, 0);
669 }
670
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -0700671 for (String featureName : mUnavailableFeatures) {
672 removeFeature(featureName);
673 }
674 }
675
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700676 private void addFeature(String name, int version) {
677 FeatureInfo fi = mAvailableFeatures.get(name);
678 if (fi == null) {
679 fi = new FeatureInfo();
680 fi.name = name;
681 fi.version = version;
682 mAvailableFeatures.put(name, fi);
683 } else {
684 fi.version = Math.max(fi.version, version);
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -0700685 }
686 }
687
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700688 private void removeFeature(String name) {
689 if (mAvailableFeatures.remove(name) != null) {
690 Slog.d(TAG, "Removed unavailable feature " + name);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700691 }
692 }
693
694 void readPermission(XmlPullParser parser, String name)
695 throws IOException, XmlPullParserException {
Jeff Sharkey00f39042015-03-23 16:51:22 -0700696 if (mPermissions.containsKey(name)) {
697 throw new IllegalStateException("Duplicate permission definition for " + name);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700698 }
Jeff Sharkey00f39042015-03-23 16:51:22 -0700699
700 final boolean perUser = XmlUtils.readBooleanAttribute(parser, "perUser", false);
701 final PermissionEntry perm = new PermissionEntry(name, perUser);
702 mPermissions.put(name, perm);
703
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700704 int outerDepth = parser.getDepth();
705 int type;
706 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
707 && (type != XmlPullParser.END_TAG
708 || parser.getDepth() > outerDepth)) {
709 if (type == XmlPullParser.END_TAG
710 || type == XmlPullParser.TEXT) {
711 continue;
712 }
713
714 String tagName = parser.getName();
715 if ("group".equals(tagName)) {
716 String gidStr = parser.getAttributeValue(null, "gid");
717 if (gidStr != null) {
718 int gid = Process.getGidForName(gidStr);
719 perm.gids = appendInt(perm.gids, gid);
720 } else {
721 Slog.w(TAG, "<group> without gid at "
722 + parser.getPositionDescription());
723 }
724 }
725 XmlUtils.skipCurrentTag(parser);
726 }
727 }
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800728
Jiyong Park002fdbd2017-02-13 20:50:31 +0900729 private void readPrivAppPermissions(XmlPullParser parser,
730 ArrayMap<String, ArraySet<String>> grantMap,
731 ArrayMap<String, ArraySet<String>> denyMap)
732 throws IOException, XmlPullParserException {
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800733 String packageName = parser.getAttributeValue(null, "package");
734 if (TextUtils.isEmpty(packageName)) {
735 Slog.w(TAG, "package is required for <privapp-permissions> in "
736 + parser.getPositionDescription());
737 return;
738 }
739
Jiyong Park002fdbd2017-02-13 20:50:31 +0900740 ArraySet<String> permissions = grantMap.get(packageName);
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800741 if (permissions == null) {
742 permissions = new ArraySet<>();
743 }
Jiyong Park002fdbd2017-02-13 20:50:31 +0900744 ArraySet<String> denyPermissions = denyMap.get(packageName);
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800745 int depth = parser.getDepth();
746 while (XmlUtils.nextElementWithin(parser, depth)) {
747 String name = parser.getName();
748 if ("permission".equals(name)) {
749 String permName = parser.getAttributeValue(null, "name");
750 if (TextUtils.isEmpty(permName)) {
751 Slog.w(TAG, "name is required for <permission> in "
752 + parser.getPositionDescription());
753 continue;
754 }
755 permissions.add(permName);
Todd Kennedy74629e32017-08-15 14:48:07 -0700756 } else if ("deny-permission".equals(name)) {
757 String permName = parser.getAttributeValue(null, "name");
758 if (TextUtils.isEmpty(permName)) {
759 Slog.w(TAG, "name is required for <deny-permission> in "
760 + parser.getPositionDescription());
761 continue;
762 }
763 if (denyPermissions == null) {
764 denyPermissions = new ArraySet<>();
765 }
766 denyPermissions.add(permName);
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800767 }
768 }
Jiyong Park002fdbd2017-02-13 20:50:31 +0900769 grantMap.put(packageName, permissions);
Todd Kennedy74629e32017-08-15 14:48:07 -0700770 if (denyPermissions != null) {
Jiyong Park002fdbd2017-02-13 20:50:31 +0900771 denyMap.put(packageName, denyPermissions);
Todd Kennedy74629e32017-08-15 14:48:07 -0700772 }
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800773 }
Svet Ganov087dce22017-09-07 15:42:16 -0700774
775 void readOemPermissions(XmlPullParser parser) throws IOException, XmlPullParserException {
776 final String packageName = parser.getAttributeValue(null, "package");
777 if (TextUtils.isEmpty(packageName)) {
778 Slog.w(TAG, "package is required for <oem-permissions> in "
779 + parser.getPositionDescription());
780 return;
781 }
782
783 ArrayMap<String, Boolean> permissions = mOemPermissions.get(packageName);
784 if (permissions == null) {
785 permissions = new ArrayMap<>();
786 }
787 final int depth = parser.getDepth();
788 while (XmlUtils.nextElementWithin(parser, depth)) {
789 final String name = parser.getName();
790 if ("permission".equals(name)) {
791 final String permName = parser.getAttributeValue(null, "name");
792 if (TextUtils.isEmpty(permName)) {
793 Slog.w(TAG, "name is required for <permission> in "
794 + parser.getPositionDescription());
795 continue;
796 }
797 permissions.put(permName, Boolean.TRUE);
798 } else if ("deny-permission".equals(name)) {
799 String permName = parser.getAttributeValue(null, "name");
800 if (TextUtils.isEmpty(permName)) {
801 Slog.w(TAG, "name is required for <deny-permission> in "
802 + parser.getPositionDescription());
803 continue;
804 }
805 permissions.put(permName, Boolean.FALSE);
806 }
807 }
808 mOemPermissions.put(packageName, permissions);
809 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700810}