1 /*
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 
17 package com.android.server;
18 
19 import static com.android.internal.util.ArrayUtils.appendInt;
20 
21 import android.annotation.NonNull;
22 import android.app.ActivityManager;
23 import android.content.ComponentName;
24 import android.content.pm.FeatureInfo;
25 import android.content.pm.PackageManager;
26 import android.os.Build;
27 import android.os.CarrierAssociatedAppEntry;
28 import android.os.Environment;
29 import android.os.FileUtils;
30 import android.os.Process;
31 import android.os.SystemProperties;
32 import android.os.Trace;
33 import android.os.incremental.IncrementalManager;
34 import android.os.storage.StorageManager;
35 import android.permission.PermissionManager.SplitPermissionInfo;
36 import android.text.TextUtils;
37 import android.util.ArrayMap;
38 import android.util.ArraySet;
39 import android.util.Slog;
40 import android.util.SparseArray;
41 import android.util.TimingsTraceLog;
42 import android.util.Xml;
43 
44 import com.android.internal.annotations.VisibleForTesting;
45 import com.android.internal.util.XmlUtils;
46 
47 import libcore.io.IoUtils;
48 
49 import org.xmlpull.v1.XmlPullParser;
50 import org.xmlpull.v1.XmlPullParserException;
51 
52 import java.io.File;
53 import java.io.FileNotFoundException;
54 import java.io.FileReader;
55 import java.io.IOException;
56 import java.util.ArrayList;
57 import java.util.Collections;
58 import java.util.List;
59 import java.util.Map;
60 import java.util.Set;
61 
62 /**
63  * Loads global system configuration info.
64  * Note: Initializing this class hits the disk and is slow.  This class should generally only be
65  * accessed by the system_server process.
66  */
67 public class SystemConfig {
68     static final String TAG = "SystemConfig";
69 
70     static SystemConfig sInstance;
71 
72     // permission flag, determines which types of configuration are allowed to be read
73     private static final int ALLOW_FEATURES = 0x01;
74     private static final int ALLOW_LIBS = 0x02;
75     private static final int ALLOW_PERMISSIONS = 0x04;
76     private static final int ALLOW_APP_CONFIGS = 0x08;
77     private static final int ALLOW_PRIVAPP_PERMISSIONS = 0x10;
78     private static final int ALLOW_OEM_PERMISSIONS = 0x20;
79     private static final int ALLOW_HIDDENAPI_WHITELISTING = 0x40;
80     private static final int ALLOW_ASSOCIATIONS = 0x80;
81     private static final int ALLOW_ALL = ~0;
82 
83     // property for runtime configuration differentiation
84     private static final String SKU_PROPERTY = "ro.boot.product.hardware.sku";
85 
86     // property for runtime configuration differentiation in vendor
87     private static final String VENDOR_SKU_PROPERTY = "ro.boot.product.vendor.sku";
88 
89     // Group-ids that are given to all packages as read from etc/permissions/*.xml.
90     int[] mGlobalGids;
91 
92     // These are the built-in uid -> permission mappings that were read from the
93     // system configuration files.
94     final SparseArray<ArraySet<String>> mSystemPermissions = new SparseArray<>();
95 
96     final ArrayList<SplitPermissionInfo> mSplitPermissions = new ArrayList<>();
97 
98     public static final class SharedLibraryEntry {
99         public final String name;
100         public final String filename;
101         public final String[] dependencies;
102 
SharedLibraryEntry(String name, String filename, String[] dependencies)103         SharedLibraryEntry(String name, String filename, String[] dependencies) {
104             this.name = name;
105             this.filename = filename;
106             this.dependencies = dependencies;
107         }
108     }
109 
110     // These are the built-in shared libraries that were read from the
111     // system configuration files. Keys are the library names; values are
112     // the individual entries that contain information such as filename
113     // and dependencies.
114     final ArrayMap<String, SharedLibraryEntry> mSharedLibraries = new ArrayMap<>();
115 
116     // These are the features this devices supports that were read from the
117     // system configuration files.
118     final ArrayMap<String, FeatureInfo> mAvailableFeatures = new ArrayMap<>();
119 
120     // These are the features which this device doesn't support; the OEM
121     // partition uses these to opt-out of features from the system image.
122     final ArraySet<String> mUnavailableFeatures = new ArraySet<>();
123 
124     public static final class PermissionEntry {
125         public final String name;
126         public int[] gids;
127         public boolean perUser;
128 
PermissionEntry(String name, boolean perUser)129         PermissionEntry(String name, boolean perUser) {
130             this.name = name;
131             this.perUser = perUser;
132         }
133     }
134 
135     // These are the permission -> gid mappings that were read from the
136     // system configuration files.
137     final ArrayMap<String, PermissionEntry> mPermissions = new ArrayMap<>();
138 
139     // These are the packages that are white-listed to be able to run in the
140     // background while in power save mode (but not whitelisted from device idle modes),
141     // as read from the configuration files.
142     final ArraySet<String> mAllowInPowerSaveExceptIdle = new ArraySet<>();
143 
144     // These are the packages that are white-listed to be able to run in the
145     // background while in power save mode, as read from the configuration files.
146     final ArraySet<String> mAllowInPowerSave = new ArraySet<>();
147 
148     // These are the packages that are white-listed to be able to run in the
149     // background while in data-usage save mode, as read from the configuration files.
150     final ArraySet<String> mAllowInDataUsageSave = new ArraySet<>();
151 
152     // These are the packages that are white-listed to be able to run background location
153     // without throttling, as read from the configuration files.
154     final ArraySet<String> mAllowUnthrottledLocation = new ArraySet<>();
155 
156     // These are the packages that are white-listed to be able to retrieve location even when user
157     // location settings are off, for emergency purposes, as read from the configuration files.
158     final ArraySet<String> mAllowIgnoreLocationSettings = new ArraySet<>();
159 
160     // These are the action strings of broadcasts which are whitelisted to
161     // be delivered anonymously even to apps which target O+.
162     final ArraySet<String> mAllowImplicitBroadcasts = new ArraySet<>();
163 
164     // These are the package names of apps which should be in the 'always'
165     // URL-handling state upon factory reset.
166     final ArraySet<String> mLinkedApps = new ArraySet<>();
167 
168     // These are the packages that are whitelisted to be able to run as system user
169     final ArraySet<String> mSystemUserWhitelistedApps = new ArraySet<>();
170 
171     // These are the packages that should not run under system user
172     final ArraySet<String> mSystemUserBlacklistedApps = new ArraySet<>();
173 
174     // These are the components that are enabled by default as VR mode listener services.
175     final ArraySet<ComponentName> mDefaultVrComponents = new ArraySet<>();
176 
177     // These are the permitted backup transport service components
178     final ArraySet<ComponentName> mBackupTransportWhitelist = new ArraySet<>();
179 
180     // These are packages mapped to maps of component class name to default enabled state.
181     final ArrayMap<String, ArrayMap<String, Boolean>> mPackageComponentEnabledState =
182             new ArrayMap<>();
183 
184     // Package names that are exempted from private API blacklisting
185     final ArraySet<String> mHiddenApiPackageWhitelist = new ArraySet<>();
186 
187     // The list of carrier applications which should be disabled until used.
188     // This function suppresses update notifications for these pre-installed apps.
189     // In SubscriptionInfoUpdater, the listed applications are disabled until used when all of the
190     // following conditions are met.
191     // 1. Not currently carrier-privileged according to the inserted SIM
192     // 2. Pre-installed
193     // 3. In the default state (enabled but not explicitly)
194     // And SubscriptionInfoUpdater undoes this and marks the app enabled when a SIM is inserted
195     // that marks the app as carrier privileged. It also grants the app default permissions
196     // for Phone and Location. As such, apps MUST only ever be added to this list if they
197     // obtain user consent to access their location through other means.
198     final ArraySet<String> mDisabledUntilUsedPreinstalledCarrierApps = new ArraySet<>();
199 
200     // These are the packages of carrier-associated apps which should be disabled until used until
201     // a SIM is inserted which grants carrier privileges to that carrier app.
202     final ArrayMap<String, List<CarrierAssociatedAppEntry>>
203             mDisabledUntilUsedPreinstalledCarrierAssociatedApps = new ArrayMap<>();
204 
205     final ArrayMap<String, ArraySet<String>> mPrivAppPermissions = new ArrayMap<>();
206     final ArrayMap<String, ArraySet<String>> mPrivAppDenyPermissions = new ArrayMap<>();
207 
208     final ArrayMap<String, ArraySet<String>> mVendorPrivAppPermissions = new ArrayMap<>();
209     final ArrayMap<String, ArraySet<String>> mVendorPrivAppDenyPermissions = new ArrayMap<>();
210 
211     final ArrayMap<String, ArraySet<String>> mProductPrivAppPermissions = new ArrayMap<>();
212     final ArrayMap<String, ArraySet<String>> mProductPrivAppDenyPermissions = new ArrayMap<>();
213 
214     final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppPermissions = new ArrayMap<>();
215     final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppDenyPermissions = new ArrayMap<>();
216 
217     final ArrayMap<String, ArrayMap<String, Boolean>> mOemPermissions = new ArrayMap<>();
218 
219     // Allowed associations between applications.  If there are any entries
220     // for an app, those are the only associations allowed; otherwise, all associations
221     // are allowed.  Allowing an association from app A to app B means app A can not
222     // associate with any other apps, but does not limit what apps B can associate with.
223     final ArrayMap<String, ArraySet<String>> mAllowedAssociations = new ArrayMap<>();
224 
225     private final ArraySet<String> mBugreportWhitelistedPackages = new ArraySet<>();
226     private final ArraySet<String> mAppDataIsolationWhitelistedApps = new ArraySet<>();
227 
228     // Map of packagesNames to userTypes. Stored temporarily until cleared by UserManagerService().
229     private ArrayMap<String, Set<String>> mPackageToUserTypeWhitelist = new ArrayMap<>();
230     private ArrayMap<String, Set<String>> mPackageToUserTypeBlacklist = new ArrayMap<>();
231 
232     private final ArraySet<String> mRollbackWhitelistedPackages = new ArraySet<>();
233     private final ArraySet<String> mWhitelistedStagedInstallers = new ArraySet<>();
234 
235     /**
236      * Map of system pre-defined, uniquely named actors; keys are namespace,
237      * value maps actor name to package name.
238      */
239     private Map<String, Map<String, String>> mNamedActors = null;
240 
getInstance()241     public static SystemConfig getInstance() {
242         if (!isSystemProcess()) {
243             Slog.wtf(TAG, "SystemConfig is being accessed by a process other than "
244                     + "system_server.");
245         }
246 
247         synchronized (SystemConfig.class) {
248             if (sInstance == null) {
249                 sInstance = new SystemConfig();
250             }
251             return sInstance;
252         }
253     }
254 
getGlobalGids()255     public int[] getGlobalGids() {
256         return mGlobalGids;
257     }
258 
getSystemPermissions()259     public SparseArray<ArraySet<String>> getSystemPermissions() {
260         return mSystemPermissions;
261     }
262 
getSplitPermissions()263     public ArrayList<SplitPermissionInfo> getSplitPermissions() {
264         return mSplitPermissions;
265     }
266 
getSharedLibraries()267     public ArrayMap<String, SharedLibraryEntry> getSharedLibraries() {
268         return mSharedLibraries;
269     }
270 
getAvailableFeatures()271     public ArrayMap<String, FeatureInfo> getAvailableFeatures() {
272         return mAvailableFeatures;
273     }
274 
getPermissions()275     public ArrayMap<String, PermissionEntry> getPermissions() {
276         return mPermissions;
277     }
278 
getAllowImplicitBroadcasts()279     public ArraySet<String> getAllowImplicitBroadcasts() {
280         return mAllowImplicitBroadcasts;
281     }
282 
getAllowInPowerSaveExceptIdle()283     public ArraySet<String> getAllowInPowerSaveExceptIdle() {
284         return mAllowInPowerSaveExceptIdle;
285     }
286 
getAllowInPowerSave()287     public ArraySet<String> getAllowInPowerSave() {
288         return mAllowInPowerSave;
289     }
290 
getAllowInDataUsageSave()291     public ArraySet<String> getAllowInDataUsageSave() {
292         return mAllowInDataUsageSave;
293     }
294 
getAllowUnthrottledLocation()295     public ArraySet<String> getAllowUnthrottledLocation() {
296         return mAllowUnthrottledLocation;
297     }
298 
getAllowIgnoreLocationSettings()299     public ArraySet<String> getAllowIgnoreLocationSettings() {
300         return mAllowIgnoreLocationSettings;
301     }
302 
getLinkedApps()303     public ArraySet<String> getLinkedApps() {
304         return mLinkedApps;
305     }
306 
getSystemUserWhitelistedApps()307     public ArraySet<String> getSystemUserWhitelistedApps() {
308         return mSystemUserWhitelistedApps;
309     }
310 
getSystemUserBlacklistedApps()311     public ArraySet<String> getSystemUserBlacklistedApps() {
312         return mSystemUserBlacklistedApps;
313     }
314 
getHiddenApiWhitelistedApps()315     public ArraySet<String> getHiddenApiWhitelistedApps() {
316         return mHiddenApiPackageWhitelist;
317     }
318 
getDefaultVrComponents()319     public ArraySet<ComponentName> getDefaultVrComponents() {
320         return mDefaultVrComponents;
321     }
322 
getBackupTransportWhitelist()323     public ArraySet<ComponentName> getBackupTransportWhitelist() {
324         return mBackupTransportWhitelist;
325     }
326 
getComponentsEnabledStates(String packageName)327     public ArrayMap<String, Boolean> getComponentsEnabledStates(String packageName) {
328         return mPackageComponentEnabledState.get(packageName);
329     }
330 
getDisabledUntilUsedPreinstalledCarrierApps()331     public ArraySet<String> getDisabledUntilUsedPreinstalledCarrierApps() {
332         return mDisabledUntilUsedPreinstalledCarrierApps;
333     }
334 
335     public ArrayMap<String, List<CarrierAssociatedAppEntry>>
getDisabledUntilUsedPreinstalledCarrierAssociatedApps()336             getDisabledUntilUsedPreinstalledCarrierAssociatedApps() {
337         return mDisabledUntilUsedPreinstalledCarrierAssociatedApps;
338     }
339 
getPrivAppPermissions(String packageName)340     public ArraySet<String> getPrivAppPermissions(String packageName) {
341         return mPrivAppPermissions.get(packageName);
342     }
343 
getPrivAppDenyPermissions(String packageName)344     public ArraySet<String> getPrivAppDenyPermissions(String packageName) {
345         return mPrivAppDenyPermissions.get(packageName);
346     }
347 
getVendorPrivAppPermissions(String packageName)348     public ArraySet<String> getVendorPrivAppPermissions(String packageName) {
349         return mVendorPrivAppPermissions.get(packageName);
350     }
351 
getVendorPrivAppDenyPermissions(String packageName)352     public ArraySet<String> getVendorPrivAppDenyPermissions(String packageName) {
353         return mVendorPrivAppDenyPermissions.get(packageName);
354     }
355 
getProductPrivAppPermissions(String packageName)356     public ArraySet<String> getProductPrivAppPermissions(String packageName) {
357         return mProductPrivAppPermissions.get(packageName);
358     }
359 
getProductPrivAppDenyPermissions(String packageName)360     public ArraySet<String> getProductPrivAppDenyPermissions(String packageName) {
361         return mProductPrivAppDenyPermissions.get(packageName);
362     }
363 
364     /**
365      * Read from "permission" tags in /system_ext/etc/permissions/*.xml
366      * @return Set of privileged permissions that are explicitly granted.
367      */
getSystemExtPrivAppPermissions(String packageName)368     public ArraySet<String> getSystemExtPrivAppPermissions(String packageName) {
369         return mSystemExtPrivAppPermissions.get(packageName);
370     }
371 
372     /**
373      * Read from "deny-permission" tags in /system_ext/etc/permissions/*.xml
374      * @return Set of privileged permissions that are explicitly denied.
375      */
getSystemExtPrivAppDenyPermissions(String packageName)376     public ArraySet<String> getSystemExtPrivAppDenyPermissions(String packageName) {
377         return mSystemExtPrivAppDenyPermissions.get(packageName);
378     }
379 
getOemPermissions(String packageName)380     public Map<String, Boolean> getOemPermissions(String packageName) {
381         final Map<String, Boolean> oemPermissions = mOemPermissions.get(packageName);
382         if (oemPermissions != null) {
383             return oemPermissions;
384         }
385         return Collections.emptyMap();
386     }
387 
getAllowedAssociations()388     public ArrayMap<String, ArraySet<String>> getAllowedAssociations() {
389         return mAllowedAssociations;
390     }
391 
getBugreportWhitelistedPackages()392     public ArraySet<String> getBugreportWhitelistedPackages() {
393         return mBugreportWhitelistedPackages;
394     }
395 
getRollbackWhitelistedPackages()396     public Set<String> getRollbackWhitelistedPackages() {
397         return mRollbackWhitelistedPackages;
398     }
399 
getWhitelistedStagedInstallers()400     public Set<String> getWhitelistedStagedInstallers() {
401         return mWhitelistedStagedInstallers;
402     }
403 
getAppDataIsolationWhitelistedApps()404     public ArraySet<String> getAppDataIsolationWhitelistedApps() {
405         return mAppDataIsolationWhitelistedApps;
406     }
407 
408     /**
409      * Gets map of packagesNames to userTypes, dictating on which user types each package should be
410      * initially installed, and then removes this map from SystemConfig.
411      * Called by UserManagerService when it is constructed.
412      */
getAndClearPackageToUserTypeWhitelist()413     public ArrayMap<String, Set<String>> getAndClearPackageToUserTypeWhitelist() {
414         ArrayMap<String, Set<String>> r = mPackageToUserTypeWhitelist;
415         mPackageToUserTypeWhitelist = new ArrayMap<>(0);
416         return r;
417     }
418 
419     /**
420      * Gets map of packagesNames to userTypes, dictating on which user types each package should NOT
421      * be initially installed, even if they are whitelisted, and then removes this map from
422      * SystemConfig.
423      * Called by UserManagerService when it is constructed.
424      */
getAndClearPackageToUserTypeBlacklist()425     public ArrayMap<String, Set<String>> getAndClearPackageToUserTypeBlacklist() {
426         ArrayMap<String, Set<String>> r = mPackageToUserTypeBlacklist;
427         mPackageToUserTypeBlacklist = new ArrayMap<>(0);
428         return r;
429     }
430 
431     @NonNull
getNamedActors()432     public Map<String, Map<String, String>> getNamedActors() {
433         return mNamedActors != null ? mNamedActors : Collections.emptyMap();
434     }
435 
436     /**
437      * Only use for testing. Do NOT use in production code.
438      * @param readPermissions false to create an empty SystemConfig; true to read the permissions.
439      */
440     @VisibleForTesting
SystemConfig(boolean readPermissions)441     public SystemConfig(boolean readPermissions) {
442         if (readPermissions) {
443             Slog.w(TAG, "Constructing a test SystemConfig");
444             readAllPermissions();
445         } else {
446             Slog.w(TAG, "Constructing an empty test SystemConfig");
447         }
448     }
449 
SystemConfig()450     SystemConfig() {
451         TimingsTraceLog log = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
452         log.traceBegin("readAllPermissions");
453         try {
454             readAllPermissions();
455         } finally {
456             log.traceEnd();
457         }
458     }
459 
readAllPermissions()460     private void readAllPermissions() {
461         // Read configuration from system
462         readPermissions(Environment.buildPath(
463                 Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL);
464 
465         // Read configuration from the old permissions dir
466         readPermissions(Environment.buildPath(
467                 Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);
468 
469         // Vendors are only allowed to customize these
470         int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS
471                 | ALLOW_ASSOCIATIONS;
472         if (Build.VERSION.FIRST_SDK_INT <= Build.VERSION_CODES.O_MR1) {
473             // For backward compatibility
474             vendorPermissionFlag |= (ALLOW_PERMISSIONS | ALLOW_APP_CONFIGS);
475         }
476         readPermissions(Environment.buildPath(
477                 Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
478         readPermissions(Environment.buildPath(
479                 Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag);
480 
481         String vendorSkuProperty = SystemProperties.get(VENDOR_SKU_PROPERTY, "");
482         if (!vendorSkuProperty.isEmpty()) {
483             String vendorSkuDir = "sku_" + vendorSkuProperty;
484             readPermissions(Environment.buildPath(
485                     Environment.getVendorDirectory(), "etc", "sysconfig", vendorSkuDir),
486                     vendorPermissionFlag);
487             readPermissions(Environment.buildPath(
488                     Environment.getVendorDirectory(), "etc", "permissions", vendorSkuDir),
489                     vendorPermissionFlag);
490         }
491 
492         // Allow ODM to customize system configs as much as Vendor, because /odm is another
493         // vendor partition other than /vendor.
494         int odmPermissionFlag = vendorPermissionFlag;
495         readPermissions(Environment.buildPath(
496                 Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);
497         readPermissions(Environment.buildPath(
498                 Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);
499 
500         String skuProperty = SystemProperties.get(SKU_PROPERTY, "");
501         if (!skuProperty.isEmpty()) {
502             String skuDir = "sku_" + skuProperty;
503 
504             readPermissions(Environment.buildPath(
505                     Environment.getOdmDirectory(), "etc", "sysconfig", skuDir), odmPermissionFlag);
506             readPermissions(Environment.buildPath(
507                     Environment.getOdmDirectory(), "etc", "permissions", skuDir),
508                     odmPermissionFlag);
509         }
510 
511         // Allow OEM to customize these
512         int oemPermissionFlag = ALLOW_FEATURES | ALLOW_OEM_PERMISSIONS | ALLOW_ASSOCIATIONS;
513         readPermissions(Environment.buildPath(
514                 Environment.getOemDirectory(), "etc", "sysconfig"), oemPermissionFlag);
515         readPermissions(Environment.buildPath(
516                 Environment.getOemDirectory(), "etc", "permissions"), oemPermissionFlag);
517 
518         // Allow Product to customize all system configs
519         readPermissions(Environment.buildPath(
520                 Environment.getProductDirectory(), "etc", "sysconfig"), ALLOW_ALL);
521         readPermissions(Environment.buildPath(
522                 Environment.getProductDirectory(), "etc", "permissions"), ALLOW_ALL);
523 
524         // Allow /system_ext to customize all system configs
525         readPermissions(Environment.buildPath(
526                 Environment.getSystemExtDirectory(), "etc", "sysconfig"), ALLOW_ALL);
527         readPermissions(Environment.buildPath(
528                 Environment.getSystemExtDirectory(), "etc", "permissions"), ALLOW_ALL);
529 
530         // Skip loading configuration from apex if it is not a system process.
531         if (!isSystemProcess()) {
532             return;
533         }
534         // Read configuration of libs from apex module.
535         // TODO: Use a solid way to filter apex module folders?
536         for (File f: FileUtils.listFilesOrEmpty(Environment.getApexDirectory())) {
537             if (f.isFile() || f.getPath().contains("@")) {
538                 continue;
539             }
540             readPermissions(Environment.buildPath(f, "etc", "permissions"), ALLOW_LIBS);
541         }
542     }
543 
544     @VisibleForTesting
readPermissions(File libraryDir, int permissionFlag)545     public void readPermissions(File libraryDir, int permissionFlag) {
546         // Read permissions from given directory.
547         if (!libraryDir.exists() || !libraryDir.isDirectory()) {
548             if (permissionFlag == ALLOW_ALL) {
549                 Slog.w(TAG, "No directory " + libraryDir + ", skipping");
550             }
551             return;
552         }
553         if (!libraryDir.canRead()) {
554             Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
555             return;
556         }
557 
558         // Iterate over the files in the directory and scan .xml files
559         File platformFile = null;
560         for (File f : libraryDir.listFiles()) {
561             if (!f.isFile()) {
562                 continue;
563             }
564 
565             // We'll read platform.xml last
566             if (f.getPath().endsWith("etc/permissions/platform.xml")) {
567                 platformFile = f;
568                 continue;
569             }
570 
571             if (!f.getPath().endsWith(".xml")) {
572                 Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
573                 continue;
574             }
575             if (!f.canRead()) {
576                 Slog.w(TAG, "Permissions library file " + f + " cannot be read");
577                 continue;
578             }
579 
580             readPermissionsFromXml(f, permissionFlag);
581         }
582 
583         // Read platform permissions last so it will take precedence
584         if (platformFile != null) {
585             readPermissionsFromXml(platformFile, permissionFlag);
586         }
587     }
588 
logNotAllowedInPartition(String name, File permFile, XmlPullParser parser)589     private void logNotAllowedInPartition(String name, File permFile, XmlPullParser parser) {
590         Slog.w(TAG, "<" + name + "> not allowed in partition of "
591                 + permFile + " at " + parser.getPositionDescription());
592     }
593 
readPermissionsFromXml(File permFile, int permissionFlag)594     private void readPermissionsFromXml(File permFile, int permissionFlag) {
595         FileReader permReader = null;
596         try {
597             permReader = new FileReader(permFile);
598         } catch (FileNotFoundException e) {
599             Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
600             return;
601         }
602         Slog.i(TAG, "Reading permissions from " + permFile);
603 
604         final boolean lowRam = ActivityManager.isLowRamDeviceStatic();
605 
606         try {
607             XmlPullParser parser = Xml.newPullParser();
608             parser.setInput(permReader);
609 
610             int type;
611             while ((type=parser.next()) != parser.START_TAG
612                        && type != parser.END_DOCUMENT) {
613                 ;
614             }
615 
616             if (type != parser.START_TAG) {
617                 throw new XmlPullParserException("No start tag found");
618             }
619 
620             if (!parser.getName().equals("permissions") && !parser.getName().equals("config")) {
621                 throw new XmlPullParserException("Unexpected start tag in " + permFile
622                         + ": found " + parser.getName() + ", expected 'permissions' or 'config'");
623             }
624 
625             final boolean allowAll = permissionFlag == ALLOW_ALL;
626             final boolean allowLibs = (permissionFlag & ALLOW_LIBS) != 0;
627             final boolean allowFeatures = (permissionFlag & ALLOW_FEATURES) != 0;
628             final boolean allowPermissions = (permissionFlag & ALLOW_PERMISSIONS) != 0;
629             final boolean allowAppConfigs = (permissionFlag & ALLOW_APP_CONFIGS) != 0;
630             final boolean allowPrivappPermissions = (permissionFlag & ALLOW_PRIVAPP_PERMISSIONS)
631                     != 0;
632             final boolean allowOemPermissions = (permissionFlag & ALLOW_OEM_PERMISSIONS) != 0;
633             final boolean allowApiWhitelisting = (permissionFlag & ALLOW_HIDDENAPI_WHITELISTING)
634                     != 0;
635             final boolean allowAssociations = (permissionFlag & ALLOW_ASSOCIATIONS) != 0;
636             while (true) {
637                 XmlUtils.nextElement(parser);
638                 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
639                     break;
640                 }
641 
642                 String name = parser.getName();
643                 if (name == null) {
644                     XmlUtils.skipCurrentTag(parser);
645                     continue;
646                 }
647                 switch (name) {
648                     case "group": {
649                         if (allowAll) {
650                             String gidStr = parser.getAttributeValue(null, "gid");
651                             if (gidStr != null) {
652                                 int gid = android.os.Process.getGidForName(gidStr);
653                                 mGlobalGids = appendInt(mGlobalGids, gid);
654                             } else {
655                                 Slog.w(TAG, "<" + name + "> without gid in " + permFile + " at "
656                                         + parser.getPositionDescription());
657                             }
658                         } else {
659                             logNotAllowedInPartition(name, permFile, parser);
660                         }
661                         XmlUtils.skipCurrentTag(parser);
662                     } break;
663                     case "permission": {
664                         if (allowPermissions) {
665                             String perm = parser.getAttributeValue(null, "name");
666                             if (perm == null) {
667                                 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
668                                         + parser.getPositionDescription());
669                                 XmlUtils.skipCurrentTag(parser);
670                                 break;
671                             }
672                             perm = perm.intern();
673                             readPermission(parser, perm);
674                         } else {
675                             logNotAllowedInPartition(name, permFile, parser);
676                             XmlUtils.skipCurrentTag(parser);
677                         }
678                     } break;
679                     case "assign-permission": {
680                         if (allowPermissions) {
681                             String perm = parser.getAttributeValue(null, "name");
682                             if (perm == null) {
683                                 Slog.w(TAG, "<" + name + "> without name in " + permFile
684                                         + " at " + parser.getPositionDescription());
685                                 XmlUtils.skipCurrentTag(parser);
686                                 break;
687                             }
688                             String uidStr = parser.getAttributeValue(null, "uid");
689                             if (uidStr == null) {
690                                 Slog.w(TAG, "<" + name + "> without uid in " + permFile
691                                         + " at " + parser.getPositionDescription());
692                                 XmlUtils.skipCurrentTag(parser);
693                                 break;
694                             }
695                             int uid = Process.getUidForName(uidStr);
696                             if (uid < 0) {
697                                 Slog.w(TAG, "<" + name + "> with unknown uid \""
698                                         + uidStr + "  in " + permFile + " at "
699                                         + parser.getPositionDescription());
700                                 XmlUtils.skipCurrentTag(parser);
701                                 break;
702                             }
703                             perm = perm.intern();
704                             ArraySet<String> perms = mSystemPermissions.get(uid);
705                             if (perms == null) {
706                                 perms = new ArraySet<String>();
707                                 mSystemPermissions.put(uid, perms);
708                             }
709                             perms.add(perm);
710                         } else {
711                             logNotAllowedInPartition(name, permFile, parser);
712                         }
713                         XmlUtils.skipCurrentTag(parser);
714                     } break;
715                     case "split-permission": {
716                         if (allowPermissions) {
717                             readSplitPermission(parser, permFile);
718                         } else {
719                             logNotAllowedInPartition(name, permFile, parser);
720                             XmlUtils.skipCurrentTag(parser);
721                         }
722                     } break;
723                     case "library": {
724                         if (allowLibs) {
725                             String lname = parser.getAttributeValue(null, "name");
726                             String lfile = parser.getAttributeValue(null, "file");
727                             String ldependency = parser.getAttributeValue(null, "dependency");
728                             if (lname == null) {
729                                 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
730                                         + parser.getPositionDescription());
731                             } else if (lfile == null) {
732                                 Slog.w(TAG, "<" + name + "> without file in " + permFile + " at "
733                                         + parser.getPositionDescription());
734                             } else {
735                                 //Log.i(TAG, "Got library " + lname + " in " + lfile);
736                                 SharedLibraryEntry entry = new SharedLibraryEntry(lname, lfile,
737                                         ldependency == null ? new String[0] : ldependency.split(":"));
738                                 mSharedLibraries.put(lname, entry);
739                             }
740                         } else {
741                             logNotAllowedInPartition(name, permFile, parser);
742                         }
743                         XmlUtils.skipCurrentTag(parser);
744                     } break;
745                     case "feature": {
746                         if (allowFeatures) {
747                             String fname = parser.getAttributeValue(null, "name");
748                             int fversion = XmlUtils.readIntAttribute(parser, "version", 0);
749                             boolean allowed;
750                             if (!lowRam) {
751                                 allowed = true;
752                             } else {
753                                 String notLowRam = parser.getAttributeValue(null, "notLowRam");
754                                 allowed = !"true".equals(notLowRam);
755                             }
756                             if (fname == null) {
757                                 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
758                                         + parser.getPositionDescription());
759                             } else if (allowed) {
760                                 addFeature(fname, fversion);
761                             }
762                         } else {
763                             logNotAllowedInPartition(name, permFile, parser);
764                         }
765                         XmlUtils.skipCurrentTag(parser);
766                     } break;
767                     case "unavailable-feature": {
768                         if (allowFeatures) {
769                             String fname = parser.getAttributeValue(null, "name");
770                             if (fname == null) {
771                                 Slog.w(TAG, "<" + name + "> without name in " + permFile
772                                         + " at " + parser.getPositionDescription());
773                             } else {
774                                 mUnavailableFeatures.add(fname);
775                             }
776                         } else {
777                             logNotAllowedInPartition(name, permFile, parser);
778                         }
779                         XmlUtils.skipCurrentTag(parser);
780                     } break;
781                     case "allow-in-power-save-except-idle": {
782                         if (allowAll) {
783                             String pkgname = parser.getAttributeValue(null, "package");
784                             if (pkgname == null) {
785                                 Slog.w(TAG, "<" + name + "> without package in "
786                                         + permFile + " at " + parser.getPositionDescription());
787                             } else {
788                                 mAllowInPowerSaveExceptIdle.add(pkgname);
789                             }
790                         } else {
791                             logNotAllowedInPartition(name, permFile, parser);
792                         }
793                         XmlUtils.skipCurrentTag(parser);
794                     } break;
795                     case "allow-in-power-save": {
796                         if (allowAll) {
797                             String pkgname = parser.getAttributeValue(null, "package");
798                             if (pkgname == null) {
799                                 Slog.w(TAG, "<" + name + "> without package in "
800                                         + permFile + " at " + parser.getPositionDescription());
801                             } else {
802                                 mAllowInPowerSave.add(pkgname);
803                             }
804                         } else {
805                             logNotAllowedInPartition(name, permFile, parser);
806                         }
807                         XmlUtils.skipCurrentTag(parser);
808                     } break;
809                     case "allow-in-data-usage-save": {
810                         if (allowAll) {
811                             String pkgname = parser.getAttributeValue(null, "package");
812                             if (pkgname == null) {
813                                 Slog.w(TAG, "<" + name + "> without package in "
814                                         + permFile + " at " + parser.getPositionDescription());
815                             } else {
816                                 mAllowInDataUsageSave.add(pkgname);
817                             }
818                         } else {
819                             logNotAllowedInPartition(name, permFile, parser);
820                         }
821                         XmlUtils.skipCurrentTag(parser);
822                     } break;
823                     case "allow-unthrottled-location": {
824                         if (allowAll) {
825                             String pkgname = parser.getAttributeValue(null, "package");
826                             if (pkgname == null) {
827                                 Slog.w(TAG, "<" + name + "> without package in "
828                                         + permFile + " at " + parser.getPositionDescription());
829                             } else {
830                                 mAllowUnthrottledLocation.add(pkgname);
831                             }
832                         } else {
833                             logNotAllowedInPartition(name, permFile, parser);
834                         }
835                         XmlUtils.skipCurrentTag(parser);
836                     } break;
837                     case "allow-ignore-location-settings": {
838                         if (allowAll) {
839                             String pkgname = parser.getAttributeValue(null, "package");
840                             if (pkgname == null) {
841                                 Slog.w(TAG, "<" + name + "> without package in "
842                                         + permFile + " at " + parser.getPositionDescription());
843                             } else {
844                                 mAllowIgnoreLocationSettings.add(pkgname);
845                             }
846                         } else {
847                             logNotAllowedInPartition(name, permFile, parser);
848                         }
849                         XmlUtils.skipCurrentTag(parser);
850                     } break;
851                     case "allow-implicit-broadcast": {
852                         if (allowAll) {
853                             String action = parser.getAttributeValue(null, "action");
854                             if (action == null) {
855                                 Slog.w(TAG, "<" + name + "> without action in "
856                                         + permFile + " at " + parser.getPositionDescription());
857                             } else {
858                                 mAllowImplicitBroadcasts.add(action);
859                             }
860                         } else {
861                             logNotAllowedInPartition(name, permFile, parser);
862                         }
863                         XmlUtils.skipCurrentTag(parser);
864                     } break;
865                     case "app-link": {
866                         if (allowAppConfigs) {
867                             String pkgname = parser.getAttributeValue(null, "package");
868                             if (pkgname == null) {
869                                 Slog.w(TAG, "<" + name + "> without package in " + permFile
870                                         + " at " + parser.getPositionDescription());
871                             } else {
872                                 mLinkedApps.add(pkgname);
873                             }
874                         } else {
875                             logNotAllowedInPartition(name, permFile, parser);
876                         }
877                         XmlUtils.skipCurrentTag(parser);
878                     } break;
879                     case "system-user-whitelisted-app": {
880                         if (allowAppConfigs) {
881                             String pkgname = parser.getAttributeValue(null, "package");
882                             if (pkgname == null) {
883                                 Slog.w(TAG, "<" + name + "> without package in "
884                                         + permFile + " at " + parser.getPositionDescription());
885                             } else {
886                                 mSystemUserWhitelistedApps.add(pkgname);
887                             }
888                         } else {
889                             logNotAllowedInPartition(name, permFile, parser);
890                         }
891                         XmlUtils.skipCurrentTag(parser);
892                     } break;
893                     case "system-user-blacklisted-app": {
894                         if (allowAppConfigs) {
895                             String pkgname = parser.getAttributeValue(null, "package");
896                             if (pkgname == null) {
897                                 Slog.w(TAG, "<" + name + "> without package in "
898                                         + permFile + " at " + parser.getPositionDescription());
899                             } else {
900                                 mSystemUserBlacklistedApps.add(pkgname);
901                             }
902                         } else {
903                             logNotAllowedInPartition(name, permFile, parser);
904                         }
905                         XmlUtils.skipCurrentTag(parser);
906                     } break;
907                     case "default-enabled-vr-app": {
908                         if (allowAppConfigs) {
909                             String pkgname = parser.getAttributeValue(null, "package");
910                             String clsname = parser.getAttributeValue(null, "class");
911                             if (pkgname == null) {
912                                 Slog.w(TAG, "<" + name + "> without package in "
913                                         + permFile + " at " + parser.getPositionDescription());
914                             } else if (clsname == null) {
915                                 Slog.w(TAG, "<" + name + "> without class in "
916                                         + permFile + " at " + parser.getPositionDescription());
917                             } else {
918                                 mDefaultVrComponents.add(new ComponentName(pkgname, clsname));
919                             }
920                         } else {
921                             logNotAllowedInPartition(name, permFile, parser);
922                         }
923                         XmlUtils.skipCurrentTag(parser);
924                     } break;
925                     case "component-override": {
926                         readComponentOverrides(parser, permFile);
927                     } break;
928                     case "backup-transport-whitelisted-service": {
929                         if (allowFeatures) {
930                             String serviceName = parser.getAttributeValue(null, "service");
931                             if (serviceName == null) {
932                                 Slog.w(TAG, "<" + name + "> without service in "
933                                         + permFile + " at " + parser.getPositionDescription());
934                             } else {
935                                 ComponentName cn = ComponentName.unflattenFromString(serviceName);
936                                 if (cn == null) {
937                                     Slog.w(TAG, "<" + name + "> with invalid service name "
938                                             + serviceName + " in " + permFile
939                                             + " at " + parser.getPositionDescription());
940                                 } else {
941                                     mBackupTransportWhitelist.add(cn);
942                                 }
943                             }
944                         } else {
945                             logNotAllowedInPartition(name, permFile, parser);
946                         }
947                         XmlUtils.skipCurrentTag(parser);
948                     } break;
949                     case "disabled-until-used-preinstalled-carrier-associated-app": {
950                         if (allowAppConfigs) {
951                             String pkgname = parser.getAttributeValue(null, "package");
952                             String carrierPkgname = parser.getAttributeValue(null,
953                                     "carrierAppPackage");
954                             if (pkgname == null || carrierPkgname == null) {
955                                 Slog.w(TAG, "<" + name
956                                         + "> without package or carrierAppPackage in " + permFile
957                                         + " at " + parser.getPositionDescription());
958                             } else {
959                                 // APKs added to system images via OTA should specify the addedInSdk
960                                 // attribute, otherwise they may be enabled-by-default in too many
961                                 // cases. See CarrierAppUtils for more info.
962                                 int addedInSdk = CarrierAssociatedAppEntry.SDK_UNSPECIFIED;
963                                 String addedInSdkStr = parser.getAttributeValue(null, "addedInSdk");
964                                 if (!TextUtils.isEmpty(addedInSdkStr)) {
965                                     try {
966                                         addedInSdk = Integer.parseInt(addedInSdkStr);
967                                     } catch (NumberFormatException e) {
968                                         Slog.w(TAG, "<" + name + "> addedInSdk not an integer in "
969                                                 + permFile + " at "
970                                                 + parser.getPositionDescription());
971                                         XmlUtils.skipCurrentTag(parser);
972                                         break;
973                                     }
974                                 }
975                                 List<CarrierAssociatedAppEntry> associatedPkgs =
976                                         mDisabledUntilUsedPreinstalledCarrierAssociatedApps.get(
977                                                 carrierPkgname);
978                                 if (associatedPkgs == null) {
979                                     associatedPkgs = new ArrayList<>();
980                                     mDisabledUntilUsedPreinstalledCarrierAssociatedApps.put(
981                                             carrierPkgname, associatedPkgs);
982                                 }
983                                 associatedPkgs.add(
984                                         new CarrierAssociatedAppEntry(pkgname, addedInSdk));
985                             }
986                         } else {
987                             logNotAllowedInPartition(name, permFile, parser);
988                         }
989                         XmlUtils.skipCurrentTag(parser);
990                     } break;
991                     case "disabled-until-used-preinstalled-carrier-app": {
992                         if (allowAppConfigs) {
993                             String pkgname = parser.getAttributeValue(null, "package");
994                             if (pkgname == null) {
995                                 Slog.w(TAG,
996                                         "<" + name + "> without "
997                                                 + "package in " + permFile + " at "
998                                                 + parser.getPositionDescription());
999                             } else {
1000                                 mDisabledUntilUsedPreinstalledCarrierApps.add(pkgname);
1001                             }
1002                         } else {
1003                             logNotAllowedInPartition(name, permFile, parser);
1004                         }
1005                         XmlUtils.skipCurrentTag(parser);
1006                     } break;
1007                     case "privapp-permissions": {
1008                         if (allowPrivappPermissions) {
1009                             // privapp permissions from system, vendor, product and system_ext
1010                             // partitions are stored separately. This is to prevent xml files in
1011                             // the vendor partition from granting permissions to priv apps in the
1012                             // system partition and vice versa.
1013                             boolean vendor = permFile.toPath().startsWith(
1014                                     Environment.getVendorDirectory().toPath() + "/")
1015                                     || permFile.toPath().startsWith(
1016                                     Environment.getOdmDirectory().toPath() + "/");
1017                             boolean product = permFile.toPath().startsWith(
1018                                     Environment.getProductDirectory().toPath() + "/");
1019                             boolean systemExt = permFile.toPath().startsWith(
1020                                     Environment.getSystemExtDirectory().toPath() + "/");
1021                             if (vendor) {
1022                                 readPrivAppPermissions(parser, mVendorPrivAppPermissions,
1023                                         mVendorPrivAppDenyPermissions);
1024                             } else if (product) {
1025                                 readPrivAppPermissions(parser, mProductPrivAppPermissions,
1026                                         mProductPrivAppDenyPermissions);
1027                             } else if (systemExt) {
1028                                 readPrivAppPermissions(parser, mSystemExtPrivAppPermissions,
1029                                         mSystemExtPrivAppDenyPermissions);
1030                             } else {
1031                                 readPrivAppPermissions(parser, mPrivAppPermissions,
1032                                         mPrivAppDenyPermissions);
1033                             }
1034                         } else {
1035                             logNotAllowedInPartition(name, permFile, parser);
1036                             XmlUtils.skipCurrentTag(parser);
1037                         }
1038                     } break;
1039                     case "oem-permissions": {
1040                         if (allowOemPermissions) {
1041                             readOemPermissions(parser);
1042                         } else {
1043                             logNotAllowedInPartition(name, permFile, parser);
1044                             XmlUtils.skipCurrentTag(parser);
1045                         }
1046                     } break;
1047                     case "hidden-api-whitelisted-app": {
1048                         if (allowApiWhitelisting) {
1049                             String pkgname = parser.getAttributeValue(null, "package");
1050                             if (pkgname == null) {
1051                                 Slog.w(TAG, "<" + name + "> without package in "
1052                                         + permFile + " at " + parser.getPositionDescription());
1053                             } else {
1054                                 mHiddenApiPackageWhitelist.add(pkgname);
1055                             }
1056                         } else {
1057                             logNotAllowedInPartition(name, permFile, parser);
1058                         }
1059                         XmlUtils.skipCurrentTag(parser);
1060                     } break;
1061                     case "allow-association": {
1062                         if (allowAssociations) {
1063                             String target = parser.getAttributeValue(null, "target");
1064                             if (target == null) {
1065                                 Slog.w(TAG, "<" + name + "> without target in " + permFile
1066                                         + " at " + parser.getPositionDescription());
1067                                 XmlUtils.skipCurrentTag(parser);
1068                                 break;
1069                             }
1070                             String allowed = parser.getAttributeValue(null, "allowed");
1071                             if (allowed == null) {
1072                                 Slog.w(TAG, "<" + name + "> without allowed in " + permFile
1073                                         + " at " + parser.getPositionDescription());
1074                                 XmlUtils.skipCurrentTag(parser);
1075                                 break;
1076                             }
1077                             target = target.intern();
1078                             allowed = allowed.intern();
1079                             ArraySet<String> associations = mAllowedAssociations.get(target);
1080                             if (associations == null) {
1081                                 associations = new ArraySet<>();
1082                                 mAllowedAssociations.put(target, associations);
1083                             }
1084                             Slog.i(TAG, "Adding association: " + target + " <- " + allowed);
1085                             associations.add(allowed);
1086                         } else {
1087                             logNotAllowedInPartition(name, permFile, parser);
1088                         }
1089                         XmlUtils.skipCurrentTag(parser);
1090                     } break;
1091                     case "app-data-isolation-whitelisted-app": {
1092                         String pkgname = parser.getAttributeValue(null, "package");
1093                         if (pkgname == null) {
1094                             Slog.w(TAG, "<" + name + "> without package in " + permFile
1095                                     + " at " + parser.getPositionDescription());
1096                         } else {
1097                             mAppDataIsolationWhitelistedApps.add(pkgname);
1098                         }
1099                         XmlUtils.skipCurrentTag(parser);
1100                     } break;
1101                     case "bugreport-whitelisted": {
1102                         String pkgname = parser.getAttributeValue(null, "package");
1103                         if (pkgname == null) {
1104                             Slog.w(TAG, "<" + name + "> without package in " + permFile
1105                                     + " at " + parser.getPositionDescription());
1106                         } else {
1107                             mBugreportWhitelistedPackages.add(pkgname);
1108                         }
1109                         XmlUtils.skipCurrentTag(parser);
1110                     } break;
1111                     case "install-in-user-type": {
1112                         // NB: We allow any directory permission to declare install-in-user-type.
1113                         readInstallInUserType(parser,
1114                                 mPackageToUserTypeWhitelist, mPackageToUserTypeBlacklist);
1115                     } break;
1116                     case "named-actor": {
1117                         String namespace = TextUtils.safeIntern(
1118                                 parser.getAttributeValue(null, "namespace"));
1119                         String actorName = parser.getAttributeValue(null, "name");
1120                         String pkgName = TextUtils.safeIntern(
1121                                 parser.getAttributeValue(null, "package"));
1122                         if (TextUtils.isEmpty(namespace)) {
1123                             Slog.wtf(TAG, "<" + name + "> without namespace in " + permFile
1124                                     + " at " + parser.getPositionDescription());
1125                         } else if (TextUtils.isEmpty(actorName)) {
1126                             Slog.wtf(TAG, "<" + name + "> without actor name in " + permFile
1127                                     + " at " + parser.getPositionDescription());
1128                         } else if (TextUtils.isEmpty(pkgName)) {
1129                             Slog.wtf(TAG, "<" + name + "> without package name in " + permFile
1130                                     + " at " + parser.getPositionDescription());
1131                         } else if ("android".equalsIgnoreCase(namespace)) {
1132                             throw new IllegalStateException("Defining " + actorName + " as "
1133                                     + pkgName + " for the android namespace is not allowed");
1134                         } else {
1135                             if (mNamedActors == null) {
1136                                 mNamedActors = new ArrayMap<>();
1137                             }
1138 
1139                             Map<String, String> nameToPkgMap = mNamedActors.get(namespace);
1140                             if (nameToPkgMap == null) {
1141                                 nameToPkgMap = new ArrayMap<>();
1142                                 mNamedActors.put(namespace, nameToPkgMap);
1143                             } else if (nameToPkgMap.containsKey(actorName)) {
1144                                 String existing = nameToPkgMap.get(actorName);
1145                                 throw new IllegalStateException("Duplicate actor definition for "
1146                                         + namespace + "/" + actorName
1147                                         + "; defined as both " + existing + " and " + pkgName);
1148                             }
1149 
1150                             nameToPkgMap.put(actorName, pkgName);
1151                         }
1152                         XmlUtils.skipCurrentTag(parser);
1153                     } break;
1154                     case "rollback-whitelisted-app": {
1155                         String pkgname = parser.getAttributeValue(null, "package");
1156                         if (pkgname == null) {
1157                             Slog.w(TAG, "<" + name + "> without package in " + permFile
1158                                     + " at " + parser.getPositionDescription());
1159                         } else {
1160                             mRollbackWhitelistedPackages.add(pkgname);
1161                         }
1162                         XmlUtils.skipCurrentTag(parser);
1163                     } break;
1164                     case "whitelisted-staged-installer": {
1165                         if (allowAppConfigs) {
1166                             String pkgname = parser.getAttributeValue(null, "package");
1167                             if (pkgname == null) {
1168                                 Slog.w(TAG, "<" + name + "> without package in " + permFile
1169                                         + " at " + parser.getPositionDescription());
1170                             } else {
1171                                 mWhitelistedStagedInstallers.add(pkgname);
1172                             }
1173                         } else {
1174                             logNotAllowedInPartition(name, permFile, parser);
1175                         }
1176                         XmlUtils.skipCurrentTag(parser);
1177                     } break;
1178                     default: {
1179                         Slog.w(TAG, "Tag " + name + " is unknown in "
1180                                 + permFile + " at " + parser.getPositionDescription());
1181                         XmlUtils.skipCurrentTag(parser);
1182                     } break;
1183                 }
1184             }
1185         } catch (XmlPullParserException e) {
1186             Slog.w(TAG, "Got exception parsing permissions.", e);
1187         } catch (IOException e) {
1188             Slog.w(TAG, "Got exception parsing permissions.", e);
1189         } finally {
1190             IoUtils.closeQuietly(permReader);
1191         }
1192 
1193         // Some devices can be field-converted to FBE, so offer to splice in
1194         // those features if not already defined by the static config
1195         if (StorageManager.isFileEncryptedNativeOnly()) {
1196             addFeature(PackageManager.FEATURE_FILE_BASED_ENCRYPTION, 0);
1197             addFeature(PackageManager.FEATURE_SECURELY_REMOVES_USERS, 0);
1198         }
1199 
1200         // Help legacy devices that may not have updated their static config
1201         if (StorageManager.hasAdoptable()) {
1202             addFeature(PackageManager.FEATURE_ADOPTABLE_STORAGE, 0);
1203         }
1204 
1205         if (ActivityManager.isLowRamDeviceStatic()) {
1206             addFeature(PackageManager.FEATURE_RAM_LOW, 0);
1207         } else {
1208             addFeature(PackageManager.FEATURE_RAM_NORMAL, 0);
1209         }
1210 
1211         if (IncrementalManager.isFeatureEnabled()) {
1212             addFeature(PackageManager.FEATURE_INCREMENTAL_DELIVERY, 0);
1213         }
1214 
1215         if (PackageManager.APP_ENUMERATION_ENABLED_BY_DEFAULT) {
1216             addFeature(PackageManager.FEATURE_APP_ENUMERATION, 0);
1217         }
1218 
1219         if (Build.VERSION.FIRST_SDK_INT >= Build.VERSION_CODES.Q) {
1220             addFeature(PackageManager.FEATURE_IPSEC_TUNNELS, 0);
1221         }
1222 
1223         for (String featureName : mUnavailableFeatures) {
1224             removeFeature(featureName);
1225         }
1226     }
1227 
addFeature(String name, int version)1228     private void addFeature(String name, int version) {
1229         FeatureInfo fi = mAvailableFeatures.get(name);
1230         if (fi == null) {
1231             fi = new FeatureInfo();
1232             fi.name = name;
1233             fi.version = version;
1234             mAvailableFeatures.put(name, fi);
1235         } else {
1236             fi.version = Math.max(fi.version, version);
1237         }
1238     }
1239 
removeFeature(String name)1240     private void removeFeature(String name) {
1241         if (mAvailableFeatures.remove(name) != null) {
1242             Slog.d(TAG, "Removed unavailable feature " + name);
1243         }
1244     }
1245 
readPermission(XmlPullParser parser, String name)1246     void readPermission(XmlPullParser parser, String name)
1247             throws IOException, XmlPullParserException {
1248         if (mPermissions.containsKey(name)) {
1249             throw new IllegalStateException("Duplicate permission definition for " + name);
1250         }
1251 
1252         final boolean perUser = XmlUtils.readBooleanAttribute(parser, "perUser", false);
1253         final PermissionEntry perm = new PermissionEntry(name, perUser);
1254         mPermissions.put(name, perm);
1255 
1256         int outerDepth = parser.getDepth();
1257         int type;
1258         while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1259                && (type != XmlPullParser.END_TAG
1260                        || parser.getDepth() > outerDepth)) {
1261             if (type == XmlPullParser.END_TAG
1262                     || type == XmlPullParser.TEXT) {
1263                 continue;
1264             }
1265 
1266             String tagName = parser.getName();
1267             if ("group".equals(tagName)) {
1268                 String gidStr = parser.getAttributeValue(null, "gid");
1269                 if (gidStr != null) {
1270                     int gid = Process.getGidForName(gidStr);
1271                     perm.gids = appendInt(perm.gids, gid);
1272                 } else {
1273                     Slog.w(TAG, "<group> without gid at "
1274                             + parser.getPositionDescription());
1275                 }
1276             }
1277             XmlUtils.skipCurrentTag(parser);
1278         }
1279     }
1280 
readPrivAppPermissions(XmlPullParser parser, ArrayMap<String, ArraySet<String>> grantMap, ArrayMap<String, ArraySet<String>> denyMap)1281     private void readPrivAppPermissions(XmlPullParser parser,
1282             ArrayMap<String, ArraySet<String>> grantMap,
1283             ArrayMap<String, ArraySet<String>> denyMap)
1284             throws IOException, XmlPullParserException {
1285         String packageName = parser.getAttributeValue(null, "package");
1286         if (TextUtils.isEmpty(packageName)) {
1287             Slog.w(TAG, "package is required for <privapp-permissions> in "
1288                     + parser.getPositionDescription());
1289             return;
1290         }
1291 
1292         ArraySet<String> permissions = grantMap.get(packageName);
1293         if (permissions == null) {
1294             permissions = new ArraySet<>();
1295         }
1296         ArraySet<String> denyPermissions = denyMap.get(packageName);
1297         int depth = parser.getDepth();
1298         while (XmlUtils.nextElementWithin(parser, depth)) {
1299             String name = parser.getName();
1300             if ("permission".equals(name)) {
1301                 String permName = parser.getAttributeValue(null, "name");
1302                 if (TextUtils.isEmpty(permName)) {
1303                     Slog.w(TAG, "name is required for <permission> in "
1304                             + parser.getPositionDescription());
1305                     continue;
1306                 }
1307                 permissions.add(permName);
1308             } else if ("deny-permission".equals(name)) {
1309                 String permName = parser.getAttributeValue(null, "name");
1310                 if (TextUtils.isEmpty(permName)) {
1311                     Slog.w(TAG, "name is required for <deny-permission> in "
1312                             + parser.getPositionDescription());
1313                     continue;
1314                 }
1315                 if (denyPermissions == null) {
1316                     denyPermissions = new ArraySet<>();
1317                 }
1318                 denyPermissions.add(permName);
1319             }
1320         }
1321         grantMap.put(packageName, permissions);
1322         if (denyPermissions != null) {
1323             denyMap.put(packageName, denyPermissions);
1324         }
1325     }
1326 
readInstallInUserType(XmlPullParser parser, Map<String, Set<String>> doInstallMap, Map<String, Set<String>> nonInstallMap)1327     private void readInstallInUserType(XmlPullParser parser,
1328             Map<String, Set<String>> doInstallMap,
1329             Map<String, Set<String>> nonInstallMap)
1330             throws IOException, XmlPullParserException {
1331         final String packageName = parser.getAttributeValue(null, "package");
1332         if (TextUtils.isEmpty(packageName)) {
1333             Slog.w(TAG, "package is required for <install-in-user-type> in "
1334                     + parser.getPositionDescription());
1335             return;
1336         }
1337 
1338         Set<String> userTypesYes = doInstallMap.get(packageName);
1339         Set<String> userTypesNo = nonInstallMap.get(packageName);
1340         final int depth = parser.getDepth();
1341         while (XmlUtils.nextElementWithin(parser, depth)) {
1342             final String name = parser.getName();
1343             if ("install-in".equals(name)) {
1344                 final String userType = parser.getAttributeValue(null, "user-type");
1345                 if (TextUtils.isEmpty(userType)) {
1346                     Slog.w(TAG, "user-type is required for <install-in-user-type> in "
1347                             + parser.getPositionDescription());
1348                     continue;
1349                 }
1350                 if (userTypesYes == null) {
1351                     userTypesYes = new ArraySet<>();
1352                     doInstallMap.put(packageName, userTypesYes);
1353                 }
1354                 userTypesYes.add(userType);
1355             } else if ("do-not-install-in".equals(name)) {
1356                 final String userType = parser.getAttributeValue(null, "user-type");
1357                 if (TextUtils.isEmpty(userType)) {
1358                     Slog.w(TAG, "user-type is required for <install-in-user-type> in "
1359                             + parser.getPositionDescription());
1360                     continue;
1361                 }
1362                 if (userTypesNo == null) {
1363                     userTypesNo = new ArraySet<>();
1364                     nonInstallMap.put(packageName, userTypesNo);
1365                 }
1366                 userTypesNo.add(userType);
1367             } else {
1368                 Slog.w(TAG, "unrecognized tag in <install-in-user-type> in "
1369                         + parser.getPositionDescription());
1370             }
1371         }
1372     }
1373 
readOemPermissions(XmlPullParser parser)1374     void readOemPermissions(XmlPullParser parser) throws IOException, XmlPullParserException {
1375         final String packageName = parser.getAttributeValue(null, "package");
1376         if (TextUtils.isEmpty(packageName)) {
1377             Slog.w(TAG, "package is required for <oem-permissions> in "
1378                     + parser.getPositionDescription());
1379             return;
1380         }
1381 
1382         ArrayMap<String, Boolean> permissions = mOemPermissions.get(packageName);
1383         if (permissions == null) {
1384             permissions = new ArrayMap<>();
1385         }
1386         final int depth = parser.getDepth();
1387         while (XmlUtils.nextElementWithin(parser, depth)) {
1388             final String name = parser.getName();
1389             if ("permission".equals(name)) {
1390                 final String permName = parser.getAttributeValue(null, "name");
1391                 if (TextUtils.isEmpty(permName)) {
1392                     Slog.w(TAG, "name is required for <permission> in "
1393                             + parser.getPositionDescription());
1394                     continue;
1395                 }
1396                 permissions.put(permName, Boolean.TRUE);
1397             } else if ("deny-permission".equals(name)) {
1398                 String permName = parser.getAttributeValue(null, "name");
1399                 if (TextUtils.isEmpty(permName)) {
1400                     Slog.w(TAG, "name is required for <deny-permission> in "
1401                             + parser.getPositionDescription());
1402                     continue;
1403                 }
1404                 permissions.put(permName, Boolean.FALSE);
1405             }
1406         }
1407         mOemPermissions.put(packageName, permissions);
1408     }
1409 
readSplitPermission(XmlPullParser parser, File permFile)1410     private void readSplitPermission(XmlPullParser parser, File permFile)
1411             throws IOException, XmlPullParserException {
1412         String splitPerm = parser.getAttributeValue(null, "name");
1413         if (splitPerm == null) {
1414             Slog.w(TAG, "<split-permission> without name in " + permFile + " at "
1415                     + parser.getPositionDescription());
1416             XmlUtils.skipCurrentTag(parser);
1417             return;
1418         }
1419         String targetSdkStr = parser.getAttributeValue(null, "targetSdk");
1420         int targetSdk = Build.VERSION_CODES.CUR_DEVELOPMENT + 1;
1421         if (!TextUtils.isEmpty(targetSdkStr)) {
1422             try {
1423                 targetSdk = Integer.parseInt(targetSdkStr);
1424             } catch (NumberFormatException e) {
1425                 Slog.w(TAG, "<split-permission> targetSdk not an integer in " + permFile + " at "
1426                         + parser.getPositionDescription());
1427                 XmlUtils.skipCurrentTag(parser);
1428                 return;
1429             }
1430         }
1431         final int depth = parser.getDepth();
1432         List<String> newPermissions = new ArrayList<>();
1433         while (XmlUtils.nextElementWithin(parser, depth)) {
1434             String name = parser.getName();
1435             if ("new-permission".equals(name)) {
1436                 final String newName = parser.getAttributeValue(null, "name");
1437                 if (TextUtils.isEmpty(newName)) {
1438                     Slog.w(TAG, "name is required for <new-permission> in "
1439                             + parser.getPositionDescription());
1440                     continue;
1441                 }
1442                 newPermissions.add(newName);
1443             } else {
1444                 XmlUtils.skipCurrentTag(parser);
1445             }
1446         }
1447         if (!newPermissions.isEmpty()) {
1448             mSplitPermissions.add(new SplitPermissionInfo(splitPerm, newPermissions, targetSdk));
1449         }
1450     }
1451 
readComponentOverrides(XmlPullParser parser, File permFile)1452     private void readComponentOverrides(XmlPullParser parser, File permFile)
1453             throws IOException, XmlPullParserException {
1454         String pkgname = parser.getAttributeValue(null, "package");
1455         if (pkgname == null) {
1456             Slog.w(TAG, "<component-override> without package in "
1457                     + permFile + " at " + parser.getPositionDescription());
1458             return;
1459         }
1460 
1461         pkgname = pkgname.intern();
1462 
1463         final int depth = parser.getDepth();
1464         while (XmlUtils.nextElementWithin(parser, depth)) {
1465             if ("component".equals(parser.getName())) {
1466                 String clsname = parser.getAttributeValue(null, "class");
1467                 String enabled = parser.getAttributeValue(null, "enabled");
1468                 if (clsname == null) {
1469                     Slog.w(TAG, "<component> without class in "
1470                             + permFile + " at " + parser.getPositionDescription());
1471                     return;
1472                 } else if (enabled == null) {
1473                     Slog.w(TAG, "<component> without enabled in "
1474                             + permFile + " at " + parser.getPositionDescription());
1475                     return;
1476                 }
1477 
1478                 if (clsname.startsWith(".")) {
1479                     clsname = pkgname + clsname;
1480                 }
1481 
1482                 clsname = clsname.intern();
1483 
1484                 ArrayMap<String, Boolean> componentEnabledStates =
1485                         mPackageComponentEnabledState.get(pkgname);
1486                 if (componentEnabledStates == null) {
1487                     componentEnabledStates = new ArrayMap<>();
1488                     mPackageComponentEnabledState.put(pkgname,
1489                             componentEnabledStates);
1490                 }
1491 
1492                 componentEnabledStates.put(clsname, !"false".equals(enabled));
1493             }
1494         }
1495     }
1496 
isSystemProcess()1497     private static boolean isSystemProcess() {
1498         return Process.myUid() == Process.SYSTEM_UID;
1499     }
1500 }
1501