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 com.android.server.pm.parsing;
18 
19 import android.annotation.CheckResult;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.UserIdInt;
23 import android.content.pm.ActivityInfo;
24 import android.content.pm.ApplicationInfo;
25 import android.content.pm.Attribution;
26 import android.content.pm.ComponentInfo;
27 import android.content.pm.ConfigurationInfo;
28 import android.content.pm.FallbackCategoryProvider;
29 import android.content.pm.FeatureGroupInfo;
30 import android.content.pm.FeatureInfo;
31 import android.content.pm.InstrumentationInfo;
32 import android.content.pm.PackageInfo;
33 import android.content.pm.PackageItemInfo;
34 import android.content.pm.PackageManager;
35 import android.content.pm.PathPermission;
36 import android.content.pm.PermissionGroupInfo;
37 import android.content.pm.PermissionInfo;
38 import android.content.pm.ProcessInfo;
39 import android.content.pm.ProviderInfo;
40 import android.content.pm.ServiceInfo;
41 import android.content.pm.SharedLibraryInfo;
42 import android.content.pm.Signature;
43 import android.content.pm.SigningDetails;
44 import android.content.pm.SigningInfo;
45 import android.content.pm.overlay.OverlayPaths;
46 import android.os.Environment;
47 import android.os.PatternMatcher;
48 import android.os.UserHandle;
49 import android.util.ArrayMap;
50 import android.util.ArraySet;
51 import android.util.Pair;
52 import android.util.Slog;
53 
54 import com.android.internal.annotations.VisibleForTesting;
55 import com.android.internal.util.ArrayUtils;
56 import com.android.server.SystemConfig;
57 import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
58 import com.android.server.pm.parsing.pkg.PackageImpl;
59 import com.android.server.pm.pkg.AndroidPackage;
60 import com.android.server.pm.pkg.PackageStateInternal;
61 import com.android.server.pm.pkg.PackageStateUnserialized;
62 import com.android.server.pm.pkg.PackageUserState;
63 import com.android.server.pm.pkg.PackageUserStateInternal;
64 import com.android.server.pm.pkg.PackageUserStateUtils;
65 import com.android.server.pm.pkg.SELinuxUtil;
66 import com.android.server.pm.pkg.component.ComponentParseUtils;
67 import com.android.server.pm.pkg.component.ParsedActivity;
68 import com.android.server.pm.pkg.component.ParsedAttribution;
69 import com.android.server.pm.pkg.component.ParsedComponent;
70 import com.android.server.pm.pkg.component.ParsedInstrumentation;
71 import com.android.server.pm.pkg.component.ParsedMainComponent;
72 import com.android.server.pm.pkg.component.ParsedPermission;
73 import com.android.server.pm.pkg.component.ParsedPermissionGroup;
74 import com.android.server.pm.pkg.component.ParsedProcess;
75 import com.android.server.pm.pkg.component.ParsedProvider;
76 import com.android.server.pm.pkg.component.ParsedService;
77 import com.android.server.pm.pkg.component.ParsedUsesPermission;
78 import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
79 import com.android.server.pm.pkg.parsing.ParsingUtils;
80 
81 import java.io.File;
82 import java.util.ArrayList;
83 import java.util.List;
84 import java.util.Map;
85 import java.util.Set;
86 
87 
88 /**
89  * Methods that use a {@link PackageStateInternal} use it to override information provided from the
90  * raw package, or to provide information that would otherwise be missing. Null can be passed if
91  * none of the state values should be applied.
92  *
93  * @hide
94  **/
95 public class PackageInfoUtils {
96     private static final String TAG = ParsingUtils.TAG;
97 
98     private static final String SYSTEM_DATA_PATH =
99             Environment.getDataDirectoryPath() + File.separator + "system";
100 
101     /**
102      * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
103      */
104     @Nullable
generate(AndroidPackage pkg, int[] gids, @PackageManager.PackageInfoFlagsBits long flags, long firstInstallTime, long lastUpdateTime, Set<String> installedPermissions, Set<String> grantedPermissions, PackageUserStateInternal state, @UserIdInt int userId, @NonNull PackageStateInternal pkgSetting)105     public static PackageInfo generate(AndroidPackage pkg, int[] gids,
106             @PackageManager.PackageInfoFlagsBits long flags, long firstInstallTime,
107             long lastUpdateTime, Set<String> installedPermissions, Set<String> grantedPermissions,
108             PackageUserStateInternal state, @UserIdInt int userId,
109             @NonNull PackageStateInternal pkgSetting) {
110         return generateWithComponents(pkg, gids, flags, firstInstallTime, lastUpdateTime,
111                 installedPermissions, grantedPermissions, state, userId, pkgSetting);
112     }
113 
114     /**
115      * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
116      */
generateWithComponents(AndroidPackage pkg, int[] gids, @PackageManager.PackageInfoFlagsBits long flags, long firstInstallTime, long lastUpdateTime, Set<String> installedPermissions, Set<String> grantedPermissions, PackageUserStateInternal state, @UserIdInt int userId, @NonNull PackageStateInternal pkgSetting)117     private static PackageInfo generateWithComponents(AndroidPackage pkg, int[] gids,
118             @PackageManager.PackageInfoFlagsBits long flags, long firstInstallTime,
119             long lastUpdateTime, Set<String> installedPermissions, Set<String> grantedPermissions,
120             PackageUserStateInternal state, @UserIdInt int userId,
121             @NonNull PackageStateInternal pkgSetting) {
122         ApplicationInfo applicationInfo = generateApplicationInfo(pkg, flags, state, userId,
123                 pkgSetting);
124         if (applicationInfo == null) {
125             return null;
126         }
127 
128         PackageInfo info = new PackageInfo();
129         info.packageName = pkg.getPackageName();
130         info.splitNames = pkg.getSplitNames();
131         AndroidPackageUtils.fillVersionCodes(pkg, info);
132         info.baseRevisionCode = pkg.getBaseRevisionCode();
133         info.splitRevisionCodes = pkg.getSplitRevisionCodes();
134         info.versionName = pkg.getVersionName();
135         info.sharedUserId = pkg.getSharedUserId();
136         info.sharedUserLabel = pkg.getSharedUserLabelResourceId();
137         info.applicationInfo = applicationInfo;
138         info.installLocation = pkg.getInstallLocation();
139         if ((info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0
140                 || (info.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
141             info.requiredForAllUsers = pkg.isRequiredForAllUsers();
142         }
143         info.restrictedAccountType = pkg.getRestrictedAccountType();
144         info.requiredAccountType = pkg.getRequiredAccountType();
145         info.overlayTarget = pkg.getOverlayTarget();
146         info.targetOverlayableName = pkg.getOverlayTargetOverlayableName();
147         info.overlayCategory = pkg.getOverlayCategory();
148         info.overlayPriority = pkg.getOverlayPriority();
149         info.mOverlayIsStatic = pkg.isOverlayIsStatic();
150         info.compileSdkVersion = pkg.getCompileSdkVersion();
151         info.compileSdkVersionCodename = pkg.getCompileSdkVersionCodeName();
152         info.firstInstallTime = firstInstallTime;
153         info.lastUpdateTime = lastUpdateTime;
154         if ((flags & PackageManager.GET_GIDS) != 0) {
155             info.gids = gids;
156         }
157         if ((flags & PackageManager.GET_CONFIGURATIONS) != 0) {
158             int size = pkg.getConfigPreferences().size();
159             if (size > 0) {
160                 info.configPreferences = new ConfigurationInfo[size];
161                 pkg.getConfigPreferences().toArray(info.configPreferences);
162             }
163             size = pkg.getRequestedFeatures().size();
164             if (size > 0) {
165                 info.reqFeatures = new FeatureInfo[size];
166                 pkg.getRequestedFeatures().toArray(info.reqFeatures);
167             }
168             size = pkg.getFeatureGroups().size();
169             if (size > 0) {
170                 info.featureGroups = new FeatureGroupInfo[size];
171                 pkg.getFeatureGroups().toArray(info.featureGroups);
172             }
173         }
174         if ((flags & PackageManager.GET_PERMISSIONS) != 0) {
175             int size = ArrayUtils.size(pkg.getPermissions());
176             if (size > 0) {
177                 info.permissions = new PermissionInfo[size];
178                 for (int i = 0; i < size; i++) {
179                     final var permission = pkg.getPermissions().get(i);
180                     final var permissionInfo = generatePermissionInfo(permission, flags);
181                     if (installedPermissions.contains(permission.getName())) {
182                         permissionInfo.flags |= PermissionInfo.FLAG_INSTALLED;
183                     }
184                     info.permissions[i] = permissionInfo;
185                 }
186             }
187             final List<ParsedUsesPermission> usesPermissions = pkg.getUsesPermissions();
188             size = usesPermissions.size();
189             if (size > 0) {
190                 info.requestedPermissions = new String[size];
191                 info.requestedPermissionsFlags = new int[size];
192                 for (int i = 0; i < size; i++) {
193                     final ParsedUsesPermission usesPermission = usesPermissions.get(i);
194                     info.requestedPermissions[i] = usesPermission.getName();
195                     // The notion of required permissions is deprecated but for compatibility.
196                     info.requestedPermissionsFlags[i] |=
197                             PackageInfo.REQUESTED_PERMISSION_REQUIRED;
198                     if (grantedPermissions != null
199                             && grantedPermissions.contains(usesPermission.getName())) {
200                         info.requestedPermissionsFlags[i] |=
201                                 PackageInfo.REQUESTED_PERMISSION_GRANTED;
202                     }
203                     if ((usesPermission.getUsesPermissionFlags()
204                             & ParsedUsesPermission.FLAG_NEVER_FOR_LOCATION) != 0) {
205                         info.requestedPermissionsFlags[i] |=
206                                 PackageInfo.REQUESTED_PERMISSION_NEVER_FOR_LOCATION;
207                     }
208                     if (pkg.getImplicitPermissions().contains(info.requestedPermissions[i])) {
209                         info.requestedPermissionsFlags[i] |=
210                                 PackageInfo.REQUESTED_PERMISSION_IMPLICIT;
211                     }
212                 }
213             }
214         }
215         if ((flags & PackageManager.GET_ATTRIBUTIONS_LONG) != 0) {
216             int size = ArrayUtils.size(pkg.getAttributions());
217             if (size > 0) {
218                 info.attributions = new Attribution[size];
219                 for (int i = 0; i < size; i++) {
220                     ParsedAttribution parsedAttribution = pkg.getAttributions().get(i);
221                     if (parsedAttribution != null) {
222                         info.attributions[i] = new Attribution(parsedAttribution.getTag(),
223                                 parsedAttribution.getLabel());
224                     }
225                 }
226             }
227             if (pkg.isAttributionsUserVisible()) {
228                 info.applicationInfo.privateFlagsExt
229                         |= ApplicationInfo.PRIVATE_FLAG_EXT_ATTRIBUTIONS_ARE_USER_VISIBLE;
230             } else {
231                 info.applicationInfo.privateFlagsExt
232                         &= ~ApplicationInfo.PRIVATE_FLAG_EXT_ATTRIBUTIONS_ARE_USER_VISIBLE;
233             }
234         } else {
235             info.applicationInfo.privateFlagsExt
236                     &= ~ApplicationInfo.PRIVATE_FLAG_EXT_ATTRIBUTIONS_ARE_USER_VISIBLE;
237         }
238 
239         final SigningDetails signingDetails = pkg.getSigningDetails();
240         // deprecated method of getting signing certificates
241         if ((flags & PackageManager.GET_SIGNATURES) != 0) {
242             if (signingDetails.hasPastSigningCertificates()) {
243                 // Package has included signing certificate rotation information.  Return the oldest
244                 // cert so that programmatic checks keep working even if unaware of key rotation.
245                 info.signatures = new Signature[1];
246                 info.signatures[0] = signingDetails.getPastSigningCertificates()[0];
247             } else if (signingDetails.hasSignatures()) {
248                 // otherwise keep old behavior
249                 int numberOfSigs = signingDetails.getSignatures().length;
250                 info.signatures = new Signature[numberOfSigs];
251                 System.arraycopy(signingDetails.getSignatures(), 0, info.signatures, 0,
252                         numberOfSigs);
253             }
254         }
255 
256         // replacement for GET_SIGNATURES
257         if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) {
258             if (signingDetails != SigningDetails.UNKNOWN) {
259                 // only return a valid SigningInfo if there is signing information to report
260                 info.signingInfo = new SigningInfo(signingDetails);
261             } else {
262                 info.signingInfo = null;
263             }
264         }
265 
266         info.isStub = pkg.isStub();
267         info.coreApp = pkg.isCoreApp();
268         info.isApex = pkg.isApex();
269 
270         if (!pkgSetting.hasSharedUser()) {
271             // It is possible that this shared UID app has left
272             info.sharedUserId = null;
273             info.sharedUserLabel = 0;
274         }
275 
276         if ((flags & PackageManager.GET_ACTIVITIES) != 0) {
277             final int N = pkg.getActivities().size();
278             if (N > 0) {
279                 int num = 0;
280                 final ActivityInfo[] res = new ActivityInfo[N];
281                 for (int i = 0; i < N; i++) {
282                     final ParsedActivity a = pkg.getActivities().get(i);
283                     if (ComponentParseUtils.isMatch(state, pkgSetting.isSystem(), pkg.isEnabled(), a,
284                             flags)) {
285                         if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(
286                                 a.getName())) {
287                             continue;
288                         }
289                         res[num++] = generateActivityInfo(pkg, a, flags, state,
290                                 applicationInfo, userId, pkgSetting);
291                     }
292                 }
293                 info.activities = ArrayUtils.trimToSize(res, num);
294             }
295         }
296         if ((flags & PackageManager.GET_RECEIVERS) != 0) {
297             final int size = pkg.getReceivers().size();
298             if (size > 0) {
299                 int num = 0;
300                 final ActivityInfo[] res = new ActivityInfo[size];
301                 for (int i = 0; i < size; i++) {
302                     final ParsedActivity a = pkg.getReceivers().get(i);
303                     if (ComponentParseUtils.isMatch(state, pkgSetting.isSystem(), pkg.isEnabled(), a,
304                             flags)) {
305                         res[num++] = generateActivityInfo(pkg, a, flags, state, applicationInfo,
306                                 userId, pkgSetting);
307                     }
308                 }
309                 info.receivers = ArrayUtils.trimToSize(res, num);
310             }
311         }
312         if ((flags & PackageManager.GET_SERVICES) != 0) {
313             final int size = pkg.getServices().size();
314             if (size > 0) {
315                 int num = 0;
316                 final ServiceInfo[] res = new ServiceInfo[size];
317                 for (int i = 0; i < size; i++) {
318                     final ParsedService s = pkg.getServices().get(i);
319                     if (ComponentParseUtils.isMatch(state, pkgSetting.isSystem(), pkg.isEnabled(), s,
320                             flags)) {
321                         res[num++] = generateServiceInfo(pkg, s, flags, state, applicationInfo,
322                                 userId, pkgSetting);
323                     }
324                 }
325                 info.services = ArrayUtils.trimToSize(res, num);
326             }
327         }
328         if ((flags & PackageManager.GET_PROVIDERS) != 0) {
329             final int size = pkg.getProviders().size();
330             if (size > 0) {
331                 int num = 0;
332                 final ProviderInfo[] res = new ProviderInfo[size];
333                 for (int i = 0; i < size; i++) {
334                     final ParsedProvider pr = pkg.getProviders()
335                             .get(i);
336                     if (ComponentParseUtils.isMatch(state, pkgSetting.isSystem(), pkg.isEnabled(), pr,
337                             flags)) {
338                         res[num++] = generateProviderInfo(pkg, pr, flags, state, applicationInfo,
339                                 userId, pkgSetting);
340                     }
341                 }
342                 info.providers = ArrayUtils.trimToSize(res, num);
343             }
344         }
345         if ((flags & PackageManager.GET_INSTRUMENTATION) != 0) {
346             int N = pkg.getInstrumentations().size();
347             if (N > 0) {
348                 info.instrumentation = new InstrumentationInfo[N];
349                 for (int i = 0; i < N; i++) {
350                     info.instrumentation[i] = generateInstrumentationInfo(
351                             pkg.getInstrumentations().get(i), pkg, flags, state,
352                             userId, pkgSetting);
353                 }
354             }
355         }
356 
357         return info;
358     }
359 
updateApplicationInfo(ApplicationInfo ai, long flags, PackageUserState state)360     private static void updateApplicationInfo(ApplicationInfo ai, long flags,
361             PackageUserState state) {
362         if ((flags & PackageManager.GET_META_DATA) == 0) {
363             ai.metaData = null;
364         }
365         if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) == 0) {
366             ai.sharedLibraryFiles = null;
367             ai.sharedLibraryInfos = null;
368         }
369 
370         // CompatibilityMode is global state.
371         if (!ParsingPackageUtils.sCompatibilityModeEnabled) {
372             ai.disableCompatibilityMode();
373         }
374 
375         ai.flags |= flag(state.isStopped(), ApplicationInfo.FLAG_STOPPED)
376                 | flag(state.isInstalled(), ApplicationInfo.FLAG_INSTALLED)
377                 | flag(state.isSuspended(), ApplicationInfo.FLAG_SUSPENDED);
378         ai.privateFlags |= flag(state.isInstantApp(), ApplicationInfo.PRIVATE_FLAG_INSTANT)
379                 | flag(state.isVirtualPreload(), ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD)
380                 | flag(state.isHidden(), ApplicationInfo.PRIVATE_FLAG_HIDDEN);
381 
382         if (state.getEnabledState() == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
383             ai.enabled = true;
384         } else if (state.getEnabledState()
385                 == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
386             ai.enabled = (flags & PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
387         } else if (state.getEnabledState() == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
388                 || state.getEnabledState()
389                 == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
390             ai.enabled = false;
391         }
392         ai.enabledSetting = state.getEnabledState();
393         if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
394             ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);
395         }
396         ai.seInfoUser = SELinuxUtil.getSeinfoUser(state);
397         final OverlayPaths overlayPaths = state.getAllOverlayPaths();
398         if (overlayPaths != null) {
399             ai.resourceDirs = overlayPaths.getResourceDirs().toArray(new String[0]);
400             ai.overlayPaths = overlayPaths.getOverlayPaths().toArray(new String[0]);
401         }
402     }
403 
404     @Nullable
generateDelegateApplicationInfo(@ullable ApplicationInfo ai, @PackageManager.ApplicationInfoFlagsBits long flags, @NonNull PackageUserState state, int userId)405     public static ApplicationInfo generateDelegateApplicationInfo(@Nullable ApplicationInfo ai,
406             @PackageManager.ApplicationInfoFlagsBits long flags,
407             @NonNull PackageUserState state, int userId) {
408         if (ai == null || !checkUseInstalledOrHidden(flags, state, ai)) {
409             return null;
410         }
411 
412         ai = new ApplicationInfo(ai);
413         ai.initForUser(userId);
414         ai.icon = (ParsingPackageUtils.sUseRoundIcon && ai.roundIconRes != 0) ? ai.roundIconRes
415                 : ai.iconRes;
416         updateApplicationInfo(ai, flags, state);
417         return ai;
418     }
419 
420     /**
421      * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
422      */
423     @VisibleForTesting
424     @Nullable
generateApplicationInfo(AndroidPackage pkg, @PackageManager.ApplicationInfoFlagsBits long flags, @NonNull PackageUserStateInternal state, @UserIdInt int userId, @NonNull PackageStateInternal pkgSetting)425     public static ApplicationInfo generateApplicationInfo(AndroidPackage pkg,
426             @PackageManager.ApplicationInfoFlagsBits long flags,
427             @NonNull PackageUserStateInternal state, @UserIdInt int userId,
428             @NonNull PackageStateInternal pkgSetting) {
429         if (pkg == null) {
430             return null;
431         }
432 
433         if (!checkUseInstalledOrHidden(pkg, pkgSetting, state, flags)
434                 || !AndroidPackageUtils.isMatchForSystemOnly(pkgSetting, flags)) {
435             return null;
436         }
437 
438         // Make shallow copy so we can store the metadata/libraries safely
439         ApplicationInfo info = AndroidPackageUtils.generateAppInfoWithoutState(pkg);
440 
441         updateApplicationInfo(info, flags, state);
442 
443         initForUser(info, pkg, userId);
444 
445         // TODO(b/135203078): Remove PackageParser1/toAppInfoWithoutState and clean all this up
446         PackageStateUnserialized pkgState = pkgSetting.getTransientState();
447         info.hiddenUntilInstalled = pkgState.isHiddenUntilInstalled();
448         List<String> usesLibraryFiles = pkgState.getUsesLibraryFiles();
449         var usesLibraries = pkgState.getUsesLibraryInfos();
450         var usesLibraryInfos = new ArrayList<SharedLibraryInfo>();
451         for (int index = 0; index < usesLibraries.size(); index++) {
452             usesLibraryInfos.add(usesLibraries.get(index).getInfo());
453         }
454         info.sharedLibraryFiles = usesLibraryFiles.isEmpty()
455                 ? null : usesLibraryFiles.toArray(new String[0]);
456         info.sharedLibraryInfos = usesLibraryInfos.isEmpty() ? null : usesLibraryInfos;
457         if (info.category == ApplicationInfo.CATEGORY_UNDEFINED) {
458             info.category = pkgSetting.getCategoryOverride();
459         }
460 
461         info.seInfo = pkgSetting.getSeInfo();
462         info.primaryCpuAbi = pkgSetting.getPrimaryCpuAbi();
463         info.secondaryCpuAbi = pkgSetting.getSecondaryCpuAbi();
464 
465         info.flags |= appInfoFlags(info.flags, pkgSetting);
466         info.privateFlags |= appInfoPrivateFlags(info.privateFlags, pkgSetting);
467         info.privateFlagsExt |= appInfoPrivateFlagsExt(info.privateFlagsExt, pkgSetting);
468 
469         return info;
470     }
471 
472     /**
473      * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
474      */
475     @VisibleForTesting
476     @Nullable
generateActivityInfo(AndroidPackage pkg, ParsedActivity a, @PackageManager.ComponentInfoFlagsBits long flags, @NonNull PackageUserStateInternal state, @UserIdInt int userId, @NonNull PackageStateInternal pkgSetting)477     public static ActivityInfo generateActivityInfo(AndroidPackage pkg, ParsedActivity a,
478             @PackageManager.ComponentInfoFlagsBits long flags,
479             @NonNull PackageUserStateInternal state, @UserIdInt int userId,
480             @NonNull PackageStateInternal pkgSetting) {
481         return generateActivityInfo(pkg, a, flags, state, null, userId, pkgSetting);
482     }
483 
484     /**
485      * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
486      */
487     @VisibleForTesting
488     @Nullable
generateActivityInfo(AndroidPackage pkg, ParsedActivity a, @PackageManager.ComponentInfoFlagsBits long flags, @NonNull PackageUserStateInternal state, @Nullable ApplicationInfo applicationInfo, @UserIdInt int userId, @NonNull PackageStateInternal pkgSetting)489     public static ActivityInfo generateActivityInfo(AndroidPackage pkg, ParsedActivity a,
490             @PackageManager.ComponentInfoFlagsBits long flags,
491             @NonNull PackageUserStateInternal state, @Nullable ApplicationInfo applicationInfo,
492             @UserIdInt int userId, @NonNull PackageStateInternal pkgSetting) {
493         if (a == null) return null;
494         if (!checkUseInstalledOrHidden(pkg, pkgSetting, state, flags)) {
495             return null;
496         }
497         if (applicationInfo == null) {
498             applicationInfo = generateApplicationInfo(pkg, flags, state, userId, pkgSetting);
499         }
500 
501         if (applicationInfo == null) {
502             return null;
503         }
504 
505         // Make shallow copies so we can store the metadata safely
506         ActivityInfo ai = new ActivityInfo();
507         ai.targetActivity = a.getTargetActivity();
508         ai.processName = a.getProcessName();
509         ai.exported = a.isExported();
510         ai.theme = a.getTheme();
511         ai.uiOptions = a.getUiOptions();
512         ai.parentActivityName = a.getParentActivityName();
513         ai.permission = a.getPermission();
514         ai.taskAffinity = a.getTaskAffinity();
515         ai.flags = a.getFlags();
516         ai.privateFlags = a.getPrivateFlags();
517         ai.launchMode = a.getLaunchMode();
518         ai.documentLaunchMode = a.getDocumentLaunchMode();
519         ai.maxRecents = a.getMaxRecents();
520         ai.configChanges = a.getConfigChanges();
521         ai.softInputMode = a.getSoftInputMode();
522         ai.persistableMode = a.getPersistableMode();
523         ai.lockTaskLaunchMode = a.getLockTaskLaunchMode();
524         ai.screenOrientation = a.getScreenOrientation();
525         ai.resizeMode = a.getResizeMode();
526         ai.setMaxAspectRatio(a.getMaxAspectRatio());
527         ai.setMinAspectRatio(a.getMinAspectRatio());
528         ai.supportsSizeChanges = a.isSupportsSizeChanges();
529         ai.requestedVrComponent = a.getRequestedVrComponent();
530         ai.rotationAnimation = a.getRotationAnimation();
531         ai.colorMode = a.getColorMode();
532         ai.windowLayout = a.getWindowLayout();
533         ai.attributionTags = a.getAttributionTags();
534         if ((flags & PackageManager.GET_META_DATA) != 0) {
535             var metaData = a.getMetaData();
536             // Backwards compatibility, coerce to null if empty
537             ai.metaData = metaData.isEmpty() ? null : metaData;
538         } else {
539             ai.metaData = null;
540         }
541         ai.applicationInfo = applicationInfo;
542         ai.requiredDisplayCategory = a.getRequiredDisplayCategory();
543         ai.setKnownActivityEmbeddingCerts(a.getKnownActivityEmbeddingCerts());
544         assignFieldsComponentInfoParsedMainComponent(ai, a, pkgSetting, userId);
545         return ai;
546     }
547 
548     @Nullable
generateDelegateActivityInfo(@ullable ActivityInfo a, @PackageManager.ComponentInfoFlagsBits long flags, @NonNull PackageUserState state, int userId)549     public static ActivityInfo generateDelegateActivityInfo(@Nullable ActivityInfo a,
550             @PackageManager.ComponentInfoFlagsBits long flags,
551             @NonNull PackageUserState state, int userId) {
552         if (a == null || !checkUseInstalledOrHidden(flags, state, a.applicationInfo)) {
553             return null;
554         }
555         // This is used to return the ResolverActivity or instantAppInstallerActivity;
556         // we will just always make a copy.
557         final ActivityInfo ai = new ActivityInfo(a);
558         ai.applicationInfo =
559                 generateDelegateApplicationInfo(ai.applicationInfo, flags, state, userId);
560         return ai;
561     }
562 
563     /**
564      * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
565      */
566     @Nullable
generateServiceInfo(AndroidPackage pkg, ParsedService s, @PackageManager.ComponentInfoFlagsBits long flags, PackageUserStateInternal state, @UserIdInt int userId, @NonNull PackageStateInternal pkgSetting)567     public static ServiceInfo generateServiceInfo(AndroidPackage pkg, ParsedService s,
568             @PackageManager.ComponentInfoFlagsBits long flags, PackageUserStateInternal state,
569             @UserIdInt int userId, @NonNull PackageStateInternal pkgSetting) {
570         return generateServiceInfo(pkg, s, flags, state, null, userId, pkgSetting);
571     }
572 
573     /**
574      * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
575      */
576     @VisibleForTesting
577     @Nullable
generateServiceInfo(AndroidPackage pkg, ParsedService s, @PackageManager.ComponentInfoFlagsBits long flags, PackageUserStateInternal state, @Nullable ApplicationInfo applicationInfo, int userId, @NonNull PackageStateInternal pkgSetting)578     public static ServiceInfo generateServiceInfo(AndroidPackage pkg, ParsedService s,
579             @PackageManager.ComponentInfoFlagsBits long flags, PackageUserStateInternal state,
580             @Nullable ApplicationInfo applicationInfo, int userId,
581             @NonNull PackageStateInternal pkgSetting) {
582         if (s == null) return null;
583         if (!checkUseInstalledOrHidden(pkg, pkgSetting, state, flags)) {
584             return null;
585         }
586         if (applicationInfo == null) {
587             applicationInfo = generateApplicationInfo(pkg, flags, state, userId, pkgSetting);
588         }
589         if (applicationInfo == null) {
590             return null;
591         }
592 
593 
594         // Make shallow copies so we can store the metadata safely
595         ServiceInfo si = new ServiceInfo();
596         si.exported = s.isExported();
597         si.flags = s.getFlags();
598         si.permission = s.getPermission();
599         si.processName = s.getProcessName();
600         si.mForegroundServiceType = s.getForegroundServiceType();
601         si.applicationInfo = applicationInfo;
602         if ((flags & PackageManager.GET_META_DATA) != 0) {
603             var metaData = s.getMetaData();
604             // Backwards compatibility, coerce to null if empty
605             si.metaData = metaData.isEmpty() ? null : metaData;
606         }
607         assignFieldsComponentInfoParsedMainComponent(si, s, pkgSetting, userId);
608         return si;
609     }
610 
611     /**
612      * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
613      */
614     @VisibleForTesting
615     @Nullable
generateProviderInfo(AndroidPackage pkg, ParsedProvider p, @PackageManager.ComponentInfoFlagsBits long flags, PackageUserStateInternal state, @NonNull ApplicationInfo applicationInfo, int userId, @NonNull PackageStateInternal pkgSetting)616     public static ProviderInfo generateProviderInfo(AndroidPackage pkg, ParsedProvider p,
617             @PackageManager.ComponentInfoFlagsBits long flags, PackageUserStateInternal state,
618             @NonNull ApplicationInfo applicationInfo, int userId,
619             @NonNull PackageStateInternal pkgSetting) {
620         if (p == null) return null;
621         if (!checkUseInstalledOrHidden(pkg, pkgSetting, state, flags)) {
622             return null;
623         }
624         if (applicationInfo == null || !pkg.getPackageName().equals(applicationInfo.packageName)) {
625             Slog.wtf(TAG, "AppInfo's package name is different. Expected=" + pkg.getPackageName()
626                     + " actual=" + (applicationInfo == null ? "(null AppInfo)"
627                     : applicationInfo.packageName));
628             applicationInfo = generateApplicationInfo(pkg, flags, state, userId, pkgSetting);
629         }
630         if (applicationInfo == null) {
631             return null;
632         }
633 
634         // Make shallow copies so we can store the metadata safely
635         ProviderInfo pi = new ProviderInfo();
636         pi.exported = p.isExported();
637         pi.flags = p.getFlags();
638         pi.processName = p.getProcessName();
639         pi.authority = p.getAuthority();
640         pi.isSyncable = p.isSyncable();
641         pi.readPermission = p.getReadPermission();
642         pi.writePermission = p.getWritePermission();
643         pi.grantUriPermissions = p.isGrantUriPermissions();
644         pi.forceUriPermissions = p.isForceUriPermissions();
645         pi.multiprocess = p.isMultiProcess();
646         pi.initOrder = p.getInitOrder();
647         pi.uriPermissionPatterns = p.getUriPermissionPatterns().toArray(new PatternMatcher[0]);
648         pi.pathPermissions = p.getPathPermissions().toArray(new PathPermission[0]);
649         if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
650             pi.uriPermissionPatterns = null;
651         }
652         if ((flags & PackageManager.GET_META_DATA) != 0) {
653             var metaData = p.getMetaData();
654             // Backwards compatibility, coerce to null if empty
655             pi.metaData = metaData.isEmpty() ? null : metaData;
656         }
657         pi.applicationInfo = applicationInfo;
658         assignFieldsComponentInfoParsedMainComponent(pi, p, pkgSetting, userId);
659         return pi;
660     }
661 
662     /**
663      * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
664      */
665     @Nullable
generateInstrumentationInfo(ParsedInstrumentation i, AndroidPackage pkg, @PackageManager.ComponentInfoFlagsBits long flags, PackageUserStateInternal state, int userId, @NonNull PackageStateInternal pkgSetting)666     public static InstrumentationInfo generateInstrumentationInfo(ParsedInstrumentation i,
667             AndroidPackage pkg, @PackageManager.ComponentInfoFlagsBits long flags,
668             PackageUserStateInternal state, int userId, @NonNull PackageStateInternal pkgSetting) {
669         if (i == null) return null;
670         if (!checkUseInstalledOrHidden(pkg, pkgSetting, state, flags)) {
671             return null;
672         }
673 
674         InstrumentationInfo info = new InstrumentationInfo();
675         info.targetPackage = i.getTargetPackage();
676         info.targetProcesses = i.getTargetProcesses();
677         info.handleProfiling = i.isHandleProfiling();
678         info.functionalTest = i.isFunctionalTest();
679 
680         info.sourceDir = pkg.getBaseApkPath();
681         info.publicSourceDir = pkg.getBaseApkPath();
682         info.splitNames = pkg.getSplitNames();
683         info.splitSourceDirs = pkg.getSplitCodePaths().length == 0 ? null : pkg.getSplitCodePaths();
684         info.splitPublicSourceDirs = pkg.getSplitCodePaths().length == 0
685                 ? null : pkg.getSplitCodePaths();
686         info.splitDependencies = pkg.getSplitDependencies().size() == 0
687                 ? null : pkg.getSplitDependencies();
688 
689         initForUser(info, pkg, userId);
690 
691         info.primaryCpuAbi = pkgSetting.getPrimaryCpuAbi();
692         info.secondaryCpuAbi = pkgSetting.getSecondaryCpuAbi();
693         info.nativeLibraryDir = pkg.getNativeLibraryDir();
694         info.secondaryNativeLibraryDir = pkg.getSecondaryNativeLibraryDir();
695 
696         assignFieldsPackageItemInfoParsedComponent(info, i, pkgSetting, userId);
697 
698         if ((flags & PackageManager.GET_META_DATA) == 0) {
699             info.metaData = null;
700         } else {
701             var metaData = i.getMetaData();
702             // Backwards compatibility, coerce to null if empty
703             info.metaData = metaData.isEmpty() ? null : metaData;
704         }
705 
706         return info;
707     }
708 
709     // TODO(b/135203078): Determine if permission methods need to pass in a non-null
710     //  PackageStateInternal os that checkUseInstalledOrHidden filter can apply
711     @Nullable
generatePermissionInfo(ParsedPermission p, @PackageManager.ComponentInfoFlagsBits long flags)712     public static PermissionInfo generatePermissionInfo(ParsedPermission p,
713             @PackageManager.ComponentInfoFlagsBits long flags) {
714         // TODO(b/135203078): Remove null checks and make all usages @NonNull
715         if (p == null) return null;
716 
717         PermissionInfo pi = new PermissionInfo(p.getBackgroundPermission());
718 
719         assignFieldsPackageItemInfoParsedComponent(pi, p);
720 
721         pi.group = p.getGroup();
722         pi.requestRes = p.getRequestRes();
723         pi.protectionLevel = p.getProtectionLevel();
724         pi.descriptionRes = p.getDescriptionRes();
725         pi.flags = p.getFlags();
726         pi.knownCerts = p.getKnownCerts();
727 
728         if ((flags & PackageManager.GET_META_DATA) == 0) {
729             pi.metaData = null;
730         } else {
731             var metaData = p.getMetaData();
732             // Backwards compatibility, coerce to null if empty
733             pi.metaData = metaData.isEmpty() ? null : metaData;
734         }
735         return pi;
736     }
737 
738     @Nullable
generatePermissionGroupInfo(ParsedPermissionGroup pg, @PackageManager.ComponentInfoFlagsBits long flags)739     public static PermissionGroupInfo generatePermissionGroupInfo(ParsedPermissionGroup pg,
740             @PackageManager.ComponentInfoFlagsBits long flags) {
741         if (pg == null) return null;
742 
743         PermissionGroupInfo pgi = new PermissionGroupInfo(
744                 pg.getRequestDetailRes(),
745                 pg.getBackgroundRequestRes(),
746                 pg.getBackgroundRequestDetailRes()
747         );
748 
749         assignFieldsPackageItemInfoParsedComponent(pgi, pg);
750         pgi.descriptionRes = pg.getDescriptionRes();
751         pgi.priority = pg.getPriority();
752         pgi.requestRes = pg.getRequestRes();
753         pgi.flags = pg.getFlags();
754 
755         if ((flags & PackageManager.GET_META_DATA) == 0) {
756             pgi.metaData = null;
757         } else {
758             var metaData = pg.getMetaData();
759             // Backwards compatibility, coerce to null if empty
760             pgi.metaData = metaData.isEmpty() ? null : metaData;
761         }
762 
763         return pgi;
764     }
765 
766     @Nullable
generateProcessInfo( Map<String, ParsedProcess> procs, @PackageManager.ComponentInfoFlagsBits long flags)767     public static ArrayMap<String, ProcessInfo> generateProcessInfo(
768             Map<String, ParsedProcess> procs, @PackageManager.ComponentInfoFlagsBits long flags) {
769         if (procs == null) {
770             return null;
771         }
772 
773         final int numProcs = procs.size();
774         ArrayMap<String, ProcessInfo> retProcs = new ArrayMap<>(numProcs);
775         for (String key : procs.keySet()) {
776             ParsedProcess proc = procs.get(key);
777             retProcs.put(proc.getName(),
778                     new ProcessInfo(proc.getName(), new ArraySet<>(proc.getDeniedPermissions()),
779                             proc.getGwpAsanMode(), proc.getMemtagMode(),
780                             proc.getNativeHeapZeroInitialized()));
781         }
782         return retProcs;
783     }
784 
785     /**
786      * Returns true if the package is installed and not hidden, or if the caller explicitly wanted
787      * all uninstalled and hidden packages as well.
788      */
checkUseInstalledOrHidden(AndroidPackage pkg, @NonNull PackageStateInternal pkgSetting, PackageUserStateInternal state, @PackageManager.PackageInfoFlagsBits long flags)789     public static boolean checkUseInstalledOrHidden(AndroidPackage pkg,
790             @NonNull PackageStateInternal pkgSetting, PackageUserStateInternal state,
791             @PackageManager.PackageInfoFlagsBits long flags) {
792         // Returns false if the package is hidden system app until installed.
793         if ((flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) == 0
794                 && !state.isInstalled()
795                 && pkgSetting.getTransientState().isHiddenUntilInstalled()) {
796             return false;
797         }
798 
799         // If available for the target user, or trying to match uninstalled packages and it's
800         // a system app.
801         return PackageUserStateUtils.isAvailable(state, flags)
802                 || (pkgSetting.isSystem()
803                 && ((flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0
804                 || (flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) != 0));
805     }
806 
checkUseInstalledOrHidden(long flags, @NonNull PackageUserState state, @Nullable ApplicationInfo appInfo)807     private static boolean checkUseInstalledOrHidden(long flags,
808             @NonNull PackageUserState state, @Nullable ApplicationInfo appInfo) {
809         // Returns false if the package is hidden system app until installed.
810         if ((flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) == 0
811                 && !state.isInstalled()
812                 && appInfo != null && appInfo.hiddenUntilInstalled) {
813             return false;
814         }
815 
816         // If available for the target user, or trying to match uninstalled packages and it's
817         // a system app.
818         return PackageUserStateUtils.isAvailable(state, flags)
819                 || (appInfo != null && appInfo.isSystemApp()
820                 && ((flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0
821                 || (flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) != 0));
822     }
823 
assignFieldsComponentInfoParsedMainComponent( @onNull ComponentInfo info, @NonNull ParsedMainComponent component)824     private static void assignFieldsComponentInfoParsedMainComponent(
825             @NonNull ComponentInfo info, @NonNull ParsedMainComponent component) {
826         assignFieldsPackageItemInfoParsedComponent(info, component);
827         info.descriptionRes = component.getDescriptionRes();
828         info.directBootAware = component.isDirectBootAware();
829         info.enabled = component.isEnabled();
830         info.splitName = component.getSplitName();
831         info.attributionTags = component.getAttributionTags();
832     }
833 
assignFieldsPackageItemInfoParsedComponent( @onNull PackageItemInfo packageItemInfo, @NonNull ParsedComponent component)834     private static void assignFieldsPackageItemInfoParsedComponent(
835             @NonNull PackageItemInfo packageItemInfo, @NonNull ParsedComponent component) {
836         packageItemInfo.nonLocalizedLabel = ComponentParseUtils.getNonLocalizedLabel(component);
837         packageItemInfo.icon = ComponentParseUtils.getIcon(component);
838         packageItemInfo.banner = component.getBanner();
839         packageItemInfo.labelRes = component.getLabelRes();
840         packageItemInfo.logo = component.getLogo();
841         packageItemInfo.name = component.getName();
842         packageItemInfo.packageName = component.getPackageName();
843     }
844 
assignFieldsComponentInfoParsedMainComponent( @onNull ComponentInfo info, @NonNull ParsedMainComponent component, @NonNull PackageStateInternal pkgSetting, @UserIdInt int userId)845     private static void assignFieldsComponentInfoParsedMainComponent(
846             @NonNull ComponentInfo info, @NonNull ParsedMainComponent component,
847             @NonNull PackageStateInternal pkgSetting, @UserIdInt int userId) {
848         assignFieldsComponentInfoParsedMainComponent(info, component);
849         Pair<CharSequence, Integer> labelAndIcon =
850                 ParsedComponentStateUtils.getNonLocalizedLabelAndIcon(component, pkgSetting,
851                         userId);
852         info.nonLocalizedLabel = labelAndIcon.first;
853         info.icon = labelAndIcon.second;
854     }
855 
assignFieldsPackageItemInfoParsedComponent( @onNull PackageItemInfo info, @NonNull ParsedComponent component, @NonNull PackageStateInternal pkgSetting, @UserIdInt int userId)856     private static void assignFieldsPackageItemInfoParsedComponent(
857             @NonNull PackageItemInfo info, @NonNull ParsedComponent component,
858             @NonNull PackageStateInternal pkgSetting, @UserIdInt int userId) {
859         assignFieldsPackageItemInfoParsedComponent(info, component);
860         Pair<CharSequence, Integer> labelAndIcon =
861                 ParsedComponentStateUtils.getNonLocalizedLabelAndIcon(component, pkgSetting,
862                         userId);
863         info.nonLocalizedLabel = labelAndIcon.first;
864         info.icon = labelAndIcon.second;
865     }
866 
867     @CheckResult
flag(boolean hasFlag, int flag)868     private static int flag(boolean hasFlag, int flag) {
869         return hasFlag ? flag : 0;
870     }
871 
872     /**
873      * @see ApplicationInfo#flags
874      */
appInfoFlags(AndroidPackage pkg, @Nullable PackageStateInternal pkgSetting)875     public static int appInfoFlags(AndroidPackage pkg, @Nullable PackageStateInternal pkgSetting) {
876         // @formatter:off
877         int pkgWithoutStateFlags = flag(pkg.isExternalStorage(), ApplicationInfo.FLAG_EXTERNAL_STORAGE)
878                 | flag(pkg.isHardwareAccelerated(), ApplicationInfo.FLAG_HARDWARE_ACCELERATED)
879                 | flag(pkg.isBackupAllowed(), ApplicationInfo.FLAG_ALLOW_BACKUP)
880                 | flag(pkg.isKillAfterRestoreAllowed(), ApplicationInfo.FLAG_KILL_AFTER_RESTORE)
881                 | flag(pkg.isRestoreAnyVersion(), ApplicationInfo.FLAG_RESTORE_ANY_VERSION)
882                 | flag(pkg.isFullBackupOnly(), ApplicationInfo.FLAG_FULL_BACKUP_ONLY)
883                 | flag(pkg.isPersistent(), ApplicationInfo.FLAG_PERSISTENT)
884                 | flag(pkg.isDebuggable(), ApplicationInfo.FLAG_DEBUGGABLE)
885                 | flag(pkg.isVmSafeMode(), ApplicationInfo.FLAG_VM_SAFE_MODE)
886                 | flag(pkg.isDeclaredHavingCode(), ApplicationInfo.FLAG_HAS_CODE)
887                 | flag(pkg.isTaskReparentingAllowed(), ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING)
888                 | flag(pkg.isClearUserDataAllowed(), ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA)
889                 | flag(pkg.isLargeHeap(), ApplicationInfo.FLAG_LARGE_HEAP)
890                 | flag(pkg.isCleartextTrafficAllowed(), ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC)
891                 | flag(pkg.isRtlSupported(), ApplicationInfo.FLAG_SUPPORTS_RTL)
892                 | flag(pkg.isTestOnly(), ApplicationInfo.FLAG_TEST_ONLY)
893                 | flag(pkg.isMultiArch(), ApplicationInfo.FLAG_MULTIARCH)
894                 | flag(pkg.isExtractNativeLibrariesRequested(), ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS)
895                 | flag(pkg.isGame(), ApplicationInfo.FLAG_IS_GAME)
896                 | flag(pkg.isSmallScreensSupported(), ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS)
897                 | flag(pkg.isNormalScreensSupported(), ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS)
898                 | flag(pkg.isLargeScreensSupported(), ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS)
899                 | flag(pkg.isExtraLargeScreensSupported(), ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS)
900                 | flag(pkg.isResizeable(), ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS)
901                 | flag(pkg.isAnyDensity(), ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
902                 | flag(AndroidPackageUtils.isSystem(pkg), ApplicationInfo.FLAG_SYSTEM)
903                 | flag(pkg.isFactoryTest(), ApplicationInfo.FLAG_FACTORY_TEST);
904 
905         return appInfoFlags(pkgWithoutStateFlags, pkgSetting);
906         // @formatter:on
907     }
908 
909     /** @see ApplicationInfo#flags */
appInfoFlags(int pkgWithoutStateFlags, @NonNull PackageStateInternal pkgSetting)910     public static int appInfoFlags(int pkgWithoutStateFlags,
911             @NonNull PackageStateInternal pkgSetting) {
912         // @formatter:off
913         int flags = pkgWithoutStateFlags;
914         if (pkgSetting != null) {
915             flags |= flag(pkgSetting.isUpdatedSystemApp(), ApplicationInfo.FLAG_UPDATED_SYSTEM_APP);
916         }
917         return flags;
918         // @formatter:on
919     }
920 
921     /** @see ApplicationInfo#privateFlags */
appInfoPrivateFlags(AndroidPackage pkg, @Nullable PackageStateInternal pkgSetting)922     public static int appInfoPrivateFlags(AndroidPackage pkg,
923             @Nullable PackageStateInternal pkgSetting) {
924         // @formatter:off
925         int pkgWithoutStateFlags = flag(pkg.isStaticSharedLibrary(), ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY)
926                 | flag(pkg.isResourceOverlay(), ApplicationInfo.PRIVATE_FLAG_IS_RESOURCE_OVERLAY)
927                 | flag(pkg.isIsolatedSplitLoading(), ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING)
928                 | flag(pkg.isHasDomainUrls(), ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS)
929                 | flag(pkg.isProfileableByShell(), ApplicationInfo.PRIVATE_FLAG_PROFILEABLE_BY_SHELL)
930                 | flag(pkg.isBackupInForeground(), ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND)
931                 | flag(pkg.isUseEmbeddedDex(), ApplicationInfo.PRIVATE_FLAG_USE_EMBEDDED_DEX)
932                 | flag(pkg.isDefaultToDeviceProtectedStorage(), ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE)
933                 | flag(pkg.isDirectBootAware(), ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE)
934                 | flag(pkg.isPartiallyDirectBootAware(), ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE)
935                 | flag(pkg.isClearUserDataOnFailedRestoreAllowed(), ApplicationInfo.PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE)
936                 | flag(pkg.isAllowAudioPlaybackCapture(), ApplicationInfo.PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE)
937                 | flag(pkg.isRequestLegacyExternalStorage(), ApplicationInfo.PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE)
938                 | flag(pkg.isNonSdkApiRequested(), ApplicationInfo.PRIVATE_FLAG_USES_NON_SDK_API)
939                 | flag(pkg.isUserDataFragile(), ApplicationInfo.PRIVATE_FLAG_HAS_FRAGILE_USER_DATA)
940                 | flag(pkg.isSaveStateDisallowed(), ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
941                 | flag(pkg.isResizeableActivityViaSdkVersion(), ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION)
942                 | flag(pkg.isAllowNativeHeapPointerTagging(), ApplicationInfo.PRIVATE_FLAG_ALLOW_NATIVE_HEAP_POINTER_TAGGING)
943                 | flag(AndroidPackageUtils.isSystemExt(pkg), ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT)
944                 | flag(AndroidPackageUtils.isPrivileged(pkg), ApplicationInfo.PRIVATE_FLAG_PRIVILEGED)
945                 | flag(AndroidPackageUtils.isOem(pkg), ApplicationInfo.PRIVATE_FLAG_OEM)
946                 | flag(AndroidPackageUtils.isVendor(pkg), ApplicationInfo.PRIVATE_FLAG_VENDOR)
947                 | flag(AndroidPackageUtils.isProduct(pkg), ApplicationInfo.PRIVATE_FLAG_PRODUCT)
948                 | flag(AndroidPackageUtils.isOdm(pkg), ApplicationInfo.PRIVATE_FLAG_ODM)
949                 | flag(pkg.isSignedWithPlatformKey(), ApplicationInfo.PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY);
950 
951         Boolean resizeableActivity = pkg.getResizeableActivity();
952         if (resizeableActivity != null) {
953             if (resizeableActivity) {
954                 pkgWithoutStateFlags |= ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;
955             } else {
956                 pkgWithoutStateFlags |= ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE;
957             }
958         }
959 
960         return appInfoPrivateFlags(pkgWithoutStateFlags, pkgSetting);
961         // @formatter:on
962     }
963 
964     /** @see ApplicationInfo#privateFlags */
appInfoPrivateFlags(int pkgWithoutStateFlags, @Nullable PackageStateInternal pkgSetting)965     public static int appInfoPrivateFlags(int pkgWithoutStateFlags,
966             @Nullable PackageStateInternal pkgSetting) {
967         // @formatter:off
968         // TODO: Add state specific flags
969         return pkgWithoutStateFlags;
970         // @formatter:on
971     }
972 
973     /** @see ApplicationInfo#privateFlagsExt */
appInfoPrivateFlagsExt(AndroidPackage pkg, @Nullable PackageStateInternal pkgSetting)974     public static int appInfoPrivateFlagsExt(AndroidPackage pkg,
975                                              @Nullable PackageStateInternal pkgSetting) {
976         var isAllowlistedForHiddenApis = SystemConfig.getInstance().getHiddenApiWhitelistedApps()
977                 .contains(pkg.getPackageName());
978         // @formatter:off
979         int pkgWithoutStateFlags = flag(pkg.isProfileable(), ApplicationInfo.PRIVATE_FLAG_EXT_PROFILEABLE)
980                 | flag(pkg.hasRequestForegroundServiceExemption(), ApplicationInfo.PRIVATE_FLAG_EXT_REQUEST_FOREGROUND_SERVICE_EXEMPTION)
981                 | flag(pkg.isAttributionsUserVisible(), ApplicationInfo.PRIVATE_FLAG_EXT_ATTRIBUTIONS_ARE_USER_VISIBLE)
982                 | flag(pkg.isOnBackInvokedCallbackEnabled(), ApplicationInfo.PRIVATE_FLAG_EXT_ENABLE_ON_BACK_INVOKED_CALLBACK)
983                 | flag(isAllowlistedForHiddenApis, ApplicationInfo.PRIVATE_FLAG_EXT_ALLOWLISTED_FOR_HIDDEN_APIS);
984         return appInfoPrivateFlagsExt(pkgWithoutStateFlags, pkgSetting);
985         // @formatter:on
986     }
987 
988     /** @see ApplicationInfo#privateFlagsExt */
appInfoPrivateFlagsExt(int pkgWithoutStateFlags, @Nullable PackageStateInternal pkgSetting)989     private static int appInfoPrivateFlagsExt(int pkgWithoutStateFlags,
990                                              @Nullable PackageStateInternal pkgSetting) {
991         // @formatter:off
992         int flags = pkgWithoutStateFlags;
993         if (pkgSetting != null) {
994             flags |= flag(pkgSetting.getCpuAbiOverride() != null, ApplicationInfo.PRIVATE_FLAG_EXT_CPU_OVERRIDE);
995         }
996         return flags;
997         // @formatter:on
998     }
999 
initForUser(ApplicationInfo output, AndroidPackage input, @UserIdInt int userId)1000     private static void initForUser(ApplicationInfo output, AndroidPackage input,
1001             @UserIdInt int userId) {
1002         PackageImpl pkg = ((PackageImpl) input);
1003         String packageName = input.getPackageName();
1004         output.uid = UserHandle.getUid(userId, UserHandle.getAppId(input.getUid()));
1005 
1006         if ("android".equals(packageName)) {
1007             output.dataDir = SYSTEM_DATA_PATH;
1008             return;
1009         }
1010 
1011         // For performance reasons, all these paths are built as strings
1012         if (userId == UserHandle.USER_SYSTEM) {
1013             output.credentialProtectedDataDir =
1014                     pkg.getBaseAppDataCredentialProtectedDirForSystemUser() + packageName;
1015             output.deviceProtectedDataDir =
1016                     pkg.getBaseAppDataDeviceProtectedDirForSystemUser() + packageName;
1017         } else {
1018             // Convert /data/user/0/ -> /data/user/1/com.example.app
1019             String userIdString = String.valueOf(userId);
1020             int credentialLength = pkg.getBaseAppDataCredentialProtectedDirForSystemUser().length();
1021             output.credentialProtectedDataDir =
1022                     new StringBuilder(pkg.getBaseAppDataCredentialProtectedDirForSystemUser())
1023                             .replace(credentialLength - 2, credentialLength - 1, userIdString)
1024                             .append(packageName)
1025                             .toString();
1026             int deviceLength = pkg.getBaseAppDataDeviceProtectedDirForSystemUser().length();
1027             output.deviceProtectedDataDir =
1028                     new StringBuilder(pkg.getBaseAppDataDeviceProtectedDirForSystemUser())
1029                             .replace(deviceLength - 2, deviceLength - 1, userIdString)
1030                             .append(packageName)
1031                             .toString();
1032         }
1033 
1034         if (input.isDefaultToDeviceProtectedStorage()
1035                 && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) {
1036             output.dataDir = output.deviceProtectedDataDir;
1037         } else {
1038             output.dataDir = output.credentialProtectedDataDir;
1039         }
1040     }
1041 
1042     // This duplicates the ApplicationInfo variant because it uses field assignment and the classes
1043     // don't inherit from each other, unfortunately. Consolidating logic would introduce overhead.
initForUser(InstrumentationInfo output, AndroidPackage input, @UserIdInt int userId)1044     private static void initForUser(InstrumentationInfo output, AndroidPackage input,
1045             @UserIdInt int userId) {
1046         PackageImpl pkg = ((PackageImpl) input);
1047         String packageName = input.getPackageName();
1048         if ("android".equals(packageName)) {
1049             output.dataDir = SYSTEM_DATA_PATH;
1050             return;
1051         }
1052 
1053         // For performance reasons, all these paths are built as strings
1054         if (userId == UserHandle.USER_SYSTEM) {
1055             output.credentialProtectedDataDir =
1056                     pkg.getBaseAppDataCredentialProtectedDirForSystemUser() + packageName;
1057             output.deviceProtectedDataDir =
1058                     pkg.getBaseAppDataDeviceProtectedDirForSystemUser() + packageName;
1059         } else {
1060             // Convert /data/user/0/ -> /data/user/1/com.example.app
1061             String userIdString = String.valueOf(userId);
1062             int credentialLength = pkg.getBaseAppDataCredentialProtectedDirForSystemUser().length();
1063             output.credentialProtectedDataDir =
1064                     new StringBuilder(pkg.getBaseAppDataCredentialProtectedDirForSystemUser())
1065                             .replace(credentialLength - 2, credentialLength - 1, userIdString)
1066                             .append(packageName)
1067                             .toString();
1068             int deviceLength = pkg.getBaseAppDataDeviceProtectedDirForSystemUser().length();
1069             output.deviceProtectedDataDir =
1070                     new StringBuilder(pkg.getBaseAppDataDeviceProtectedDirForSystemUser())
1071                             .replace(deviceLength - 2, deviceLength - 1, userIdString)
1072                             .append(packageName)
1073                             .toString();
1074         }
1075 
1076         if (input.isDefaultToDeviceProtectedStorage()
1077                 && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) {
1078             output.dataDir = output.deviceProtectedDataDir;
1079         } else {
1080             output.dataDir = output.credentialProtectedDataDir;
1081         }
1082     }
1083 
1084     @NonNull
getDataDir(AndroidPackage pkg, int userId)1085     public static File getDataDir(AndroidPackage pkg, int userId) {
1086         if ("android".equals(pkg.getPackageName())) {
1087             return Environment.getDataSystemDirectory();
1088         }
1089 
1090         if (pkg.isDefaultToDeviceProtectedStorage()
1091                 && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) {
1092             return Environment.getDataUserDePackageDirectory(pkg.getVolumeUuid(), userId,
1093                     pkg.getPackageName());
1094         } else {
1095             return Environment.getDataUserCePackageDirectory(pkg.getVolumeUuid(), userId,
1096                     pkg.getPackageName());
1097         }
1098     }
1099 
1100     /**
1101      * Wraps {@link PackageInfoUtils#generateApplicationInfo} with a cache.
1102      */
1103     public static class CachedApplicationInfoGenerator {
1104         // Map from a package name to the corresponding app info.
1105         private ArrayMap<String, ApplicationInfo> mCache = new ArrayMap<>();
1106 
1107         /**
1108          * {@link PackageInfoUtils#generateApplicationInfo} with a cache.
1109          */
1110         @Nullable
generate(AndroidPackage pkg, @PackageManager.ApplicationInfoFlagsBits long flags, PackageUserStateInternal state, int userId, @NonNull PackageStateInternal pkgSetting)1111         public ApplicationInfo generate(AndroidPackage pkg,
1112                 @PackageManager.ApplicationInfoFlagsBits long flags, PackageUserStateInternal state,
1113                 int userId, @NonNull PackageStateInternal pkgSetting) {
1114             ApplicationInfo appInfo = mCache.get(pkg.getPackageName());
1115             if (appInfo != null) {
1116                 return appInfo;
1117             }
1118             appInfo = PackageInfoUtils.generateApplicationInfo(
1119                     pkg, flags, state, userId, pkgSetting);
1120             mCache.put(pkg.getPackageName(), appInfo);
1121             return appInfo;
1122         }
1123     }
1124 }
1125