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