1 /*
2  * Copyright (C) 2020 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 android.content.pm.parsing;
18 
19 import android.annotation.CheckResult;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.apex.ApexInfo;
23 import android.content.pm.ActivityInfo;
24 import android.content.pm.ApplicationInfo;
25 import android.content.pm.ComponentInfo;
26 import android.content.pm.ConfigurationInfo;
27 import android.content.pm.FallbackCategoryProvider;
28 import android.content.pm.FeatureGroupInfo;
29 import android.content.pm.FeatureInfo;
30 import android.content.pm.InstrumentationInfo;
31 import android.content.pm.PackageInfo;
32 import android.content.pm.PackageItemInfo;
33 import android.content.pm.PackageManager;
34 import android.content.pm.PackageParser;
35 import android.content.pm.PackageUserState;
36 import android.content.pm.PermissionGroupInfo;
37 import android.content.pm.PermissionInfo;
38 import android.content.pm.ProviderInfo;
39 import android.content.pm.SELinuxUtil;
40 import android.content.pm.ServiceInfo;
41 import android.content.pm.Signature;
42 import android.content.pm.SigningInfo;
43 import android.content.pm.parsing.component.ComponentParseUtils;
44 import android.content.pm.parsing.component.ParsedActivity;
45 import android.content.pm.parsing.component.ParsedComponent;
46 import android.content.pm.parsing.component.ParsedInstrumentation;
47 import android.content.pm.parsing.component.ParsedMainComponent;
48 import android.content.pm.parsing.component.ParsedPermission;
49 import android.content.pm.parsing.component.ParsedPermissionGroup;
50 import android.content.pm.parsing.component.ParsedProvider;
51 import android.content.pm.parsing.component.ParsedService;
52 import android.os.Environment;
53 import android.os.UserHandle;
54 
55 import com.android.internal.util.ArrayUtils;
56 
57 import libcore.util.EmptyArray;
58 
59 import java.io.File;
60 import java.util.Collections;
61 import java.util.Set;
62 
63 /** @hide **/
64 public class PackageInfoWithoutStateUtils {
65 
66     @Nullable
generate(ParsingPackageRead pkg, int[] gids, @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime, Set<String> grantedPermissions, PackageUserState state, int userId)67     public static PackageInfo generate(ParsingPackageRead pkg, int[] gids,
68             @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,
69             Set<String> grantedPermissions, PackageUserState state, int userId) {
70         return generateWithComponents(pkg, gids, flags, firstInstallTime, lastUpdateTime, grantedPermissions,
71                 state, userId, null);
72     }
73 
74     @Nullable
generate(ParsingPackageRead pkg, ApexInfo apexInfo, int flags)75     public static PackageInfo generate(ParsingPackageRead pkg, ApexInfo apexInfo, int flags) {
76         return generateWithComponents(pkg, EmptyArray.INT, flags, 0, 0, Collections.emptySet(),
77                 new PackageUserState(), UserHandle.getCallingUserId(), apexInfo);
78     }
79 
80     @Nullable
generateWithComponents(ParsingPackageRead pkg, int[] gids, @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime, Set<String> grantedPermissions, PackageUserState state, int userId, @Nullable ApexInfo apexInfo)81     private static PackageInfo generateWithComponents(ParsingPackageRead pkg, int[] gids,
82             @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,
83             Set<String> grantedPermissions, PackageUserState state, int userId,
84             @Nullable ApexInfo apexInfo) {
85         ApplicationInfo applicationInfo = generateApplicationInfo(pkg, flags, state, userId);
86         if (applicationInfo == null) {
87             return null;
88         }
89         PackageInfo info = generateWithoutComponents(pkg, gids, flags, firstInstallTime,
90                 lastUpdateTime, grantedPermissions, state, userId, apexInfo, applicationInfo);
91 
92         if (info == null) {
93             return null;
94         }
95 
96         if ((flags & PackageManager.GET_ACTIVITIES) != 0) {
97             final int N = pkg.getActivities().size();
98             if (N > 0) {
99                 int num = 0;
100                 final ActivityInfo[] res = new ActivityInfo[N];
101                 for (int i = 0; i < N; i++) {
102                     final ParsedActivity a = pkg.getActivities().get(i);
103                     if (ComponentParseUtils.isMatch(state, false, pkg.isEnabled(), a,
104                             flags)) {
105                         if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(
106                                 a.getName())) {
107                             continue;
108                         }
109                         res[num++] = generateActivityInfo(pkg, a, flags, state,
110                                 applicationInfo, userId);
111                     }
112                 }
113                 info.activities = ArrayUtils.trimToSize(res, num);
114             }
115         }
116         if ((flags & PackageManager.GET_RECEIVERS) != 0) {
117             final int size = pkg.getReceivers().size();
118             if (size > 0) {
119                 int num = 0;
120                 final ActivityInfo[] res = new ActivityInfo[size];
121                 for (int i = 0; i < size; i++) {
122                     final ParsedActivity a = pkg.getReceivers().get(i);
123                     if (ComponentParseUtils.isMatch(state, false, pkg.isEnabled(), a,
124                             flags)) {
125                         res[num++] = generateActivityInfo(pkg, a, flags, state,
126                                 applicationInfo, userId);
127                     }
128                 }
129                 info.receivers = ArrayUtils.trimToSize(res, num);
130             }
131         }
132         if ((flags & PackageManager.GET_SERVICES) != 0) {
133             final int size = pkg.getServices().size();
134             if (size > 0) {
135                 int num = 0;
136                 final ServiceInfo[] res = new ServiceInfo[size];
137                 for (int i = 0; i < size; i++) {
138                     final ParsedService s = pkg.getServices().get(i);
139                     if (ComponentParseUtils.isMatch(state, false, pkg.isEnabled(), s,
140                             flags)) {
141                         res[num++] = generateServiceInfo(pkg, s, flags, state,
142                                 applicationInfo, userId);
143                     }
144                 }
145                 info.services = ArrayUtils.trimToSize(res, num);
146             }
147         }
148         if ((flags & PackageManager.GET_PROVIDERS) != 0) {
149             final int size = pkg.getProviders().size();
150             if (size > 0) {
151                 int num = 0;
152                 final ProviderInfo[] res = new ProviderInfo[size];
153                 for (int i = 0; i < size; i++) {
154                     final ParsedProvider pr = pkg.getProviders()
155                             .get(i);
156                     if (ComponentParseUtils.isMatch(state, false, pkg.isEnabled(), pr,
157                             flags)) {
158                         res[num++] = generateProviderInfo(pkg, pr, flags, state,
159                                 applicationInfo, userId);
160                     }
161                 }
162                 info.providers = ArrayUtils.trimToSize(res, num);
163             }
164         }
165         if ((flags & PackageManager.GET_INSTRUMENTATION) != 0) {
166             int N = pkg.getInstrumentations().size();
167             if (N > 0) {
168                 info.instrumentation = new InstrumentationInfo[N];
169                 for (int i = 0; i < N; i++) {
170                     info.instrumentation[i] = generateInstrumentationInfo(
171                             pkg.getInstrumentations().get(i), pkg, flags, userId);
172                 }
173             }
174         }
175 
176         return info;
177     }
178 
179     @Nullable
generateWithoutComponents(ParsingPackageRead pkg, int[] gids, @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime, Set<String> grantedPermissions, PackageUserState state, int userId, @Nullable ApexInfo apexInfo, @NonNull ApplicationInfo applicationInfo)180     public static PackageInfo generateWithoutComponents(ParsingPackageRead pkg, int[] gids,
181             @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,
182             Set<String> grantedPermissions, PackageUserState state, int userId,
183             @Nullable ApexInfo apexInfo, @NonNull ApplicationInfo applicationInfo) {
184         if (!checkUseInstalled(pkg, state, flags)) {
185             return null;
186         }
187 
188         return generateWithoutComponentsUnchecked(pkg, gids, flags, firstInstallTime,
189                 lastUpdateTime, grantedPermissions, state, userId, apexInfo, applicationInfo);
190     }
191 
192     /**
193      * This bypasses critical checks that are necessary for usage with data passed outside of
194      * system server.
195      *
196      * Prefer {@link #generateWithoutComponents(ParsingPackageRead, int[], int, long, long, Set,
197      * PackageUserState, int, ApexInfo, ApplicationInfo)}.
198      */
199     @NonNull
generateWithoutComponentsUnchecked(ParsingPackageRead pkg, int[] gids, @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime, Set<String> grantedPermissions, PackageUserState state, int userId, @Nullable ApexInfo apexInfo, @NonNull ApplicationInfo applicationInfo)200     public static PackageInfo generateWithoutComponentsUnchecked(ParsingPackageRead pkg, int[] gids,
201             @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,
202             Set<String> grantedPermissions, PackageUserState state, int userId,
203             @Nullable ApexInfo apexInfo, @NonNull ApplicationInfo applicationInfo) {
204         PackageInfo pi = new PackageInfo();
205         pi.packageName = pkg.getPackageName();
206         pi.splitNames = pkg.getSplitNames();
207         pi.versionCode = pkg.getVersionCode();
208         pi.versionCodeMajor = pkg.getVersionCodeMajor();
209         pi.baseRevisionCode = pkg.getBaseRevisionCode();
210         pi.splitRevisionCodes = pkg.getSplitRevisionCodes();
211         pi.versionName = pkg.getVersionName();
212         pi.sharedUserId = pkg.getSharedUserId();
213         pi.sharedUserLabel = pkg.getSharedUserLabel();
214         pi.applicationInfo = applicationInfo;
215         pi.installLocation = pkg.getInstallLocation();
216         if ((pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0
217                 || (pi.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
218             pi.requiredForAllUsers = pkg.isRequiredForAllUsers();
219         }
220         pi.restrictedAccountType = pkg.getRestrictedAccountType();
221         pi.requiredAccountType = pkg.getRequiredAccountType();
222         pi.overlayTarget = pkg.getOverlayTarget();
223         pi.targetOverlayableName = pkg.getOverlayTargetName();
224         pi.overlayCategory = pkg.getOverlayCategory();
225         pi.overlayPriority = pkg.getOverlayPriority();
226         pi.mOverlayIsStatic = pkg.isOverlayIsStatic();
227         pi.compileSdkVersion = pkg.getCompileSdkVersion();
228         pi.compileSdkVersionCodename = pkg.getCompileSdkVersionCodeName();
229         pi.firstInstallTime = firstInstallTime;
230         pi.lastUpdateTime = lastUpdateTime;
231         if ((flags & PackageManager.GET_GIDS) != 0) {
232             pi.gids = gids;
233         }
234         if ((flags & PackageManager.GET_CONFIGURATIONS) != 0) {
235             int size = pkg.getConfigPreferences().size();
236             if (size > 0) {
237                 pi.configPreferences = new ConfigurationInfo[size];
238                 pkg.getConfigPreferences().toArray(pi.configPreferences);
239             }
240             size = pkg.getReqFeatures().size();
241             if (size > 0) {
242                 pi.reqFeatures = new FeatureInfo[size];
243                 pkg.getReqFeatures().toArray(pi.reqFeatures);
244             }
245             size = pkg.getFeatureGroups().size();
246             if (size > 0) {
247                 pi.featureGroups = new FeatureGroupInfo[size];
248                 pkg.getFeatureGroups().toArray(pi.featureGroups);
249             }
250         }
251         if ((flags & PackageManager.GET_PERMISSIONS) != 0) {
252             int size = ArrayUtils.size(pkg.getPermissions());
253             if (size > 0) {
254                 pi.permissions = new PermissionInfo[size];
255                 for (int i = 0; i < size; i++) {
256                     pi.permissions[i] = generatePermissionInfo(pkg.getPermissions().get(i),
257                             flags);
258                 }
259             }
260             size = pkg.getRequestedPermissions().size();
261             if (size > 0) {
262                 pi.requestedPermissions = new String[size];
263                 pi.requestedPermissionsFlags = new int[size];
264                 for (int i = 0; i < size; i++) {
265                     final String perm = pkg.getRequestedPermissions().get(i);
266                     pi.requestedPermissions[i] = perm;
267                     // The notion of required permissions is deprecated but for compatibility.
268                     pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
269                     if (grantedPermissions != null && grantedPermissions.contains(perm)) {
270                         pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
271                     }
272                 }
273             }
274         }
275 
276         if (apexInfo != null) {
277             File apexFile = new File(apexInfo.modulePath);
278 
279             pi.applicationInfo.sourceDir = apexFile.getPath();
280             pi.applicationInfo.publicSourceDir = apexFile.getPath();
281             if (apexInfo.isFactory) {
282                 pi.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
283             } else {
284                 pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
285             }
286             if (apexInfo.isActive) {
287                 pi.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED;
288             } else {
289                 pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED;
290             }
291             pi.isApex = true;
292         }
293 
294         PackageParser.SigningDetails signingDetails = pkg.getSigningDetails();
295         // deprecated method of getting signing certificates
296         if ((flags & PackageManager.GET_SIGNATURES) != 0) {
297             if (signingDetails.hasPastSigningCertificates()) {
298                 // Package has included signing certificate rotation information.  Return the oldest
299                 // cert so that programmatic checks keep working even if unaware of key rotation.
300                 pi.signatures = new Signature[1];
301                 pi.signatures[0] = signingDetails.pastSigningCertificates[0];
302             } else if (signingDetails.hasSignatures()) {
303                 // otherwise keep old behavior
304                 int numberOfSigs = signingDetails.signatures.length;
305                 pi.signatures = new Signature[numberOfSigs];
306                 System.arraycopy(signingDetails.signatures, 0, pi.signatures, 0,
307                         numberOfSigs);
308             }
309         }
310 
311         // replacement for GET_SIGNATURES
312         if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) {
313             if (signingDetails != PackageParser.SigningDetails.UNKNOWN) {
314                 // only return a valid SigningInfo if there is signing information to report
315                 pi.signingInfo = new SigningInfo(signingDetails);
316             } else {
317                 pi.signingInfo = null;
318             }
319         }
320 
321         return pi;
322     }
323 
324     @Nullable
generateApplicationInfo(ParsingPackageRead pkg, @PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId)325     public static ApplicationInfo generateApplicationInfo(ParsingPackageRead pkg,
326             @PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId) {
327         if (pkg == null) {
328             return null;
329         }
330 
331         if (!checkUseInstalled(pkg, state, flags)) {
332             return null;
333         }
334 
335         return generateApplicationInfoUnchecked(pkg, flags, state, userId);
336     }
337 
338     /**
339      * This bypasses critical checks that are necessary for usage with data passed outside of
340      * system server.
341      *
342      * Prefer {@link #generateApplicationInfo(ParsingPackageRead, int, PackageUserState, int)}.
343      */
344     @NonNull
generateApplicationInfoUnchecked(@onNull ParsingPackageRead pkg, @PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId)345     public static ApplicationInfo generateApplicationInfoUnchecked(@NonNull ParsingPackageRead pkg,
346             @PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId) {
347         // Make shallow copy so we can store the metadata/libraries safely
348         ApplicationInfo ai = pkg.toAppInfoWithoutState();
349         // Init handles data directories
350         // TODO(b/135203078): Consolidate the data directory logic, remove initForUser
351         ai.initForUser(userId);
352 
353         if ((flags & PackageManager.GET_META_DATA) == 0) {
354             ai.metaData = null;
355         }
356         if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) == 0) {
357             ai.sharedLibraryFiles = null;
358             ai.sharedLibraryInfos = null;
359         }
360 
361         // CompatibilityMode is global state.
362         if (!PackageParser.sCompatibilityModeEnabled) {
363             ai.disableCompatibilityMode();
364         }
365 
366         ai.flags |= flag(state.stopped, ApplicationInfo.FLAG_STOPPED)
367                 | flag(state.installed, ApplicationInfo.FLAG_INSTALLED)
368                 | flag(state.suspended, ApplicationInfo.FLAG_SUSPENDED);
369         ai.privateFlags |= flag(state.instantApp, ApplicationInfo.PRIVATE_FLAG_INSTANT)
370                 | flag(state.virtualPreload, ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD)
371                 | flag(state.hidden, ApplicationInfo.PRIVATE_FLAG_HIDDEN);
372 
373         if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
374             ai.enabled = true;
375         } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
376             ai.enabled = (flags & PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
377         } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
378                 || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
379             ai.enabled = false;
380         }
381         ai.enabledSetting = state.enabled;
382         if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
383             ai.category = state.categoryHint;
384         }
385         if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
386             ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);
387         }
388         ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state);
389         ai.resourceDirs = state.getAllOverlayPaths();
390 
391         return ai;
392     }
393 
394     @Nullable
generateActivityInfo(ParsingPackageRead pkg, ParsedActivity a, @PackageManager.ComponentInfoFlags int flags, PackageUserState state, @Nullable ApplicationInfo applicationInfo, int userId)395     public static ActivityInfo generateActivityInfo(ParsingPackageRead pkg, ParsedActivity a,
396             @PackageManager.ComponentInfoFlags int flags, PackageUserState state,
397             @Nullable ApplicationInfo applicationInfo, int userId) {
398         if (a == null) return null;
399         if (!checkUseInstalled(pkg, state, flags)) {
400             return null;
401         }
402         if (applicationInfo == null) {
403             applicationInfo = generateApplicationInfo(pkg, flags, state, userId);
404         }
405         if (applicationInfo == null) {
406             return null;
407         }
408 
409         return generateActivityInfoUnchecked(a, applicationInfo);
410     }
411 
412     /**
413      * This bypasses critical checks that are necessary for usage with data passed outside of
414      * system server.
415      *
416      * Prefer {@link #generateActivityInfo(ParsingPackageRead, ParsedActivity, int,
417      * PackageUserState, ApplicationInfo, int)}.
418      */
419     @NonNull
generateActivityInfoUnchecked(@onNull ParsedActivity a, @NonNull ApplicationInfo applicationInfo)420     public static ActivityInfo generateActivityInfoUnchecked(@NonNull ParsedActivity a,
421             @NonNull ApplicationInfo applicationInfo) {
422         // Make shallow copies so we can store the metadata safely
423         ActivityInfo ai = new ActivityInfo();
424         assignSharedFieldsForComponentInfo(ai, a);
425         ai.targetActivity = a.getTargetActivity();
426         ai.processName = a.getProcessName();
427         ai.exported = a.isExported();
428         ai.theme = a.getTheme();
429         ai.uiOptions = a.getUiOptions();
430         ai.parentActivityName = a.getParentActivityName();
431         ai.permission = a.getPermission();
432         ai.taskAffinity = a.getTaskAffinity();
433         ai.flags = a.getFlags();
434         ai.privateFlags = a.getPrivateFlags();
435         ai.launchMode = a.getLaunchMode();
436         ai.documentLaunchMode = a.getDocumentLaunchMode();
437         ai.maxRecents = a.getMaxRecents();
438         ai.configChanges = a.getConfigChanges();
439         ai.softInputMode = a.getSoftInputMode();
440         ai.persistableMode = a.getPersistableMode();
441         ai.lockTaskLaunchMode = a.getLockTaskLaunchMode();
442         ai.screenOrientation = a.getScreenOrientation();
443         ai.resizeMode = a.getResizeMode();
444         Float maxAspectRatio = a.getMaxAspectRatio();
445         ai.maxAspectRatio = maxAspectRatio != null ? maxAspectRatio : 0f;
446         Float minAspectRatio = a.getMinAspectRatio();
447         ai.minAspectRatio = minAspectRatio != null ? minAspectRatio : 0f;
448         ai.supportsSizeChanges = a.getSupportsSizeChanges();
449         ai.requestedVrComponent = a.getRequestedVrComponent();
450         ai.rotationAnimation = a.getRotationAnimation();
451         ai.colorMode = a.getColorMode();
452         ai.windowLayout = a.getWindowLayout();
453         ai.metaData = a.getMetaData();
454         ai.applicationInfo = applicationInfo;
455         return ai;
456     }
457 
458     @Nullable
generateActivityInfo(ParsingPackageRead pkg, ParsedActivity a, @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId)459     public static ActivityInfo generateActivityInfo(ParsingPackageRead pkg, ParsedActivity a,
460             @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId) {
461         return generateActivityInfo(pkg, a, flags, state, null, userId);
462     }
463 
464     @Nullable
generateServiceInfo(ParsingPackageRead pkg, ParsedService s, @PackageManager.ComponentInfoFlags int flags, PackageUserState state, @Nullable ApplicationInfo applicationInfo, int userId)465     public static ServiceInfo generateServiceInfo(ParsingPackageRead pkg, ParsedService s,
466             @PackageManager.ComponentInfoFlags int flags, PackageUserState state,
467             @Nullable ApplicationInfo applicationInfo, int userId) {
468         if (s == null) return null;
469         if (!checkUseInstalled(pkg, state, flags)) {
470             return null;
471         }
472         if (applicationInfo == null) {
473             applicationInfo = generateApplicationInfo(pkg, flags, state, userId);
474         }
475         if (applicationInfo == null) {
476             return null;
477         }
478 
479         return generateServiceInfoUnchecked(s, applicationInfo);
480     }
481 
482     /**
483      * This bypasses critical checks that are necessary for usage with data passed outside of
484      * system server.
485      *
486      * Prefer {@link #generateServiceInfo(ParsingPackageRead, ParsedService, int, PackageUserState,
487      * ApplicationInfo, int)}.
488      */
489     @NonNull
generateServiceInfoUnchecked(@onNull ParsedService s, @NonNull ApplicationInfo applicationInfo)490     public static ServiceInfo generateServiceInfoUnchecked(@NonNull ParsedService s,
491             @NonNull ApplicationInfo applicationInfo) {
492         // Make shallow copies so we can store the metadata safely
493         ServiceInfo si = new ServiceInfo();
494         assignSharedFieldsForComponentInfo(si, s);
495         si.exported = s.isExported();
496         si.flags = s.getFlags();
497         si.metaData = s.getMetaData();
498         si.permission = s.getPermission();
499         si.processName = s.getProcessName();
500         si.mForegroundServiceType = s.getForegroundServiceType();
501         si.applicationInfo = applicationInfo;
502         return si;
503     }
504 
505     @Nullable
generateServiceInfo(ParsingPackageRead pkg, ParsedService s, @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId)506     public static ServiceInfo generateServiceInfo(ParsingPackageRead pkg, ParsedService s,
507             @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId) {
508         return generateServiceInfo(pkg, s, flags, state, null, userId);
509     }
510 
511     @Nullable
generateProviderInfo(ParsingPackageRead pkg, ParsedProvider p, @PackageManager.ComponentInfoFlags int flags, PackageUserState state, @Nullable ApplicationInfo applicationInfo, int userId)512     public static ProviderInfo generateProviderInfo(ParsingPackageRead pkg, ParsedProvider p,
513             @PackageManager.ComponentInfoFlags int flags, PackageUserState state,
514             @Nullable ApplicationInfo applicationInfo, int userId) {
515         if (p == null) return null;
516         if (!checkUseInstalled(pkg, state, flags)) {
517             return null;
518         }
519         if (applicationInfo == null) {
520             applicationInfo = generateApplicationInfo(pkg, flags, state, userId);
521         }
522         if (applicationInfo == null) {
523             return null;
524         }
525 
526         return generateProviderInfoUnchecked(p, flags, applicationInfo);
527     }
528 
529     /**
530      * This bypasses critical checks that are necessary for usage with data passed outside of
531      * system server.
532      *
533      * Prefer {@link #generateProviderInfo(ParsingPackageRead, ParsedProvider, int,
534      * PackageUserState, ApplicationInfo, int)}.
535      */
536     @NonNull
generateProviderInfoUnchecked(@onNull ParsedProvider p, @PackageManager.ComponentInfoFlags int flags, @NonNull ApplicationInfo applicationInfo)537     public static ProviderInfo generateProviderInfoUnchecked(@NonNull ParsedProvider p,
538             @PackageManager.ComponentInfoFlags int flags,
539             @NonNull ApplicationInfo applicationInfo) {
540         // Make shallow copies so we can store the metadata safely
541         ProviderInfo pi = new ProviderInfo();
542         assignSharedFieldsForComponentInfo(pi, p);
543         pi.exported = p.isExported();
544         pi.flags = p.getFlags();
545         pi.processName = p.getProcessName();
546         pi.authority = p.getAuthority();
547         pi.isSyncable = p.isSyncable();
548         pi.readPermission = p.getReadPermission();
549         pi.writePermission = p.getWritePermission();
550         pi.grantUriPermissions = p.isGrantUriPermissions();
551         pi.forceUriPermissions = p.isForceUriPermissions();
552         pi.multiprocess = p.isMultiProcess();
553         pi.initOrder = p.getInitOrder();
554         pi.uriPermissionPatterns = p.getUriPermissionPatterns();
555         pi.pathPermissions = p.getPathPermissions();
556         pi.metaData = p.getMetaData();
557         if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
558             pi.uriPermissionPatterns = null;
559         }
560         pi.applicationInfo = applicationInfo;
561         return pi;
562     }
563 
564     @Nullable
generateProviderInfo(ParsingPackageRead pkg, ParsedProvider p, @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId)565     public static ProviderInfo generateProviderInfo(ParsingPackageRead pkg, ParsedProvider p,
566             @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId) {
567         return generateProviderInfo(pkg, p, flags, state, null, userId);
568     }
569 
570     @Nullable
generateInstrumentationInfo(ParsedInstrumentation i, ParsingPackageRead pkg, @PackageManager.ComponentInfoFlags int flags, int userId)571     public static InstrumentationInfo generateInstrumentationInfo(ParsedInstrumentation i,
572             ParsingPackageRead pkg, @PackageManager.ComponentInfoFlags int flags, int userId) {
573         if (i == null) return null;
574 
575         InstrumentationInfo ii = new InstrumentationInfo();
576         assignSharedFieldsForPackageItemInfo(ii, i);
577         ii.targetPackage = i.getTargetPackage();
578         ii.targetProcesses = i.getTargetProcesses();
579         ii.handleProfiling = i.isHandleProfiling();
580         ii.functionalTest = i.isFunctionalTest();
581 
582         ii.sourceDir = pkg.getBaseCodePath();
583         ii.publicSourceDir = pkg.getBaseCodePath();
584         ii.splitNames = pkg.getSplitNames();
585         ii.splitSourceDirs = pkg.getSplitCodePaths();
586         ii.splitPublicSourceDirs = pkg.getSplitCodePaths();
587         ii.splitDependencies = pkg.getSplitDependencies();
588         ii.dataDir = getDataDir(pkg, userId).getAbsolutePath();
589         ii.deviceProtectedDataDir = getDeviceProtectedDataDir(pkg, userId).getAbsolutePath();
590         ii.credentialProtectedDataDir = getCredentialProtectedDataDir(pkg,
591                 userId).getAbsolutePath();
592 
593         if ((flags & PackageManager.GET_META_DATA) == 0) {
594             return ii;
595         }
596         ii.metaData = i.getMetaData();
597         return ii;
598     }
599 
600     @Nullable
generatePermissionInfo(ParsedPermission p, @PackageManager.ComponentInfoFlags int flags)601     public static PermissionInfo generatePermissionInfo(ParsedPermission p,
602             @PackageManager.ComponentInfoFlags int flags) {
603         if (p == null) return null;
604 
605         PermissionInfo pi = new PermissionInfo(p.getBackgroundPermission());
606 
607         assignSharedFieldsForPackageItemInfo(pi, p);
608 
609         pi.group = p.getGroup();
610         pi.requestRes = p.getRequestRes();
611         pi.protectionLevel = p.getProtectionLevel();
612         pi.descriptionRes = p.getDescriptionRes();
613         pi.flags = p.getFlags();
614 
615         if ((flags & PackageManager.GET_META_DATA) == 0) {
616             return pi;
617         }
618         pi.metaData = p.getMetaData();
619         return pi;
620     }
621 
622     @Nullable
generatePermissionGroupInfo(ParsedPermissionGroup pg, @PackageManager.ComponentInfoFlags int flags)623     public static PermissionGroupInfo generatePermissionGroupInfo(ParsedPermissionGroup pg,
624             @PackageManager.ComponentInfoFlags int flags) {
625         if (pg == null) return null;
626 
627         PermissionGroupInfo pgi = new PermissionGroupInfo(
628                 pg.getRequestDetailResourceId(),
629                 pg.getBackgroundRequestResourceId(),
630                 pg.getBackgroundRequestDetailResourceId()
631         );
632 
633         assignSharedFieldsForPackageItemInfo(pgi, pg);
634         pgi.descriptionRes = pg.getDescriptionRes();
635         pgi.priority = pg.getPriority();
636         pgi.requestRes = pg.getRequestRes();
637         pgi.flags = pg.getFlags();
638 
639         if ((flags & PackageManager.GET_META_DATA) == 0) {
640             return pgi;
641         }
642         pgi.metaData = pg.getMetaData();
643         return pgi;
644     }
645 
assignSharedFieldsForComponentInfo(@onNull ComponentInfo componentInfo, @NonNull ParsedMainComponent mainComponent)646     private static void assignSharedFieldsForComponentInfo(@NonNull ComponentInfo componentInfo,
647             @NonNull ParsedMainComponent mainComponent) {
648         assignSharedFieldsForPackageItemInfo(componentInfo, mainComponent);
649         componentInfo.descriptionRes = mainComponent.getDescriptionRes();
650         componentInfo.directBootAware = mainComponent.isDirectBootAware();
651         componentInfo.enabled = mainComponent.isEnabled();
652         componentInfo.splitName = mainComponent.getSplitName();
653     }
654 
assignSharedFieldsForPackageItemInfo( @onNull PackageItemInfo packageItemInfo, @NonNull ParsedComponent component)655     private static void assignSharedFieldsForPackageItemInfo(
656             @NonNull PackageItemInfo packageItemInfo, @NonNull ParsedComponent component) {
657         packageItemInfo.nonLocalizedLabel = ComponentParseUtils.getNonLocalizedLabel(component);
658         packageItemInfo.icon = ComponentParseUtils.getIcon(component);
659 
660         packageItemInfo.banner = component.getBanner();
661         packageItemInfo.labelRes = component.getLabelRes();
662         packageItemInfo.logo = component.getLogo();
663         packageItemInfo.name = component.getName();
664         packageItemInfo.packageName = component.getPackageName();
665     }
666 
667     @CheckResult
flag(boolean hasFlag, int flag)668     private static int flag(boolean hasFlag, int flag) {
669         if (hasFlag) {
670             return flag;
671         } else {
672             return 0;
673         }
674     }
675 
676     /** @see ApplicationInfo#flags */
appInfoFlags(ParsingPackageRead pkg)677     public static int appInfoFlags(ParsingPackageRead pkg) {
678         // @formatter:off
679         return flag(pkg.isExternalStorage(), ApplicationInfo.FLAG_EXTERNAL_STORAGE)
680                 | flag(pkg.isBaseHardwareAccelerated(), ApplicationInfo.FLAG_HARDWARE_ACCELERATED)
681                 | flag(pkg.isAllowBackup(), ApplicationInfo.FLAG_ALLOW_BACKUP)
682                 | flag(pkg.isKillAfterRestore(), ApplicationInfo.FLAG_KILL_AFTER_RESTORE)
683                 | flag(pkg.isRestoreAnyVersion(), ApplicationInfo.FLAG_RESTORE_ANY_VERSION)
684                 | flag(pkg.isFullBackupOnly(), ApplicationInfo.FLAG_FULL_BACKUP_ONLY)
685                 | flag(pkg.isPersistent(), ApplicationInfo.FLAG_PERSISTENT)
686                 | flag(pkg.isDebuggable(), ApplicationInfo.FLAG_DEBUGGABLE)
687                 | flag(pkg.isVmSafeMode(), ApplicationInfo.FLAG_VM_SAFE_MODE)
688                 | flag(pkg.isHasCode(), ApplicationInfo.FLAG_HAS_CODE)
689                 | flag(pkg.isAllowTaskReparenting(), ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING)
690                 | flag(pkg.isAllowClearUserData(), ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA)
691                 | flag(pkg.isLargeHeap(), ApplicationInfo.FLAG_LARGE_HEAP)
692                 | flag(pkg.isUsesCleartextTraffic(), ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC)
693                 | flag(pkg.isSupportsRtl(), ApplicationInfo.FLAG_SUPPORTS_RTL)
694                 | flag(pkg.isTestOnly(), ApplicationInfo.FLAG_TEST_ONLY)
695                 | flag(pkg.isMultiArch(), ApplicationInfo.FLAG_MULTIARCH)
696                 | flag(pkg.isExtractNativeLibs(), ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS)
697                 | flag(pkg.isGame(), ApplicationInfo.FLAG_IS_GAME)
698                 | flag(pkg.isSupportsSmallScreens(), ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS)
699                 | flag(pkg.isSupportsNormalScreens(), ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS)
700                 | flag(pkg.isSupportsLargeScreens(), ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS)
701                 | flag(pkg.isSupportsExtraLargeScreens(), ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS)
702                 | flag(pkg.isResizeable(), ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS)
703                 | flag(pkg.isAnyDensity(), ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES);
704         // @formatter:on
705     }
706 
707     /** @see ApplicationInfo#privateFlags */
appInfoPrivateFlags(ParsingPackageRead pkg)708     public static int appInfoPrivateFlags(ParsingPackageRead pkg) {
709         // @formatter:off
710         int privateFlags = flag(pkg.isStaticSharedLibrary(), ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY)
711                 | flag(pkg.isOverlay(), ApplicationInfo.PRIVATE_FLAG_IS_RESOURCE_OVERLAY)
712                 | flag(pkg.isIsolatedSplitLoading(), ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING)
713                 | flag(pkg.isHasDomainUrls(), ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS)
714                 | flag(pkg.isProfileableByShell(), ApplicationInfo.PRIVATE_FLAG_PROFILEABLE_BY_SHELL)
715                 | flag(pkg.isBackupInForeground(), ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND)
716                 | flag(pkg.isUseEmbeddedDex(), ApplicationInfo.PRIVATE_FLAG_USE_EMBEDDED_DEX)
717                 | flag(pkg.isDefaultToDeviceProtectedStorage(), ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE)
718                 | flag(pkg.isDirectBootAware(), ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE)
719                 | flag(pkg.isPartiallyDirectBootAware(), ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE)
720                 | flag(pkg.isAllowClearUserDataOnFailedRestore(), ApplicationInfo.PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE)
721                 | flag(pkg.isAllowAudioPlaybackCapture(), ApplicationInfo.PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE)
722                 | flag(pkg.isRequestLegacyExternalStorage(), ApplicationInfo.PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE)
723                 | flag(pkg.isUsesNonSdkApi(), ApplicationInfo.PRIVATE_FLAG_USES_NON_SDK_API)
724                 | flag(pkg.isHasFragileUserData(), ApplicationInfo.PRIVATE_FLAG_HAS_FRAGILE_USER_DATA)
725                 | flag(pkg.isCantSaveState(), ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
726                 | flag(pkg.isResizeableActivityViaSdkVersion(), ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION)
727                 | flag(pkg.isAllowNativeHeapPointerTagging(), ApplicationInfo.PRIVATE_FLAG_ALLOW_NATIVE_HEAP_POINTER_TAGGING);
728         // @formatter:on
729 
730         Boolean resizeableActivity = pkg.getResizeableActivity();
731         if (resizeableActivity != null) {
732             if (resizeableActivity) {
733                 privateFlags |= ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;
734             } else {
735                 privateFlags |= ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE;
736             }
737         }
738 
739         return privateFlags;
740     }
741 
checkUseInstalled(ParsingPackageRead pkg, PackageUserState state, @PackageManager.PackageInfoFlags int flags)742     private static boolean checkUseInstalled(ParsingPackageRead pkg, PackageUserState state,
743             @PackageManager.PackageInfoFlags int flags) {
744         // If available for the target user
745         return state.isAvailable(flags);
746     }
747 
748     @NonNull
getDataDir(ParsingPackageRead pkg, int userId)749     public static File getDataDir(ParsingPackageRead pkg, int userId) {
750         if ("android".equals(pkg.getPackageName())) {
751             return Environment.getDataSystemDirectory();
752         }
753 
754         if (pkg.isDefaultToDeviceProtectedStorage()
755                 && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) {
756             return getDeviceProtectedDataDir(pkg, userId);
757         } else {
758             return getCredentialProtectedDataDir(pkg, userId);
759         }
760     }
761 
762     @NonNull
getDeviceProtectedDataDir(ParsingPackageRead pkg, int userId)763     public static File getDeviceProtectedDataDir(ParsingPackageRead pkg, int userId) {
764         return Environment.getDataUserDePackageDirectory(pkg.getVolumeUuid(), userId,
765                 pkg.getPackageName());
766     }
767 
768     @NonNull
getCredentialProtectedDataDir(ParsingPackageRead pkg, int userId)769     public static File getCredentialProtectedDataDir(ParsingPackageRead pkg, int userId) {
770         return Environment.getDataUserCePackageDirectory(pkg.getVolumeUuid(), userId,
771                 pkg.getPackageName());
772     }
773 }
774