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 android.content.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.ConfigurationInfo; 27 import android.content.pm.FallbackCategoryProvider; 28 import android.content.pm.FeatureGroupInfo; 29 import android.content.pm.FeatureInfo; 30 import android.content.pm.InstrumentationInfo; 31 import android.content.pm.PackageInfo; 32 import android.content.pm.PackageItemInfo; 33 import android.content.pm.PackageManager; 34 import android.content.pm.PackageParser; 35 import android.content.pm.PackageUserState; 36 import android.content.pm.PermissionGroupInfo; 37 import android.content.pm.PermissionInfo; 38 import android.content.pm.ProviderInfo; 39 import android.content.pm.SELinuxUtil; 40 import android.content.pm.ServiceInfo; 41 import android.content.pm.Signature; 42 import android.content.pm.SigningInfo; 43 import android.content.pm.parsing.component.ComponentParseUtils; 44 import android.content.pm.parsing.component.ParsedActivity; 45 import android.content.pm.parsing.component.ParsedComponent; 46 import android.content.pm.parsing.component.ParsedInstrumentation; 47 import android.content.pm.parsing.component.ParsedMainComponent; 48 import android.content.pm.parsing.component.ParsedPermission; 49 import android.content.pm.parsing.component.ParsedPermissionGroup; 50 import android.content.pm.parsing.component.ParsedProvider; 51 import android.content.pm.parsing.component.ParsedService; 52 import android.os.Environment; 53 import android.os.UserHandle; 54 55 import com.android.internal.util.ArrayUtils; 56 57 import libcore.util.EmptyArray; 58 59 import java.io.File; 60 import java.util.Collections; 61 import java.util.Set; 62 63 /** @hide **/ 64 public class PackageInfoWithoutStateUtils { 65 66 @Nullable generate(ParsingPackageRead pkg, int[] gids, @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime, Set<String> grantedPermissions, PackageUserState state, int userId)67 public static PackageInfo generate(ParsingPackageRead pkg, int[] gids, 68 @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime, 69 Set<String> grantedPermissions, PackageUserState state, int userId) { 70 return generateWithComponents(pkg, gids, flags, firstInstallTime, lastUpdateTime, grantedPermissions, 71 state, userId, null); 72 } 73 74 @Nullable generate(ParsingPackageRead pkg, ApexInfo apexInfo, int flags)75 public static PackageInfo generate(ParsingPackageRead pkg, ApexInfo apexInfo, int flags) { 76 return generateWithComponents(pkg, EmptyArray.INT, flags, 0, 0, Collections.emptySet(), 77 new PackageUserState(), UserHandle.getCallingUserId(), apexInfo); 78 } 79 80 @Nullable generateWithComponents(ParsingPackageRead pkg, int[] gids, @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime, Set<String> grantedPermissions, PackageUserState state, int userId, @Nullable ApexInfo apexInfo)81 private static PackageInfo generateWithComponents(ParsingPackageRead pkg, int[] gids, 82 @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime, 83 Set<String> grantedPermissions, PackageUserState state, int userId, 84 @Nullable ApexInfo apexInfo) { 85 ApplicationInfo applicationInfo = generateApplicationInfo(pkg, flags, state, userId); 86 if (applicationInfo == null) { 87 return null; 88 } 89 PackageInfo info = generateWithoutComponents(pkg, gids, flags, firstInstallTime, 90 lastUpdateTime, grantedPermissions, state, userId, apexInfo, applicationInfo); 91 92 if (info == null) { 93 return null; 94 } 95 96 if ((flags & PackageManager.GET_ACTIVITIES) != 0) { 97 final int N = pkg.getActivities().size(); 98 if (N > 0) { 99 int num = 0; 100 final ActivityInfo[] res = new ActivityInfo[N]; 101 for (int i = 0; i < N; i++) { 102 final ParsedActivity a = pkg.getActivities().get(i); 103 if (ComponentParseUtils.isMatch(state, false, pkg.isEnabled(), a, 104 flags)) { 105 if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals( 106 a.getName())) { 107 continue; 108 } 109 res[num++] = generateActivityInfo(pkg, a, flags, state, 110 applicationInfo, userId); 111 } 112 } 113 info.activities = ArrayUtils.trimToSize(res, num); 114 } 115 } 116 if ((flags & PackageManager.GET_RECEIVERS) != 0) { 117 final int size = pkg.getReceivers().size(); 118 if (size > 0) { 119 int num = 0; 120 final ActivityInfo[] res = new ActivityInfo[size]; 121 for (int i = 0; i < size; i++) { 122 final ParsedActivity a = pkg.getReceivers().get(i); 123 if (ComponentParseUtils.isMatch(state, false, pkg.isEnabled(), a, 124 flags)) { 125 res[num++] = generateActivityInfo(pkg, a, flags, state, 126 applicationInfo, userId); 127 } 128 } 129 info.receivers = ArrayUtils.trimToSize(res, num); 130 } 131 } 132 if ((flags & PackageManager.GET_SERVICES) != 0) { 133 final int size = pkg.getServices().size(); 134 if (size > 0) { 135 int num = 0; 136 final ServiceInfo[] res = new ServiceInfo[size]; 137 for (int i = 0; i < size; i++) { 138 final ParsedService s = pkg.getServices().get(i); 139 if (ComponentParseUtils.isMatch(state, false, pkg.isEnabled(), s, 140 flags)) { 141 res[num++] = generateServiceInfo(pkg, s, flags, state, 142 applicationInfo, userId); 143 } 144 } 145 info.services = ArrayUtils.trimToSize(res, num); 146 } 147 } 148 if ((flags & PackageManager.GET_PROVIDERS) != 0) { 149 final int size = pkg.getProviders().size(); 150 if (size > 0) { 151 int num = 0; 152 final ProviderInfo[] res = new ProviderInfo[size]; 153 for (int i = 0; i < size; i++) { 154 final ParsedProvider pr = pkg.getProviders() 155 .get(i); 156 if (ComponentParseUtils.isMatch(state, false, pkg.isEnabled(), pr, 157 flags)) { 158 res[num++] = generateProviderInfo(pkg, pr, flags, state, 159 applicationInfo, userId); 160 } 161 } 162 info.providers = ArrayUtils.trimToSize(res, num); 163 } 164 } 165 if ((flags & PackageManager.GET_INSTRUMENTATION) != 0) { 166 int N = pkg.getInstrumentations().size(); 167 if (N > 0) { 168 info.instrumentation = new InstrumentationInfo[N]; 169 for (int i = 0; i < N; i++) { 170 info.instrumentation[i] = generateInstrumentationInfo( 171 pkg.getInstrumentations().get(i), pkg, flags, userId); 172 } 173 } 174 } 175 176 return info; 177 } 178 179 @Nullable generateWithoutComponents(ParsingPackageRead pkg, int[] gids, @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime, Set<String> grantedPermissions, PackageUserState state, int userId, @Nullable ApexInfo apexInfo, @NonNull ApplicationInfo applicationInfo)180 public static PackageInfo generateWithoutComponents(ParsingPackageRead pkg, int[] gids, 181 @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime, 182 Set<String> grantedPermissions, PackageUserState state, int userId, 183 @Nullable ApexInfo apexInfo, @NonNull ApplicationInfo applicationInfo) { 184 if (!checkUseInstalled(pkg, state, flags)) { 185 return null; 186 } 187 188 return generateWithoutComponentsUnchecked(pkg, gids, flags, firstInstallTime, 189 lastUpdateTime, grantedPermissions, state, userId, apexInfo, applicationInfo); 190 } 191 192 /** 193 * This bypasses critical checks that are necessary for usage with data passed outside of 194 * system server. 195 * 196 * Prefer {@link #generateWithoutComponents(ParsingPackageRead, int[], int, long, long, Set, 197 * PackageUserState, int, ApexInfo, ApplicationInfo)}. 198 */ 199 @NonNull generateWithoutComponentsUnchecked(ParsingPackageRead pkg, int[] gids, @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime, Set<String> grantedPermissions, PackageUserState state, int userId, @Nullable ApexInfo apexInfo, @NonNull ApplicationInfo applicationInfo)200 public static PackageInfo generateWithoutComponentsUnchecked(ParsingPackageRead pkg, int[] gids, 201 @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime, 202 Set<String> grantedPermissions, PackageUserState state, int userId, 203 @Nullable ApexInfo apexInfo, @NonNull ApplicationInfo applicationInfo) { 204 PackageInfo pi = new PackageInfo(); 205 pi.packageName = pkg.getPackageName(); 206 pi.splitNames = pkg.getSplitNames(); 207 pi.versionCode = pkg.getVersionCode(); 208 pi.versionCodeMajor = pkg.getVersionCodeMajor(); 209 pi.baseRevisionCode = pkg.getBaseRevisionCode(); 210 pi.splitRevisionCodes = pkg.getSplitRevisionCodes(); 211 pi.versionName = pkg.getVersionName(); 212 pi.sharedUserId = pkg.getSharedUserId(); 213 pi.sharedUserLabel = pkg.getSharedUserLabel(); 214 pi.applicationInfo = applicationInfo; 215 pi.installLocation = pkg.getInstallLocation(); 216 if ((pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0 217 || (pi.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) { 218 pi.requiredForAllUsers = pkg.isRequiredForAllUsers(); 219 } 220 pi.restrictedAccountType = pkg.getRestrictedAccountType(); 221 pi.requiredAccountType = pkg.getRequiredAccountType(); 222 pi.overlayTarget = pkg.getOverlayTarget(); 223 pi.targetOverlayableName = pkg.getOverlayTargetName(); 224 pi.overlayCategory = pkg.getOverlayCategory(); 225 pi.overlayPriority = pkg.getOverlayPriority(); 226 pi.mOverlayIsStatic = pkg.isOverlayIsStatic(); 227 pi.compileSdkVersion = pkg.getCompileSdkVersion(); 228 pi.compileSdkVersionCodename = pkg.getCompileSdkVersionCodeName(); 229 pi.firstInstallTime = firstInstallTime; 230 pi.lastUpdateTime = lastUpdateTime; 231 if ((flags & PackageManager.GET_GIDS) != 0) { 232 pi.gids = gids; 233 } 234 if ((flags & PackageManager.GET_CONFIGURATIONS) != 0) { 235 int size = pkg.getConfigPreferences().size(); 236 if (size > 0) { 237 pi.configPreferences = new ConfigurationInfo[size]; 238 pkg.getConfigPreferences().toArray(pi.configPreferences); 239 } 240 size = pkg.getReqFeatures().size(); 241 if (size > 0) { 242 pi.reqFeatures = new FeatureInfo[size]; 243 pkg.getReqFeatures().toArray(pi.reqFeatures); 244 } 245 size = pkg.getFeatureGroups().size(); 246 if (size > 0) { 247 pi.featureGroups = new FeatureGroupInfo[size]; 248 pkg.getFeatureGroups().toArray(pi.featureGroups); 249 } 250 } 251 if ((flags & PackageManager.GET_PERMISSIONS) != 0) { 252 int size = ArrayUtils.size(pkg.getPermissions()); 253 if (size > 0) { 254 pi.permissions = new PermissionInfo[size]; 255 for (int i = 0; i < size; i++) { 256 pi.permissions[i] = generatePermissionInfo(pkg.getPermissions().get(i), 257 flags); 258 } 259 } 260 size = pkg.getRequestedPermissions().size(); 261 if (size > 0) { 262 pi.requestedPermissions = new String[size]; 263 pi.requestedPermissionsFlags = new int[size]; 264 for (int i = 0; i < size; i++) { 265 final String perm = pkg.getRequestedPermissions().get(i); 266 pi.requestedPermissions[i] = perm; 267 // The notion of required permissions is deprecated but for compatibility. 268 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED; 269 if (grantedPermissions != null && grantedPermissions.contains(perm)) { 270 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED; 271 } 272 } 273 } 274 } 275 276 if (apexInfo != null) { 277 File apexFile = new File(apexInfo.modulePath); 278 279 pi.applicationInfo.sourceDir = apexFile.getPath(); 280 pi.applicationInfo.publicSourceDir = apexFile.getPath(); 281 if (apexInfo.isFactory) { 282 pi.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM; 283 } else { 284 pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM; 285 } 286 if (apexInfo.isActive) { 287 pi.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED; 288 } else { 289 pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED; 290 } 291 pi.isApex = true; 292 } 293 294 PackageParser.SigningDetails signingDetails = pkg.getSigningDetails(); 295 // deprecated method of getting signing certificates 296 if ((flags & PackageManager.GET_SIGNATURES) != 0) { 297 if (signingDetails.hasPastSigningCertificates()) { 298 // Package has included signing certificate rotation information. Return the oldest 299 // cert so that programmatic checks keep working even if unaware of key rotation. 300 pi.signatures = new Signature[1]; 301 pi.signatures[0] = signingDetails.pastSigningCertificates[0]; 302 } else if (signingDetails.hasSignatures()) { 303 // otherwise keep old behavior 304 int numberOfSigs = signingDetails.signatures.length; 305 pi.signatures = new Signature[numberOfSigs]; 306 System.arraycopy(signingDetails.signatures, 0, pi.signatures, 0, 307 numberOfSigs); 308 } 309 } 310 311 // replacement for GET_SIGNATURES 312 if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) { 313 if (signingDetails != PackageParser.SigningDetails.UNKNOWN) { 314 // only return a valid SigningInfo if there is signing information to report 315 pi.signingInfo = new SigningInfo(signingDetails); 316 } else { 317 pi.signingInfo = null; 318 } 319 } 320 321 return pi; 322 } 323 324 @Nullable generateApplicationInfo(ParsingPackageRead pkg, @PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId)325 public static ApplicationInfo generateApplicationInfo(ParsingPackageRead pkg, 326 @PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId) { 327 if (pkg == null) { 328 return null; 329 } 330 331 if (!checkUseInstalled(pkg, state, flags)) { 332 return null; 333 } 334 335 return generateApplicationInfoUnchecked(pkg, flags, state, userId); 336 } 337 338 /** 339 * This bypasses critical checks that are necessary for usage with data passed outside of 340 * system server. 341 * 342 * Prefer {@link #generateApplicationInfo(ParsingPackageRead, int, PackageUserState, int)}. 343 */ 344 @NonNull generateApplicationInfoUnchecked(@onNull ParsingPackageRead pkg, @PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId)345 public static ApplicationInfo generateApplicationInfoUnchecked(@NonNull ParsingPackageRead pkg, 346 @PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId) { 347 // Make shallow copy so we can store the metadata/libraries safely 348 ApplicationInfo ai = pkg.toAppInfoWithoutState(); 349 // Init handles data directories 350 // TODO(b/135203078): Consolidate the data directory logic, remove initForUser 351 ai.initForUser(userId); 352 353 if ((flags & PackageManager.GET_META_DATA) == 0) { 354 ai.metaData = null; 355 } 356 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) == 0) { 357 ai.sharedLibraryFiles = null; 358 ai.sharedLibraryInfos = null; 359 } 360 361 // CompatibilityMode is global state. 362 if (!PackageParser.sCompatibilityModeEnabled) { 363 ai.disableCompatibilityMode(); 364 } 365 366 ai.flags |= flag(state.stopped, ApplicationInfo.FLAG_STOPPED) 367 | flag(state.installed, ApplicationInfo.FLAG_INSTALLED) 368 | flag(state.suspended, ApplicationInfo.FLAG_SUSPENDED); 369 ai.privateFlags |= flag(state.instantApp, ApplicationInfo.PRIVATE_FLAG_INSTANT) 370 | flag(state.virtualPreload, ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD) 371 | flag(state.hidden, ApplicationInfo.PRIVATE_FLAG_HIDDEN); 372 373 if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) { 374 ai.enabled = true; 375 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) { 376 ai.enabled = (flags & PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0; 377 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED 378 || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) { 379 ai.enabled = false; 380 } 381 ai.enabledSetting = state.enabled; 382 if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) { 383 ai.category = state.categoryHint; 384 } 385 if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) { 386 ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName); 387 } 388 ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state); 389 ai.resourceDirs = state.getAllOverlayPaths(); 390 391 return ai; 392 } 393 394 @Nullable generateActivityInfo(ParsingPackageRead pkg, ParsedActivity a, @PackageManager.ComponentInfoFlags int flags, PackageUserState state, @Nullable ApplicationInfo applicationInfo, int userId)395 public static ActivityInfo generateActivityInfo(ParsingPackageRead pkg, ParsedActivity a, 396 @PackageManager.ComponentInfoFlags int flags, PackageUserState state, 397 @Nullable ApplicationInfo applicationInfo, int userId) { 398 if (a == null) return null; 399 if (!checkUseInstalled(pkg, state, flags)) { 400 return null; 401 } 402 if (applicationInfo == null) { 403 applicationInfo = generateApplicationInfo(pkg, flags, state, userId); 404 } 405 if (applicationInfo == null) { 406 return null; 407 } 408 409 return generateActivityInfoUnchecked(a, applicationInfo); 410 } 411 412 /** 413 * This bypasses critical checks that are necessary for usage with data passed outside of 414 * system server. 415 * 416 * Prefer {@link #generateActivityInfo(ParsingPackageRead, ParsedActivity, int, 417 * PackageUserState, ApplicationInfo, int)}. 418 */ 419 @NonNull generateActivityInfoUnchecked(@onNull ParsedActivity a, @NonNull ApplicationInfo applicationInfo)420 public static ActivityInfo generateActivityInfoUnchecked(@NonNull ParsedActivity a, 421 @NonNull ApplicationInfo applicationInfo) { 422 // Make shallow copies so we can store the metadata safely 423 ActivityInfo ai = new ActivityInfo(); 424 assignSharedFieldsForComponentInfo(ai, a); 425 ai.targetActivity = a.getTargetActivity(); 426 ai.processName = a.getProcessName(); 427 ai.exported = a.isExported(); 428 ai.theme = a.getTheme(); 429 ai.uiOptions = a.getUiOptions(); 430 ai.parentActivityName = a.getParentActivityName(); 431 ai.permission = a.getPermission(); 432 ai.taskAffinity = a.getTaskAffinity(); 433 ai.flags = a.getFlags(); 434 ai.privateFlags = a.getPrivateFlags(); 435 ai.launchMode = a.getLaunchMode(); 436 ai.documentLaunchMode = a.getDocumentLaunchMode(); 437 ai.maxRecents = a.getMaxRecents(); 438 ai.configChanges = a.getConfigChanges(); 439 ai.softInputMode = a.getSoftInputMode(); 440 ai.persistableMode = a.getPersistableMode(); 441 ai.lockTaskLaunchMode = a.getLockTaskLaunchMode(); 442 ai.screenOrientation = a.getScreenOrientation(); 443 ai.resizeMode = a.getResizeMode(); 444 Float maxAspectRatio = a.getMaxAspectRatio(); 445 ai.maxAspectRatio = maxAspectRatio != null ? maxAspectRatio : 0f; 446 Float minAspectRatio = a.getMinAspectRatio(); 447 ai.minAspectRatio = minAspectRatio != null ? minAspectRatio : 0f; 448 ai.supportsSizeChanges = a.getSupportsSizeChanges(); 449 ai.requestedVrComponent = a.getRequestedVrComponent(); 450 ai.rotationAnimation = a.getRotationAnimation(); 451 ai.colorMode = a.getColorMode(); 452 ai.windowLayout = a.getWindowLayout(); 453 ai.metaData = a.getMetaData(); 454 ai.applicationInfo = applicationInfo; 455 return ai; 456 } 457 458 @Nullable generateActivityInfo(ParsingPackageRead pkg, ParsedActivity a, @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId)459 public static ActivityInfo generateActivityInfo(ParsingPackageRead pkg, ParsedActivity a, 460 @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId) { 461 return generateActivityInfo(pkg, a, flags, state, null, userId); 462 } 463 464 @Nullable generateServiceInfo(ParsingPackageRead pkg, ParsedService s, @PackageManager.ComponentInfoFlags int flags, PackageUserState state, @Nullable ApplicationInfo applicationInfo, int userId)465 public static ServiceInfo generateServiceInfo(ParsingPackageRead pkg, ParsedService s, 466 @PackageManager.ComponentInfoFlags int flags, PackageUserState state, 467 @Nullable ApplicationInfo applicationInfo, int userId) { 468 if (s == null) return null; 469 if (!checkUseInstalled(pkg, state, flags)) { 470 return null; 471 } 472 if (applicationInfo == null) { 473 applicationInfo = generateApplicationInfo(pkg, flags, state, userId); 474 } 475 if (applicationInfo == null) { 476 return null; 477 } 478 479 return generateServiceInfoUnchecked(s, applicationInfo); 480 } 481 482 /** 483 * This bypasses critical checks that are necessary for usage with data passed outside of 484 * system server. 485 * 486 * Prefer {@link #generateServiceInfo(ParsingPackageRead, ParsedService, int, PackageUserState, 487 * ApplicationInfo, int)}. 488 */ 489 @NonNull generateServiceInfoUnchecked(@onNull ParsedService s, @NonNull ApplicationInfo applicationInfo)490 public static ServiceInfo generateServiceInfoUnchecked(@NonNull ParsedService s, 491 @NonNull ApplicationInfo applicationInfo) { 492 // Make shallow copies so we can store the metadata safely 493 ServiceInfo si = new ServiceInfo(); 494 assignSharedFieldsForComponentInfo(si, s); 495 si.exported = s.isExported(); 496 si.flags = s.getFlags(); 497 si.metaData = s.getMetaData(); 498 si.permission = s.getPermission(); 499 si.processName = s.getProcessName(); 500 si.mForegroundServiceType = s.getForegroundServiceType(); 501 si.applicationInfo = applicationInfo; 502 return si; 503 } 504 505 @Nullable generateServiceInfo(ParsingPackageRead pkg, ParsedService s, @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId)506 public static ServiceInfo generateServiceInfo(ParsingPackageRead pkg, ParsedService s, 507 @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId) { 508 return generateServiceInfo(pkg, s, flags, state, null, userId); 509 } 510 511 @Nullable generateProviderInfo(ParsingPackageRead pkg, ParsedProvider p, @PackageManager.ComponentInfoFlags int flags, PackageUserState state, @Nullable ApplicationInfo applicationInfo, int userId)512 public static ProviderInfo generateProviderInfo(ParsingPackageRead pkg, ParsedProvider p, 513 @PackageManager.ComponentInfoFlags int flags, PackageUserState state, 514 @Nullable ApplicationInfo applicationInfo, int userId) { 515 if (p == null) return null; 516 if (!checkUseInstalled(pkg, state, flags)) { 517 return null; 518 } 519 if (applicationInfo == null) { 520 applicationInfo = generateApplicationInfo(pkg, flags, state, userId); 521 } 522 if (applicationInfo == null) { 523 return null; 524 } 525 526 return generateProviderInfoUnchecked(p, flags, applicationInfo); 527 } 528 529 /** 530 * This bypasses critical checks that are necessary for usage with data passed outside of 531 * system server. 532 * 533 * Prefer {@link #generateProviderInfo(ParsingPackageRead, ParsedProvider, int, 534 * PackageUserState, ApplicationInfo, int)}. 535 */ 536 @NonNull generateProviderInfoUnchecked(@onNull ParsedProvider p, @PackageManager.ComponentInfoFlags int flags, @NonNull ApplicationInfo applicationInfo)537 public static ProviderInfo generateProviderInfoUnchecked(@NonNull ParsedProvider p, 538 @PackageManager.ComponentInfoFlags int flags, 539 @NonNull ApplicationInfo applicationInfo) { 540 // Make shallow copies so we can store the metadata safely 541 ProviderInfo pi = new ProviderInfo(); 542 assignSharedFieldsForComponentInfo(pi, p); 543 pi.exported = p.isExported(); 544 pi.flags = p.getFlags(); 545 pi.processName = p.getProcessName(); 546 pi.authority = p.getAuthority(); 547 pi.isSyncable = p.isSyncable(); 548 pi.readPermission = p.getReadPermission(); 549 pi.writePermission = p.getWritePermission(); 550 pi.grantUriPermissions = p.isGrantUriPermissions(); 551 pi.forceUriPermissions = p.isForceUriPermissions(); 552 pi.multiprocess = p.isMultiProcess(); 553 pi.initOrder = p.getInitOrder(); 554 pi.uriPermissionPatterns = p.getUriPermissionPatterns(); 555 pi.pathPermissions = p.getPathPermissions(); 556 pi.metaData = p.getMetaData(); 557 if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) { 558 pi.uriPermissionPatterns = null; 559 } 560 pi.applicationInfo = applicationInfo; 561 return pi; 562 } 563 564 @Nullable generateProviderInfo(ParsingPackageRead pkg, ParsedProvider p, @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId)565 public static ProviderInfo generateProviderInfo(ParsingPackageRead pkg, ParsedProvider p, 566 @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId) { 567 return generateProviderInfo(pkg, p, flags, state, null, userId); 568 } 569 570 @Nullable generateInstrumentationInfo(ParsedInstrumentation i, ParsingPackageRead pkg, @PackageManager.ComponentInfoFlags int flags, int userId)571 public static InstrumentationInfo generateInstrumentationInfo(ParsedInstrumentation i, 572 ParsingPackageRead pkg, @PackageManager.ComponentInfoFlags int flags, int userId) { 573 if (i == null) return null; 574 575 InstrumentationInfo ii = new InstrumentationInfo(); 576 assignSharedFieldsForPackageItemInfo(ii, i); 577 ii.targetPackage = i.getTargetPackage(); 578 ii.targetProcesses = i.getTargetProcesses(); 579 ii.handleProfiling = i.isHandleProfiling(); 580 ii.functionalTest = i.isFunctionalTest(); 581 582 ii.sourceDir = pkg.getBaseCodePath(); 583 ii.publicSourceDir = pkg.getBaseCodePath(); 584 ii.splitNames = pkg.getSplitNames(); 585 ii.splitSourceDirs = pkg.getSplitCodePaths(); 586 ii.splitPublicSourceDirs = pkg.getSplitCodePaths(); 587 ii.splitDependencies = pkg.getSplitDependencies(); 588 ii.dataDir = getDataDir(pkg, userId).getAbsolutePath(); 589 ii.deviceProtectedDataDir = getDeviceProtectedDataDir(pkg, userId).getAbsolutePath(); 590 ii.credentialProtectedDataDir = getCredentialProtectedDataDir(pkg, 591 userId).getAbsolutePath(); 592 593 if ((flags & PackageManager.GET_META_DATA) == 0) { 594 return ii; 595 } 596 ii.metaData = i.getMetaData(); 597 return ii; 598 } 599 600 @Nullable generatePermissionInfo(ParsedPermission p, @PackageManager.ComponentInfoFlags int flags)601 public static PermissionInfo generatePermissionInfo(ParsedPermission p, 602 @PackageManager.ComponentInfoFlags int flags) { 603 if (p == null) return null; 604 605 PermissionInfo pi = new PermissionInfo(p.getBackgroundPermission()); 606 607 assignSharedFieldsForPackageItemInfo(pi, p); 608 609 pi.group = p.getGroup(); 610 pi.requestRes = p.getRequestRes(); 611 pi.protectionLevel = p.getProtectionLevel(); 612 pi.descriptionRes = p.getDescriptionRes(); 613 pi.flags = p.getFlags(); 614 615 if ((flags & PackageManager.GET_META_DATA) == 0) { 616 return pi; 617 } 618 pi.metaData = p.getMetaData(); 619 return pi; 620 } 621 622 @Nullable generatePermissionGroupInfo(ParsedPermissionGroup pg, @PackageManager.ComponentInfoFlags int flags)623 public static PermissionGroupInfo generatePermissionGroupInfo(ParsedPermissionGroup pg, 624 @PackageManager.ComponentInfoFlags int flags) { 625 if (pg == null) return null; 626 627 PermissionGroupInfo pgi = new PermissionGroupInfo( 628 pg.getRequestDetailResourceId(), 629 pg.getBackgroundRequestResourceId(), 630 pg.getBackgroundRequestDetailResourceId() 631 ); 632 633 assignSharedFieldsForPackageItemInfo(pgi, pg); 634 pgi.descriptionRes = pg.getDescriptionRes(); 635 pgi.priority = pg.getPriority(); 636 pgi.requestRes = pg.getRequestRes(); 637 pgi.flags = pg.getFlags(); 638 639 if ((flags & PackageManager.GET_META_DATA) == 0) { 640 return pgi; 641 } 642 pgi.metaData = pg.getMetaData(); 643 return pgi; 644 } 645 assignSharedFieldsForComponentInfo(@onNull ComponentInfo componentInfo, @NonNull ParsedMainComponent mainComponent)646 private static void assignSharedFieldsForComponentInfo(@NonNull ComponentInfo componentInfo, 647 @NonNull ParsedMainComponent mainComponent) { 648 assignSharedFieldsForPackageItemInfo(componentInfo, mainComponent); 649 componentInfo.descriptionRes = mainComponent.getDescriptionRes(); 650 componentInfo.directBootAware = mainComponent.isDirectBootAware(); 651 componentInfo.enabled = mainComponent.isEnabled(); 652 componentInfo.splitName = mainComponent.getSplitName(); 653 } 654 assignSharedFieldsForPackageItemInfo( @onNull PackageItemInfo packageItemInfo, @NonNull ParsedComponent component)655 private static void assignSharedFieldsForPackageItemInfo( 656 @NonNull PackageItemInfo packageItemInfo, @NonNull ParsedComponent component) { 657 packageItemInfo.nonLocalizedLabel = ComponentParseUtils.getNonLocalizedLabel(component); 658 packageItemInfo.icon = ComponentParseUtils.getIcon(component); 659 660 packageItemInfo.banner = component.getBanner(); 661 packageItemInfo.labelRes = component.getLabelRes(); 662 packageItemInfo.logo = component.getLogo(); 663 packageItemInfo.name = component.getName(); 664 packageItemInfo.packageName = component.getPackageName(); 665 } 666 667 @CheckResult flag(boolean hasFlag, int flag)668 private static int flag(boolean hasFlag, int flag) { 669 if (hasFlag) { 670 return flag; 671 } else { 672 return 0; 673 } 674 } 675 676 /** @see ApplicationInfo#flags */ appInfoFlags(ParsingPackageRead pkg)677 public static int appInfoFlags(ParsingPackageRead pkg) { 678 // @formatter:off 679 return flag(pkg.isExternalStorage(), ApplicationInfo.FLAG_EXTERNAL_STORAGE) 680 | flag(pkg.isBaseHardwareAccelerated(), ApplicationInfo.FLAG_HARDWARE_ACCELERATED) 681 | flag(pkg.isAllowBackup(), ApplicationInfo.FLAG_ALLOW_BACKUP) 682 | flag(pkg.isKillAfterRestore(), ApplicationInfo.FLAG_KILL_AFTER_RESTORE) 683 | flag(pkg.isRestoreAnyVersion(), ApplicationInfo.FLAG_RESTORE_ANY_VERSION) 684 | flag(pkg.isFullBackupOnly(), ApplicationInfo.FLAG_FULL_BACKUP_ONLY) 685 | flag(pkg.isPersistent(), ApplicationInfo.FLAG_PERSISTENT) 686 | flag(pkg.isDebuggable(), ApplicationInfo.FLAG_DEBUGGABLE) 687 | flag(pkg.isVmSafeMode(), ApplicationInfo.FLAG_VM_SAFE_MODE) 688 | flag(pkg.isHasCode(), ApplicationInfo.FLAG_HAS_CODE) 689 | flag(pkg.isAllowTaskReparenting(), ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) 690 | flag(pkg.isAllowClearUserData(), ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA) 691 | flag(pkg.isLargeHeap(), ApplicationInfo.FLAG_LARGE_HEAP) 692 | flag(pkg.isUsesCleartextTraffic(), ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC) 693 | flag(pkg.isSupportsRtl(), ApplicationInfo.FLAG_SUPPORTS_RTL) 694 | flag(pkg.isTestOnly(), ApplicationInfo.FLAG_TEST_ONLY) 695 | flag(pkg.isMultiArch(), ApplicationInfo.FLAG_MULTIARCH) 696 | flag(pkg.isExtractNativeLibs(), ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS) 697 | flag(pkg.isGame(), ApplicationInfo.FLAG_IS_GAME) 698 | flag(pkg.isSupportsSmallScreens(), ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) 699 | flag(pkg.isSupportsNormalScreens(), ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) 700 | flag(pkg.isSupportsLargeScreens(), ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) 701 | flag(pkg.isSupportsExtraLargeScreens(), ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) 702 | flag(pkg.isResizeable(), ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) 703 | flag(pkg.isAnyDensity(), ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES); 704 // @formatter:on 705 } 706 707 /** @see ApplicationInfo#privateFlags */ appInfoPrivateFlags(ParsingPackageRead pkg)708 public static int appInfoPrivateFlags(ParsingPackageRead pkg) { 709 // @formatter:off 710 int privateFlags = flag(pkg.isStaticSharedLibrary(), ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY) 711 | flag(pkg.isOverlay(), ApplicationInfo.PRIVATE_FLAG_IS_RESOURCE_OVERLAY) 712 | flag(pkg.isIsolatedSplitLoading(), ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING) 713 | flag(pkg.isHasDomainUrls(), ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) 714 | flag(pkg.isProfileableByShell(), ApplicationInfo.PRIVATE_FLAG_PROFILEABLE_BY_SHELL) 715 | flag(pkg.isBackupInForeground(), ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND) 716 | flag(pkg.isUseEmbeddedDex(), ApplicationInfo.PRIVATE_FLAG_USE_EMBEDDED_DEX) 717 | flag(pkg.isDefaultToDeviceProtectedStorage(), ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) 718 | flag(pkg.isDirectBootAware(), ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE) 719 | flag(pkg.isPartiallyDirectBootAware(), ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE) 720 | flag(pkg.isAllowClearUserDataOnFailedRestore(), ApplicationInfo.PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE) 721 | flag(pkg.isAllowAudioPlaybackCapture(), ApplicationInfo.PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE) 722 | flag(pkg.isRequestLegacyExternalStorage(), ApplicationInfo.PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE) 723 | flag(pkg.isUsesNonSdkApi(), ApplicationInfo.PRIVATE_FLAG_USES_NON_SDK_API) 724 | flag(pkg.isHasFragileUserData(), ApplicationInfo.PRIVATE_FLAG_HAS_FRAGILE_USER_DATA) 725 | flag(pkg.isCantSaveState(), ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) 726 | flag(pkg.isResizeableActivityViaSdkVersion(), ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) 727 | flag(pkg.isAllowNativeHeapPointerTagging(), ApplicationInfo.PRIVATE_FLAG_ALLOW_NATIVE_HEAP_POINTER_TAGGING); 728 // @formatter:on 729 730 Boolean resizeableActivity = pkg.getResizeableActivity(); 731 if (resizeableActivity != null) { 732 if (resizeableActivity) { 733 privateFlags |= ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE; 734 } else { 735 privateFlags |= ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE; 736 } 737 } 738 739 return privateFlags; 740 } 741 checkUseInstalled(ParsingPackageRead pkg, PackageUserState state, @PackageManager.PackageInfoFlags int flags)742 private static boolean checkUseInstalled(ParsingPackageRead pkg, PackageUserState state, 743 @PackageManager.PackageInfoFlags int flags) { 744 // If available for the target user 745 return state.isAvailable(flags); 746 } 747 748 @NonNull getDataDir(ParsingPackageRead pkg, int userId)749 public static File getDataDir(ParsingPackageRead pkg, int userId) { 750 if ("android".equals(pkg.getPackageName())) { 751 return Environment.getDataSystemDirectory(); 752 } 753 754 if (pkg.isDefaultToDeviceProtectedStorage() 755 && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) { 756 return getDeviceProtectedDataDir(pkg, userId); 757 } else { 758 return getCredentialProtectedDataDir(pkg, userId); 759 } 760 } 761 762 @NonNull getDeviceProtectedDataDir(ParsingPackageRead pkg, int userId)763 public static File getDeviceProtectedDataDir(ParsingPackageRead pkg, int userId) { 764 return Environment.getDataUserDePackageDirectory(pkg.getVolumeUuid(), userId, 765 pkg.getPackageName()); 766 } 767 768 @NonNull getCredentialProtectedDataDir(ParsingPackageRead pkg, int userId)769 public static File getCredentialProtectedDataDir(ParsingPackageRead pkg, int userId) { 770 return Environment.getDataUserCePackageDirectory(pkg.getVolumeUuid(), userId, 771 pkg.getPackageName()); 772 } 773 } 774