1 /* 2 * Copyright (C) 2023 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 package com.android.internal.pm.parsing; 17 18 import static com.android.internal.pm.pkg.SEInfoUtil.COMPLETE_STR; 19 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.UserIdInt; 23 import android.content.pm.ActivityInfo; 24 import android.content.pm.ApplicationInfo; 25 import android.content.pm.Attribution; 26 import android.content.pm.ComponentInfo; 27 import android.content.pm.ConfigurationInfo; 28 import android.content.pm.FallbackCategoryProvider; 29 import android.content.pm.FeatureGroupInfo; 30 import android.content.pm.FeatureInfo; 31 import android.content.pm.InstrumentationInfo; 32 import android.content.pm.PackageInfo; 33 import android.content.pm.PackageItemInfo; 34 import android.content.pm.PackageManager; 35 import android.content.pm.PathPermission; 36 import android.content.pm.PermissionInfo; 37 import android.content.pm.ProviderInfo; 38 import android.content.pm.ServiceInfo; 39 import android.content.pm.Signature; 40 import android.content.pm.SigningDetails; 41 import android.content.pm.SigningInfo; 42 import android.os.Debug; 43 import android.os.PatternMatcher; 44 import android.os.UserHandle; 45 import android.util.DebugUtils; 46 import android.util.Slog; 47 48 import com.android.internal.pm.parsing.pkg.AndroidPackageHidden; 49 import com.android.internal.pm.parsing.pkg.AndroidPackageLegacyUtils; 50 import com.android.internal.pm.parsing.pkg.PackageImpl; 51 import com.android.internal.pm.pkg.component.ComponentParseUtils; 52 import com.android.internal.pm.pkg.component.ParsedActivity; 53 import com.android.internal.pm.pkg.component.ParsedAttribution; 54 import com.android.internal.pm.pkg.component.ParsedComponent; 55 import com.android.internal.pm.pkg.component.ParsedInstrumentation; 56 import com.android.internal.pm.pkg.component.ParsedMainComponent; 57 import com.android.internal.pm.pkg.component.ParsedPermission; 58 import com.android.internal.pm.pkg.component.ParsedProvider; 59 import com.android.internal.pm.pkg.component.ParsedService; 60 import com.android.internal.pm.pkg.component.ParsedUsesPermission; 61 import com.android.internal.pm.pkg.parsing.ParsingPackageHidden; 62 import com.android.internal.pm.pkg.parsing.ParsingPackageUtils; 63 import com.android.internal.pm.pkg.parsing.ParsingUtils; 64 import com.android.internal.util.ArrayUtils; 65 import com.android.server.pm.pkg.AndroidPackage; 66 67 import java.util.List; 68 69 /** 70 * Method that use a {@link AndroidPackage} to generate a {@link PackageInfo} though 71 * the given {@link PackageManager.PackageInfoFlags} 72 * @hide 73 **/ 74 // TODO(b/317215254): refactor coped code from PackageInfoUtils 75 public class PackageInfoCommonUtils { 76 77 private static final String TAG = ParsingUtils.TAG; 78 private static final boolean DEBUG = false; 79 80 /** 81 * Generates a {@link PackageInfo} from the given {@link AndroidPackage} 82 */ 83 @Nullable generate(@ullable AndroidPackage pkg, @PackageManager.PackageInfoFlagsBits long flags, int userId)84 public static PackageInfo generate(@Nullable AndroidPackage pkg, 85 @PackageManager.PackageInfoFlagsBits long flags, int userId) { 86 if (pkg == null) { 87 return null; 88 } 89 ApplicationInfo applicationInfo = generateApplicationInfo(pkg, flags, userId); 90 91 PackageInfo info = new PackageInfo(); 92 info.packageName = pkg.getPackageName(); 93 info.splitNames = pkg.getSplitNames(); 94 info.versionCode = ((ParsingPackageHidden) pkg).getVersionCode(); 95 info.versionCodeMajor = ((ParsingPackageHidden) pkg).getVersionCodeMajor(); 96 info.baseRevisionCode = pkg.getBaseRevisionCode(); 97 info.splitRevisionCodes = pkg.getSplitRevisionCodes(); 98 info.versionName = pkg.getVersionName(); 99 if (!pkg.isLeavingSharedUser()) { 100 info.sharedUserId = pkg.getSharedUserId(); 101 info.sharedUserLabel = pkg.getSharedUserLabelResourceId(); 102 } 103 info.applicationInfo = applicationInfo; 104 info.installLocation = pkg.getInstallLocation(); 105 if ((info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0 106 || (info.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) { 107 info.requiredForAllUsers = pkg.isRequiredForAllUsers(); 108 } 109 info.restrictedAccountType = pkg.getRestrictedAccountType(); 110 info.requiredAccountType = pkg.getRequiredAccountType(); 111 info.overlayTarget = pkg.getOverlayTarget(); 112 info.targetOverlayableName = pkg.getOverlayTargetOverlayableName(); 113 info.overlayCategory = pkg.getOverlayCategory(); 114 info.overlayPriority = pkg.getOverlayPriority(); 115 info.mOverlayIsStatic = pkg.isOverlayIsStatic(); 116 info.compileSdkVersion = pkg.getCompileSdkVersion(); 117 info.compileSdkVersionCodename = pkg.getCompileSdkVersionCodeName(); 118 info.isStub = pkg.isStub(); 119 info.coreApp = pkg.isCoreApp(); 120 info.isApex = pkg.isApex(); 121 122 if ((flags & PackageManager.GET_CONFIGURATIONS) != 0) { 123 int size = pkg.getConfigPreferences().size(); 124 if (size > 0) { 125 info.configPreferences = new ConfigurationInfo[size]; 126 pkg.getConfigPreferences().toArray(info.configPreferences); 127 } 128 size = pkg.getRequestedFeatures().size(); 129 if (size > 0) { 130 info.reqFeatures = new FeatureInfo[size]; 131 pkg.getRequestedFeatures().toArray(info.reqFeatures); 132 } 133 size = pkg.getFeatureGroups().size(); 134 if (size > 0) { 135 info.featureGroups = new FeatureGroupInfo[size]; 136 pkg.getFeatureGroups().toArray(info.featureGroups); 137 } 138 } 139 if ((flags & PackageManager.GET_PERMISSIONS) != 0) { 140 int size = ArrayUtils.size(pkg.getPermissions()); 141 if (size > 0) { 142 info.permissions = new PermissionInfo[size]; 143 for (int i = 0; i < size; i++) { 144 final var permission = pkg.getPermissions().get(i); 145 final var permissionInfo = generatePermissionInfo(permission, flags); 146 info.permissions[i] = permissionInfo; 147 } 148 } 149 final List<ParsedUsesPermission> usesPermissions = pkg.getUsesPermissions(); 150 size = usesPermissions.size(); 151 if (size > 0) { 152 info.requestedPermissions = new String[size]; 153 info.requestedPermissionsFlags = new int[size]; 154 for (int i = 0; i < size; i++) { 155 final ParsedUsesPermission usesPermission = usesPermissions.get(i); 156 info.requestedPermissions[i] = usesPermission.getName(); 157 // The notion of required permissions is deprecated but for compatibility. 158 info.requestedPermissionsFlags[i] |= 159 PackageInfo.REQUESTED_PERMISSION_REQUIRED; 160 if ((usesPermission.getUsesPermissionFlags() 161 & ParsedUsesPermission.FLAG_NEVER_FOR_LOCATION) != 0) { 162 info.requestedPermissionsFlags[i] |= 163 PackageInfo.REQUESTED_PERMISSION_NEVER_FOR_LOCATION; 164 } 165 if (pkg.getImplicitPermissions().contains(info.requestedPermissions[i])) { 166 info.requestedPermissionsFlags[i] |= 167 PackageInfo.REQUESTED_PERMISSION_IMPLICIT; 168 } 169 } 170 } 171 } 172 if ((flags & PackageManager.GET_ATTRIBUTIONS_LONG) != 0) { 173 int size = ArrayUtils.size(pkg.getAttributions()); 174 if (size > 0) { 175 info.attributions = new Attribution[size]; 176 for (int i = 0; i < size; i++) { 177 ParsedAttribution parsedAttribution = pkg.getAttributions().get(i); 178 if (parsedAttribution != null) { 179 info.attributions[i] = new Attribution(parsedAttribution.getTag(), 180 parsedAttribution.getLabel()); 181 } 182 } 183 } 184 if (pkg.isAttributionsUserVisible()) { 185 info.applicationInfo.privateFlagsExt 186 |= ApplicationInfo.PRIVATE_FLAG_EXT_ATTRIBUTIONS_ARE_USER_VISIBLE; 187 } else { 188 info.applicationInfo.privateFlagsExt 189 &= ~ApplicationInfo.PRIVATE_FLAG_EXT_ATTRIBUTIONS_ARE_USER_VISIBLE; 190 } 191 } else { 192 info.applicationInfo.privateFlagsExt 193 &= ~ApplicationInfo.PRIVATE_FLAG_EXT_ATTRIBUTIONS_ARE_USER_VISIBLE; 194 } 195 196 final SigningDetails signingDetails = pkg.getSigningDetails(); 197 // deprecated method of getting signing certificates 198 if ((flags & PackageManager.GET_SIGNATURES) != 0) { 199 if (signingDetails.hasPastSigningCertificates()) { 200 // Package has included signing certificate rotation information. Return the oldest 201 // cert so that programmatic checks keep working even if unaware of key rotation. 202 info.signatures = new Signature[1]; 203 info.signatures[0] = signingDetails.getPastSigningCertificates()[0]; 204 } else if (signingDetails.hasSignatures()) { 205 // otherwise keep old behavior 206 int numberOfSigs = signingDetails.getSignatures().length; 207 info.signatures = new Signature[numberOfSigs]; 208 System.arraycopy(signingDetails.getSignatures(), 0, info.signatures, 0, 209 numberOfSigs); 210 } 211 } 212 213 // replacement for GET_SIGNATURES 214 if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) { 215 if (signingDetails != SigningDetails.UNKNOWN) { 216 // only return a valid SigningInfo if there is signing information to report 217 info.signingInfo = new SigningInfo(signingDetails); 218 } else { 219 info.signingInfo = null; 220 } 221 } 222 223 if ((flags & PackageManager.GET_ACTIVITIES) != 0) { 224 final int size = pkg.getActivities().size(); 225 if (size > 0) { 226 int num = 0; 227 final ActivityInfo[] res = new ActivityInfo[size]; 228 for (int i = 0; i < size; i++) { 229 final ParsedActivity a = pkg.getActivities().get(i); 230 if (isMatch(pkg, a.isDirectBootAware(), flags)) { 231 if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals( 232 a.getName())) { 233 continue; 234 } 235 res[num++] = generateActivityInfo(a, flags, applicationInfo); 236 } 237 } 238 info.activities = ArrayUtils.trimToSize(res, num); 239 } 240 } 241 if ((flags & PackageManager.GET_RECEIVERS) != 0) { 242 final int size = pkg.getReceivers().size(); 243 if (size > 0) { 244 int num = 0; 245 final ActivityInfo[] res = new ActivityInfo[size]; 246 for (int i = 0; i < size; i++) { 247 final ParsedActivity a = pkg.getReceivers().get(i); 248 if (isMatch(pkg, a.isDirectBootAware(), flags)) { 249 res[num++] = generateActivityInfo(a, flags, applicationInfo); 250 } 251 } 252 info.receivers = ArrayUtils.trimToSize(res, num); 253 } 254 } 255 if ((flags & PackageManager.GET_SERVICES) != 0) { 256 final int size = pkg.getServices().size(); 257 if (size > 0) { 258 int num = 0; 259 final ServiceInfo[] res = new ServiceInfo[size]; 260 for (int i = 0; i < size; i++) { 261 final ParsedService s = pkg.getServices().get(i); 262 if (isMatch(pkg, s.isDirectBootAware(), flags)) { 263 res[num++] = generateServiceInfo(s, flags, applicationInfo); 264 } 265 } 266 info.services = ArrayUtils.trimToSize(res, num); 267 } 268 } 269 if ((flags & PackageManager.GET_PROVIDERS) != 0) { 270 final int size = pkg.getProviders().size(); 271 if (size > 0) { 272 int num = 0; 273 final ProviderInfo[] res = new ProviderInfo[size]; 274 for (int i = 0; i < size; i++) { 275 final ParsedProvider pr = pkg.getProviders().get(i); 276 if (isMatch(pkg, pr.isDirectBootAware(), flags)) { 277 res[num++] = generateProviderInfo(pkg, pr, flags, applicationInfo, userId); 278 } 279 } 280 info.providers = ArrayUtils.trimToSize(res, num); 281 } 282 } 283 if ((flags & PackageManager.GET_INSTRUMENTATION) != 0) { 284 final int size = pkg.getInstrumentations().size(); 285 if (size > 0) { 286 info.instrumentation = new InstrumentationInfo[size]; 287 for (int i = 0; i < size; i++) { 288 info.instrumentation[i] = generateInstrumentationInfo( 289 pkg.getInstrumentations().get(i), pkg, flags, userId); 290 } 291 } 292 } 293 294 return info; 295 } 296 updateApplicationInfo(ApplicationInfo ai, long flags)297 private static void updateApplicationInfo(ApplicationInfo ai, long flags) { 298 if ((flags & PackageManager.GET_META_DATA) == 0) { 299 ai.metaData = null; 300 } 301 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) == 0) { 302 ai.sharedLibraryFiles = null; 303 ai.sharedLibraryInfos = null; 304 } 305 306 // CompatibilityMode is global state. 307 if (!ParsingPackageUtils.sCompatibilityModeEnabled) { 308 ai.disableCompatibilityMode(); 309 } 310 311 if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) { 312 ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName); 313 } 314 ai.seInfoUser = COMPLETE_STR; 315 } 316 317 @Nullable generateApplicationInfo(@onNull AndroidPackage pkg, @PackageManager.ApplicationInfoFlagsBits long flags, @UserIdInt int userId)318 private static ApplicationInfo generateApplicationInfo(@NonNull AndroidPackage pkg, 319 @PackageManager.ApplicationInfoFlagsBits long flags, @UserIdInt int userId) { 320 321 // Make shallow copy so we can store the metadata/libraries safely 322 ApplicationInfo info = ((AndroidPackageHidden) pkg).toAppInfoWithoutState(); 323 324 updateApplicationInfo(info, flags); 325 326 initForUser(info, pkg, userId); 327 328 info.primaryCpuAbi = AndroidPackageLegacyUtils.getRawPrimaryCpuAbi(pkg); 329 info.secondaryCpuAbi = AndroidPackageLegacyUtils.getRawSecondaryCpuAbi(pkg); 330 331 if ((flags & PackageManager.GET_META_DATA) != 0) { 332 info.metaData = pkg.getMetaData(); 333 } 334 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) { 335 List<String> usesLibraryFiles = pkg.getUsesLibraries(); 336 337 info.sharedLibraryFiles = usesLibraryFiles.isEmpty() 338 ? null : usesLibraryFiles.toArray(new String[0]); 339 } 340 341 return info; 342 } 343 344 @Nullable generateActivityInfo(ParsedActivity a, @PackageManager.ComponentInfoFlagsBits long flags, @NonNull ApplicationInfo applicationInfo)345 private static ActivityInfo generateActivityInfo(ParsedActivity a, 346 @PackageManager.ComponentInfoFlagsBits long flags, 347 @NonNull ApplicationInfo applicationInfo) { 348 if (a == null) return null; 349 350 // Make shallow copies so we can store the metadata safely 351 ActivityInfo ai = new ActivityInfo(); 352 ai.targetActivity = a.getTargetActivity(); 353 ai.processName = a.getProcessName(); 354 ai.exported = a.isExported(); 355 ai.theme = a.getTheme(); 356 ai.uiOptions = a.getUiOptions(); 357 ai.parentActivityName = a.getParentActivityName(); 358 ai.permission = a.getPermission(); 359 ai.taskAffinity = a.getTaskAffinity(); 360 ai.flags = a.getFlags(); 361 ai.privateFlags = a.getPrivateFlags(); 362 ai.launchMode = a.getLaunchMode(); 363 ai.documentLaunchMode = a.getDocumentLaunchMode(); 364 ai.maxRecents = a.getMaxRecents(); 365 ai.configChanges = a.getConfigChanges(); 366 ai.softInputMode = a.getSoftInputMode(); 367 ai.persistableMode = a.getPersistableMode(); 368 ai.lockTaskLaunchMode = a.getLockTaskLaunchMode(); 369 ai.screenOrientation = a.getScreenOrientation(); 370 ai.resizeMode = a.getResizeMode(); 371 ai.setMaxAspectRatio(a.getMaxAspectRatio()); 372 ai.setMinAspectRatio(a.getMinAspectRatio()); 373 ai.supportsSizeChanges = a.isSupportsSizeChanges(); 374 ai.requestedVrComponent = a.getRequestedVrComponent(); 375 ai.rotationAnimation = a.getRotationAnimation(); 376 ai.colorMode = a.getColorMode(); 377 ai.windowLayout = a.getWindowLayout(); 378 ai.attributionTags = a.getAttributionTags(); 379 if ((flags & PackageManager.GET_META_DATA) != 0) { 380 var metaData = a.getMetaData(); 381 // Backwards compatibility, coerce to null if empty 382 ai.metaData = metaData.isEmpty() ? null : metaData; 383 } else { 384 ai.metaData = null; 385 } 386 ai.applicationInfo = applicationInfo; 387 ai.requiredDisplayCategory = a.getRequiredDisplayCategory(); 388 ai.setKnownActivityEmbeddingCerts(a.getKnownActivityEmbeddingCerts()); 389 assignFieldsComponentInfoParsedMainComponent(ai, a); 390 return ai; 391 } 392 393 @Nullable generateServiceInfo(ParsedService s, @PackageManager.ComponentInfoFlagsBits long flags, @NonNull ApplicationInfo applicationInfo)394 private static ServiceInfo generateServiceInfo(ParsedService s, 395 @PackageManager.ComponentInfoFlagsBits long flags, 396 @NonNull ApplicationInfo applicationInfo) { 397 if (s == null) return null; 398 399 // Make shallow copies so we can store the metadata safely 400 ServiceInfo si = new ServiceInfo(); 401 si.exported = s.isExported(); 402 si.flags = s.getFlags(); 403 si.permission = s.getPermission(); 404 si.processName = s.getProcessName(); 405 si.mForegroundServiceType = s.getForegroundServiceType(); 406 si.applicationInfo = applicationInfo; 407 if ((flags & PackageManager.GET_META_DATA) != 0) { 408 var metaData = s.getMetaData(); 409 // Backwards compatibility, coerce to null if empty 410 si.metaData = metaData.isEmpty() ? null : metaData; 411 } 412 assignFieldsComponentInfoParsedMainComponent(si, s); 413 return si; 414 } 415 416 @Nullable generateProviderInfo(AndroidPackage pkg, ParsedProvider p, @PackageManager.ComponentInfoFlagsBits long flags, @NonNull ApplicationInfo applicationInfo, int userId)417 private static ProviderInfo generateProviderInfo(AndroidPackage pkg, ParsedProvider p, 418 @PackageManager.ComponentInfoFlagsBits long flags, 419 @NonNull ApplicationInfo applicationInfo, int userId) { 420 if (p == null) return null; 421 422 if (!pkg.getPackageName().equals(applicationInfo.packageName)) { 423 Slog.wtf(TAG, "AppInfo's package name is different. Expected=" + pkg.getPackageName() 424 + " actual=" + applicationInfo.packageName); 425 applicationInfo = generateApplicationInfo(pkg, flags, userId); 426 } 427 428 // Make shallow copies so we can store the metadata safely 429 ProviderInfo pi = new ProviderInfo(); 430 pi.exported = p.isExported(); 431 pi.flags = p.getFlags(); 432 pi.processName = p.getProcessName(); 433 pi.authority = p.getAuthority(); 434 pi.isSyncable = p.isSyncable(); 435 pi.readPermission = p.getReadPermission(); 436 pi.writePermission = p.getWritePermission(); 437 pi.grantUriPermissions = p.isGrantUriPermissions(); 438 pi.forceUriPermissions = p.isForceUriPermissions(); 439 pi.multiprocess = p.isMultiProcess(); 440 pi.initOrder = p.getInitOrder(); 441 pi.uriPermissionPatterns = p.getUriPermissionPatterns().toArray(new PatternMatcher[0]); 442 pi.pathPermissions = p.getPathPermissions().toArray(new PathPermission[0]); 443 if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) { 444 pi.uriPermissionPatterns = null; 445 } 446 if ((flags & PackageManager.GET_META_DATA) != 0) { 447 var metaData = p.getMetaData(); 448 // Backwards compatibility, coerce to null if empty 449 pi.metaData = metaData.isEmpty() ? null : metaData; 450 } 451 pi.applicationInfo = applicationInfo; 452 assignFieldsComponentInfoParsedMainComponent(pi, p); 453 return pi; 454 } 455 456 @Nullable generateInstrumentationInfo(ParsedInstrumentation i, AndroidPackage pkg, @PackageManager.ComponentInfoFlagsBits long flags, int userId)457 private static InstrumentationInfo generateInstrumentationInfo(ParsedInstrumentation i, 458 AndroidPackage pkg, @PackageManager.ComponentInfoFlagsBits long flags, int userId) { 459 if (i == null) return null; 460 461 InstrumentationInfo info = new InstrumentationInfo(); 462 info.targetPackage = i.getTargetPackage(); 463 info.targetProcesses = i.getTargetProcesses(); 464 info.handleProfiling = i.isHandleProfiling(); 465 info.functionalTest = i.isFunctionalTest(); 466 467 info.sourceDir = pkg.getBaseApkPath(); 468 info.publicSourceDir = pkg.getBaseApkPath(); 469 info.splitNames = pkg.getSplitNames(); 470 info.splitSourceDirs = pkg.getSplitCodePaths().length == 0 ? null : pkg.getSplitCodePaths(); 471 info.splitPublicSourceDirs = pkg.getSplitCodePaths().length == 0 472 ? null : pkg.getSplitCodePaths(); 473 info.splitDependencies = pkg.getSplitDependencies().size() == 0 474 ? null : pkg.getSplitDependencies(); 475 476 initForUser(info, pkg, userId); 477 478 info.primaryCpuAbi = AndroidPackageLegacyUtils.getRawPrimaryCpuAbi(pkg); 479 info.secondaryCpuAbi = AndroidPackageLegacyUtils.getRawSecondaryCpuAbi(pkg); 480 info.nativeLibraryDir = pkg.getNativeLibraryDir(); 481 info.secondaryNativeLibraryDir = pkg.getSecondaryNativeLibraryDir(); 482 483 assignFieldsPackageItemInfoParsedComponent(info, i); 484 485 if ((flags & PackageManager.GET_META_DATA) == 0) { 486 info.metaData = null; 487 } else { 488 var metaData = i.getMetaData(); 489 // Backwards compatibility, coerce to null if empty 490 info.metaData = metaData.isEmpty() ? null : metaData; 491 } 492 493 return info; 494 } 495 496 @Nullable generatePermissionInfo(ParsedPermission p, @PackageManager.ComponentInfoFlagsBits long flags)497 private static PermissionInfo generatePermissionInfo(ParsedPermission p, 498 @PackageManager.ComponentInfoFlagsBits long flags) { 499 // TODO(b/135203078): Remove null checks and make all usages @NonNull 500 if (p == null) return null; 501 502 PermissionInfo pi = new PermissionInfo(p.getBackgroundPermission()); 503 504 assignFieldsPackageItemInfoParsedComponent(pi, p); 505 506 pi.group = p.getGroup(); 507 pi.requestRes = p.getRequestRes(); 508 pi.protectionLevel = p.getProtectionLevel(); 509 pi.descriptionRes = p.getDescriptionRes(); 510 pi.flags = p.getFlags(); 511 pi.knownCerts = p.getKnownCerts(); 512 513 if ((flags & PackageManager.GET_META_DATA) == 0) { 514 pi.metaData = null; 515 } else { 516 var metaData = p.getMetaData(); 517 // Backwards compatibility, coerce to null if empty 518 pi.metaData = metaData.isEmpty() ? null : metaData; 519 } 520 return pi; 521 } 522 assignFieldsComponentInfoParsedMainComponent( @onNull ComponentInfo info, @NonNull ParsedMainComponent component)523 private static void assignFieldsComponentInfoParsedMainComponent( 524 @NonNull ComponentInfo info, @NonNull ParsedMainComponent component) { 525 assignFieldsPackageItemInfoParsedComponent(info, component); 526 info.descriptionRes = component.getDescriptionRes(); 527 info.directBootAware = component.isDirectBootAware(); 528 info.enabled = component.isEnabled(); 529 info.splitName = component.getSplitName(); 530 info.attributionTags = component.getAttributionTags(); 531 info.nonLocalizedLabel = component.getNonLocalizedLabel(); 532 info.icon = component.getIcon(); 533 } 534 assignFieldsPackageItemInfoParsedComponent( @onNull PackageItemInfo packageItemInfo, @NonNull ParsedComponent component)535 private static void assignFieldsPackageItemInfoParsedComponent( 536 @NonNull PackageItemInfo packageItemInfo, @NonNull ParsedComponent component) { 537 packageItemInfo.nonLocalizedLabel = ComponentParseUtils.getNonLocalizedLabel(component); 538 packageItemInfo.icon = ComponentParseUtils.getIcon(component); 539 packageItemInfo.banner = component.getBanner(); 540 packageItemInfo.labelRes = component.getLabelRes(); 541 packageItemInfo.logo = component.getLogo(); 542 packageItemInfo.name = component.getName(); 543 packageItemInfo.packageName = component.getPackageName(); 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 // For performance reasons, all these paths are built as strings 553 final String credentialDir = pkg.getBaseAppDataCredentialProtectedDirForSystemUser(); 554 final String deviceDir = pkg.getBaseAppDataDeviceProtectedDirForSystemUser(); 555 if (credentialDir != null && deviceDir != null) { 556 if (userId == UserHandle.USER_SYSTEM) { 557 output.credentialProtectedDataDir = credentialDir + packageName; 558 output.deviceProtectedDataDir = deviceDir + packageName; 559 } else { 560 // Convert /data/user/0/ -> /data/user/1/com.example.app 561 String userIdString = String.valueOf(userId); 562 int credentialLength = credentialDir.length(); 563 output.credentialProtectedDataDir = new StringBuilder(credentialDir) 564 .replace(credentialLength - 2, credentialLength - 1, userIdString) 565 .append(packageName) 566 .toString(); 567 int deviceLength = deviceDir.length(); 568 output.deviceProtectedDataDir = new StringBuilder(deviceDir) 569 .replace(deviceLength - 2, deviceLength - 1, userIdString) 570 .append(packageName) 571 .toString(); 572 } 573 } 574 575 if (input.isDefaultToDeviceProtectedStorage() 576 && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) { 577 output.dataDir = output.deviceProtectedDataDir; 578 } else { 579 output.dataDir = output.credentialProtectedDataDir; 580 } 581 } 582 583 // This duplicates the ApplicationInfo variant because it uses field assignment and the classes 584 // don't inherit from each other, unfortunately. Consolidating logic would introduce overhead. initForUser(InstrumentationInfo output, AndroidPackage input, @UserIdInt int userId)585 private static void initForUser(InstrumentationInfo output, AndroidPackage input, 586 @UserIdInt int userId) { 587 PackageImpl pkg = ((PackageImpl) input); 588 String packageName = input.getPackageName(); 589 590 // For performance reasons, all these paths are built as strings 591 final String credentialDir = pkg.getBaseAppDataCredentialProtectedDirForSystemUser(); 592 final String deviceDir = pkg.getBaseAppDataDeviceProtectedDirForSystemUser(); 593 if (credentialDir != null && deviceDir != null) { 594 if (userId == UserHandle.USER_SYSTEM) { 595 output.credentialProtectedDataDir = credentialDir + packageName; 596 output.deviceProtectedDataDir = deviceDir + packageName; 597 } else { 598 // Convert /data/user/0/ -> /data/user/1/com.example.app 599 String userIdString = String.valueOf(userId); 600 int credentialLength = credentialDir.length(); 601 output.credentialProtectedDataDir = new StringBuilder(credentialDir) 602 .replace(credentialLength - 2, credentialLength - 1, userIdString) 603 .append(packageName) 604 .toString(); 605 int deviceLength = deviceDir.length(); 606 output.deviceProtectedDataDir = new StringBuilder(deviceDir) 607 .replace(deviceLength - 2, deviceLength - 1, userIdString) 608 .append(packageName) 609 .toString(); 610 } 611 } 612 613 if (input.isDefaultToDeviceProtectedStorage() 614 && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) { 615 output.dataDir = output.deviceProtectedDataDir; 616 } else { 617 output.dataDir = output.credentialProtectedDataDir; 618 } 619 } 620 621 /** 622 * Test if the given component is considered system, enabled and a match for the given 623 * flags. 624 * 625 * <p> 626 * Expects at least one of {@link PackageManager#MATCH_DIRECT_BOOT_AWARE} and {@link 627 * PackageManager#MATCH_DIRECT_BOOT_UNAWARE} are specified in {@code flags}. 628 * </p> 629 */ isMatch(AndroidPackage pkg, boolean isComponentDirectBootAware, long flags)630 private static boolean isMatch(AndroidPackage pkg, 631 boolean isComponentDirectBootAware, long flags) { 632 final boolean isSystem = ((AndroidPackageHidden) pkg).isSystem(); 633 if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) { 634 if (!isSystem) { 635 return reportIfDebug(false, flags); 636 } 637 } 638 639 final boolean matchesUnaware = ((flags & PackageManager.MATCH_DIRECT_BOOT_UNAWARE) != 0) 640 && !isComponentDirectBootAware; 641 final boolean matchesAware = ((flags & PackageManager.MATCH_DIRECT_BOOT_AWARE) != 0) 642 && isComponentDirectBootAware; 643 return reportIfDebug(matchesUnaware || matchesAware, flags); 644 } 645 reportIfDebug(boolean result, long flags)646 private static boolean reportIfDebug(boolean result, long flags) { 647 if (DEBUG && !result) { 648 Slog.i(TAG, "No match!; flags: " 649 + DebugUtils.flagsToString(PackageManager.class, "MATCH_", flags) + " " 650 + Debug.getCaller()); 651 } 652 return result; 653 } 654 } 655