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.apex.ApexInfo; 24 import android.content.pm.ActivityInfo; 25 import android.content.pm.ApplicationInfo; 26 import android.content.pm.ComponentInfo; 27 import android.content.pm.InstrumentationInfo; 28 import android.content.pm.PackageInfo; 29 import android.content.pm.PackageItemInfo; 30 import android.content.pm.PackageManager; 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.os.UserHandle; 38 import android.util.ArrayMap; 39 import android.util.ArraySet; 40 import android.util.Pair; 41 import android.util.Slog; 42 43 import com.android.internal.util.ArrayUtils; 44 import com.android.server.pm.parsing.pkg.AndroidPackage; 45 import com.android.server.pm.parsing.pkg.AndroidPackageUtils; 46 import com.android.server.pm.parsing.pkg.PackageImpl; 47 import com.android.server.pm.pkg.PackageStateInternal; 48 import com.android.server.pm.pkg.PackageStateUnserialized; 49 import com.android.server.pm.pkg.PackageUserStateInternal; 50 import com.android.server.pm.pkg.PackageUserStateUtils; 51 import com.android.server.pm.pkg.component.ComponentParseUtils; 52 import com.android.server.pm.pkg.component.ParsedActivity; 53 import com.android.server.pm.pkg.component.ParsedComponent; 54 import com.android.server.pm.pkg.component.ParsedInstrumentation; 55 import com.android.server.pm.pkg.component.ParsedMainComponent; 56 import com.android.server.pm.pkg.component.ParsedPermission; 57 import com.android.server.pm.pkg.component.ParsedPermissionGroup; 58 import com.android.server.pm.pkg.component.ParsedProcess; 59 import com.android.server.pm.pkg.component.ParsedProvider; 60 import com.android.server.pm.pkg.component.ParsedService; 61 import com.android.server.pm.pkg.parsing.PackageInfoWithoutStateUtils; 62 import com.android.server.pm.pkg.parsing.ParsingUtils; 63 64 import libcore.util.EmptyArray; 65 66 import java.util.Collections; 67 import java.util.List; 68 import java.util.Map; 69 import java.util.Set; 70 71 72 /** 73 * Methods that use a {@link PackageStateInternal} use it to override information provided from the 74 * raw package, or to provide information that would otherwise be missing. Null can be passed if 75 * none of the state values should be applied. 76 * 77 * @hide 78 **/ 79 public class PackageInfoUtils { 80 private static final String TAG = ParsingUtils.TAG; 81 82 /** 83 * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage. 84 */ 85 @Nullable generate(AndroidPackage pkg, int[] gids, @PackageManager.PackageInfoFlagsBits long flags, long firstInstallTime, long lastUpdateTime, Set<String> grantedPermissions, PackageUserStateInternal state, @UserIdInt int userId, @Nullable PackageStateInternal pkgSetting)86 public static PackageInfo generate(AndroidPackage pkg, int[] gids, 87 @PackageManager.PackageInfoFlagsBits long flags, long firstInstallTime, 88 long lastUpdateTime, Set<String> grantedPermissions, PackageUserStateInternal state, 89 @UserIdInt int userId, @Nullable PackageStateInternal pkgSetting) { 90 return generateWithComponents(pkg, gids, flags, firstInstallTime, lastUpdateTime, 91 grantedPermissions, state, userId, null, pkgSetting); 92 } 93 94 /** 95 * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage. 96 */ 97 @Nullable generate(AndroidPackage pkg, ApexInfo apexInfo, int flags, @Nullable PackageStateInternal pkgSetting)98 public static PackageInfo generate(AndroidPackage pkg, ApexInfo apexInfo, int flags, 99 @Nullable PackageStateInternal pkgSetting) { 100 return generateWithComponents(pkg, EmptyArray.INT, flags, 0, 0, Collections.emptySet(), 101 PackageUserStateInternal.DEFAULT, UserHandle.getCallingUserId(), apexInfo, pkgSetting); 102 } 103 104 /** 105 * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage. 106 */ generateWithComponents(AndroidPackage pkg, int[] gids, @PackageManager.PackageInfoFlagsBits long flags, long firstInstallTime, long lastUpdateTime, Set<String> grantedPermissions, PackageUserStateInternal state, @UserIdInt int userId, @Nullable ApexInfo apexInfo, @Nullable PackageStateInternal pkgSetting)107 private static PackageInfo generateWithComponents(AndroidPackage pkg, int[] gids, 108 @PackageManager.PackageInfoFlagsBits long flags, long firstInstallTime, 109 long lastUpdateTime, Set<String> grantedPermissions, PackageUserStateInternal state, 110 @UserIdInt int userId, @Nullable ApexInfo apexInfo, 111 @Nullable PackageStateInternal pkgSetting) { 112 ApplicationInfo applicationInfo = generateApplicationInfo(pkg, flags, state, userId, 113 pkgSetting); 114 if (applicationInfo == null) { 115 return null; 116 } 117 118 PackageInfo info = PackageInfoWithoutStateUtils.generateWithoutComponentsUnchecked(pkg, 119 gids, flags, firstInstallTime, lastUpdateTime, grantedPermissions, state, userId, 120 apexInfo, applicationInfo); 121 122 info.isStub = pkg.isStub(); 123 info.coreApp = pkg.isCoreApp(); 124 125 if (pkgSetting != null && !pkgSetting.hasSharedUser()) { 126 // It is possible that this shared UID app has left 127 info.sharedUserId = null; 128 info.sharedUserLabel = 0; 129 } 130 131 if ((flags & PackageManager.GET_ACTIVITIES) != 0) { 132 final int N = pkg.getActivities().size(); 133 if (N > 0) { 134 int num = 0; 135 final ActivityInfo[] res = new ActivityInfo[N]; 136 for (int i = 0; i < N; i++) { 137 final ParsedActivity a = pkg.getActivities().get(i); 138 if (ComponentParseUtils.isMatch(state, pkg.isSystem(), pkg.isEnabled(), a, 139 flags)) { 140 if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals( 141 a.getName())) { 142 continue; 143 } 144 res[num++] = generateActivityInfo(pkg, a, flags, state, 145 applicationInfo, userId, pkgSetting); 146 } 147 } 148 info.activities = ArrayUtils.trimToSize(res, num); 149 } 150 } 151 if ((flags & PackageManager.GET_RECEIVERS) != 0) { 152 final int size = pkg.getReceivers().size(); 153 if (size > 0) { 154 int num = 0; 155 final ActivityInfo[] res = new ActivityInfo[size]; 156 for (int i = 0; i < size; i++) { 157 final ParsedActivity a = pkg.getReceivers().get(i); 158 if (ComponentParseUtils.isMatch(state, pkg.isSystem(), pkg.isEnabled(), a, 159 flags)) { 160 res[num++] = generateActivityInfo(pkg, a, flags, state, applicationInfo, 161 userId, pkgSetting); 162 } 163 } 164 info.receivers = ArrayUtils.trimToSize(res, num); 165 } 166 } 167 if ((flags & PackageManager.GET_SERVICES) != 0) { 168 final int size = pkg.getServices().size(); 169 if (size > 0) { 170 int num = 0; 171 final ServiceInfo[] res = new ServiceInfo[size]; 172 for (int i = 0; i < size; i++) { 173 final ParsedService s = pkg.getServices().get(i); 174 if (ComponentParseUtils.isMatch(state, pkg.isSystem(), pkg.isEnabled(), s, 175 flags)) { 176 res[num++] = generateServiceInfo(pkg, s, flags, state, applicationInfo, 177 userId, pkgSetting); 178 } 179 } 180 info.services = ArrayUtils.trimToSize(res, num); 181 } 182 } 183 if ((flags & PackageManager.GET_PROVIDERS) != 0) { 184 final int size = pkg.getProviders().size(); 185 if (size > 0) { 186 int num = 0; 187 final ProviderInfo[] res = new ProviderInfo[size]; 188 for (int i = 0; i < size; i++) { 189 final ParsedProvider pr = pkg.getProviders() 190 .get(i); 191 if (ComponentParseUtils.isMatch(state, pkg.isSystem(), pkg.isEnabled(), pr, 192 flags)) { 193 res[num++] = generateProviderInfo(pkg, pr, flags, state, applicationInfo, 194 userId, pkgSetting); 195 } 196 } 197 info.providers = ArrayUtils.trimToSize(res, num); 198 } 199 } 200 if ((flags & PackageManager.GET_INSTRUMENTATION) != 0) { 201 int N = pkg.getInstrumentations().size(); 202 if (N > 0) { 203 info.instrumentation = new InstrumentationInfo[N]; 204 for (int i = 0; i < N; i++) { 205 info.instrumentation[i] = generateInstrumentationInfo( 206 pkg.getInstrumentations().get(i), pkg, flags, userId, pkgSetting); 207 } 208 } 209 } 210 211 return info; 212 } 213 214 /** 215 * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage. 216 */ 217 @Nullable generateApplicationInfo(AndroidPackage pkg, @PackageManager.ApplicationInfoFlagsBits long flags, @NonNull PackageUserStateInternal state, @UserIdInt int userId, @Nullable PackageStateInternal pkgSetting)218 public static ApplicationInfo generateApplicationInfo(AndroidPackage pkg, 219 @PackageManager.ApplicationInfoFlagsBits long flags, 220 @NonNull PackageUserStateInternal state, @UserIdInt int userId, 221 @Nullable PackageStateInternal pkgSetting) { 222 if (pkg == null) { 223 return null; 224 } 225 226 if (!checkUseInstalledOrHidden(pkg, pkgSetting, state, flags) 227 || !AndroidPackageUtils.isMatchForSystemOnly(pkg, flags)) { 228 return null; 229 } 230 231 ApplicationInfo info = PackageInfoWithoutStateUtils.generateApplicationInfoUnchecked(pkg, 232 flags, state, userId, false /* assignUserFields */); 233 234 initForUser(info, pkg, userId); 235 236 if (pkgSetting != null) { 237 // TODO(b/135203078): Remove PackageParser1/toAppInfoWithoutState and clean all this up 238 PackageStateUnserialized pkgState = pkgSetting.getTransientState(); 239 info.hiddenUntilInstalled = pkgState.isHiddenUntilInstalled(); 240 List<String> usesLibraryFiles = pkgState.getUsesLibraryFiles(); 241 List<SharedLibraryInfo> usesLibraryInfos = pkgState.getUsesLibraryInfos(); 242 info.sharedLibraryFiles = usesLibraryFiles.isEmpty() 243 ? null : usesLibraryFiles.toArray(new String[0]); 244 info.sharedLibraryInfos = usesLibraryInfos.isEmpty() ? null : usesLibraryInfos; 245 if (info.category == ApplicationInfo.CATEGORY_UNDEFINED) { 246 info.category = pkgSetting.getCategoryOverride(); 247 } 248 } 249 250 info.seInfo = AndroidPackageUtils.getSeInfo(pkg, pkgSetting); 251 info.primaryCpuAbi = AndroidPackageUtils.getPrimaryCpuAbi(pkg, pkgSetting); 252 info.secondaryCpuAbi = AndroidPackageUtils.getSecondaryCpuAbi(pkg, pkgSetting); 253 254 info.flags |= appInfoFlags(info.flags, pkgSetting); 255 info.privateFlags |= appInfoPrivateFlags(info.privateFlags, pkgSetting); 256 info.privateFlagsExt |= appInfoPrivateFlagsExt(info.privateFlagsExt, pkgSetting); 257 258 return info; 259 } 260 261 /** 262 * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage. 263 */ 264 @Nullable generateActivityInfo(AndroidPackage pkg, ParsedActivity a, @PackageManager.ComponentInfoFlagsBits long flags, @NonNull PackageUserStateInternal state, @UserIdInt int userId, @Nullable PackageStateInternal pkgSetting)265 public static ActivityInfo generateActivityInfo(AndroidPackage pkg, ParsedActivity a, 266 @PackageManager.ComponentInfoFlagsBits long flags, 267 @NonNull PackageUserStateInternal state, @UserIdInt int userId, 268 @Nullable PackageStateInternal pkgSetting) { 269 return generateActivityInfo(pkg, a, flags, state, null, userId, pkgSetting); 270 } 271 272 /** 273 * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage. 274 */ 275 @Nullable generateActivityInfo(AndroidPackage pkg, ParsedActivity a, @PackageManager.ComponentInfoFlagsBits long flags, @NonNull PackageUserStateInternal state, @Nullable ApplicationInfo applicationInfo, @UserIdInt int userId, @Nullable PackageStateInternal pkgSetting)276 private static ActivityInfo generateActivityInfo(AndroidPackage pkg, ParsedActivity a, 277 @PackageManager.ComponentInfoFlagsBits long flags, 278 @NonNull PackageUserStateInternal state, @Nullable ApplicationInfo applicationInfo, 279 @UserIdInt int userId, @Nullable PackageStateInternal pkgSetting) { 280 if (a == null) return null; 281 if (!checkUseInstalledOrHidden(pkg, pkgSetting, state, flags)) { 282 return null; 283 } 284 if (applicationInfo == null) { 285 applicationInfo = generateApplicationInfo(pkg, flags, state, userId, pkgSetting); 286 } 287 288 if (applicationInfo == null) { 289 return null; 290 } 291 292 final ActivityInfo info = PackageInfoWithoutStateUtils.generateActivityInfoUnchecked( 293 a, flags, applicationInfo); 294 assignSharedFieldsForComponentInfo(info, a, pkgSetting, userId); 295 return info; 296 } 297 298 /** 299 * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage. 300 */ 301 @Nullable generateServiceInfo(AndroidPackage pkg, ParsedService s, @PackageManager.ComponentInfoFlagsBits long flags, PackageUserStateInternal state, @UserIdInt int userId, @Nullable PackageStateInternal pkgSetting)302 public static ServiceInfo generateServiceInfo(AndroidPackage pkg, ParsedService s, 303 @PackageManager.ComponentInfoFlagsBits long flags, PackageUserStateInternal state, 304 @UserIdInt int userId, @Nullable PackageStateInternal pkgSetting) { 305 return generateServiceInfo(pkg, s, flags, state, null, userId, pkgSetting); 306 } 307 308 /** 309 * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage. 310 */ 311 @Nullable generateServiceInfo(AndroidPackage pkg, ParsedService s, @PackageManager.ComponentInfoFlagsBits long flags, PackageUserStateInternal state, @Nullable ApplicationInfo applicationInfo, int userId, @Nullable PackageStateInternal pkgSetting)312 private static ServiceInfo generateServiceInfo(AndroidPackage pkg, ParsedService s, 313 @PackageManager.ComponentInfoFlagsBits long flags, PackageUserStateInternal state, 314 @Nullable ApplicationInfo applicationInfo, int userId, 315 @Nullable PackageStateInternal pkgSetting) { 316 if (s == null) return null; 317 if (!checkUseInstalledOrHidden(pkg, pkgSetting, state, flags)) { 318 return null; 319 } 320 if (applicationInfo == null) { 321 applicationInfo = generateApplicationInfo(pkg, flags, state, userId, pkgSetting); 322 } 323 if (applicationInfo == null) { 324 return null; 325 } 326 327 final ServiceInfo info = PackageInfoWithoutStateUtils.generateServiceInfoUnchecked( 328 s, flags, applicationInfo); 329 assignSharedFieldsForComponentInfo(info, s, pkgSetting, userId); 330 return info; 331 } 332 333 /** 334 * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage. 335 */ 336 @Nullable generateProviderInfo(AndroidPackage pkg, ParsedProvider p, @PackageManager.ComponentInfoFlagsBits long flags, PackageUserStateInternal state, @NonNull ApplicationInfo applicationInfo, int userId, @Nullable PackageStateInternal pkgSetting)337 public static ProviderInfo generateProviderInfo(AndroidPackage pkg, ParsedProvider p, 338 @PackageManager.ComponentInfoFlagsBits long flags, PackageUserStateInternal state, 339 @NonNull ApplicationInfo applicationInfo, int userId, 340 @Nullable PackageStateInternal pkgSetting) { 341 if (p == null) return null; 342 if (!checkUseInstalledOrHidden(pkg, pkgSetting, state, flags)) { 343 return null; 344 } 345 if (applicationInfo == null || !pkg.getPackageName().equals(applicationInfo.packageName)) { 346 Slog.wtf(TAG, "AppInfo's package name is different. Expected=" + pkg.getPackageName() 347 + " actual=" + (applicationInfo == null ? "(null AppInfo)" 348 : applicationInfo.packageName)); 349 applicationInfo = generateApplicationInfo(pkg, flags, state, userId, pkgSetting); 350 } 351 if (applicationInfo == null) { 352 return null; 353 } 354 ProviderInfo info = PackageInfoWithoutStateUtils.generateProviderInfoUnchecked(p, flags, 355 applicationInfo); 356 assignSharedFieldsForComponentInfo(info, p, pkgSetting, userId); 357 return info; 358 } 359 360 /** 361 * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage. 362 */ 363 @Nullable generateInstrumentationInfo(ParsedInstrumentation i, AndroidPackage pkg, @PackageManager.ComponentInfoFlagsBits long flags, int userId, @Nullable PackageStateInternal pkgSetting)364 public static InstrumentationInfo generateInstrumentationInfo(ParsedInstrumentation i, 365 AndroidPackage pkg, @PackageManager.ComponentInfoFlagsBits long flags, int userId, 366 @Nullable PackageStateInternal pkgSetting) { 367 if (i == null) return null; 368 369 InstrumentationInfo info = 370 PackageInfoWithoutStateUtils.generateInstrumentationInfo(i, pkg, flags, userId, 371 false /* assignUserFields */); 372 373 initForUser(info, pkg, userId); 374 375 if (info == null) { 376 return null; 377 } 378 379 info.primaryCpuAbi = AndroidPackageUtils.getPrimaryCpuAbi(pkg, pkgSetting); 380 info.secondaryCpuAbi = AndroidPackageUtils.getSecondaryCpuAbi(pkg, pkgSetting); 381 info.nativeLibraryDir = pkg.getNativeLibraryDir(); 382 info.secondaryNativeLibraryDir = pkg.getSecondaryNativeLibraryDir(); 383 384 assignStateFieldsForPackageItemInfo(info, i, pkgSetting, userId); 385 386 return info; 387 } 388 389 // TODO(b/135203078): Determine if permission methods need to pass in a non-null 390 // PackageStateInternal os that checkUseInstalledOrHidden filter can apply 391 @Nullable generatePermissionInfo(ParsedPermission p, @PackageManager.ComponentInfoFlagsBits long flags)392 public static PermissionInfo generatePermissionInfo(ParsedPermission p, 393 @PackageManager.ComponentInfoFlagsBits long flags) { 394 // TODO(b/135203078): Remove null checks and make all usages @NonNull 395 if (p == null) return null; 396 397 // For now, permissions don't have state-adjustable fields; return directly 398 return PackageInfoWithoutStateUtils.generatePermissionInfo(p, flags); 399 } 400 401 @Nullable generatePermissionGroupInfo(ParsedPermissionGroup pg, @PackageManager.ComponentInfoFlagsBits long flags)402 public static PermissionGroupInfo generatePermissionGroupInfo(ParsedPermissionGroup pg, 403 @PackageManager.ComponentInfoFlagsBits long flags) { 404 if (pg == null) return null; 405 406 // For now, permissions don't have state-adjustable fields; return directly 407 return PackageInfoWithoutStateUtils.generatePermissionGroupInfo(pg, flags); 408 } 409 410 @Nullable generateProcessInfo( Map<String, ParsedProcess> procs, @PackageManager.ComponentInfoFlagsBits long flags)411 public static ArrayMap<String, ProcessInfo> generateProcessInfo( 412 Map<String, ParsedProcess> procs, @PackageManager.ComponentInfoFlagsBits long flags) { 413 if (procs == null) { 414 return null; 415 } 416 417 final int numProcs = procs.size(); 418 ArrayMap<String, ProcessInfo> retProcs = new ArrayMap<>(numProcs); 419 for (String key : procs.keySet()) { 420 ParsedProcess proc = procs.get(key); 421 retProcs.put(proc.getName(), 422 new ProcessInfo(proc.getName(), new ArraySet<>(proc.getDeniedPermissions()), 423 proc.getGwpAsanMode(), proc.getMemtagMode(), 424 proc.getNativeHeapZeroInitialized())); 425 } 426 return retProcs; 427 } 428 429 /** 430 * Returns true if the package is installed and not hidden, or if the caller explicitly wanted 431 * all uninstalled and hidden packages as well. 432 */ checkUseInstalledOrHidden(AndroidPackage pkg, PackageStateInternal pkgSetting, PackageUserStateInternal state, @PackageManager.PackageInfoFlagsBits long flags)433 public static boolean checkUseInstalledOrHidden(AndroidPackage pkg, 434 PackageStateInternal pkgSetting, PackageUserStateInternal state, 435 @PackageManager.PackageInfoFlagsBits long flags) { 436 // Returns false if the package is hidden system app until installed. 437 if ((flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) == 0 438 && !state.isInstalled() 439 && pkgSetting != null 440 && pkgSetting.getTransientState().isHiddenUntilInstalled()) { 441 return false; 442 } 443 444 // If available for the target user, or trying to match uninstalled packages and it's 445 // a system app. 446 return PackageUserStateUtils.isAvailable(state, flags) 447 || (pkg.isSystem() 448 && ((flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0 449 || (flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) != 0)); 450 } 451 assignSharedFieldsForComponentInfo(@onNull ComponentInfo componentInfo, @NonNull ParsedMainComponent mainComponent, @Nullable PackageStateInternal pkgSetting, int userId)452 private static void assignSharedFieldsForComponentInfo(@NonNull ComponentInfo componentInfo, 453 @NonNull ParsedMainComponent mainComponent, @Nullable PackageStateInternal pkgSetting, 454 int userId) { 455 assignStateFieldsForPackageItemInfo(componentInfo, mainComponent, pkgSetting, userId); 456 componentInfo.descriptionRes = mainComponent.getDescriptionRes(); 457 componentInfo.directBootAware = mainComponent.isDirectBootAware(); 458 componentInfo.enabled = mainComponent.isEnabled(); 459 componentInfo.splitName = mainComponent.getSplitName(); 460 componentInfo.attributionTags = mainComponent.getAttributionTags(); 461 } 462 assignStateFieldsForPackageItemInfo( @onNull PackageItemInfo packageItemInfo, @NonNull ParsedComponent component, @Nullable PackageStateInternal pkgSetting, int userId)463 private static void assignStateFieldsForPackageItemInfo( 464 @NonNull PackageItemInfo packageItemInfo, @NonNull ParsedComponent component, 465 @Nullable PackageStateInternal pkgSetting, int userId) { 466 Pair<CharSequence, Integer> labelAndIcon = 467 ParsedComponentStateUtils.getNonLocalizedLabelAndIcon(component, pkgSetting, 468 userId); 469 packageItemInfo.nonLocalizedLabel = labelAndIcon.first; 470 packageItemInfo.icon = labelAndIcon.second; 471 } 472 473 @CheckResult flag(boolean hasFlag, int flag)474 private static int flag(boolean hasFlag, int flag) { 475 return hasFlag ? flag : 0; 476 } 477 478 /** 479 * @see ApplicationInfo#flags 480 */ appInfoFlags(AndroidPackage pkg, @Nullable PackageStateInternal pkgSetting)481 public static int appInfoFlags(AndroidPackage pkg, @Nullable PackageStateInternal pkgSetting) { 482 // @formatter:off 483 int pkgWithoutStateFlags = PackageInfoWithoutStateUtils.appInfoFlags(pkg) 484 | flag(pkg.isSystem(), ApplicationInfo.FLAG_SYSTEM) 485 | flag(pkg.isFactoryTest(), ApplicationInfo.FLAG_FACTORY_TEST); 486 487 return appInfoFlags(pkgWithoutStateFlags, pkgSetting); 488 // @formatter:on 489 } 490 491 /** @see ApplicationInfo#flags */ appInfoFlags(int pkgWithoutStateFlags, @NonNull PackageStateInternal pkgSetting)492 public static int appInfoFlags(int pkgWithoutStateFlags, 493 @NonNull PackageStateInternal pkgSetting) { 494 // @formatter:off 495 int flags = pkgWithoutStateFlags; 496 if (pkgSetting != null) { 497 flags |= flag(pkgSetting.getTransientState().isUpdatedSystemApp(), ApplicationInfo.FLAG_UPDATED_SYSTEM_APP); 498 } 499 return flags; 500 // @formatter:on 501 } 502 503 /** @see ApplicationInfo#privateFlags */ appInfoPrivateFlags(AndroidPackage pkg, @Nullable PackageStateInternal pkgSetting)504 public static int appInfoPrivateFlags(AndroidPackage pkg, 505 @Nullable PackageStateInternal pkgSetting) { 506 // @formatter:off 507 int pkgWithoutStateFlags = PackageInfoWithoutStateUtils.appInfoPrivateFlags(pkg) 508 | flag(pkg.isSystemExt(), ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT) 509 | flag(pkg.isPrivileged(), ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) 510 | flag(pkg.isOem(), ApplicationInfo.PRIVATE_FLAG_OEM) 511 | flag(pkg.isVendor(), ApplicationInfo.PRIVATE_FLAG_VENDOR) 512 | flag(pkg.isProduct(), ApplicationInfo.PRIVATE_FLAG_PRODUCT) 513 | flag(pkg.isOdm(), ApplicationInfo.PRIVATE_FLAG_ODM) 514 | flag(pkg.isSignedWithPlatformKey(), ApplicationInfo.PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY); 515 return appInfoPrivateFlags(pkgWithoutStateFlags, pkgSetting); 516 // @formatter:on 517 } 518 519 /** @see ApplicationInfo#privateFlags */ appInfoPrivateFlags(int pkgWithoutStateFlags, @Nullable PackageStateInternal pkgSetting)520 public static int appInfoPrivateFlags(int pkgWithoutStateFlags, 521 @Nullable PackageStateInternal pkgSetting) { 522 // @formatter:off 523 // TODO: Add state specific flags 524 return pkgWithoutStateFlags; 525 // @formatter:on 526 } 527 528 /** @see ApplicationInfo#privateFlagsExt */ appInfoPrivateFlagsExt(AndroidPackage pkg, @Nullable PackageStateInternal pkgSetting)529 public static int appInfoPrivateFlagsExt(AndroidPackage pkg, 530 @Nullable PackageStateInternal pkgSetting) { 531 // @formatter:off 532 int pkgWithoutStateFlags = PackageInfoWithoutStateUtils.appInfoPrivateFlagsExt(pkg); 533 return appInfoPrivateFlagsExt(pkgWithoutStateFlags, pkgSetting); 534 // @formatter:on 535 } 536 537 /** @see ApplicationInfo#privateFlagsExt */ appInfoPrivateFlagsExt(int pkgWithoutStateFlags, @Nullable PackageStateInternal pkgSetting)538 public static int appInfoPrivateFlagsExt(int pkgWithoutStateFlags, 539 @Nullable PackageStateInternal pkgSetting) { 540 // @formatter:off 541 // TODO: Add state specific flags 542 return pkgWithoutStateFlags; 543 // @formatter:on 544 } 545 initForUser(ApplicationInfo output, AndroidPackage input, @UserIdInt int userId)546 private static void initForUser(ApplicationInfo output, AndroidPackage input, 547 @UserIdInt int userId) { 548 PackageImpl pkg = ((PackageImpl) input); 549 String packageName = input.getPackageName(); 550 output.uid = UserHandle.getUid(userId, UserHandle.getAppId(input.getUid())); 551 552 if ("android".equals(packageName)) { 553 output.dataDir = PackageInfoWithoutStateUtils.SYSTEM_DATA_PATH; 554 return; 555 } 556 557 // For performance reasons, all these paths are built as strings 558 if (userId == UserHandle.USER_SYSTEM) { 559 output.credentialProtectedDataDir = 560 pkg.getBaseAppDataCredentialProtectedDirForSystemUser() + packageName; 561 output.deviceProtectedDataDir = 562 pkg.getBaseAppDataDeviceProtectedDirForSystemUser() + packageName; 563 } else { 564 // Convert /data/user/0/ -> /data/user/1/com.example.app 565 String userIdString = String.valueOf(userId); 566 int credentialLength = pkg.getBaseAppDataCredentialProtectedDirForSystemUser().length(); 567 output.credentialProtectedDataDir = 568 new StringBuilder(pkg.getBaseAppDataCredentialProtectedDirForSystemUser()) 569 .replace(credentialLength - 2, credentialLength - 1, userIdString) 570 .append(packageName) 571 .toString(); 572 int deviceLength = pkg.getBaseAppDataDeviceProtectedDirForSystemUser().length(); 573 output.deviceProtectedDataDir = 574 new StringBuilder(pkg.getBaseAppDataDeviceProtectedDirForSystemUser()) 575 .replace(deviceLength - 2, deviceLength - 1, userIdString) 576 .append(packageName) 577 .toString(); 578 } 579 580 if (input.isDefaultToDeviceProtectedStorage() 581 && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) { 582 output.dataDir = output.deviceProtectedDataDir; 583 } else { 584 output.dataDir = output.credentialProtectedDataDir; 585 } 586 } 587 588 // This duplicates the ApplicationInfo variant because it uses field assignment and the classes 589 // don't inherit from each other, unfortunately. Consolidating logic would introduce overhead. initForUser(InstrumentationInfo output, AndroidPackage input, @UserIdInt int userId)590 private static void initForUser(InstrumentationInfo output, AndroidPackage input, 591 @UserIdInt int userId) { 592 PackageImpl pkg = ((PackageImpl) input); 593 String packageName = input.getPackageName(); 594 if ("android".equals(packageName)) { 595 output.dataDir = PackageInfoWithoutStateUtils.SYSTEM_DATA_PATH; 596 return; 597 } 598 599 // For performance reasons, all these paths are built as strings 600 if (userId == UserHandle.USER_SYSTEM) { 601 output.credentialProtectedDataDir = 602 pkg.getBaseAppDataCredentialProtectedDirForSystemUser() + packageName; 603 output.deviceProtectedDataDir = 604 pkg.getBaseAppDataDeviceProtectedDirForSystemUser() + packageName; 605 } else { 606 // Convert /data/user/0/ -> /data/user/1/com.example.app 607 String userIdString = String.valueOf(userId); 608 int credentialLength = pkg.getBaseAppDataCredentialProtectedDirForSystemUser().length(); 609 output.credentialProtectedDataDir = 610 new StringBuilder(pkg.getBaseAppDataCredentialProtectedDirForSystemUser()) 611 .replace(credentialLength - 2, credentialLength - 1, userIdString) 612 .append(packageName) 613 .toString(); 614 int deviceLength = pkg.getBaseAppDataDeviceProtectedDirForSystemUser().length(); 615 output.deviceProtectedDataDir = 616 new StringBuilder(pkg.getBaseAppDataDeviceProtectedDirForSystemUser()) 617 .replace(deviceLength - 2, deviceLength - 1, userIdString) 618 .append(packageName) 619 .toString(); 620 } 621 622 if (input.isDefaultToDeviceProtectedStorage() 623 && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) { 624 output.dataDir = output.deviceProtectedDataDir; 625 } else { 626 output.dataDir = output.credentialProtectedDataDir; 627 } 628 } 629 630 /** 631 * Wraps {@link PackageInfoUtils#generateApplicationInfo} with a cache. 632 */ 633 public static class CachedApplicationInfoGenerator { 634 // Map from a package name to the corresponding app info. 635 private ArrayMap<String, ApplicationInfo> mCache = new ArrayMap<>(); 636 637 /** 638 * {@link PackageInfoUtils#generateApplicationInfo} with a cache. 639 */ 640 @Nullable generate(AndroidPackage pkg, @PackageManager.ApplicationInfoFlagsBits long flags, PackageUserStateInternal state, int userId, @Nullable PackageStateInternal pkgSetting)641 public ApplicationInfo generate(AndroidPackage pkg, 642 @PackageManager.ApplicationInfoFlagsBits long flags, PackageUserStateInternal state, 643 int userId, @Nullable PackageStateInternal pkgSetting) { 644 ApplicationInfo appInfo = mCache.get(pkg.getPackageName()); 645 if (appInfo != null) { 646 return appInfo; 647 } 648 appInfo = PackageInfoUtils.generateApplicationInfo( 649 pkg, flags, state, userId, pkgSetting); 650 mCache.put(pkg.getPackageName(), appInfo); 651 return appInfo; 652 } 653 } 654 } 655