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