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