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 static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertNotNull; 22 import static org.junit.Assert.assertNull; 23 import static org.junit.Assert.assertTrue; 24 25 import android.apex.ApexInfo; 26 import android.content.Context; 27 import android.content.pm.ApplicationInfo; 28 import android.content.pm.PackageInfo; 29 import android.content.pm.PackageManager; 30 import android.content.pm.PackageParser; 31 import android.content.pm.PermissionInfo; 32 import android.content.pm.parsing.PackageInfoWithoutStateUtils; 33 import android.content.pm.parsing.ParsingPackage; 34 import android.content.pm.parsing.ParsingPackageUtils; 35 import android.content.pm.parsing.component.ParsedComponent; 36 import android.content.pm.parsing.component.ParsedPermission; 37 import android.content.pm.parsing.result.ParseResult; 38 import android.os.Build; 39 import android.os.Bundle; 40 import android.os.FileUtils; 41 import android.platform.test.annotations.Presubmit; 42 import android.util.Pair; 43 import android.util.SparseIntArray; 44 45 import androidx.test.InstrumentationRegistry; 46 import androidx.test.filters.SmallTest; 47 import androidx.test.runner.AndroidJUnit4; 48 49 import com.android.frameworks.servicestests.R; 50 import com.android.internal.util.ArrayUtils; 51 import com.android.server.pm.parsing.pkg.AndroidPackage; 52 import com.android.server.pm.parsing.pkg.ParsedPackage; 53 54 import com.google.common.truth.Expect; 55 56 import org.junit.Rule; 57 import org.junit.Test; 58 import org.junit.runner.RunWith; 59 60 import java.io.File; 61 import java.io.InputStream; 62 import java.util.Collections; 63 import java.util.HashMap; 64 import java.util.Map; 65 import java.util.function.Function; 66 67 /** 68 * {@link ParsedPackage} was moved to the server, so this test moved along with it. 69 * 70 * This should be eventually refactored to a comprehensive parsing test, combined with its 71 * server variant in the parent package. 72 * 73 * TODO(b/135203078): Remove this test and replicate the cases in the actual com.android.server 74 * variant. 75 */ 76 @Presubmit 77 @SmallTest 78 @RunWith(AndroidJUnit4.class) 79 public class PackageParserLegacyCoreTest { 80 private static final String RELEASED = null; 81 private static final String OLDER_PRE_RELEASE = "A"; 82 private static final String PRE_RELEASE = "B"; 83 private static final String NEWER_PRE_RELEASE = "C"; 84 85 // Codenames with a fingerprint attached to them. These may only be present in the apps 86 // declared min SDK and not as platform codenames. 87 private static final String OLDER_PRE_RELEASE_WITH_FINGERPRINT = "A.fingerprint"; 88 private static final String PRE_RELEASE_WITH_FINGERPRINT = "B.fingerprint"; 89 private static final String NEWER_PRE_RELEASE_WITH_FINGERPRINT = "C.fingerprint"; 90 91 private static final String[] CODENAMES_RELEASED = { /* empty */}; 92 private static final String[] CODENAMES_PRE_RELEASE = {PRE_RELEASE}; 93 94 private static final int OLDER_VERSION = 10; 95 private static final int PLATFORM_VERSION = 20; 96 private static final int NEWER_VERSION = 30; 97 98 @Rule public final Expect expect = Expect.create(); 99 verifyComputeMinSdkVersion(int minSdkVersion, String minSdkCodename, boolean isPlatformReleased, int expectedMinSdk)100 private void verifyComputeMinSdkVersion(int minSdkVersion, String minSdkCodename, 101 boolean isPlatformReleased, int expectedMinSdk) { 102 final String[] outError = new String[1]; 103 final int result = PackageParser.computeMinSdkVersion( 104 minSdkVersion, 105 minSdkCodename, 106 PLATFORM_VERSION, 107 isPlatformReleased ? CODENAMES_RELEASED : CODENAMES_PRE_RELEASE, 108 outError); 109 110 assertEquals("Error msg: " + outError[0], expectedMinSdk, result); 111 112 if (expectedMinSdk == -1) { 113 assertNotNull(outError[0]); 114 } else { 115 assertNull(outError[0]); 116 } 117 } 118 119 @Test testComputeMinSdkVersion_preReleasePlatform()120 public void testComputeMinSdkVersion_preReleasePlatform() { 121 // Do allow older release minSdkVersion on pre-release platform. 122 // APP: Released API 10 123 // DEV: Pre-release API 20 124 verifyComputeMinSdkVersion(OLDER_VERSION, RELEASED, false, OLDER_VERSION); 125 126 // Do allow same release minSdkVersion on pre-release platform. 127 // APP: Released API 20 128 // DEV: Pre-release API 20 129 verifyComputeMinSdkVersion(PLATFORM_VERSION, RELEASED, false, PLATFORM_VERSION); 130 131 // Don't allow newer release minSdkVersion on pre-release platform. 132 // APP: Released API 30 133 // DEV: Pre-release API 20 134 verifyComputeMinSdkVersion(NEWER_VERSION, RELEASED, false, -1); 135 136 // Don't allow older pre-release minSdkVersion on pre-release platform. 137 // APP: Pre-release API 10 138 // DEV: Pre-release API 20 139 verifyComputeMinSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE, false, -1); 140 verifyComputeMinSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE_WITH_FINGERPRINT, false, -1); 141 142 // Do allow same pre-release minSdkVersion on pre-release platform, 143 // but overwrite the specified version with CUR_DEVELOPMENT. 144 // APP: Pre-release API 20 145 // DEV: Pre-release API 20 146 verifyComputeMinSdkVersion(PLATFORM_VERSION, PRE_RELEASE, false, 147 Build.VERSION_CODES.CUR_DEVELOPMENT); 148 verifyComputeMinSdkVersion(PLATFORM_VERSION, PRE_RELEASE_WITH_FINGERPRINT, false, 149 Build.VERSION_CODES.CUR_DEVELOPMENT); 150 151 152 // Don't allow newer pre-release minSdkVersion on pre-release platform. 153 // APP: Pre-release API 30 154 // DEV: Pre-release API 20 155 verifyComputeMinSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, false, -1); 156 verifyComputeMinSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, false, -1); 157 } 158 159 @Test testComputeMinSdkVersion_releasedPlatform()160 public void testComputeMinSdkVersion_releasedPlatform() { 161 // Do allow older release minSdkVersion on released platform. 162 // APP: Released API 10 163 // DEV: Released API 20 164 verifyComputeMinSdkVersion(OLDER_VERSION, RELEASED, true, OLDER_VERSION); 165 166 // Do allow same release minSdkVersion on released platform. 167 // APP: Released API 20 168 // DEV: Released API 20 169 verifyComputeMinSdkVersion(PLATFORM_VERSION, RELEASED, true, PLATFORM_VERSION); 170 171 // Don't allow newer release minSdkVersion on released platform. 172 // APP: Released API 30 173 // DEV: Released API 20 174 verifyComputeMinSdkVersion(NEWER_VERSION, RELEASED, true, -1); 175 176 // Don't allow older pre-release minSdkVersion on released platform. 177 // APP: Pre-release API 10 178 // DEV: Released API 20 179 verifyComputeMinSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE, true, -1); 180 verifyComputeMinSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE_WITH_FINGERPRINT, true, -1); 181 182 // Don't allow same pre-release minSdkVersion on released platform. 183 // APP: Pre-release API 20 184 // DEV: Released API 20 185 verifyComputeMinSdkVersion(PLATFORM_VERSION, PRE_RELEASE, true, -1); 186 verifyComputeMinSdkVersion(PLATFORM_VERSION, PRE_RELEASE_WITH_FINGERPRINT, true, -1); 187 188 189 // Don't allow newer pre-release minSdkVersion on released platform. 190 // APP: Pre-release API 30 191 // DEV: Released API 20 192 verifyComputeMinSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, true, -1); 193 verifyComputeMinSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, true, -1); 194 } 195 verifyComputeTargetSdkVersion(int targetSdkVersion, String targetSdkCodename, boolean isPlatformReleased, int expectedTargetSdk)196 private void verifyComputeTargetSdkVersion(int targetSdkVersion, String targetSdkCodename, 197 boolean isPlatformReleased, int expectedTargetSdk) { 198 final String[] outError = new String[1]; 199 final int result = PackageParser.computeTargetSdkVersion( 200 targetSdkVersion, 201 targetSdkCodename, 202 isPlatformReleased ? CODENAMES_RELEASED : CODENAMES_PRE_RELEASE, 203 outError); 204 205 assertEquals(result, expectedTargetSdk); 206 207 if (expectedTargetSdk == -1) { 208 assertNotNull(outError[0]); 209 } else { 210 assertNull(outError[0]); 211 } 212 } 213 214 @Test testComputeTargetSdkVersion_preReleasePlatform()215 public void testComputeTargetSdkVersion_preReleasePlatform() { 216 // Do allow older release targetSdkVersion on pre-release platform. 217 // APP: Released API 10 218 // DEV: Pre-release API 20 219 verifyComputeTargetSdkVersion(OLDER_VERSION, RELEASED, false, OLDER_VERSION); 220 221 // Do allow same release targetSdkVersion on pre-release platform. 222 // APP: Released API 20 223 // DEV: Pre-release API 20 224 verifyComputeTargetSdkVersion(PLATFORM_VERSION, RELEASED, false, PLATFORM_VERSION); 225 226 // Do allow newer release targetSdkVersion on pre-release platform. 227 // APP: Released API 30 228 // DEV: Pre-release API 20 229 verifyComputeTargetSdkVersion(NEWER_VERSION, RELEASED, false, NEWER_VERSION); 230 231 // Don't allow older pre-release targetSdkVersion on pre-release platform. 232 // APP: Pre-release API 10 233 // DEV: Pre-release API 20 234 verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE, false, -1); 235 verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE_WITH_FINGERPRINT, false, -1); 236 237 238 // Do allow same pre-release targetSdkVersion on pre-release platform, 239 // but overwrite the specified version with CUR_DEVELOPMENT. 240 // APP: Pre-release API 20 241 // DEV: Pre-release API 20 242 verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE, false, 243 Build.VERSION_CODES.CUR_DEVELOPMENT); 244 verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE_WITH_FINGERPRINT, false, 245 Build.VERSION_CODES.CUR_DEVELOPMENT); 246 247 248 // Don't allow newer pre-release targetSdkVersion on pre-release platform. 249 // APP: Pre-release API 30 250 // DEV: Pre-release API 20 251 verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, false, -1); 252 verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, false, -1); 253 } 254 255 @Test testComputeTargetSdkVersion_releasedPlatform()256 public void testComputeTargetSdkVersion_releasedPlatform() { 257 // Do allow older release targetSdkVersion on released platform. 258 // APP: Released API 10 259 // DEV: Released API 20 260 verifyComputeTargetSdkVersion(OLDER_VERSION, RELEASED, true, OLDER_VERSION); 261 262 // Do allow same release targetSdkVersion on released platform. 263 // APP: Released API 20 264 // DEV: Released API 20 265 verifyComputeTargetSdkVersion(PLATFORM_VERSION, RELEASED, true, PLATFORM_VERSION); 266 267 // Do allow newer release targetSdkVersion on released platform. 268 // APP: Released API 30 269 // DEV: Released API 20 270 verifyComputeTargetSdkVersion(NEWER_VERSION, RELEASED, true, NEWER_VERSION); 271 272 // Don't allow older pre-release targetSdkVersion on released platform. 273 // APP: Pre-release API 10 274 // DEV: Released API 20 275 verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE, true, -1); 276 verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE_WITH_FINGERPRINT, true, -1); 277 278 // Don't allow same pre-release targetSdkVersion on released platform. 279 // APP: Pre-release API 20 280 // DEV: Released API 20 281 verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE, true, -1); 282 verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE_WITH_FINGERPRINT, true, -1); 283 284 285 // Don't allow newer pre-release targetSdkVersion on released platform. 286 // APP: Pre-release API 30 287 // DEV: Released API 20 288 verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, true, -1); 289 verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, true, -1); 290 } 291 292 /** 293 * Unit test for PackageParser.getActivityConfigChanges(). 294 * If the bit is 1 in the original configChanges, it is still 1 in the final configChanges. 295 * If the bit is 0 in the original configChanges and the bit is not set to 1 in 296 * recreateOnConfigChanges, the bit is changed to 1 in the final configChanges by default. 297 */ 298 @Test testGetActivityConfigChanges()299 public void testGetActivityConfigChanges() { 300 // Not set in either configChanges or recreateOnConfigChanges. 301 int configChanges = 0x0000; // 00000000. 302 int recreateOnConfigChanges = 0x0000; // 00000000. 303 int finalConfigChanges = 304 PackageParser.getActivityConfigChanges(configChanges, recreateOnConfigChanges); 305 assertEquals(0x0003, finalConfigChanges); // Should be 00000011. 306 307 // Not set in configChanges, but set in recreateOnConfigChanges. 308 configChanges = 0x0000; // 00000000. 309 recreateOnConfigChanges = 0x0003; // 00000011. 310 finalConfigChanges = 311 PackageParser.getActivityConfigChanges(configChanges, recreateOnConfigChanges); 312 assertEquals(0x0000, finalConfigChanges); // Should be 00000000. 313 314 // Set in configChanges. 315 configChanges = 0x0003; // 00000011. 316 recreateOnConfigChanges = 0X0000; // 00000000. 317 finalConfigChanges = 318 PackageParser.getActivityConfigChanges(configChanges, recreateOnConfigChanges); 319 assertEquals(0x0003, finalConfigChanges); // Should be 00000011. 320 321 recreateOnConfigChanges = 0x0003; // 00000011. 322 finalConfigChanges = 323 PackageParser.getActivityConfigChanges(configChanges, recreateOnConfigChanges); 324 assertEquals(0x0003, finalConfigChanges); // Should still be 00000011. 325 326 // Other bit set in configChanges. 327 configChanges = 0x0080; // 10000000, orientation. 328 recreateOnConfigChanges = 0x0000; // 00000000. 329 finalConfigChanges = 330 PackageParser.getActivityConfigChanges(configChanges, recreateOnConfigChanges); 331 assertEquals(0x0083, finalConfigChanges); // Should be 10000011. 332 } 333 334 /** 335 * Copies a specified {@code resourceId} to a file. Returns a non-null file if the copy 336 * succeeded, or {@code null} otherwise. 337 */ copyRawResourceToFile(String baseName, int resourceId)338 File copyRawResourceToFile(String baseName, int resourceId) throws Exception { 339 // Copy the resource to a file. 340 Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); 341 InputStream is = context.getResources().openRawResource(resourceId); 342 File outFile = null; 343 try { 344 outFile = new File(context.getFilesDir(), baseName); 345 assertTrue(FileUtils.copyToFile(is, outFile)); 346 return outFile; 347 } catch (Exception e) { 348 if (outFile != null) { 349 outFile.delete(); 350 } 351 352 return null; 353 } 354 } 355 356 /** 357 * Attempts to parse a package. 358 * 359 * APKs are put into coretests/apks/packageparser_*. 360 * 361 * @param apkFileName temporary file name to store apk extracted from resources 362 * @param apkResourceId identifier of the apk as a resource 363 */ parsePackage(String apkFileName, int apkResourceId, Function<ParsedPackage, ParsedPackage> converter)364 ParsedPackage parsePackage(String apkFileName, int apkResourceId, 365 Function<ParsedPackage, ParsedPackage> converter) throws Exception { 366 // Copy the resource to a file. 367 File outFile = null; 368 try { 369 outFile = copyRawResourceToFile(apkFileName, apkResourceId); 370 return converter.apply(new TestPackageParser2() 371 .parsePackage(outFile, 0 /* flags */, false)); 372 } finally { 373 if (outFile != null) { 374 outFile.delete(); 375 } 376 } 377 } 378 379 /** 380 * Asserts basic properties about a component. 381 */ assertComponent(String className, int numIntents, ParsedComponent component)382 private void assertComponent(String className, int numIntents, ParsedComponent component) { 383 assertEquals(className, component.getName()); 384 assertEquals(numIntents, component.getIntents().size()); 385 } 386 387 /** 388 * Asserts four regularly-named components of each type: one Activity, one Service, one 389 * Provider, and one Receiver. 390 * 391 * @param template templated string with %s subbed with Activity, Service, Provider, Receiver 392 */ assertOneComponentOfEachType(String template, AndroidPackage p)393 private void assertOneComponentOfEachType(String template, AndroidPackage p) { 394 assertEquals(1, p.getActivities().size()); 395 assertComponent(String.format(template, "Activity"), 396 0 /* intents */, p.getActivities().get(0)); 397 assertEquals(1, p.getServices().size()); 398 assertComponent(String.format(template, "Service"), 399 0 /* intents */, p.getServices().get(0)); 400 assertEquals(1, p.getProviders().size()); 401 assertComponent(String.format(template, "Provider"), 402 0 /* intents */, p.getProviders().get(0)); 403 assertEquals(1, p.getReceivers().size()); 404 assertComponent(String.format(template, "Receiver"), 405 0 /* intents */, p.getReceivers().get(0)); 406 } 407 assertPermission(String name, int protectionLevel, ParsedPermission permission)408 private void assertPermission(String name, int protectionLevel, ParsedPermission permission) { 409 assertEquals(name, permission.getName()); 410 assertEquals(protectionLevel, permission.getProtection()); 411 } 412 assertMetadata(Bundle b, String... keysAndValues)413 private void assertMetadata(Bundle b, String... keysAndValues) { 414 assertTrue("Odd number of elements in keysAndValues", (keysAndValues.length % 2) == 0); 415 416 assertNotNull(b); 417 assertEquals(keysAndValues.length / 2, b.size()); 418 419 for (int i = 0; i < keysAndValues.length; i += 2) { 420 final String key = keysAndValues[i]; 421 final String value = keysAndValues[i + 1]; 422 423 assertEquals(value, b.getString(key)); 424 } 425 } 426 427 // TODO Add a "_cached" test for testMultiPackageComponents() too, after fixing b/64295061. 428 // Package.writeToParcel can't handle circular package references. 429 430 @Test testPackageWithComponents_no_cache()431 public void testPackageWithComponents_no_cache() throws Exception { 432 checkPackageWithComponents(p -> p); 433 } 434 435 @Test testPackageWithComponents_cached()436 public void testPackageWithComponents_cached() throws Exception { 437 checkPackageWithComponents(p -> 438 PackageCacher.fromCacheEntryStatic(PackageCacher.toCacheEntryStatic(p))); 439 } 440 checkPackageWithComponents( Function<ParsedPackage, ParsedPackage> converter)441 private void checkPackageWithComponents( 442 Function<ParsedPackage, ParsedPackage> converter) throws Exception { 443 ParsedPackage p = parsePackage( 444 "install_complete_package_info.apk", R.raw.install_complete_package_info, 445 converter); 446 String packageName = "com.android.frameworks.coretests.install_complete_package_info"; 447 448 assertEquals(packageName, p.getPackageName()); 449 assertEquals(1, p.getPermissions().size()); 450 assertPermission( 451 "com.android.frameworks.coretests.install_complete_package_info.test_permission", 452 PermissionInfo.PROTECTION_NORMAL, p.getPermissions().get(0)); 453 454 findAndRemoveAppDetailsActivity(p); 455 456 assertOneComponentOfEachType("com.android.frameworks.coretests.Test%s", p); 457 458 assertMetadata(p.getMetaData(), 459 "key1", "value1", 460 "key2", "this_is_app"); 461 assertMetadata(p.getActivities().get(0).getMetaData(), 462 "key1", "value1", 463 "key2", "this_is_activity"); 464 assertMetadata(p.getServices().get(0).getMetaData(), 465 "key1", "value1", 466 "key2", "this_is_service"); 467 assertMetadata(p.getReceivers().get(0).getMetaData(), 468 "key1", "value1", 469 "key2", "this_is_receiver"); 470 assertMetadata(p.getProviders().get(0).getMetaData(), 471 "key1", "value1", 472 "key2", "this_is_provider"); 473 474 } 475 findAndRemoveAppDetailsActivity(ParsedPackage p)476 private void findAndRemoveAppDetailsActivity(ParsedPackage p) { 477 // Hidden "app details" activity is added to every package. 478 boolean foundAppDetailsActivity = false; 479 for (int i = 0; i < ArrayUtils.size(p.getActivities()); i++) { 480 if (p.getActivities().get(i).getClassName().equals( 481 PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME)) { 482 foundAppDetailsActivity = true; 483 p.getActivities().remove(i); 484 break; 485 } 486 } 487 assertTrue("Did not find app details activity", foundAppDetailsActivity); 488 } 489 490 @Test testPackageWithIntentFilters_no_cache()491 public void testPackageWithIntentFilters_no_cache() throws Exception { 492 checkPackageWithIntentFilters(p -> p); 493 } 494 495 @Test testPackageWithIntentFilters_cached()496 public void testPackageWithIntentFilters_cached() throws Exception { 497 checkPackageWithIntentFilters(p -> 498 PackageCacher.fromCacheEntryStatic(PackageCacher.toCacheEntryStatic(p))); 499 } 500 checkPackageWithIntentFilters( Function<ParsedPackage, ParsedPackage> converter)501 private void checkPackageWithIntentFilters( 502 Function<ParsedPackage, ParsedPackage> converter) throws Exception { 503 ParsedPackage p = parsePackage( 504 "install_intent_filters.apk", R.raw.install_intent_filters, 505 converter); 506 String packageName = "com.android.frameworks.servicestests.install_intent_filters"; 507 508 assertEquals(packageName, p.getPackageName()); 509 510 findAndRemoveAppDetailsActivity(p); 511 512 assertEquals("Expected exactly one activity", 1, p.getActivities().size()); 513 assertEquals("Expected exactly one intent filter", 514 1, p.getActivities().get(0).getIntents().size()); 515 assertEquals("Expected exactly one mime group in intent filter", 516 1, p.getActivities().get(0).getIntents().get(0).countMimeGroups()); 517 assertTrue("Did not find expected mime group 'mime_group_1'", 518 p.getActivities().get(0).getIntents().get(0).hasMimeGroup("mime_group_1")); 519 } 520 521 @Test testApexPackageInfoGeneration()522 public void testApexPackageInfoGeneration() throws Exception { 523 String apexModuleName = "com.android.tzdata.apex"; 524 File apexFile = copyRawResourceToFile(apexModuleName, 525 R.raw.com_android_tzdata); 526 ApexInfo apexInfo = new ApexInfo(); 527 apexInfo.isActive = true; 528 apexInfo.isFactory = false; 529 apexInfo.moduleName = apexModuleName; 530 apexInfo.modulePath = apexFile.getPath(); 531 apexInfo.versionCode = 191000070; 532 int flags = PackageManager.GET_META_DATA | PackageManager.GET_SIGNING_CERTIFICATES; 533 534 ParseResult<ParsingPackage> result = ParsingPackageUtils.parseDefaultOneTime(apexFile, 535 flags, Collections.emptyList(), false /*collectCertificates*/); 536 if (result.isError()) { 537 throw new IllegalStateException(result.getErrorMessage(), result.getException()); 538 } 539 540 ParsingPackage pkg = result.getResult(); 541 pkg.setSigningDetails(ParsingPackageUtils.getSigningDetails(pkg, false)); 542 PackageInfo pi = PackageInfoWithoutStateUtils.generate(pkg, apexInfo, flags); 543 544 assertEquals("com.google.android.tzdata", pi.applicationInfo.packageName); 545 assertTrue(pi.applicationInfo.enabled); 546 assertEquals(28, pi.applicationInfo.targetSdkVersion); 547 assertEquals(191000070, pi.applicationInfo.longVersionCode); 548 assertNotNull(pi.applicationInfo.metaData); 549 assertEquals(apexFile.getPath(), pi.applicationInfo.sourceDir); 550 assertEquals("Bundle[{com.android.vending.derived.apk.id=1}]", 551 pi.applicationInfo.metaData.toString()); 552 553 assertEquals("com.google.android.tzdata", pi.packageName); 554 assertEquals(191000070, pi.getLongVersionCode()); 555 assertNotNull(pi.signingInfo); 556 assertTrue(pi.signingInfo.getApkContentsSigners().length > 0); 557 assertTrue(pi.isApex); 558 assertTrue((pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0); 559 assertTrue((pi.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) != 0); 560 } 561 562 @Test testUsesSdk()563 public void testUsesSdk() throws Exception { 564 ParsedPackage pkg; 565 SparseIntArray minExtVers; 566 pkg = parsePackage("install_uses_sdk.apk_r0", R.raw.install_uses_sdk_r0, x -> x); 567 minExtVers = pkg.getMinExtensionVersions(); 568 assertEquals(1, minExtVers.size()); 569 assertEquals(0, minExtVers.get(30, -1)); 570 571 pkg = parsePackage("install_uses_sdk.apk_r0_s0", R.raw.install_uses_sdk_r0_s0, x -> x); 572 minExtVers = pkg.getMinExtensionVersions(); 573 assertEquals(2, minExtVers.size()); 574 assertEquals(0, minExtVers.get(30, -1)); 575 assertEquals(0, minExtVers.get(31, -1)); 576 577 Map<Pair<String, Integer>, Integer> appToError = new HashMap<>(); 578 appToError.put(Pair.create("install_uses_sdk.apk_r5", R.raw.install_uses_sdk_r5), 579 PackageManager.INSTALL_FAILED_OLDER_SDK); 580 appToError.put(Pair.create("install_uses_sdk.apk_r0_s5", R.raw.install_uses_sdk_r0_s5), 581 PackageManager.INSTALL_FAILED_OLDER_SDK); 582 583 appToError.put(Pair.create("install_uses_sdk.apk_q0", R.raw.install_uses_sdk_q0), 584 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED); 585 appToError.put(Pair.create("install_uses_sdk.apk_q0_r0", R.raw.install_uses_sdk_q0_r0), 586 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED); 587 appToError.put(Pair.create("install_uses_sdk.apk_r_none", R.raw.install_uses_sdk_r_none), 588 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED); 589 appToError.put(Pair.create("install_uses_sdk.apk_0", R.raw.install_uses_sdk_0), 590 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED); 591 592 for (Map.Entry<Pair<String, Integer>, Integer> entry : appToError.entrySet()) { 593 String filename = entry.getKey().first; 594 int resId = entry.getKey().second; 595 int result = entry.getValue(); 596 try { 597 parsePackage(filename, resId, x -> x); 598 expect.withMessage("Expected parsing error %d from %s", result, filename).fail(); 599 } catch (PackageParser.PackageParserException expected) { 600 expect.that(expected.error).isEqualTo(result); 601 } 602 } 603 } 604 } 605