• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.apex.ApexInfo;
23 import android.content.pm.ActivityInfo;
24 import android.content.pm.ApplicationInfo;
25 import android.content.pm.ComponentInfo;
26 import android.content.pm.InstrumentationInfo;
27 import android.content.pm.PackageInfo;
28 import android.content.pm.PackageItemInfo;
29 import android.content.pm.PackageManager;
30 import android.content.pm.PackageUserState;
31 import android.content.pm.PermissionGroupInfo;
32 import android.content.pm.PermissionInfo;
33 import android.content.pm.ProcessInfo;
34 import android.content.pm.ProviderInfo;
35 import android.content.pm.ServiceInfo;
36 import android.content.pm.SharedLibraryInfo;
37 import android.content.pm.parsing.PackageInfoWithoutStateUtils;
38 import android.content.pm.parsing.component.ComponentParseUtils;
39 import android.content.pm.parsing.component.ParsedActivity;
40 import android.content.pm.parsing.component.ParsedComponent;
41 import android.content.pm.parsing.component.ParsedInstrumentation;
42 import android.content.pm.parsing.component.ParsedMainComponent;
43 import android.content.pm.parsing.component.ParsedPermission;
44 import android.content.pm.parsing.component.ParsedPermissionGroup;
45 import android.content.pm.parsing.component.ParsedProcess;
46 import android.content.pm.parsing.component.ParsedProvider;
47 import android.content.pm.parsing.component.ParsedService;
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.util.ArrayUtils;
55 import com.android.server.pm.PackageSetting;
56 import com.android.server.pm.parsing.pkg.AndroidPackage;
57 import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
58 import com.android.server.pm.pkg.PackageStateUnserialized;
59 
60 import libcore.util.EmptyArray;
61 
62 import java.util.Collections;
63 import java.util.List;
64 import java.util.Map;
65 import java.util.Set;
66 
67 
68 /**
69  * Methods that use a {@link PackageSetting} use it to override information provided from the raw
70  * package, or to provide information that would otherwise be missing. Null can be passed if none
71  * of the state values should be applied.
72  *
73  * @hide
74  **/
75 public class PackageInfoUtils {
76     private static final String TAG = PackageParser2.TAG;
77 
78     /**
79      * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
80      */
81     @Nullable
generate(AndroidPackage pkg, int[] gids, @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime, Set<String> grantedPermissions, PackageUserState state, int userId, @Nullable PackageSetting pkgSetting)82     public static PackageInfo generate(AndroidPackage pkg, int[] gids,
83             @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,
84             Set<String> grantedPermissions, PackageUserState state, int userId,
85             @Nullable PackageSetting pkgSetting) {
86         return generateWithComponents(pkg, gids, flags, firstInstallTime, lastUpdateTime,
87                 grantedPermissions, state, userId, null, pkgSetting);
88     }
89 
90     /**
91      * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
92      */
93     @Nullable
generate(AndroidPackage pkg, ApexInfo apexInfo, int flags, @Nullable PackageSetting pkgSetting)94     public static PackageInfo generate(AndroidPackage pkg, ApexInfo apexInfo, int flags,
95             @Nullable PackageSetting pkgSetting) {
96         return generateWithComponents(pkg, EmptyArray.INT, flags, 0, 0, Collections.emptySet(),
97                 new PackageUserState(), UserHandle.getCallingUserId(), apexInfo, pkgSetting);
98     }
99 
100     /**
101      * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
102      */
generateWithComponents(AndroidPackage pkg, int[] gids, @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime, Set<String> grantedPermissions, PackageUserState state, int userId, @Nullable ApexInfo apexInfo, @Nullable PackageSetting pkgSetting)103     private static PackageInfo generateWithComponents(AndroidPackage pkg, int[] gids,
104             @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,
105             Set<String> grantedPermissions, PackageUserState state, int userId,
106             @Nullable ApexInfo apexInfo, @Nullable PackageSetting pkgSetting) {
107         ApplicationInfo applicationInfo = generateApplicationInfo(pkg, flags, state, userId,
108                 pkgSetting);
109         if (applicationInfo == null) {
110             return null;
111         }
112 
113         PackageInfo info = PackageInfoWithoutStateUtils.generateWithoutComponentsUnchecked(pkg,
114                 gids, flags, firstInstallTime, lastUpdateTime, grantedPermissions, state, userId,
115                 apexInfo, applicationInfo);
116 
117         info.isStub = pkg.isStub();
118         info.coreApp = pkg.isCoreApp();
119 
120         if ((flags & PackageManager.GET_ACTIVITIES) != 0) {
121             final int N = pkg.getActivities().size();
122             if (N > 0) {
123                 int num = 0;
124                 final ActivityInfo[] res = new ActivityInfo[N];
125                 for (int i = 0; i < N; i++) {
126                     final ParsedActivity a = pkg.getActivities().get(i);
127                     if (ComponentParseUtils.isMatch(state, pkg.isSystem(), pkg.isEnabled(), a,
128                             flags)) {
129                         if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(
130                                 a.getName())) {
131                             continue;
132                         }
133                         res[num++] = generateActivityInfo(pkg, a, flags, state,
134                                 applicationInfo, userId, pkgSetting);
135                     }
136                 }
137                 info.activities = ArrayUtils.trimToSize(res, num);
138             }
139         }
140         if ((flags & PackageManager.GET_RECEIVERS) != 0) {
141             final int size = pkg.getReceivers().size();
142             if (size > 0) {
143                 int num = 0;
144                 final ActivityInfo[] res = new ActivityInfo[size];
145                 for (int i = 0; i < size; i++) {
146                     final ParsedActivity a = pkg.getReceivers().get(i);
147                     if (ComponentParseUtils.isMatch(state, pkg.isSystem(), pkg.isEnabled(), a,
148                             flags)) {
149                         res[num++] = generateActivityInfo(pkg, a, flags, state, applicationInfo,
150                                 userId, pkgSetting);
151                     }
152                 }
153                 info.receivers = ArrayUtils.trimToSize(res, num);
154             }
155         }
156         if ((flags & PackageManager.GET_SERVICES) != 0) {
157             final int size = pkg.getServices().size();
158             if (size > 0) {
159                 int num = 0;
160                 final ServiceInfo[] res = new ServiceInfo[size];
161                 for (int i = 0; i < size; i++) {
162                     final ParsedService s = pkg.getServices().get(i);
163                     if (ComponentParseUtils.isMatch(state, pkg.isSystem(), pkg.isEnabled(), s,
164                             flags)) {
165                         res[num++] = generateServiceInfo(pkg, s, flags, state, applicationInfo,
166                                 userId, pkgSetting);
167                     }
168                 }
169                 info.services = ArrayUtils.trimToSize(res, num);
170             }
171         }
172         if ((flags & PackageManager.GET_PROVIDERS) != 0) {
173             final int size = pkg.getProviders().size();
174             if (size > 0) {
175                 int num = 0;
176                 final ProviderInfo[] res = new ProviderInfo[size];
177                 for (int i = 0; i < size; i++) {
178                     final ParsedProvider pr = pkg.getProviders()
179                             .get(i);
180                     if (ComponentParseUtils.isMatch(state, pkg.isSystem(), pkg.isEnabled(), pr,
181                             flags)) {
182                         res[num++] = generateProviderInfo(pkg, pr, flags, state, applicationInfo,
183                                 userId, pkgSetting);
184                     }
185                 }
186                 info.providers = ArrayUtils.trimToSize(res, num);
187             }
188         }
189         if ((flags & PackageManager.GET_INSTRUMENTATION) != 0) {
190             int N = pkg.getInstrumentations().size();
191             if (N > 0) {
192                 info.instrumentation = new InstrumentationInfo[N];
193                 for (int i = 0; i < N; i++) {
194                     info.instrumentation[i] = generateInstrumentationInfo(
195                             pkg.getInstrumentations().get(i), pkg, flags, userId, pkgSetting);
196                 }
197             }
198         }
199 
200         return info;
201     }
202 
203     /**
204      * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
205      */
206     @Nullable
generateApplicationInfo(AndroidPackage pkg, @PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId, @Nullable PackageSetting pkgSetting)207     public static ApplicationInfo generateApplicationInfo(AndroidPackage pkg,
208             @PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId,
209             @Nullable PackageSetting pkgSetting) {
210         // TODO(b/135203078): Consider cases where we don't have a PkgSetting
211         if (pkg == null) {
212             return null;
213         }
214 
215         if (!checkUseInstalledOrHidden(pkg, pkgSetting, state, flags)
216                 || !AndroidPackageUtils.isMatchForSystemOnly(pkg, flags)) {
217             return null;
218         }
219 
220         ApplicationInfo info = PackageInfoWithoutStateUtils.generateApplicationInfoUnchecked(pkg,
221                 flags, state, userId);
222 
223         if (pkgSetting != null) {
224             // TODO(b/135203078): Remove PackageParser1/toAppInfoWithoutState and clean all this up
225             PackageStateUnserialized pkgState = pkgSetting.getPkgState();
226             info.hiddenUntilInstalled = pkgState.isHiddenUntilInstalled();
227             List<String> usesLibraryFiles = pkgState.getUsesLibraryFiles();
228             List<SharedLibraryInfo> usesLibraryInfos = pkgState.getUsesLibraryInfos();
229             info.sharedLibraryFiles = usesLibraryFiles.isEmpty()
230                     ? null : usesLibraryFiles.toArray(new String[0]);
231             info.sharedLibraryInfos = usesLibraryInfos.isEmpty() ? null : usesLibraryInfos;
232         }
233 
234         info.seInfo = AndroidPackageUtils.getSeInfo(pkg, pkgSetting);
235         info.primaryCpuAbi = AndroidPackageUtils.getPrimaryCpuAbi(pkg, pkgSetting);
236         info.secondaryCpuAbi = AndroidPackageUtils.getSecondaryCpuAbi(pkg, pkgSetting);
237 
238         info.flags |= appInfoFlags(info.flags, pkgSetting);
239         info.privateFlags |= appInfoPrivateFlags(info.privateFlags, pkgSetting);
240 
241         return info;
242     }
243 
244     /**
245      * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
246      */
247     @Nullable
generateActivityInfo(AndroidPackage pkg, ParsedActivity a, @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId, @Nullable PackageSetting pkgSetting)248     public static ActivityInfo generateActivityInfo(AndroidPackage pkg, ParsedActivity a,
249             @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId,
250             @Nullable PackageSetting pkgSetting) {
251         return generateActivityInfo(pkg, a, flags, state, null, userId, pkgSetting);
252     }
253 
254     /**
255      * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
256      */
257     @Nullable
generateActivityInfo(AndroidPackage pkg, ParsedActivity a, @PackageManager.ComponentInfoFlags int flags, PackageUserState state, @Nullable ApplicationInfo applicationInfo, int userId, @Nullable PackageSetting pkgSetting)258     private static ActivityInfo generateActivityInfo(AndroidPackage pkg, ParsedActivity a,
259             @PackageManager.ComponentInfoFlags int flags, PackageUserState state,
260             @Nullable ApplicationInfo applicationInfo, int userId,
261             @Nullable PackageSetting pkgSetting) {
262         if (a == null) return null;
263         if (!checkUseInstalledOrHidden(pkg, pkgSetting, state, flags)) {
264             return null;
265         }
266         if (applicationInfo == null) {
267             applicationInfo = generateApplicationInfo(pkg, flags, state, userId, pkgSetting);
268         }
269 
270         if (applicationInfo == null) {
271             return null;
272         }
273 
274         ActivityInfo info =
275                 PackageInfoWithoutStateUtils.generateActivityInfoUnchecked(a, applicationInfo);
276         assignSharedFieldsForComponentInfo(info, a, pkgSetting, userId);
277         return info;
278     }
279 
280     /**
281      * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
282      */
283     @Nullable
generateServiceInfo(AndroidPackage pkg, ParsedService s, @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId, @Nullable PackageSetting pkgSetting)284     public static ServiceInfo generateServiceInfo(AndroidPackage pkg, ParsedService s,
285             @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId,
286             @Nullable PackageSetting pkgSetting) {
287         return generateServiceInfo(pkg, s, flags, state, null, userId, pkgSetting);
288     }
289 
290     /**
291      * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
292      */
293     @Nullable
generateServiceInfo(AndroidPackage pkg, ParsedService s, @PackageManager.ComponentInfoFlags int flags, PackageUserState state, @Nullable ApplicationInfo applicationInfo, int userId, @Nullable PackageSetting pkgSetting)294     private static ServiceInfo generateServiceInfo(AndroidPackage pkg, ParsedService s,
295             @PackageManager.ComponentInfoFlags int flags, PackageUserState state,
296             @Nullable ApplicationInfo applicationInfo, int userId,
297             @Nullable PackageSetting pkgSetting) {
298         if (s == null) return null;
299         if (!checkUseInstalledOrHidden(pkg, pkgSetting, state, flags)) {
300             return null;
301         }
302         if (applicationInfo == null) {
303             applicationInfo = generateApplicationInfo(pkg, flags, state, userId, pkgSetting);
304         }
305         if (applicationInfo == null) {
306             return null;
307         }
308 
309         ServiceInfo info =
310                 PackageInfoWithoutStateUtils.generateServiceInfoUnchecked(s, applicationInfo);
311         assignSharedFieldsForComponentInfo(info, s, pkgSetting, userId);
312         return info;
313     }
314 
315     /**
316      * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
317      */
318     @Nullable
generateProviderInfo(AndroidPackage pkg, ParsedProvider p, @PackageManager.ComponentInfoFlags int flags, PackageUserState state, @NonNull ApplicationInfo applicationInfo, int userId, @Nullable PackageSetting pkgSetting)319     public static ProviderInfo generateProviderInfo(AndroidPackage pkg, ParsedProvider p,
320             @PackageManager.ComponentInfoFlags int flags, PackageUserState state,
321             @NonNull ApplicationInfo applicationInfo, int userId,
322             @Nullable PackageSetting pkgSetting) {
323         if (p == null) return null;
324         if (!checkUseInstalledOrHidden(pkg, pkgSetting, state, flags)) {
325             return null;
326         }
327         if (applicationInfo == null || !pkg.getPackageName().equals(applicationInfo.packageName)) {
328             Slog.wtf(TAG, "AppInfo's package name is different. Expected=" + pkg.getPackageName()
329                     + " actual=" + (applicationInfo == null ? "(null AppInfo)"
330                     : applicationInfo.packageName));
331             applicationInfo = generateApplicationInfo(pkg, flags, state, userId, pkgSetting);
332         }
333         if (applicationInfo == null) {
334             return null;
335         }
336         ProviderInfo info = PackageInfoWithoutStateUtils.generateProviderInfoUnchecked(p, flags,
337                 applicationInfo);
338         assignSharedFieldsForComponentInfo(info, p, pkgSetting, userId);
339         return info;
340     }
341 
342     /**
343      * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
344      */
345     @Nullable
generateInstrumentationInfo(ParsedInstrumentation i, AndroidPackage pkg, @PackageManager.ComponentInfoFlags int flags, int userId, @Nullable PackageSetting pkgSetting)346     public static InstrumentationInfo generateInstrumentationInfo(ParsedInstrumentation i,
347             AndroidPackage pkg, @PackageManager.ComponentInfoFlags int flags, int userId,
348             @Nullable PackageSetting pkgSetting) {
349         if (i == null) return null;
350 
351         InstrumentationInfo info =
352                 PackageInfoWithoutStateUtils.generateInstrumentationInfo(i, pkg, flags, userId);
353         if (info == null) {
354             return null;
355         }
356 
357         // TODO(b/135203078): Add setting related state
358         info.primaryCpuAbi = AndroidPackageUtils.getPrimaryCpuAbi(pkg, pkgSetting);
359         info.secondaryCpuAbi = AndroidPackageUtils.getSecondaryCpuAbi(pkg, pkgSetting);
360         info.nativeLibraryDir = pkg.getNativeLibraryDir();
361         info.secondaryNativeLibraryDir = pkg.getSecondaryNativeLibraryDir();
362 
363         assignStateFieldsForPackageItemInfo(info, i, pkgSetting, userId);
364 
365         return info;
366     }
367 
368     // TODO(b/135203078): Determine if permission methods need to pass in a non-null PackageSetting
369     //  os that checkUseInstalledOrHidden filter can apply
370     @Nullable
generatePermissionInfo(ParsedPermission p, @PackageManager.ComponentInfoFlags int flags)371     public static PermissionInfo generatePermissionInfo(ParsedPermission p,
372             @PackageManager.ComponentInfoFlags int flags) {
373         // TODO(b/135203078): Remove null checks and make all usages @NonNull
374         if (p == null) return null;
375 
376         // For now, permissions don't have state-adjustable fields; return directly
377         return PackageInfoWithoutStateUtils.generatePermissionInfo(p, flags);
378     }
379 
380     @Nullable
generatePermissionGroupInfo(ParsedPermissionGroup pg, @PackageManager.ComponentInfoFlags int flags)381     public static PermissionGroupInfo generatePermissionGroupInfo(ParsedPermissionGroup pg,
382             @PackageManager.ComponentInfoFlags int flags) {
383         if (pg == null) return null;
384 
385         // For now, permissions don't have state-adjustable fields; return directly
386         return PackageInfoWithoutStateUtils.generatePermissionGroupInfo(pg, flags);
387     }
388 
389     @Nullable
generateProcessInfo( Map<String, ParsedProcess> procs, @PackageManager.ComponentInfoFlags int flags)390     public static ArrayMap<String, ProcessInfo> generateProcessInfo(
391             Map<String, ParsedProcess> procs, @PackageManager.ComponentInfoFlags int flags) {
392         if (procs == null) {
393             return null;
394         }
395 
396         final int numProcs = procs.size();
397         ArrayMap<String, ProcessInfo> retProcs = new ArrayMap<>(numProcs);
398         for (String key : procs.keySet()) {
399             ParsedProcess proc = procs.get(key);
400             retProcs.put(proc.getName(),
401                     new ProcessInfo(proc.getName(), new ArraySet<>(proc.getDeniedPermissions()),
402                             proc.getGwpAsanMode()));
403         }
404         return retProcs;
405     }
406 
407     /**
408      * Returns true if the package is installed and not hidden, or if the caller
409      * explicitly wanted all uninstalled and hidden packages as well.
410      */
checkUseInstalledOrHidden(AndroidPackage pkg, PackageSetting pkgSetting, PackageUserState state, @PackageManager.PackageInfoFlags int flags)411     private static boolean checkUseInstalledOrHidden(AndroidPackage pkg,
412             PackageSetting pkgSetting, PackageUserState state,
413             @PackageManager.PackageInfoFlags int flags) {
414         // Returns false if the package is hidden system app until installed.
415         if ((flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) == 0
416                 && !state.installed
417                 && pkgSetting != null
418                 && pkgSetting.getPkgState().isHiddenUntilInstalled()) {
419             return false;
420         }
421 
422         // If available for the target user, or trying to match uninstalled packages and it's
423         // a system app.
424         return state.isAvailable(flags)
425                 || (pkg.isSystem()
426                 && ((flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0
427                 || (flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) != 0));
428     }
429 
assignSharedFieldsForComponentInfo(@onNull ComponentInfo componentInfo, @NonNull ParsedMainComponent mainComponent, @Nullable PackageSetting pkgSetting, int userId)430     private static void assignSharedFieldsForComponentInfo(@NonNull ComponentInfo componentInfo,
431             @NonNull ParsedMainComponent mainComponent, @Nullable PackageSetting pkgSetting,
432             int userId) {
433         assignStateFieldsForPackageItemInfo(componentInfo, mainComponent, pkgSetting, userId);
434         componentInfo.descriptionRes = mainComponent.getDescriptionRes();
435         componentInfo.directBootAware = mainComponent.isDirectBootAware();
436         componentInfo.enabled = mainComponent.isEnabled();
437         componentInfo.splitName = mainComponent.getSplitName();
438     }
439 
assignStateFieldsForPackageItemInfo( @onNull PackageItemInfo packageItemInfo, @NonNull ParsedComponent component, @Nullable PackageSetting pkgSetting, int userId)440     private static void assignStateFieldsForPackageItemInfo(
441             @NonNull PackageItemInfo packageItemInfo, @NonNull ParsedComponent component,
442             @Nullable PackageSetting pkgSetting, int userId) {
443         Pair<CharSequence, Integer> labelAndIcon =
444                 ParsedComponentStateUtils.getNonLocalizedLabelAndIcon(component, pkgSetting,
445                         userId);
446         packageItemInfo.nonLocalizedLabel = labelAndIcon.first;
447         packageItemInfo.icon = labelAndIcon.second;
448     }
449 
450     @CheckResult
flag(boolean hasFlag, int flag)451     private static int flag(boolean hasFlag, int flag) {
452         return hasFlag ? flag : 0;
453     }
454 
455     /** @see ApplicationInfo#flags */
appInfoFlags(AndroidPackage pkg, @Nullable PackageSetting pkgSetting)456     public static int appInfoFlags(AndroidPackage pkg, @Nullable PackageSetting pkgSetting) {
457         // TODO(b/135203078): Add setting related state
458         // @formatter:off
459         int pkgWithoutStateFlags = PackageInfoWithoutStateUtils.appInfoFlags(pkg)
460                 | flag(pkg.isSystem(), ApplicationInfo.FLAG_SYSTEM)
461                 | flag(pkg.isFactoryTest(), ApplicationInfo.FLAG_FACTORY_TEST);
462 
463         return appInfoFlags(pkgWithoutStateFlags, pkgSetting);
464         // @formatter:on
465     }
466 
467     /** @see ApplicationInfo#flags */
appInfoFlags(int pkgWithoutStateFlags, @NonNull PackageSetting pkgSetting)468     public static int appInfoFlags(int pkgWithoutStateFlags, @NonNull PackageSetting pkgSetting) {
469         // @formatter:off
470         int flags = pkgWithoutStateFlags;
471         if (pkgSetting != null) {
472             flags |= flag(pkgSetting.getPkgState().isUpdatedSystemApp(), ApplicationInfo.FLAG_UPDATED_SYSTEM_APP);
473         }
474         return flags;
475         // @formatter:on
476     }
477 
478     /** @see ApplicationInfo#privateFlags */
appInfoPrivateFlags(AndroidPackage pkg, @Nullable PackageSetting pkgSetting)479     public static int appInfoPrivateFlags(AndroidPackage pkg, @Nullable PackageSetting pkgSetting) {
480         // @formatter:off
481         int pkgWithoutStateFlags = PackageInfoWithoutStateUtils.appInfoPrivateFlags(pkg)
482                 | flag(pkg.isSystemExt(), ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT)
483                 | flag(pkg.isPrivileged(), ApplicationInfo.PRIVATE_FLAG_PRIVILEGED)
484                 | flag(pkg.isOem(), ApplicationInfo.PRIVATE_FLAG_OEM)
485                 | flag(pkg.isVendor(), ApplicationInfo.PRIVATE_FLAG_VENDOR)
486                 | flag(pkg.isProduct(), ApplicationInfo.PRIVATE_FLAG_PRODUCT)
487                 | flag(pkg.isOdm(), ApplicationInfo.PRIVATE_FLAG_ODM)
488                 | flag(pkg.isSignedWithPlatformKey(), ApplicationInfo.PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY);
489         return appInfoPrivateFlags(pkgWithoutStateFlags, pkgSetting);
490         // @formatter:on
491     }
492 
493     /** @see ApplicationInfo#privateFlags */
appInfoPrivateFlags(int pkgWithoutStateFlags, @Nullable PackageSetting pkgSetting)494     public static int appInfoPrivateFlags(int pkgWithoutStateFlags, @Nullable PackageSetting pkgSetting) {
495         // @formatter:off
496         // TODO: Add state specific flags
497         return pkgWithoutStateFlags;
498         // @formatter:on
499     }
500 
501     /**
502      * Wraps {@link PackageInfoUtils#generateApplicationInfo} with a cache.
503      */
504     public static class CachedApplicationInfoGenerator {
505         // Map from a package name to the corresponding app info.
506         private ArrayMap<String, ApplicationInfo> mCache = new ArrayMap<>();
507 
508         /**
509          * {@link PackageInfoUtils#generateApplicationInfo} with a cache.
510          */
511         @Nullable
generate(AndroidPackage pkg, @PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId, @Nullable PackageSetting pkgSetting)512         public ApplicationInfo generate(AndroidPackage pkg,
513                 @PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId,
514                 @Nullable PackageSetting pkgSetting) {
515             ApplicationInfo appInfo = mCache.get(pkg.getPackageName());
516             if (appInfo != null) {
517                 return appInfo;
518             }
519             appInfo = PackageInfoUtils.generateApplicationInfo(
520                     pkg, flags, state, userId, pkgSetting);
521             mCache.put(pkg.getPackageName(), appInfo);
522             return appInfo;
523         }
524     }
525 }
526