blob: 67f9f8f49ee6c72bf814f27bf5bcc383b9c53e84 [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;
47import java.util.List;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070048
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070049/**
50 * Loads global system configuration info.
51 */
52public class SystemConfig {
53 static final String TAG = "SystemConfig";
54
55 static SystemConfig sInstance;
56
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +080057 // permission flag, determines which types of configuration are allowed to be read
58 private static final int ALLOW_FEATURES = 0x01;
59 private static final int ALLOW_LIBS = 0x02;
60 private static final int ALLOW_PERMISSIONS = 0x04;
61 private static final int ALLOW_APP_CONFIGS = 0x08;
Jaekyun Seoke3b6bf12017-02-16 13:48:30 +090062 private static final int ALLOW_PRIVAPP_PERMISSIONS = 0x10;
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +080063 private static final int ALLOW_ALL = ~0;
64
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070065 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
66 int[] mGlobalGids;
67
68 // These are the built-in uid -> permission mappings that were read from the
69 // system configuration files.
Jeff Sharkey9f837a92014-10-24 12:07:24 -070070 final SparseArray<ArraySet<String>> mSystemPermissions = new SparseArray<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070071
72 // These are the built-in shared libraries that were read from the
73 // system configuration files. Keys are the library names; strings are the
74 // paths to the libraries.
Dianne Hackbornbb8aa5a2014-09-17 13:20:38 -070075 final ArrayMap<String, String> mSharedLibraries = new ArrayMap<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070076
77 // These are the features this devices supports that were read from the
78 // system configuration files.
Jeff Sharkey9f837a92014-10-24 12:07:24 -070079 final ArrayMap<String, FeatureInfo> mAvailableFeatures = new ArrayMap<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070080
Jeff Sharkey1c4ae802014-12-19 11:08:55 -080081 // These are the features which this device doesn't support; the OEM
82 // partition uses these to opt-out of features from the system image.
83 final ArraySet<String> mUnavailableFeatures = new ArraySet<>();
84
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070085 public static final class PermissionEntry {
86 public final String name;
87 public int[] gids;
Jeff Sharkey00f39042015-03-23 16:51:22 -070088 public boolean perUser;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070089
Jeff Sharkey00f39042015-03-23 16:51:22 -070090 PermissionEntry(String name, boolean perUser) {
91 this.name = name;
92 this.perUser = perUser;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070093 }
94 }
95
96 // These are the permission -> gid mappings that were read from the
97 // system configuration files.
Dianne Hackbornbb8aa5a2014-09-17 13:20:38 -070098 final ArrayMap<String, PermissionEntry> mPermissions = new ArrayMap<>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -070099
100 // These are the packages that are white-listed to be able to run in the
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700101 // background while in power save mode (but not whitelisted from device idle modes),
102 // as read from the configuration files.
103 final ArraySet<String> mAllowInPowerSaveExceptIdle = new ArraySet<>();
104
105 // These are the packages that are white-listed to be able to run in the
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700106 // background while in power save mode, as read from the configuration files.
Dianne Hackbornbb8aa5a2014-09-17 13:20:38 -0700107 final ArraySet<String> mAllowInPowerSave = new ArraySet<>();
108
Felipe Lemea9505cc2016-02-26 10:28:41 -0800109 // These are the packages that are white-listed to be able to run in the
110 // background while in data-usage save mode, as read from the configuration files.
111 final ArraySet<String> mAllowInDataUsageSave = new ArraySet<>();
112
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800113 // These are the packages that are white-listed to be able to run background location
114 // without throttling, as read from the configuration files.
115 final ArraySet<String> mAllowUnthrottledLocation = new ArraySet<>();
116
Christopher Tate42a386b2016-11-07 12:21:21 -0800117 // These are the action strings of broadcasts which are whitelisted to
118 // be delivered anonymously even to apps which target O+.
119 final ArraySet<String> mAllowImplicitBroadcasts = new ArraySet<>();
120
Christopher Tate01e18642015-07-07 18:10:38 -0700121 // These are the package names of apps which should be in the 'always'
122 // URL-handling state upon factory reset.
123 final ArraySet<String> mLinkedApps = new ArraySet<>();
124
Fyodor Kupolov7db5af12015-07-31 16:50:27 -0700125 // These are the packages that are whitelisted to be able to run as system user
126 final ArraySet<String> mSystemUserWhitelistedApps = new ArraySet<>();
127
128 // These are the packages that should not run under system user
129 final ArraySet<String> mSystemUserBlacklistedApps = new ArraySet<>();
130
Ruben Brunk98576cf2016-03-07 18:54:28 -0800131 // These are the components that are enabled by default as VR mode listener services.
132 final ArraySet<ComponentName> mDefaultVrComponents = new ArraySet<>();
133
Christopher Tate494df792016-05-10 17:05:38 -0700134 // These are the permitted backup transport service components
135 final ArraySet<ComponentName> mBackupTransportWhitelist = new ArraySet<>();
136
Jeff Davidson24b9d962016-07-21 12:35:10 -0700137 // These are the packages of carrier-associated apps which should be disabled until used until
138 // a SIM is inserted which grants carrier privileges to that carrier app.
139 final ArrayMap<String, List<String>> mDisabledUntilUsedPreinstalledCarrierAssociatedApps =
140 new ArrayMap<>();
141
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800142
143 final ArrayMap<String, ArraySet<String>> mPrivAppPermissions = new ArrayMap<>();
144
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700145 public static SystemConfig getInstance() {
146 synchronized (SystemConfig.class) {
147 if (sInstance == null) {
148 sInstance = new SystemConfig();
149 }
150 return sInstance;
151 }
152 }
153
154 public int[] getGlobalGids() {
155 return mGlobalGids;
156 }
157
Jeff Sharkey9f837a92014-10-24 12:07:24 -0700158 public SparseArray<ArraySet<String>> getSystemPermissions() {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700159 return mSystemPermissions;
160 }
161
162 public ArrayMap<String, String> getSharedLibraries() {
163 return mSharedLibraries;
164 }
165
Jeff Sharkey9f837a92014-10-24 12:07:24 -0700166 public ArrayMap<String, FeatureInfo> getAvailableFeatures() {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700167 return mAvailableFeatures;
168 }
169
170 public ArrayMap<String, PermissionEntry> getPermissions() {
171 return mPermissions;
172 }
173
Christopher Tate42a386b2016-11-07 12:21:21 -0800174 public ArraySet<String> getAllowImplicitBroadcasts() {
175 return mAllowImplicitBroadcasts;
176 }
177
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700178 public ArraySet<String> getAllowInPowerSaveExceptIdle() {
179 return mAllowInPowerSaveExceptIdle;
180 }
181
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700182 public ArraySet<String> getAllowInPowerSave() {
183 return mAllowInPowerSave;
184 }
185
Felipe Lemea9505cc2016-02-26 10:28:41 -0800186 public ArraySet<String> getAllowInDataUsageSave() {
187 return mAllowInDataUsageSave;
188 }
189
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800190 public ArraySet<String> getAllowUnthrottledLocation() {
191 return mAllowUnthrottledLocation;
192 }
193
Christopher Tate01e18642015-07-07 18:10:38 -0700194 public ArraySet<String> getLinkedApps() {
195 return mLinkedApps;
196 }
197
Fyodor Kupolov7db5af12015-07-31 16:50:27 -0700198 public ArraySet<String> getSystemUserWhitelistedApps() {
199 return mSystemUserWhitelistedApps;
200 }
201
202 public ArraySet<String> getSystemUserBlacklistedApps() {
203 return mSystemUserBlacklistedApps;
204 }
205
Ruben Brunk98576cf2016-03-07 18:54:28 -0800206 public ArraySet<ComponentName> getDefaultVrComponents() {
207 return mDefaultVrComponents;
208 }
209
Christopher Tate494df792016-05-10 17:05:38 -0700210 public ArraySet<ComponentName> getBackupTransportWhitelist() {
211 return mBackupTransportWhitelist;
212 }
213
Jeff Davidson24b9d962016-07-21 12:35:10 -0700214 public ArrayMap<String, List<String>> getDisabledUntilUsedPreinstalledCarrierAssociatedApps() {
215 return mDisabledUntilUsedPreinstalledCarrierAssociatedApps;
216 }
217
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800218 public ArraySet<String> getPrivAppPermissions(String packageName) {
219 return mPrivAppPermissions.get(packageName);
220 }
221
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700222 SystemConfig() {
223 // Read configuration from system
224 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800225 Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700226 // Read configuration from the old permissions dir
227 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800228 Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);
Jaekyun Seoke3b6bf12017-02-16 13:48:30 +0900229 // Allow Vendor to customize system configs around libs, features, permissions and apps
230 int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS |
231 ALLOW_APP_CONFIGS;
232 readPermissions(Environment.buildPath(
233 Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
234 readPermissions(Environment.buildPath(
235 Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag);
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800236 // Allow ODM to customize system configs around libs, features and apps
237 int odmPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_APP_CONFIGS;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700238 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800239 Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700240 readPermissions(Environment.buildPath(
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800241 Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);
242 // Only allow OEM to customize features
243 readPermissions(Environment.buildPath(
244 Environment.getOemDirectory(), "etc", "sysconfig"), ALLOW_FEATURES);
245 readPermissions(Environment.buildPath(
246 Environment.getOemDirectory(), "etc", "permissions"), ALLOW_FEATURES);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700247 }
248
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800249 void readPermissions(File libraryDir, int permissionFlag) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700250 // Read permissions from given directory.
251 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800252 if (permissionFlag == ALLOW_ALL) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700253 Slog.w(TAG, "No directory " + libraryDir + ", skipping");
254 }
255 return;
256 }
257 if (!libraryDir.canRead()) {
258 Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
259 return;
260 }
261
262 // Iterate over the files in the directory and scan .xml files
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800263 File platformFile = null;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700264 for (File f : libraryDir.listFiles()) {
265 // We'll read platform.xml last
266 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800267 platformFile = f;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700268 continue;
269 }
270
271 if (!f.getPath().endsWith(".xml")) {
272 Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
273 continue;
274 }
275 if (!f.canRead()) {
276 Slog.w(TAG, "Permissions library file " + f + " cannot be read");
277 continue;
278 }
279
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800280 readPermissionsFromXml(f, permissionFlag);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700281 }
282
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800283 // Read platform permissions last so it will take precedence
284 if (platformFile != null) {
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800285 readPermissionsFromXml(platformFile, permissionFlag);
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800286 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700287 }
288
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800289 private void readPermissionsFromXml(File permFile, int permissionFlag) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700290 FileReader permReader = null;
291 try {
292 permReader = new FileReader(permFile);
293 } catch (FileNotFoundException e) {
294 Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
295 return;
296 }
297
Dianne Hackbornc0e4aaa2014-11-14 10:55:50 -0800298 final boolean lowRam = ActivityManager.isLowRamDeviceStatic();
299
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700300 try {
301 XmlPullParser parser = Xml.newPullParser();
302 parser.setInput(permReader);
303
304 int type;
305 while ((type=parser.next()) != parser.START_TAG
306 && type != parser.END_DOCUMENT) {
307 ;
308 }
309
310 if (type != parser.START_TAG) {
311 throw new XmlPullParserException("No start tag found");
312 }
313
314 if (!parser.getName().equals("permissions") && !parser.getName().equals("config")) {
Dianne Hackbornb3d4cb32015-01-09 09:54:06 -0800315 throw new XmlPullParserException("Unexpected start tag in " + permFile
316 + ": found " + parser.getName() + ", expected 'permissions' or 'config'");
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700317 }
318
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800319 boolean allowAll = permissionFlag == ALLOW_ALL;
320 boolean allowLibs = (permissionFlag & ALLOW_LIBS) != 0;
321 boolean allowFeatures = (permissionFlag & ALLOW_FEATURES) != 0;
322 boolean allowPermissions = (permissionFlag & ALLOW_PERMISSIONS) != 0;
323 boolean allowAppConfigs = (permissionFlag & ALLOW_APP_CONFIGS) != 0;
Jaekyun Seoke3b6bf12017-02-16 13:48:30 +0900324 boolean allowPrivappPermissions = (permissionFlag & ALLOW_PRIVAPP_PERMISSIONS) != 0;
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700325 while (true) {
326 XmlUtils.nextElement(parser);
327 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
328 break;
329 }
330
331 String name = parser.getName();
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800332 if ("group".equals(name) && allowAll) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700333 String gidStr = parser.getAttributeValue(null, "gid");
334 if (gidStr != null) {
335 int gid = android.os.Process.getGidForName(gidStr);
336 mGlobalGids = appendInt(mGlobalGids, gid);
337 } else {
Dianne Hackbornb3d4cb32015-01-09 09:54:06 -0800338 Slog.w(TAG, "<group> without gid in " + permFile + " at "
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700339 + parser.getPositionDescription());
340 }
341
342 XmlUtils.skipCurrentTag(parser);
343 continue;
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800344 } else if ("permission".equals(name) && allowPermissions) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700345 String perm = parser.getAttributeValue(null, "name");
346 if (perm == null) {
Dianne Hackbornb3d4cb32015-01-09 09:54:06 -0800347 Slog.w(TAG, "<permission> without name in " + permFile + " at "
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700348 + parser.getPositionDescription());
349 XmlUtils.skipCurrentTag(parser);
350 continue;
351 }
352 perm = perm.intern();
353 readPermission(parser, perm);
354
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800355 } else if ("assign-permission".equals(name) && allowPermissions) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700356 String perm = parser.getAttributeValue(null, "name");
357 if (perm == null) {
Dianne Hackbornb3d4cb32015-01-09 09:54:06 -0800358 Slog.w(TAG, "<assign-permission> without name in " + permFile + " at "
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700359 + parser.getPositionDescription());
360 XmlUtils.skipCurrentTag(parser);
361 continue;
362 }
363 String uidStr = parser.getAttributeValue(null, "uid");
364 if (uidStr == null) {
Dianne Hackbornb3d4cb32015-01-09 09:54:06 -0800365 Slog.w(TAG, "<assign-permission> without uid in " + permFile + " at "
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700366 + parser.getPositionDescription());
367 XmlUtils.skipCurrentTag(parser);
368 continue;
369 }
370 int uid = Process.getUidForName(uidStr);
371 if (uid < 0) {
372 Slog.w(TAG, "<assign-permission> with unknown uid \""
Dianne Hackbornb3d4cb32015-01-09 09:54:06 -0800373 + uidStr + " in " + permFile + " at "
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700374 + parser.getPositionDescription());
375 XmlUtils.skipCurrentTag(parser);
376 continue;
377 }
378 perm = perm.intern();
Jeff Sharkey9f837a92014-10-24 12:07:24 -0700379 ArraySet<String> perms = mSystemPermissions.get(uid);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700380 if (perms == null) {
Jeff Sharkey9f837a92014-10-24 12:07:24 -0700381 perms = new ArraySet<String>();
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700382 mSystemPermissions.put(uid, perms);
383 }
384 perms.add(perm);
385 XmlUtils.skipCurrentTag(parser);
386
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800387 } else if ("library".equals(name) && allowLibs) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700388 String lname = parser.getAttributeValue(null, "name");
389 String lfile = parser.getAttributeValue(null, "file");
390 if (lname == null) {
Dianne Hackbornb3d4cb32015-01-09 09:54:06 -0800391 Slog.w(TAG, "<library> without name in " + permFile + " at "
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700392 + parser.getPositionDescription());
393 } else if (lfile == null) {
Dianne Hackbornb3d4cb32015-01-09 09:54:06 -0800394 Slog.w(TAG, "<library> without file in " + permFile + " at "
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700395 + parser.getPositionDescription());
396 } else {
397 //Log.i(TAG, "Got library " + lname + " in " + lfile);
398 mSharedLibraries.put(lname, lfile);
399 }
400 XmlUtils.skipCurrentTag(parser);
401 continue;
402
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800403 } else if ("feature".equals(name) && allowFeatures) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700404 String fname = parser.getAttributeValue(null, "name");
Arunesh Mishra4e0bdf32016-02-15 23:50:38 -0800405 int fversion = XmlUtils.readIntAttribute(parser, "version", 0);
Dianne Hackbornc0e4aaa2014-11-14 10:55:50 -0800406 boolean allowed;
407 if (!lowRam) {
408 allowed = true;
409 } else {
410 String notLowRam = parser.getAttributeValue(null, "notLowRam");
411 allowed = !"true".equals(notLowRam);
412 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700413 if (fname == null) {
Dianne Hackbornb3d4cb32015-01-09 09:54:06 -0800414 Slog.w(TAG, "<feature> without name in " + permFile + " at "
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700415 + parser.getPositionDescription());
Dianne Hackbornc0e4aaa2014-11-14 10:55:50 -0800416 } else if (allowed) {
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700417 addFeature(fname, fversion);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700418 }
419 XmlUtils.skipCurrentTag(parser);
420 continue;
421
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800422 } else if ("unavailable-feature".equals(name) && allowFeatures) {
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800423 String fname = parser.getAttributeValue(null, "name");
424 if (fname == null) {
Dianne Hackbornb3d4cb32015-01-09 09:54:06 -0800425 Slog.w(TAG, "<unavailable-feature> without name in " + permFile + " at "
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800426 + parser.getPositionDescription());
427 } else {
428 mUnavailableFeatures.add(fname);
429 }
430 XmlUtils.skipCurrentTag(parser);
431 continue;
432
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800433 } else if ("allow-in-power-save-except-idle".equals(name) && allowAll) {
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700434 String pkgname = parser.getAttributeValue(null, "package");
435 if (pkgname == null) {
436 Slog.w(TAG, "<allow-in-power-save-except-idle> without package in "
437 + permFile + " at " + parser.getPositionDescription());
438 } else {
439 mAllowInPowerSaveExceptIdle.add(pkgname);
440 }
441 XmlUtils.skipCurrentTag(parser);
442 continue;
443
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800444 } else if ("allow-in-power-save".equals(name) && allowAll) {
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700445 String pkgname = parser.getAttributeValue(null, "package");
446 if (pkgname == null) {
Dianne Hackbornb3d4cb32015-01-09 09:54:06 -0800447 Slog.w(TAG, "<allow-in-power-save> without package in " + permFile + " at "
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700448 + parser.getPositionDescription());
449 } else {
450 mAllowInPowerSave.add(pkgname);
451 }
452 XmlUtils.skipCurrentTag(parser);
453 continue;
454
Felipe Lemea9505cc2016-02-26 10:28:41 -0800455 } else if ("allow-in-data-usage-save".equals(name) && allowAll) {
456 String pkgname = parser.getAttributeValue(null, "package");
457 if (pkgname == null) {
458 Slog.w(TAG, "<allow-in-data-usage-save> without package in " + permFile
459 + " at " + parser.getPositionDescription());
460 } else {
461 mAllowInDataUsageSave.add(pkgname);
462 }
463 XmlUtils.skipCurrentTag(parser);
464 continue;
465
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800466 } else if ("allow-unthrottled-location".equals(name) && allowAll) {
467 String pkgname = parser.getAttributeValue(null, "package");
468 if (pkgname == null) {
469 Slog.w(TAG, "<allow-unthrottled-location> without package in "
470 + permFile + " at " + parser.getPositionDescription());
471 } else {
472 mAllowUnthrottledLocation.add(pkgname);
473 }
474 XmlUtils.skipCurrentTag(parser);
475 continue;
476
Christopher Tate42a386b2016-11-07 12:21:21 -0800477 } else if ("allow-implicit-broadcast".equals(name) && allowAll) {
478 String action = parser.getAttributeValue(null, "action");
479 if (action == null) {
480 Slog.w(TAG, "<allow-implicit-broadcast> without action in " + permFile
481 + " at " + parser.getPositionDescription());
482 } else {
483 mAllowImplicitBroadcasts.add(action);
484 }
485 XmlUtils.skipCurrentTag(parser);
486 continue;
487
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800488 } else if ("app-link".equals(name) && allowAppConfigs) {
Christopher Tate01e18642015-07-07 18:10:38 -0700489 String pkgname = parser.getAttributeValue(null, "package");
490 if (pkgname == null) {
491 Slog.w(TAG, "<app-link> without package in " + permFile + " at "
492 + parser.getPositionDescription());
493 } else {
494 mLinkedApps.add(pkgname);
495 }
496 XmlUtils.skipCurrentTag(parser);
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800497 } else if ("system-user-whitelisted-app".equals(name) && allowAppConfigs) {
Fyodor Kupolov7db5af12015-07-31 16:50:27 -0700498 String pkgname = parser.getAttributeValue(null, "package");
499 if (pkgname == null) {
500 Slog.w(TAG, "<system-user-whitelisted-app> without package in " + permFile
501 + " at " + parser.getPositionDescription());
502 } else {
503 mSystemUserWhitelistedApps.add(pkgname);
504 }
505 XmlUtils.skipCurrentTag(parser);
Hung-ying Tyanbdc9d582015-11-20 11:53:39 +0800506 } else if ("system-user-blacklisted-app".equals(name) && allowAppConfigs) {
Fyodor Kupolov7db5af12015-07-31 16:50:27 -0700507 String pkgname = parser.getAttributeValue(null, "package");
508 if (pkgname == null) {
509 Slog.w(TAG, "<system-user-blacklisted-app without package in " + permFile
510 + " at " + parser.getPositionDescription());
511 } else {
512 mSystemUserBlacklistedApps.add(pkgname);
513 }
514 XmlUtils.skipCurrentTag(parser);
Ruben Brunk98576cf2016-03-07 18:54:28 -0800515 } else if ("default-enabled-vr-app".equals(name) && allowAppConfigs) {
516 String pkgname = parser.getAttributeValue(null, "package");
517 String clsname = parser.getAttributeValue(null, "class");
518 if (pkgname == null) {
519 Slog.w(TAG, "<default-enabled-vr-app without package in " + permFile
520 + " at " + parser.getPositionDescription());
521 } else if (clsname == null) {
522 Slog.w(TAG, "<default-enabled-vr-app without class in " + permFile
523 + " at " + parser.getPositionDescription());
524 } else {
525 mDefaultVrComponents.add(new ComponentName(pkgname, clsname));
526 }
527 XmlUtils.skipCurrentTag(parser);
Christopher Tate494df792016-05-10 17:05:38 -0700528 } else if ("backup-transport-whitelisted-service".equals(name) && allowFeatures) {
529 String serviceName = parser.getAttributeValue(null, "service");
530 if (serviceName == null) {
531 Slog.w(TAG, "<backup-transport-whitelisted-service> without service in "
532 + permFile + " at " + parser.getPositionDescription());
533 } else {
534 ComponentName cn = ComponentName.unflattenFromString(serviceName);
535 if (cn == null) {
536 Slog.w(TAG,
537 "<backup-transport-whitelisted-service> with invalid service name "
538 + serviceName + " in "+ permFile
539 + " at " + parser.getPositionDescription());
540 } else {
541 mBackupTransportWhitelist.add(cn);
542 }
543 }
544 XmlUtils.skipCurrentTag(parser);
Jeff Davidson24b9d962016-07-21 12:35:10 -0700545 } else if ("disabled-until-used-preinstalled-carrier-associated-app".equals(name)
546 && allowAppConfigs) {
547 String pkgname = parser.getAttributeValue(null, "package");
548 String carrierPkgname = parser.getAttributeValue(null, "carrierAppPackage");
549 if (pkgname == null || carrierPkgname == null) {
550 Slog.w(TAG, "<disabled-until-used-preinstalled-carrier-associated-app"
551 + " without package or carrierAppPackage in " + permFile + " at "
552 + parser.getPositionDescription());
553 } else {
554 List<String> associatedPkgs =
555 mDisabledUntilUsedPreinstalledCarrierAssociatedApps.get(
556 carrierPkgname);
557 if (associatedPkgs == null) {
558 associatedPkgs = new ArrayList<>();
559 mDisabledUntilUsedPreinstalledCarrierAssociatedApps.put(
560 carrierPkgname, associatedPkgs);
561 }
562 associatedPkgs.add(pkgname);
563 }
564 XmlUtils.skipCurrentTag(parser);
Jaekyun Seoke3b6bf12017-02-16 13:48:30 +0900565 } else if ("privapp-permissions".equals(name) && allowPrivappPermissions) {
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800566 readPrivAppPermissions(parser);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700567 } else {
568 XmlUtils.skipCurrentTag(parser);
569 continue;
570 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700571 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700572 } catch (XmlPullParserException e) {
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800573 Slog.w(TAG, "Got exception parsing permissions.", e);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700574 } catch (IOException e) {
Jeff Sharkey1c4ae802014-12-19 11:08:55 -0800575 Slog.w(TAG, "Got exception parsing permissions.", e);
576 } finally {
577 IoUtils.closeQuietly(permReader);
578 }
579
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -0700580 // Some devices can be field-converted to FBE, so offer to splice in
581 // those features if not already defined by the static config
Paul Lawrence20be5d62016-02-26 13:51:17 -0800582 if (StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700583 addFeature(PackageManager.FEATURE_FILE_BASED_ENCRYPTION, 0);
584 addFeature(PackageManager.FEATURE_SECURELY_REMOVES_USERS, 0);
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -0700585 }
586
587 for (String featureName : mUnavailableFeatures) {
588 removeFeature(featureName);
589 }
590 }
591
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700592 private void addFeature(String name, int version) {
593 FeatureInfo fi = mAvailableFeatures.get(name);
594 if (fi == null) {
595 fi = new FeatureInfo();
596 fi.name = name;
597 fi.version = version;
598 mAvailableFeatures.put(name, fi);
599 } else {
600 fi.version = Math.max(fi.version, version);
Jeff Sharkeyb92b05b2016-01-28 09:50:00 -0700601 }
602 }
603
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700604 private void removeFeature(String name) {
605 if (mAvailableFeatures.remove(name) != null) {
606 Slog.d(TAG, "Removed unavailable feature " + name);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700607 }
608 }
609
610 void readPermission(XmlPullParser parser, String name)
611 throws IOException, XmlPullParserException {
Jeff Sharkey00f39042015-03-23 16:51:22 -0700612 if (mPermissions.containsKey(name)) {
613 throw new IllegalStateException("Duplicate permission definition for " + name);
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700614 }
Jeff Sharkey00f39042015-03-23 16:51:22 -0700615
616 final boolean perUser = XmlUtils.readBooleanAttribute(parser, "perUser", false);
617 final PermissionEntry perm = new PermissionEntry(name, perUser);
618 mPermissions.put(name, perm);
619
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700620 int outerDepth = parser.getDepth();
621 int type;
622 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
623 && (type != XmlPullParser.END_TAG
624 || parser.getDepth() > outerDepth)) {
625 if (type == XmlPullParser.END_TAG
626 || type == XmlPullParser.TEXT) {
627 continue;
628 }
629
630 String tagName = parser.getName();
631 if ("group".equals(tagName)) {
632 String gidStr = parser.getAttributeValue(null, "gid");
633 if (gidStr != null) {
634 int gid = Process.getGidForName(gidStr);
635 perm.gids = appendInt(perm.gids, gid);
636 } else {
637 Slog.w(TAG, "<group> without gid at "
638 + parser.getPositionDescription());
639 }
640 }
641 XmlUtils.skipCurrentTag(parser);
642 }
643 }
Fyodor Kupolov964d2eb2016-11-09 14:32:27 -0800644
645 void readPrivAppPermissions(XmlPullParser parser) throws IOException, XmlPullParserException {
646 String packageName = parser.getAttributeValue(null, "package");
647 if (TextUtils.isEmpty(packageName)) {
648 Slog.w(TAG, "package is required for <privapp-permissions> in "
649 + parser.getPositionDescription());
650 return;
651 }
652
653 ArraySet<String> permissions = mPrivAppPermissions.get(packageName);
654 if (permissions == null) {
655 permissions = new ArraySet<>();
656 }
657 int depth = parser.getDepth();
658 while (XmlUtils.nextElementWithin(parser, depth)) {
659 String name = parser.getName();
660 if ("permission".equals(name)) {
661 String permName = parser.getAttributeValue(null, "name");
662 if (TextUtils.isEmpty(permName)) {
663 Slog.w(TAG, "name is required for <permission> in "
664 + parser.getPositionDescription());
665 continue;
666 }
667 permissions.add(permName);
668 }
669 }
670 mPrivAppPermissions.put(packageName, permissions);
671 }
Dianne Hackbornbe7c50e2014-06-30 14:43:28 -0700672}