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