1 /* 2 * Copyright (C) 2016 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; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertNotNull; 21 import static org.junit.Assert.assertNull; 22 import static org.junit.Assert.assertTrue; 23 24 import android.apex.ApexInfo; 25 import android.content.Context; 26 import android.content.pm.PackageParser.Component; 27 import android.content.pm.PackageParser.Package; 28 import android.content.pm.PackageParser.Permission; 29 import android.os.Build; 30 import android.os.Bundle; 31 import android.os.FileUtils; 32 import android.os.SystemProperties; 33 34 import androidx.test.InstrumentationRegistry; 35 import androidx.test.filters.SmallTest; 36 import androidx.test.runner.AndroidJUnit4; 37 38 import com.android.frameworks.coretests.R; 39 40 import org.junit.Test; 41 import org.junit.runner.RunWith; 42 43 import java.io.File; 44 import java.io.InputStream; 45 import java.util.Arrays; 46 import java.util.function.Function; 47 48 @SmallTest 49 @RunWith(AndroidJUnit4.class) 50 public class PackageParserTest { 51 private static final String RELEASED = null; 52 private static final String OLDER_PRE_RELEASE = "A"; 53 private static final String PRE_RELEASE = "B"; 54 private static final String NEWER_PRE_RELEASE = "C"; 55 56 // Codenames with a fingerprint attached to them. These may only be present in the apps 57 // declared min SDK and not as platform codenames. 58 private static final String OLDER_PRE_RELEASE_WITH_FINGERPRINT = "A.fingerprint"; 59 private static final String PRE_RELEASE_WITH_FINGERPRINT = "B.fingerprint"; 60 private static final String NEWER_PRE_RELEASE_WITH_FINGERPRINT = "C.fingerprint"; 61 62 private static final String[] CODENAMES_RELEASED = { /* empty */ }; 63 private static final String[] CODENAMES_PRE_RELEASE = { PRE_RELEASE }; 64 65 private static final int OLDER_VERSION = 10; 66 private static final int PLATFORM_VERSION = 20; 67 private static final int NEWER_VERSION = 30; 68 verifyComputeMinSdkVersion(int minSdkVersion, String minSdkCodename, boolean isPlatformReleased, int expectedMinSdk)69 private void verifyComputeMinSdkVersion(int minSdkVersion, String minSdkCodename, 70 boolean isPlatformReleased, int expectedMinSdk) { 71 final String[] outError = new String[1]; 72 final int result = PackageParser.computeMinSdkVersion( 73 minSdkVersion, 74 minSdkCodename, 75 PLATFORM_VERSION, 76 isPlatformReleased ? CODENAMES_RELEASED : CODENAMES_PRE_RELEASE, 77 outError); 78 79 assertEquals("Error msg: " + outError[0], expectedMinSdk, result); 80 81 if (expectedMinSdk == -1) { 82 assertNotNull(outError[0]); 83 } else { 84 assertNull(outError[0]); 85 } 86 } 87 88 @Test testComputeMinSdkVersion_preReleasePlatform()89 public void testComputeMinSdkVersion_preReleasePlatform() { 90 // Do allow older release minSdkVersion on pre-release platform. 91 // APP: Released API 10 92 // DEV: Pre-release API 20 93 verifyComputeMinSdkVersion(OLDER_VERSION, RELEASED, false, OLDER_VERSION); 94 95 // Do allow same release minSdkVersion on pre-release platform. 96 // APP: Released API 20 97 // DEV: Pre-release API 20 98 verifyComputeMinSdkVersion(PLATFORM_VERSION, RELEASED, false, PLATFORM_VERSION); 99 100 // Don't allow newer release minSdkVersion on pre-release platform. 101 // APP: Released API 30 102 // DEV: Pre-release API 20 103 verifyComputeMinSdkVersion(NEWER_VERSION, RELEASED, false, -1); 104 105 // Don't allow older pre-release minSdkVersion on pre-release platform. 106 // APP: Pre-release API 10 107 // DEV: Pre-release API 20 108 verifyComputeMinSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE, false, -1); 109 verifyComputeMinSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE_WITH_FINGERPRINT, false, -1); 110 111 // Do allow same pre-release minSdkVersion on pre-release platform, 112 // but overwrite the specified version with CUR_DEVELOPMENT. 113 // APP: Pre-release API 20 114 // DEV: Pre-release API 20 115 verifyComputeMinSdkVersion(PLATFORM_VERSION, PRE_RELEASE, false, 116 Build.VERSION_CODES.CUR_DEVELOPMENT); 117 verifyComputeMinSdkVersion(PLATFORM_VERSION, PRE_RELEASE_WITH_FINGERPRINT, false, 118 Build.VERSION_CODES.CUR_DEVELOPMENT); 119 120 121 // Don't allow newer pre-release minSdkVersion on pre-release platform. 122 // APP: Pre-release API 30 123 // DEV: Pre-release API 20 124 verifyComputeMinSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, false, -1); 125 verifyComputeMinSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, false, -1); 126 } 127 128 @Test testComputeMinSdkVersion_releasedPlatform()129 public void testComputeMinSdkVersion_releasedPlatform() { 130 // Do allow older release minSdkVersion on released platform. 131 // APP: Released API 10 132 // DEV: Released API 20 133 verifyComputeMinSdkVersion(OLDER_VERSION, RELEASED, true, OLDER_VERSION); 134 135 // Do allow same release minSdkVersion on released platform. 136 // APP: Released API 20 137 // DEV: Released API 20 138 verifyComputeMinSdkVersion(PLATFORM_VERSION, RELEASED, true, PLATFORM_VERSION); 139 140 // Don't allow newer release minSdkVersion on released platform. 141 // APP: Released API 30 142 // DEV: Released API 20 143 verifyComputeMinSdkVersion(NEWER_VERSION, RELEASED, true, -1); 144 145 // Don't allow older pre-release minSdkVersion on released platform. 146 // APP: Pre-release API 10 147 // DEV: Released API 20 148 verifyComputeMinSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE, true, -1); 149 verifyComputeMinSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE_WITH_FINGERPRINT, true, -1); 150 151 // Don't allow same pre-release minSdkVersion on released platform. 152 // APP: Pre-release API 20 153 // DEV: Released API 20 154 verifyComputeMinSdkVersion(PLATFORM_VERSION, PRE_RELEASE, true, -1); 155 verifyComputeMinSdkVersion(PLATFORM_VERSION, PRE_RELEASE_WITH_FINGERPRINT, true, -1); 156 157 158 // Don't allow newer pre-release minSdkVersion on released platform. 159 // APP: Pre-release API 30 160 // DEV: Released API 20 161 verifyComputeMinSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, true, -1); 162 verifyComputeMinSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, true, -1); 163 } 164 verifyComputeTargetSdkVersion(int targetSdkVersion, String targetSdkCodename, boolean isPlatformReleased, int expectedTargetSdk)165 private void verifyComputeTargetSdkVersion(int targetSdkVersion, String targetSdkCodename, 166 boolean isPlatformReleased, int expectedTargetSdk) { 167 final String[] outError = new String[1]; 168 final int result = PackageParser.computeTargetSdkVersion( 169 targetSdkVersion, 170 targetSdkCodename, 171 isPlatformReleased ? CODENAMES_RELEASED : CODENAMES_PRE_RELEASE, 172 outError); 173 174 assertEquals(result, expectedTargetSdk); 175 176 if (expectedTargetSdk == -1) { 177 assertNotNull(outError[0]); 178 } else { 179 assertNull(outError[0]); 180 } 181 } 182 183 @Test testComputeTargetSdkVersion_preReleasePlatform()184 public void testComputeTargetSdkVersion_preReleasePlatform() { 185 // Do allow older release targetSdkVersion on pre-release platform. 186 // APP: Released API 10 187 // DEV: Pre-release API 20 188 verifyComputeTargetSdkVersion(OLDER_VERSION, RELEASED, false, OLDER_VERSION); 189 190 // Do allow same release targetSdkVersion on pre-release platform. 191 // APP: Released API 20 192 // DEV: Pre-release API 20 193 verifyComputeTargetSdkVersion(PLATFORM_VERSION, RELEASED, false, PLATFORM_VERSION); 194 195 // Do allow newer release targetSdkVersion on pre-release platform. 196 // APP: Released API 30 197 // DEV: Pre-release API 20 198 verifyComputeTargetSdkVersion(NEWER_VERSION, RELEASED, false, NEWER_VERSION); 199 200 // Don't allow older pre-release targetSdkVersion on pre-release platform. 201 // APP: Pre-release API 10 202 // DEV: Pre-release API 20 203 verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE, false, -1); 204 verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE_WITH_FINGERPRINT, false, -1); 205 206 207 // Do allow same pre-release targetSdkVersion on pre-release platform, 208 // but overwrite the specified version with CUR_DEVELOPMENT. 209 // APP: Pre-release API 20 210 // DEV: Pre-release API 20 211 verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE, false, 212 Build.VERSION_CODES.CUR_DEVELOPMENT); 213 verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE_WITH_FINGERPRINT, false, 214 Build.VERSION_CODES.CUR_DEVELOPMENT); 215 216 217 // Don't allow newer pre-release targetSdkVersion on pre-release platform. 218 // APP: Pre-release API 30 219 // DEV: Pre-release API 20 220 verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, false, -1); 221 verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, false, -1); 222 } 223 224 @Test testComputeTargetSdkVersion_releasedPlatform()225 public void testComputeTargetSdkVersion_releasedPlatform() { 226 // Do allow older release targetSdkVersion on released platform. 227 // APP: Released API 10 228 // DEV: Released API 20 229 verifyComputeTargetSdkVersion(OLDER_VERSION, RELEASED, true, OLDER_VERSION); 230 231 // Do allow same release targetSdkVersion on released platform. 232 // APP: Released API 20 233 // DEV: Released API 20 234 verifyComputeTargetSdkVersion(PLATFORM_VERSION, RELEASED, true, PLATFORM_VERSION); 235 236 // Do allow newer release targetSdkVersion on released platform. 237 // APP: Released API 30 238 // DEV: Released API 20 239 verifyComputeTargetSdkVersion(NEWER_VERSION, RELEASED, true, NEWER_VERSION); 240 241 // Don't allow older pre-release targetSdkVersion on released platform. 242 // APP: Pre-release API 10 243 // DEV: Released API 20 244 verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE, true, -1); 245 verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE_WITH_FINGERPRINT, true, -1); 246 247 // Don't allow same pre-release targetSdkVersion on released platform. 248 // APP: Pre-release API 20 249 // DEV: Released API 20 250 verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE, true, -1); 251 verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE_WITH_FINGERPRINT, true, -1); 252 253 254 // Don't allow newer pre-release targetSdkVersion on released platform. 255 // APP: Pre-release API 30 256 // DEV: Released API 20 257 verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, true, -1); 258 verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, true, -1); 259 } 260 261 /** 262 * Unit test for PackageParser.getActivityConfigChanges(). 263 * If the bit is 1 in the original configChanges, it is still 1 in the final configChanges. 264 * If the bit is 0 in the original configChanges and the bit is not set to 1 in 265 * recreateOnConfigChanges, the bit is changed to 1 in the final configChanges by default. 266 */ 267 @Test testGetActivityConfigChanges()268 public void testGetActivityConfigChanges() { 269 // Not set in either configChanges or recreateOnConfigChanges. 270 int configChanges = 0x0000; // 00000000. 271 int recreateOnConfigChanges = 0x0000; // 00000000. 272 int finalConfigChanges = 273 PackageParser.getActivityConfigChanges(configChanges, recreateOnConfigChanges); 274 assertEquals(0x0003, finalConfigChanges); // Should be 00000011. 275 276 // Not set in configChanges, but set in recreateOnConfigChanges. 277 configChanges = 0x0000; // 00000000. 278 recreateOnConfigChanges = 0x0003; // 00000011. 279 finalConfigChanges = 280 PackageParser.getActivityConfigChanges(configChanges, recreateOnConfigChanges); 281 assertEquals(0x0000, finalConfigChanges); // Should be 00000000. 282 283 // Set in configChanges. 284 configChanges = 0x0003; // 00000011. 285 recreateOnConfigChanges = 0X0000; // 00000000. 286 finalConfigChanges = 287 PackageParser.getActivityConfigChanges(configChanges, recreateOnConfigChanges); 288 assertEquals(0x0003, finalConfigChanges); // Should be 00000011. 289 290 recreateOnConfigChanges = 0x0003; // 00000011. 291 finalConfigChanges = 292 PackageParser.getActivityConfigChanges(configChanges, recreateOnConfigChanges); 293 assertEquals(0x0003, finalConfigChanges); // Should still be 00000011. 294 295 // Other bit set in configChanges. 296 configChanges = 0x0080; // 10000000, orientation. 297 recreateOnConfigChanges = 0x0000; // 00000000. 298 finalConfigChanges = 299 PackageParser.getActivityConfigChanges(configChanges, recreateOnConfigChanges); 300 assertEquals(0x0083, finalConfigChanges); // Should be 10000011. 301 } 302 parsePackage(String apkFileName, int apkResourceId)303 Package parsePackage(String apkFileName, int apkResourceId) throws Exception { 304 return parsePackage(apkFileName, apkResourceId, p -> p); 305 } 306 307 /** 308 * Copies a specified {@code resourceId} to a file. Returns a non-null file if the copy 309 * succeeded, or {@code null} otherwise. 310 */ copyRawResourceToFile(String baseName, int resourceId)311 File copyRawResourceToFile(String baseName, int resourceId) throws Exception { 312 // Copy the resource to a file. 313 Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); 314 InputStream is = context.getResources().openRawResource(resourceId); 315 File outFile = null; 316 try { 317 outFile = new File(context.getFilesDir(), baseName); 318 assertTrue(FileUtils.copyToFile(is, outFile)); 319 return outFile; 320 } catch (Exception e) { 321 if (outFile != null) { 322 outFile.delete(); 323 } 324 325 return null; 326 } 327 } 328 329 /** 330 * Attempts to parse a package. 331 * 332 * APKs are put into coretests/apks/packageparser_*. 333 * 334 * @param apkFileName temporary file name to store apk extracted from resources 335 * @param apkResourceId identifier of the apk as a resource 336 */ parsePackage(String apkFileName, int apkResourceId, Function<Package, Package> converter)337 Package parsePackage(String apkFileName, int apkResourceId, 338 Function<Package, Package> converter) throws Exception { 339 // Copy the resource to a file. 340 File outFile = null; 341 try { 342 outFile = copyRawResourceToFile(apkFileName, apkResourceId); 343 return converter.apply(new PackageParser().parsePackage(outFile, 0 /* flags */)); 344 } finally { 345 if (outFile != null) { 346 outFile.delete(); 347 } 348 } 349 } 350 351 /** 352 * Asserts basic properties about a component. 353 */ assertComponent(String className, String packageName, int numIntents, Component<?> component)354 private void assertComponent(String className, String packageName, int numIntents, 355 Component<?> component) { 356 assertEquals(className, component.className); 357 assertEquals(packageName, component.owner.packageName); 358 assertEquals(numIntents, component.intents.size()); 359 } 360 361 /** 362 * Asserts four regularly-named components of each type: one Activity, one Service, one 363 * Provider, and one Receiver. 364 * @param template templated string with %s subbed with Activity, Service, Provider, Receiver 365 */ assertOneComponentOfEachType(String template, Package p)366 private void assertOneComponentOfEachType(String template, Package p) { 367 String packageName = p.packageName; 368 369 assertEquals(1, p.activities.size()); 370 assertComponent(String.format(template, "Activity"), 371 packageName, 0 /* intents */, p.activities.get(0)); 372 assertEquals(1, p.services.size()); 373 assertComponent(String.format(template, "Service"), 374 packageName, 0 /* intents */, p.services.get(0)); 375 assertEquals(1, p.providers.size()); 376 assertComponent(String.format(template, "Provider"), 377 packageName, 0 /* intents */, p.providers.get(0)); 378 assertEquals(1, p.receivers.size()); 379 assertComponent(String.format(template, "Receiver"), 380 packageName, 0 /* intents */, p.receivers.get(0)); 381 } 382 assertPermission(String name, String packageName, int protectionLevel, Permission permission)383 private void assertPermission(String name, String packageName, int protectionLevel, 384 Permission permission) { 385 assertEquals(packageName, permission.owner.packageName); 386 assertEquals(name, permission.info.name); 387 assertEquals(protectionLevel, permission.info.protectionLevel); 388 } 389 assertMetadata(Bundle b, String... keysAndValues)390 private void assertMetadata(Bundle b, String... keysAndValues) { 391 assertTrue("Odd number of elements in keysAndValues", (keysAndValues.length % 2) == 0); 392 393 assertNotNull(b); 394 assertEquals(keysAndValues.length / 2, b.size()); 395 396 for (int i = 0; i < keysAndValues.length; i += 2) { 397 final String key = keysAndValues[i]; 398 final String value = keysAndValues[i + 1]; 399 400 assertEquals(value, b.getString(key)); 401 } 402 } 403 404 // TODO Add a "_cached" test for testMultiPackageComponents() too, after fixing b/64295061. 405 // Package.writeToParcel can't handle circular package references. 406 407 @Test testPackageWithComponents_no_cache()408 public void testPackageWithComponents_no_cache() throws Exception { 409 checkPackageWithComponents(p -> p); 410 } 411 412 @Test testPackageWithComponents_cached()413 public void testPackageWithComponents_cached() throws Exception { 414 checkPackageWithComponents(p -> 415 PackageParser.fromCacheEntryStatic(PackageParser.toCacheEntryStatic(p))); 416 } 417 checkPackageWithComponents( Function<Package, Package> converter)418 private void checkPackageWithComponents( 419 Function<Package, Package> converter) throws Exception { 420 Package p = parsePackage( 421 "install_complete_package_info.apk", R.raw.install_complete_package_info, 422 converter); 423 String packageName = "com.android.frameworks.coretests.install_complete_package_info"; 424 425 assertEquals(packageName, p.packageName); 426 assertEquals(1, p.permissions.size()); 427 assertPermission( 428 "com.android.frameworks.coretests.install_complete_package_info.test_permission", 429 packageName, PermissionInfo.PROTECTION_NORMAL, p.permissions.get(0)); 430 431 assertOneComponentOfEachType("com.android.frameworks.coretests.Test%s", p); 432 433 assertMetadata(p.mAppMetaData, 434 "key1", "value1", 435 "key2", "this_is_app"); 436 assertMetadata(p.activities.get(0).metaData, 437 "key1", "value1", 438 "key2", "this_is_activity"); 439 assertMetadata(p.services.get(0).metaData, 440 "key1", "value1", 441 "key2", "this_is_service"); 442 assertMetadata(p.receivers.get(0).metaData, 443 "key1", "value1", 444 "key2", "this_is_receiver"); 445 assertMetadata(p.providers.get(0).metaData, 446 "key1", "value1", 447 "key2", "this_is_provider"); 448 } 449 450 /** 451 * Determines if the current device supports multi-package APKs. 452 */ supportsMultiPackageApk()453 private boolean supportsMultiPackageApk() { 454 return SystemProperties.getBoolean("persist.sys.child_packages_enabled", false); 455 } 456 457 @Test testMultiPackageComponents()458 public void testMultiPackageComponents() throws Exception { 459 // TODO(gboyer): Remove once we decide to launch multi-package APKs. 460 if (!supportsMultiPackageApk()) { 461 return; 462 } 463 String parentName = "com.android.frameworks.coretests.install_multi_package"; 464 String firstChildName = 465 "com.android.frameworks.coretests.install_multi_package.first_child"; 466 String secondChildName = // NOTE: intentionally inconsistent! 467 "com.android.frameworks.coretests.blah.second_child"; 468 469 Package parent = parsePackage("install_multi_package.apk", R.raw.install_multi_package); 470 assertEquals(parentName, parent.packageName); 471 assertEquals(2, parent.childPackages.size()); 472 assertOneComponentOfEachType("com.android.frameworks.coretests.Test%s", parent); 473 assertEquals(1, parent.permissions.size()); 474 assertPermission(parentName + ".test_permission", parentName, 475 PermissionInfo.PROTECTION_NORMAL, parent.permissions.get(0)); 476 assertEquals(Arrays.asList("android.permission.INTERNET"), 477 parent.requestedPermissions); 478 479 Package firstChild = parent.childPackages.get(0); 480 assertEquals(firstChildName, firstChild.packageName); 481 assertOneComponentOfEachType( 482 "com.android.frameworks.coretests.FirstChildTest%s", firstChild); 483 assertEquals(0, firstChild.permissions.size()); // Child APKs cannot declare permissions. 484 assertEquals(Arrays.asList("android.permission.NFC"), 485 firstChild.requestedPermissions); 486 487 Package secondChild = parent.childPackages.get(1); 488 assertEquals(secondChildName, secondChild.packageName); 489 assertOneComponentOfEachType( 490 "com.android.frameworks.coretests.SecondChildTest%s", secondChild); 491 assertEquals(0, secondChild.permissions.size()); // Child APKs cannot declare permissions. 492 assertEquals( 493 Arrays.asList( 494 "android.permission.ACCESS_NETWORK_STATE", 495 "android.permission.READ_CONTACTS"), 496 secondChild.requestedPermissions); 497 } 498 499 @Test testApexPackageInfoGeneration()500 public void testApexPackageInfoGeneration() throws Exception { 501 String apexPackageName = "com.android.tzdata.apex"; 502 File apexFile = copyRawResourceToFile(apexPackageName, 503 R.raw.com_android_tzdata); 504 ApexInfo apexInfo = new ApexInfo(); 505 apexInfo.isActive = true; 506 apexInfo.isFactory = false; 507 apexInfo.packageName = apexPackageName; 508 apexInfo.packagePath = apexFile.getPath(); 509 apexInfo.versionCode = 191000070; 510 int flags = PackageManager.GET_META_DATA | PackageManager.GET_SIGNING_CERTIFICATES; 511 PackageInfo pi = PackageParser.generatePackageInfoFromApex(apexInfo, flags); 512 assertEquals("com.google.android.tzdata", pi.applicationInfo.packageName); 513 assertTrue(pi.applicationInfo.enabled); 514 assertEquals(28, pi.applicationInfo.targetSdkVersion); 515 assertEquals(191000070, pi.applicationInfo.longVersionCode); 516 assertNotNull(pi.applicationInfo.metaData); 517 assertEquals(apexFile.getPath(), pi.applicationInfo.sourceDir); 518 assertEquals("Bundle[{com.android.vending.derived.apk.id=1}]", 519 pi.applicationInfo.metaData.toString()); 520 521 assertEquals("com.google.android.tzdata", pi.packageName); 522 assertEquals(191000070, pi.getLongVersionCode()); 523 assertNotNull(pi.signingInfo); 524 assertTrue(pi.signingInfo.getApkContentsSigners().length > 0); 525 assertTrue(pi.isApex); 526 assertTrue((pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0); 527 assertTrue((pi.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) != 0); 528 } 529 } 530