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