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 package com.android.server.pm; 17 18 import static com.android.server.pm.permission.CompatibilityPermissionInfo.COMPAT_PERMS; 19 20 import static com.google.common.truth.Truth.assertThat; 21 import static com.google.common.truth.Truth.assertWithMessage; 22 23 import static org.junit.Assert.assertArrayEquals; 24 import static org.junit.Assert.assertEquals; 25 import static org.junit.Assert.assertFalse; 26 import static org.junit.Assert.assertNotEquals; 27 import static org.junit.Assert.assertNotNull; 28 import static org.junit.Assert.assertNull; 29 import static org.junit.Assert.assertSame; 30 import static org.junit.Assert.assertTrue; 31 import static org.junit.Assert.fail; 32 33 import static java.lang.Boolean.TRUE; 34 import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; 35 import static java.util.stream.Collectors.toList; 36 37 import android.annotation.NonNull; 38 import android.content.Context; 39 import android.content.pm.ActivityInfo; 40 import android.content.pm.ApplicationInfo; 41 import android.content.pm.ConfigurationInfo; 42 import android.content.pm.FeatureGroupInfo; 43 import android.content.pm.FeatureInfo; 44 import android.content.pm.PackageInfo; 45 import android.content.pm.PackageManager.Property; 46 import android.content.pm.ServiceInfo; 47 import android.content.pm.Signature; 48 import android.content.pm.SigningDetails; 49 import android.os.Bundle; 50 import android.os.Parcel; 51 import android.os.Parcelable; 52 import android.platform.test.annotations.Presubmit; 53 import android.util.ArraySet; 54 55 import androidx.annotation.Nullable; 56 import androidx.test.InstrumentationRegistry; 57 import androidx.test.filters.MediumTest; 58 import androidx.test.filters.SmallTest; 59 import androidx.test.runner.AndroidJUnit4; 60 61 import com.android.internal.util.ArrayUtils; 62 import com.android.server.pm.parsing.PackageCacher; 63 import com.android.server.pm.parsing.PackageInfoUtils; 64 import com.android.server.pm.parsing.PackageParser2; 65 import com.android.server.pm.parsing.TestPackageParser2; 66 import com.android.server.pm.parsing.pkg.AndroidPackageUtils; 67 import com.android.server.pm.parsing.pkg.PackageImpl; 68 import com.android.server.pm.parsing.pkg.ParsedPackage; 69 import com.android.server.pm.permission.CompatibilityPermissionInfo; 70 import com.android.server.pm.pkg.AndroidPackage; 71 import com.android.server.pm.pkg.PackageUserStateInternal; 72 import com.android.server.pm.pkg.component.ParsedActivity; 73 import com.android.server.pm.pkg.component.ParsedActivityImpl; 74 import com.android.server.pm.pkg.component.ParsedApexSystemService; 75 import com.android.server.pm.pkg.component.ParsedComponent; 76 import com.android.server.pm.pkg.component.ParsedInstrumentation; 77 import com.android.server.pm.pkg.component.ParsedInstrumentationImpl; 78 import com.android.server.pm.pkg.component.ParsedIntentInfo; 79 import com.android.server.pm.pkg.component.ParsedIntentInfoImpl; 80 import com.android.server.pm.pkg.component.ParsedPermission; 81 import com.android.server.pm.pkg.component.ParsedPermissionGroup; 82 import com.android.server.pm.pkg.component.ParsedPermissionGroupImpl; 83 import com.android.server.pm.pkg.component.ParsedPermissionImpl; 84 import com.android.server.pm.pkg.component.ParsedPermissionUtils; 85 import com.android.server.pm.pkg.component.ParsedProvider; 86 import com.android.server.pm.pkg.component.ParsedProviderImpl; 87 import com.android.server.pm.pkg.component.ParsedService; 88 import com.android.server.pm.pkg.component.ParsedServiceImpl; 89 import com.android.server.pm.pkg.component.ParsedUsesPermission; 90 import com.android.server.pm.pkg.component.ParsedUsesPermissionImpl; 91 import com.android.server.pm.pkg.parsing.ParsingPackage; 92 93 import org.junit.Before; 94 import org.junit.Rule; 95 import org.junit.Test; 96 import org.junit.rules.TemporaryFolder; 97 import org.junit.runner.RunWith; 98 99 import java.io.File; 100 import java.io.IOException; 101 import java.io.InputStream; 102 import java.lang.reflect.Array; 103 import java.lang.reflect.Field; 104 import java.nio.file.Files; 105 import java.util.ArrayList; 106 import java.util.Arrays; 107 import java.util.Collections; 108 import java.util.HashSet; 109 import java.util.Iterator; 110 import java.util.List; 111 import java.util.Map; 112 import java.util.Set; 113 114 @Presubmit 115 @RunWith(AndroidJUnit4.class) 116 @MediumTest 117 public class PackageParserTest { 118 // TODO(b/135203078): Update this test with all fields and validate equality. Initial change 119 // was just migrating to new interfaces. Consider adding actual equals() methods. 120 121 @Rule 122 public TemporaryFolder mTemporaryFolder = new TemporaryFolder(); 123 124 private File mTmpDir; 125 private static final File FRAMEWORK = new File("/system/framework/framework-res.apk"); 126 private static final String TEST_APP1_APK = "PackageParserTestApp1.apk"; 127 private static final String TEST_APP2_APK = "PackageParserTestApp2.apk"; 128 private static final String TEST_APP3_APK = "PackageParserTestApp3.apk"; 129 private static final String TEST_APP4_APK = "PackageParserTestApp4.apk"; 130 private static final String TEST_APP5_APK = "PackageParserTestApp5.apk"; 131 private static final String TEST_APP6_APK = "PackageParserTestApp6.apk"; 132 private static final String PACKAGE_NAME = "com.android.servicestests.apps.packageparserapp"; 133 134 @Before setUp()135 public void setUp() throws IOException { 136 // Create a new temporary directory for each of our tests. 137 mTmpDir = mTemporaryFolder.newFolder("PackageParserTest"); 138 } 139 140 @Test testParse_noCache()141 public void testParse_noCache() throws Exception { 142 CachePackageNameParser pp = new CachePackageNameParser(null); 143 ParsedPackage pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, 144 false /* useCaches */); 145 assertNotNull(pkg); 146 147 pp.setCacheDir(mTmpDir); 148 pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, 149 false /* useCaches */); 150 assertNotNull(pkg); 151 152 // Make sure that we always write out a cache entry for future reference, 153 // whether or not we're asked to use caches. 154 assertEquals(1, mTmpDir.list().length); 155 } 156 157 @Test testParse_withCache()158 public void testParse_withCache() throws Exception { 159 CachePackageNameParser pp = new CachePackageNameParser(null); 160 161 pp.setCacheDir(mTmpDir); 162 // The first parse will write this package to the cache. 163 pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, true /* useCaches */); 164 165 // Now attempt to parse the package again, should return the 166 // cached result. 167 ParsedPackage pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, 168 true /* useCaches */); 169 assertEquals("cache_android", pkg.getPackageName()); 170 171 // Try again, with useCaches == false, shouldn't return the parsed 172 // result. 173 pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, false /* useCaches */); 174 assertEquals("android", pkg.getPackageName()); 175 176 // We haven't set a cache directory here : the parse should still succeed, 177 // just not using the cached results. 178 pp = new CachePackageNameParser(null); 179 pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, true /* useCaches */); 180 assertEquals("android", pkg.getPackageName()); 181 182 pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, false /* useCaches */); 183 assertEquals("android", pkg.getPackageName()); 184 } 185 186 @Test test_serializePackage()187 public void test_serializePackage() throws Exception { 188 try (PackageParser2 pp = PackageParser2.forParsingFileWithDefaults()) { 189 AndroidPackage pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, 190 true /* useCaches */).hideAsFinal(); 191 192 Parcel p = Parcel.obtain(); 193 ((Parcelable) pkg).writeToParcel(p, 0 /* flags */); 194 195 p.setDataPosition(0); 196 ParsedPackage deserialized = new PackageImpl(p); 197 198 assertPackagesEqual(pkg, deserialized); 199 } 200 } 201 202 @Test 203 @SmallTest 204 @Presubmit test_roundTripKnownFields()205 public void test_roundTripKnownFields() throws Exception { 206 ParsingPackage pkg = PackageImpl.forTesting("foo"); 207 setKnownFields(pkg); 208 209 Parcel p = Parcel.obtain(); 210 ((Parcelable) pkg).writeToParcel(p, 0 /* flags */); 211 212 p.setDataPosition(0); 213 ParsedPackage deserialized = new PackageImpl(p); 214 assertAllFieldsExist(deserialized); 215 } 216 217 @Test test_stringInterning()218 public void test_stringInterning() throws Exception { 219 ParsingPackage pkg = PackageImpl.forTesting("foo"); 220 setKnownFields(pkg); 221 222 Parcel p = Parcel.obtain(); 223 ((Parcelable) pkg.hideAsParsed().hideAsFinal()).writeToParcel(p, 0 /* flags */); 224 225 p.setDataPosition(0); 226 AndroidPackage deserialized = new PackageImpl(p); 227 228 p.setDataPosition(0); 229 AndroidPackage deserialized2 = new PackageImpl(p); 230 231 assertSame(deserialized.getPackageName(), deserialized2.getPackageName()); 232 assertSame(deserialized.getPermission(), 233 deserialized2.getPermission()); 234 assertSame(deserialized.getRequestedPermissions().get(0), 235 deserialized2.getRequestedPermissions().get(0)); 236 237 List<String> protectedBroadcastsOne = new ArrayList<>(1); 238 protectedBroadcastsOne.addAll(deserialized.getProtectedBroadcasts()); 239 240 List<String> protectedBroadcastsTwo = new ArrayList<>(1); 241 protectedBroadcastsTwo.addAll(deserialized2.getProtectedBroadcasts()); 242 243 assertSame(protectedBroadcastsOne.get(0), protectedBroadcastsTwo.get(0)); 244 245 assertSame(deserialized.getUsesLibraries().get(0), 246 deserialized2.getUsesLibraries().get(0)); 247 assertSame(deserialized.getUsesOptionalLibraries().get(0), 248 deserialized2.getUsesOptionalLibraries().get(0)); 249 assertSame(deserialized.getVersionName(), deserialized2.getVersionName()); 250 assertSame(deserialized.getSharedUserId(), deserialized2.getSharedUserId()); 251 } 252 extractFile(String filename)253 private File extractFile(String filename) throws Exception { 254 final Context context = InstrumentationRegistry.getTargetContext(); 255 final File tmpFile = File.createTempFile(filename, ".apk"); 256 try (InputStream inputStream = context.getAssets().openNonAsset(filename)) { 257 Files.copy(inputStream, tmpFile.toPath(), REPLACE_EXISTING); 258 } 259 return tmpFile; 260 } 261 262 /** 263 * Extracts the asset file to $mTmpDir/$dirname/$filename. 264 */ extractFile(String filename, String dirname)265 private File extractFile(String filename, String dirname) throws Exception { 266 final Context context = InstrumentationRegistry.getTargetContext(); 267 File dir = new File(mTmpDir, dirname); 268 dir.mkdir(); 269 final File tmpFile = new File(dir, filename); 270 try (InputStream inputStream = context.getAssets().openNonAsset(filename)) { 271 Files.copy(inputStream, tmpFile.toPath(), REPLACE_EXISTING); 272 } 273 return tmpFile; 274 } 275 276 /** 277 * Tests the path of cached ParsedPackage. 278 */ 279 @Test testCache_SameFileName()280 public void testCache_SameFileName() throws Exception { 281 // Prepare 2 package files with the same name but different paths 282 TestPackageParser2 parser = new TestPackageParser2(mTmpDir); 283 final File f1 = extractFile(TEST_APP1_APK, "dir1"); 284 final File f2 = extractFile(TEST_APP1_APK, "dir2"); 285 // Sleep for a while so that the cache file will be newer and valid 286 Thread.sleep(1000); 287 ParsedPackage pr1 = parser.parsePackage(f1, 0, true); 288 ParsedPackage pr2 = parser.parsePackage(f2, 0, true); 289 // Check the path of cached ParsedPackage 290 assertThat(pr1.getPath()).isEqualTo(f1.getAbsolutePath()); 291 assertThat(pr2.getPath()).isEqualTo(f2.getAbsolutePath()); 292 } 293 294 /** 295 * Tests AndroidManifest.xml with no android:isolatedSplits attribute. 296 */ 297 @Test testParseIsolatedSplitsDefault()298 public void testParseIsolatedSplitsDefault() throws Exception { 299 final File testFile = extractFile(TEST_APP1_APK); 300 try { 301 final ParsedPackage pkg = new TestPackageParser2().parsePackage(testFile, 0, false); 302 assertFalse("isolatedSplits", pkg.isIsolatedSplitLoading()); 303 } finally { 304 testFile.delete(); 305 } 306 } 307 308 /** 309 * Tests AndroidManifest.xml with an android:isolatedSplits attribute set to a constant. 310 */ 311 @Test testParseIsolatedSplitsConstant()312 public void testParseIsolatedSplitsConstant() throws Exception { 313 final File testFile = extractFile(TEST_APP2_APK); 314 try { 315 final ParsedPackage pkg = new TestPackageParser2().parsePackage(testFile, 0, false); 316 assertTrue("isolatedSplits", pkg.isIsolatedSplitLoading()); 317 } finally { 318 testFile.delete(); 319 } 320 } 321 322 /** 323 * Tests AndroidManifest.xml with an android:isolatedSplits attribute set to a resource. 324 */ 325 @Test testParseIsolatedSplitsResource()326 public void testParseIsolatedSplitsResource() throws Exception { 327 final File testFile = extractFile(TEST_APP3_APK); 328 try { 329 final ParsedPackage pkg = new TestPackageParser2().parsePackage(testFile, 0, false); 330 assertTrue("isolatedSplits", pkg.isIsolatedSplitLoading()); 331 } finally { 332 testFile.delete(); 333 } 334 } 335 336 @Test testParseActivityRequiredDisplayCategoryValid()337 public void testParseActivityRequiredDisplayCategoryValid() throws Exception { 338 final File testFile = extractFile(TEST_APP4_APK); 339 String actualDisplayCategory = null; 340 try { 341 final ParsedPackage pkg = new TestPackageParser2().parsePackage(testFile, 0, false); 342 final List<ParsedActivity> activities = pkg.getActivities(); 343 for (ParsedActivity activity : activities) { 344 if ((PACKAGE_NAME + ".MyActivity").equals(activity.getName())) { 345 actualDisplayCategory = activity.getRequiredDisplayCategory(); 346 } 347 } 348 } finally { 349 testFile.delete(); 350 } 351 assertEquals("automotive", actualDisplayCategory); 352 } 353 354 @Test testParseActivityRequiredDisplayCategoryInvalid()355 public void testParseActivityRequiredDisplayCategoryInvalid() throws Exception { 356 final File testFile = extractFile(TEST_APP6_APK); 357 String actualDisplayCategory = null; 358 try { 359 final ParsedPackage pkg = new TestPackageParser2().parsePackage(testFile, 0, false); 360 final List<ParsedActivity> activities = pkg.getActivities(); 361 for (ParsedActivity activity : activities) { 362 if ((PACKAGE_NAME + ".MyActivity").equals(activity.getName())) { 363 actualDisplayCategory = activity.getRequiredDisplayCategory(); 364 } 365 } 366 } catch (PackageManagerException e) { 367 assertThat(e.getMessage()).contains( 368 "requiredDisplayCategory attribute can only consist" 369 + " of alphanumeric characters, '_', and '.'"); 370 } finally { 371 testFile.delete(); 372 } 373 assertNotEquals("$automotive", actualDisplayCategory); 374 } 375 376 private static final int PROPERTY_TYPE_BOOLEAN = 1; 377 private static final int PROPERTY_TYPE_FLOAT = 2; 378 private static final int PROPERTY_TYPE_INTEGER = 3; 379 private static final int PROPERTY_TYPE_RESOURCE = 4; 380 private static final int PROPERTY_TYPE_STRING = 5; assertProperty(Map<String, Property> properties, String propertyName, int propertyType, Object propertyValue)381 public void assertProperty(Map<String, Property> properties, String propertyName, 382 int propertyType, Object propertyValue) { 383 assertTrue(properties.containsKey(propertyName)); 384 385 final Property testProperty = properties.get(propertyName); 386 assertEquals(propertyType, testProperty.getType()); 387 388 if (propertyType == PROPERTY_TYPE_BOOLEAN) { 389 assertTrue(testProperty.isBoolean()); 390 assertFalse(testProperty.isFloat()); 391 assertFalse(testProperty.isInteger()); 392 assertFalse(testProperty.isResourceId()); 393 assertFalse(testProperty.isString()); 394 395 // assert the property's type is set correctly 396 final Boolean boolValue = (Boolean) propertyValue; 397 if (boolValue.booleanValue()) { 398 assertTrue(testProperty.getBoolean()); 399 } else { 400 assertFalse(testProperty.getBoolean()); 401 } 402 // assert the other values have an appropriate default 403 assertEquals(0.0f, testProperty.getFloat(), 0.0f); 404 assertEquals(0, testProperty.getInteger()); 405 assertEquals(0, testProperty.getResourceId()); 406 assertEquals(null, testProperty.getString()); 407 } else if (propertyType == PROPERTY_TYPE_FLOAT) { 408 assertFalse(testProperty.isBoolean()); 409 assertTrue(testProperty.isFloat()); 410 assertFalse(testProperty.isInteger()); 411 assertFalse(testProperty.isResourceId()); 412 assertFalse(testProperty.isString()); 413 414 // assert the property's type is set correctly 415 final Float floatValue = (Float) propertyValue; 416 assertEquals(floatValue.floatValue(), testProperty.getFloat(), 0.0f); 417 // assert the other values have an appropriate default 418 assertFalse(testProperty.getBoolean()); 419 assertEquals(0, testProperty.getInteger()); 420 assertEquals(0, testProperty.getResourceId()); 421 assertEquals(null, testProperty.getString()); 422 } else if (propertyType == PROPERTY_TYPE_INTEGER) { 423 assertFalse(testProperty.isBoolean()); 424 assertFalse(testProperty.isFloat()); 425 assertTrue(testProperty.isInteger()); 426 assertFalse(testProperty.isResourceId()); 427 assertFalse(testProperty.isString()); 428 429 // assert the property's type is set correctly 430 final Integer integerValue = (Integer) propertyValue; 431 assertEquals(integerValue.intValue(), testProperty.getInteger()); 432 // assert the other values have an appropriate default 433 assertFalse(testProperty.getBoolean()); 434 assertEquals(0.0f, testProperty.getFloat(), 0.0f); 435 assertEquals(0, testProperty.getResourceId()); 436 assertEquals(null, testProperty.getString()); 437 } else if (propertyType == PROPERTY_TYPE_RESOURCE) { 438 assertFalse(testProperty.isBoolean()); 439 assertFalse(testProperty.isFloat()); 440 assertFalse(testProperty.isInteger()); 441 assertTrue(testProperty.isResourceId()); 442 assertFalse(testProperty.isString()); 443 444 // assert the property's type is set correctly 445 final Integer resourceValue = (Integer) propertyValue; 446 assertEquals(resourceValue.intValue(), testProperty.getResourceId()); 447 // assert the other values have an appropriate default 448 assertFalse(testProperty.getBoolean()); 449 assertEquals(0.0f, testProperty.getFloat(), 0.0f); 450 assertEquals(0, testProperty.getInteger()); 451 assertEquals(null, testProperty.getString()); 452 } else if (propertyType == PROPERTY_TYPE_STRING) { 453 assertFalse(testProperty.isBoolean()); 454 assertFalse(testProperty.isFloat()); 455 assertFalse(testProperty.isInteger()); 456 assertFalse(testProperty.isResourceId()); 457 assertTrue(testProperty.isString()); 458 459 // assert the property's type is set correctly 460 final String stringValue = (String) propertyValue; 461 assertEquals(stringValue, testProperty.getString()); 462 // assert the other values have an appropriate default 463 assertFalse(testProperty.getBoolean()); 464 assertEquals(0.0f, testProperty.getFloat(), 0.0f); 465 assertEquals(0, testProperty.getInteger()); 466 assertEquals(0, testProperty.getResourceId()); 467 } else { 468 fail("Unknown property type"); 469 } 470 } 471 472 @Test testParseApplicationProperties()473 public void testParseApplicationProperties() throws Exception { 474 final File testFile = extractFile(TEST_APP4_APK); 475 try { 476 final ParsedPackage pkg = new TestPackageParser2().parsePackage(testFile, 0, false); 477 final Map<String, Property> properties = pkg.getProperties(); 478 assertEquals(10, properties.size()); 479 assertProperty(properties, 480 "android.cts.PROPERTY_RESOURCE_XML", PROPERTY_TYPE_RESOURCE, 0x7f060000); 481 assertProperty(properties, 482 "android.cts.PROPERTY_RESOURCE_INTEGER", PROPERTY_TYPE_RESOURCE, 0x7f040000); 483 assertProperty(properties, 484 "android.cts.PROPERTY_BOOLEAN", PROPERTY_TYPE_BOOLEAN, TRUE); 485 assertProperty(properties, 486 "android.cts.PROPERTY_BOOLEAN_VIA_RESOURCE", PROPERTY_TYPE_BOOLEAN, TRUE); 487 assertProperty(properties, 488 "android.cts.PROPERTY_FLOAT", PROPERTY_TYPE_FLOAT, 3.14f); 489 assertProperty(properties, 490 "android.cts.PROPERTY_FLOAT_VIA_RESOURCE", PROPERTY_TYPE_FLOAT, 2.718f); 491 assertProperty(properties, 492 "android.cts.PROPERTY_INTEGER", PROPERTY_TYPE_INTEGER, 42); 493 assertProperty(properties, 494 "android.cts.PROPERTY_INTEGER_VIA_RESOURCE", PROPERTY_TYPE_INTEGER, 123); 495 assertProperty(properties, 496 "android.cts.PROPERTY_STRING", PROPERTY_TYPE_STRING, "koala"); 497 assertProperty(properties, 498 "android.cts.PROPERTY_STRING_VIA_RESOURCE", PROPERTY_TYPE_STRING, "giraffe"); 499 } finally { 500 testFile.delete(); 501 } 502 } 503 504 @Test testParseActivityProperties()505 public void testParseActivityProperties() throws Exception { 506 final File testFile = extractFile(TEST_APP4_APK); 507 try { 508 final ParsedPackage pkg = new TestPackageParser2().parsePackage(testFile, 0, false); 509 final List<ParsedActivity> activities = pkg.getActivities(); 510 for (ParsedActivity activity : activities) { 511 final Map<String, Property> properties = activity.getProperties(); 512 if ((PACKAGE_NAME + ".MyActivityAlias").equals(activity.getName())) { 513 assertEquals(2, properties.size()); 514 assertProperty(properties, 515 "android.cts.PROPERTY_ACTIVITY_ALIAS", PROPERTY_TYPE_INTEGER, 123); 516 assertProperty(properties, 517 "android.cts.PROPERTY_COMPONENT", PROPERTY_TYPE_INTEGER, 123); 518 } else if ((PACKAGE_NAME + ".MyActivity").equals(activity.getName())) { 519 assertEquals(3, properties.size()); 520 assertProperty(properties, 521 "android.cts.PROPERTY_ACTIVITY", PROPERTY_TYPE_INTEGER, 123); 522 assertProperty(properties, 523 "android.cts.PROPERTY_COMPONENT", PROPERTY_TYPE_INTEGER, 123); 524 assertProperty(properties, 525 "android.cts.PROPERTY_STRING", PROPERTY_TYPE_STRING, "koala activity"); 526 } else if ("android.app.AppDetailsActivity".equals(activity.getName())) { 527 // ignore default added activity 528 } else { 529 fail("Found unknown activity; name = " + activity.getName()); 530 } 531 } 532 } finally { 533 testFile.delete(); 534 } 535 } 536 537 @Test testParseProviderProperties()538 public void testParseProviderProperties() throws Exception { 539 final File testFile = extractFile(TEST_APP4_APK); 540 try { 541 final ParsedPackage pkg = new TestPackageParser2().parsePackage(testFile, 0, false); 542 final List<ParsedProvider> providers = pkg.getProviders(); 543 for (ParsedProvider provider : providers) { 544 final Map<String, Property> properties = provider.getProperties(); 545 if ((PACKAGE_NAME + ".MyProvider").equals(provider.getName())) { 546 assertEquals(1, properties.size()); 547 assertProperty(properties, 548 "android.cts.PROPERTY_PROVIDER", PROPERTY_TYPE_INTEGER, 123); 549 } else { 550 fail("Found unknown provider; name = " + provider.getName()); 551 } 552 } 553 } finally { 554 testFile.delete(); 555 } 556 } 557 558 @Test testParseReceiverProperties()559 public void testParseReceiverProperties() throws Exception { 560 final File testFile = extractFile(TEST_APP4_APK); 561 try { 562 final ParsedPackage pkg = new TestPackageParser2().parsePackage(testFile, 0, false); 563 final List<ParsedActivity> receivers = pkg.getReceivers(); 564 for (ParsedActivity receiver : receivers) { 565 final Map<String, Property> properties = receiver.getProperties(); 566 if ((PACKAGE_NAME + ".MyReceiver").equals(receiver.getName())) { 567 assertEquals(2, properties.size()); 568 assertProperty(properties, 569 "android.cts.PROPERTY_RECEIVER", PROPERTY_TYPE_INTEGER, 123); 570 assertProperty(properties, 571 "android.cts.PROPERTY_STRING", PROPERTY_TYPE_STRING, "koala receiver"); 572 } else { 573 fail("Found unknown receiver; name = " + receiver.getName()); 574 } 575 } 576 } finally { 577 testFile.delete(); 578 } 579 } 580 581 @Test testParseServiceProperties()582 public void testParseServiceProperties() throws Exception { 583 final File testFile = extractFile(TEST_APP4_APK); 584 try { 585 final ParsedPackage pkg = new TestPackageParser2().parsePackage(testFile, 0, false); 586 final List<ParsedService> services = pkg.getServices(); 587 for (ParsedService service : services) { 588 final Map<String, Property> properties = service.getProperties(); 589 if ((PACKAGE_NAME + ".MyService").equals(service.getName())) { 590 assertEquals(2, properties.size()); 591 assertProperty(properties, 592 "android.cts.PROPERTY_SERVICE", PROPERTY_TYPE_INTEGER, 123); 593 assertProperty(properties, 594 "android.cts.PROPERTY_COMPONENT", PROPERTY_TYPE_RESOURCE, 0x7f040000); 595 } else { 596 fail("Found unknown service; name = " + service.getName()); 597 } 598 } 599 } finally { 600 testFile.delete(); 601 } 602 } 603 604 @Test testParseApexSystemService()605 public void testParseApexSystemService() throws Exception { 606 final File testFile = extractFile(TEST_APP4_APK); 607 try { 608 final ParsedPackage pkg = new TestPackageParser2().parsePackage(testFile, 0, false); 609 final List<ParsedApexSystemService> systemServices = pkg.getApexSystemServices(); 610 for (ParsedApexSystemService systemService: systemServices) { 611 assertEquals(PACKAGE_NAME + ".SystemService", systemService.getName()); 612 assertEquals("service-test.jar", systemService.getJarPath()); 613 assertEquals("30", systemService.getMinSdkVersion()); 614 assertEquals("31", systemService.getMaxSdkVersion()); 615 } 616 } finally { 617 testFile.delete(); 618 } 619 } 620 621 @Test testParseModernPackageHasNoCompatPermissions()622 public void testParseModernPackageHasNoCompatPermissions() throws Exception { 623 final File testFile = extractFile(TEST_APP1_APK); 624 try { 625 final ParsedPackage pkg = new TestPackageParser2() 626 .parsePackage(testFile, 0 /*flags*/, false /*useCaches*/); 627 final List<String> compatPermissions = 628 Arrays.stream(COMPAT_PERMS).map(CompatibilityPermissionInfo::getName) 629 .collect(toList()); 630 assertWithMessage( 631 "Compatibility permissions shouldn't be added into uses permissions.") 632 .that(pkg.getUsesPermissions().stream().map(ParsedUsesPermission::getName) 633 .collect(toList())) 634 .containsNoneIn(compatPermissions); 635 assertWithMessage( 636 "Compatibility permissions shouldn't be added into requested permissions.") 637 .that(pkg.getRequestedPermissions()).containsNoneIn(compatPermissions); 638 assertWithMessage( 639 "Compatibility permissions shouldn't be added into implicit permissions.") 640 .that(pkg.getImplicitPermissions()).containsNoneIn(compatPermissions); 641 } finally { 642 testFile.delete(); 643 } 644 } 645 646 @Test testParseLegacyPackageHasCompatPermissions()647 public void testParseLegacyPackageHasCompatPermissions() throws Exception { 648 final File testFile = extractFile(TEST_APP5_APK); 649 try { 650 final ParsedPackage pkg = new TestPackageParser2() 651 .parsePackage(testFile, 0 /*flags*/, false /*useCaches*/); 652 assertWithMessage( 653 "Compatibility permissions should be added into uses permissions.") 654 .that(Arrays.stream(COMPAT_PERMS).map(CompatibilityPermissionInfo::getName) 655 .allMatch(pkg.getUsesPermissions().stream() 656 .map(ParsedUsesPermission::getName) 657 .collect(toList())::contains)) 658 .isTrue(); 659 assertWithMessage( 660 "Compatibility permissions should be added into requested permissions.") 661 .that(Arrays.stream(COMPAT_PERMS).map(CompatibilityPermissionInfo::getName) 662 .allMatch(pkg.getRequestedPermissions()::contains)) 663 .isTrue(); 664 assertWithMessage( 665 "Compatibility permissions should be added into implicit permissions.") 666 .that(Arrays.stream(COMPAT_PERMS).map(CompatibilityPermissionInfo::getName) 667 .allMatch(pkg.getImplicitPermissions()::contains)) 668 .isTrue(); 669 } finally { 670 testFile.delete(); 671 } 672 } 673 674 @Test testNoComponentMetadataIsCoercedToNullForInfoObject()675 public void testNoComponentMetadataIsCoercedToNullForInfoObject() throws Exception { 676 final File testFile = extractFile(TEST_APP4_APK); 677 try { 678 final ParsedPackage pkg = new TestPackageParser2().parsePackage(testFile, 0, false); 679 var pkgSetting = mockPkgSetting(pkg); 680 ApplicationInfo appInfo = PackageInfoUtils.generateApplicationInfo(pkg, 0, 681 PackageUserStateInternal.DEFAULT, 0, pkgSetting); 682 for (ParsedActivity activity : pkg.getActivities()) { 683 assertNotNull(activity.getMetaData()); 684 assertNull(PackageInfoUtils.generateActivityInfo(pkg, activity, 0, 685 PackageUserStateInternal.DEFAULT, appInfo, 0, pkgSetting) 686 .metaData); 687 } 688 for (ParsedProvider provider : pkg.getProviders()) { 689 assertNotNull(provider.getMetaData()); 690 assertNull(PackageInfoUtils.generateProviderInfo(pkg, provider, 0, 691 PackageUserStateInternal.DEFAULT, appInfo, 0, pkgSetting) 692 .metaData); 693 } 694 for (ParsedActivity receiver : pkg.getReceivers()) { 695 assertNotNull(receiver.getMetaData()); 696 assertNull(PackageInfoUtils.generateActivityInfo(pkg, receiver, 0, 697 PackageUserStateInternal.DEFAULT, appInfo, 0, pkgSetting) 698 .metaData); 699 } 700 for (ParsedService service : pkg.getServices()) { 701 assertNotNull(service.getMetaData()); 702 assertNull(PackageInfoUtils.generateServiceInfo(pkg, service, 0, 703 PackageUserStateInternal.DEFAULT, appInfo, 0, pkgSetting) 704 .metaData); 705 } 706 } finally { 707 testFile.delete(); 708 } 709 } 710 711 /** 712 * A subclass of package parser that adds a "cache_" prefix to the package name for the cached 713 * results. This is used by tests to tell if a ParsedPackage is generated from the cache or not. 714 */ 715 public static class CachePackageNameParser extends PackageParser2 { 716 CachePackageNameParser(@ullable File cacheDir)717 CachePackageNameParser(@Nullable File cacheDir) { 718 super(null, null, null, new Callback() { 719 @Override 720 public boolean isChangeEnabled(long changeId, @NonNull ApplicationInfo appInfo) { 721 return true; 722 } 723 724 @Override 725 public boolean hasFeature(String feature) { 726 return false; 727 } 728 }); 729 if (cacheDir != null) { 730 setCacheDir(cacheDir); 731 } 732 } 733 setCacheDir(@onNull File cacheDir)734 void setCacheDir(@NonNull File cacheDir) { 735 this.mCacher = new PackageCacher(cacheDir) { 736 @Override 737 public ParsedPackage fromCacheEntry(byte[] cacheEntry) { 738 ParsedPackage parsed = super.fromCacheEntry(cacheEntry); 739 parsed.setPackageName("cache_" + parsed.getPackageName()); 740 return parsed; 741 } 742 }; 743 } 744 } 745 mockPkgSetting(AndroidPackage pkg)746 private static PackageSetting mockPkgSetting(AndroidPackage pkg) { 747 return new PackageSettingBuilder() 748 .setName(pkg.getPackageName()) 749 .setRealName(pkg.getManifestPackageName()) 750 .setCodePath(pkg.getPath()) 751 .setPrimaryCpuAbiString(AndroidPackageUtils.getRawPrimaryCpuAbi(pkg)) 752 .setSecondaryCpuAbiString(AndroidPackageUtils.getRawSecondaryCpuAbi(pkg)) 753 .setPVersionCode(pkg.getLongVersionCode()) 754 .setPkgFlags(PackageInfoUtils.appInfoFlags(pkg, null)) 755 .setPrivateFlags(PackageInfoUtils.appInfoPrivateFlags(pkg, null)) 756 .setSharedUserId(pkg.getSharedUserLabelResourceId()) 757 .build(); 758 } 759 760 // NOTE: The equality assertions below are based on code autogenerated by IntelliJ. 761 assertPackagesEqual(AndroidPackage a, AndroidPackage b)762 public static void assertPackagesEqual(AndroidPackage a, AndroidPackage b) { 763 assertEquals(a.getBaseRevisionCode(), b.getBaseRevisionCode()); 764 assertEquals(a.isHardwareAccelerated(), b.isHardwareAccelerated()); 765 assertEquals(a.getLongVersionCode(), b.getLongVersionCode()); 766 assertEquals(a.getSharedUserLabelResourceId(), b.getSharedUserLabelResourceId()); 767 assertEquals(a.getInstallLocation(), b.getInstallLocation()); 768 assertEquals(a.isCoreApp(), b.isCoreApp()); 769 assertEquals(a.isRequiredForAllUsers(), b.isRequiredForAllUsers()); 770 assertEquals(a.getCompileSdkVersion(), b.getCompileSdkVersion()); 771 assertEquals(a.getCompileSdkVersionCodeName(), b.getCompileSdkVersionCodeName()); 772 assertEquals(a.is32BitAbiPreferred(), b.is32BitAbiPreferred()); 773 assertEquals(a.getPackageName(), b.getPackageName()); 774 assertArrayEquals(a.getSplitNames(), b.getSplitNames()); 775 assertEquals(a.getVolumeUuid(), b.getVolumeUuid()); 776 assertEquals(a.getPath(), b.getPath()); 777 assertEquals(a.getBaseApkPath(), b.getBaseApkPath()); 778 assertArrayEquals(a.getSplitCodePaths(), b.getSplitCodePaths()); 779 assertArrayEquals(a.getSplitRevisionCodes(), b.getSplitRevisionCodes()); 780 assertArrayEquals(a.getSplitFlags(), b.getSplitFlags()); 781 782 PackageInfo aInfo = PackageInfoUtils.generate(a, new int[]{}, 0, 0, 0, 783 Collections.emptySet(), Collections.emptySet(), PackageUserStateInternal.DEFAULT, 0, 784 mockPkgSetting(a)); 785 PackageInfo bInfo = PackageInfoUtils.generate(b, new int[]{}, 0, 0, 0, 786 Collections.emptySet(), Collections.emptySet(), PackageUserStateInternal.DEFAULT, 0, 787 mockPkgSetting(b)); 788 assertApplicationInfoEqual(aInfo.applicationInfo, bInfo.applicationInfo); 789 790 assertEquals(ArrayUtils.size(a.getPermissions()), ArrayUtils.size(b.getPermissions())); 791 for (int i = 0; i < ArrayUtils.size(a.getPermissions()); ++i) { 792 assertPermissionsEqual(a.getPermissions().get(i), b.getPermissions().get(i)); 793 } 794 795 assertEquals(ArrayUtils.size(a.getPermissionGroups()), 796 ArrayUtils.size(b.getPermissionGroups())); 797 for (int i = 0; i < a.getPermissionGroups().size(); ++i) { 798 assertPermissionGroupsEqual(a.getPermissionGroups().get(i), 799 b.getPermissionGroups().get(i)); 800 } 801 802 assertEquals(ArrayUtils.size(a.getActivities()), ArrayUtils.size(b.getActivities())); 803 for (int i = 0; i < ArrayUtils.size(a.getActivities()); ++i) { 804 assertActivitiesEqual(a, a.getActivities().get(i), b, b.getActivities().get(i)); 805 } 806 807 assertEquals(ArrayUtils.size(a.getReceivers()), ArrayUtils.size(b.getReceivers())); 808 for (int i = 0; i < ArrayUtils.size(a.getReceivers()); ++i) { 809 assertActivitiesEqual(a, a.getReceivers().get(i), b, b.getReceivers().get(i)); 810 } 811 812 assertEquals(ArrayUtils.size(a.getProviders()), ArrayUtils.size(b.getProviders())); 813 for (int i = 0; i < ArrayUtils.size(a.getProviders()); ++i) { 814 assertProvidersEqual(a, a.getProviders().get(i), b, b.getProviders().get(i)); 815 } 816 817 assertEquals(ArrayUtils.size(a.getServices()), ArrayUtils.size(b.getServices())); 818 for (int i = 0; i < ArrayUtils.size(a.getServices()); ++i) { 819 assertServicesEqual(a, a.getServices().get(i), b, b.getServices().get(i)); 820 } 821 822 assertEquals(ArrayUtils.size(a.getInstrumentations()), 823 ArrayUtils.size(b.getInstrumentations())); 824 for (int i = 0; i < ArrayUtils.size(a.getInstrumentations()); ++i) { 825 assertInstrumentationEqual(a.getInstrumentations().get(i), 826 b.getInstrumentations().get(i)); 827 } 828 829 assertEquals(a.getProperties().size(), b.getProperties().size()); 830 final Iterator<String> iter = a.getProperties().keySet().iterator(); 831 while (iter.hasNext()) { 832 final String key = iter.next(); 833 assertEquals(a.getProperties().get(key), b.getProperties().get(key)); 834 } 835 836 assertEquals(a.getRequestedPermissions(), b.getRequestedPermissions()); 837 assertEquals(a.getProtectedBroadcasts(), b.getProtectedBroadcasts()); 838 assertEquals(a.getLibraryNames(), b.getLibraryNames()); 839 assertEquals(a.getUsesLibraries(), b.getUsesLibraries()); 840 assertEquals(a.getUsesOptionalLibraries(), b.getUsesOptionalLibraries()); 841 assertEquals(a.getOriginalPackages(), b.getOriginalPackages()); 842 assertEquals(a.getManifestPackageName(), b.getManifestPackageName()); 843 assertEquals(a.getAdoptPermissions(), b.getAdoptPermissions()); 844 assertBundleApproximateEquals(a.getMetaData(), b.getMetaData()); 845 assertEquals(a.getVersionName(), b.getVersionName()); 846 assertEquals(a.getSharedUserId(), b.getSharedUserId()); 847 assertArrayEquals(a.getSigningDetails().getSignatures(), 848 b.getSigningDetails().getSignatures()); 849 assertEquals(a.getRestrictedAccountType(), b.getRestrictedAccountType()); 850 assertEquals(a.getRequiredAccountType(), b.getRequiredAccountType()); 851 assertEquals(a.getOverlayTarget(), b.getOverlayTarget()); 852 assertEquals(a.getOverlayTargetOverlayableName(), b.getOverlayTargetOverlayableName()); 853 assertEquals(a.getOverlayCategory(), b.getOverlayCategory()); 854 assertEquals(a.getOverlayPriority(), b.getOverlayPriority()); 855 assertEquals(a.isOverlayIsStatic(), b.isOverlayIsStatic()); 856 assertEquals(a.getSigningDetails().getPublicKeys(), b.getSigningDetails().getPublicKeys()); 857 assertEquals(a.getUpgradeKeySets(), b.getUpgradeKeySets()); 858 assertEquals(a.getKeySetMapping(), b.getKeySetMapping()); 859 assertArrayEquals(a.getRestrictUpdateHash(), b.getRestrictUpdateHash()); 860 } 861 assertBundleApproximateEquals(Bundle a, Bundle b)862 private static void assertBundleApproximateEquals(Bundle a, Bundle b) { 863 if (a == b) { 864 return; 865 } 866 867 // Force the bundles to be unparceled. 868 a.getBoolean("foo"); 869 b.getBoolean("foo"); 870 871 assertEquals(a.toString(), b.toString()); 872 } 873 assertComponentsEqual(ParsedComponent a, ParsedComponent b)874 private static void assertComponentsEqual(ParsedComponent a, ParsedComponent b) { 875 assertEquals(a.getName(), b.getName()); 876 assertBundleApproximateEquals(a.getMetaData(), b.getMetaData()); 877 assertEquals(a.getComponentName(), b.getComponentName()); 878 879 if (a.getIntents() != null && b.getIntents() != null) { 880 assertEquals(a.getIntents().size(), b.getIntents().size()); 881 } else if (a.getIntents() == null || b.getIntents() == null) { 882 return; 883 } 884 885 for (int i = 0; i < a.getIntents().size(); ++i) { 886 ParsedIntentInfo aIntent = a.getIntents().get(i); 887 ParsedIntentInfo bIntent = b.getIntents().get(i); 888 889 assertEquals(aIntent.isHasDefault(), bIntent.isHasDefault()); 890 assertEquals(aIntent.getLabelRes(), bIntent.getLabelRes()); 891 assertEquals(aIntent.getNonLocalizedLabel(), bIntent.getNonLocalizedLabel()); 892 assertEquals(aIntent.getIcon(), bIntent.getIcon()); 893 } 894 895 assertEquals(a.getProperties().size(), b.getProperties().size()); 896 final Iterator<String> iter = a.getProperties().keySet().iterator(); 897 while (iter.hasNext()) { 898 final String key = iter.next(); 899 assertEquals(a.getProperties().get(key), b.getProperties().get(key)); 900 } 901 } 902 assertPermissionsEqual(ParsedPermission a, ParsedPermission b)903 private static void assertPermissionsEqual(ParsedPermission a, ParsedPermission b) { 904 assertComponentsEqual(a, b); 905 assertEquals(a.isTree(), b.isTree()); 906 907 // Verify basic flags in PermissionInfo to make sure they're consistent. We don't perform 908 // a full structural equality here because the code that serializes them isn't parser 909 // specific and is tested elsewhere. 910 assertEquals(ParsedPermissionUtils.getProtection(a), 911 ParsedPermissionUtils.getProtection(b)); 912 assertEquals(a.getGroup(), b.getGroup()); 913 assertEquals(a.getFlags(), b.getFlags()); 914 915 if (a.getParsedPermissionGroup() != null && b.getParsedPermissionGroup() != null) { 916 assertPermissionGroupsEqual(a.getParsedPermissionGroup(), b.getParsedPermissionGroup()); 917 } else if (a.getParsedPermissionGroup() != null || b.getParsedPermissionGroup() != null) { 918 throw new AssertionError(); 919 } 920 } 921 assertInstrumentationEqual(ParsedInstrumentation a, ParsedInstrumentation b)922 private static void assertInstrumentationEqual(ParsedInstrumentation a, 923 ParsedInstrumentation b) { 924 assertComponentsEqual(a, b); 925 926 // Validity check for InstrumentationInfo. 927 assertEquals(a.getTargetPackage(), b.getTargetPackage()); 928 assertEquals(a.getTargetProcesses(), b.getTargetProcesses()); 929 assertEquals(a.isHandleProfiling(), b.isHandleProfiling()); 930 assertEquals(a.isFunctionalTest(), b.isFunctionalTest()); 931 } 932 assertServicesEqual( AndroidPackage aPkg, ParsedService a, AndroidPackage bPkg, ParsedService b )933 private static void assertServicesEqual( 934 AndroidPackage aPkg, 935 ParsedService a, 936 AndroidPackage bPkg, 937 ParsedService b 938 ) { 939 assertComponentsEqual(a, b); 940 941 // Validity check for ServiceInfo. 942 ServiceInfo aInfo = PackageInfoUtils.generateServiceInfo(aPkg, a, 0, 943 PackageUserStateInternal.DEFAULT, 0, mockPkgSetting(aPkg)); 944 ServiceInfo bInfo = PackageInfoUtils.generateServiceInfo(bPkg, b, 0, 945 PackageUserStateInternal.DEFAULT, 0, mockPkgSetting(bPkg)); 946 assertApplicationInfoEqual(aInfo.applicationInfo, bInfo.applicationInfo); 947 assertEquals(a.getName(), b.getName()); 948 } 949 assertProvidersEqual( AndroidPackage aPkg, ParsedProvider a, AndroidPackage bPkg, ParsedProvider b )950 private static void assertProvidersEqual( 951 AndroidPackage aPkg, 952 ParsedProvider a, 953 AndroidPackage bPkg, 954 ParsedProvider b 955 ) { 956 assertComponentsEqual(a, b); 957 assertEquals(a.getName(), b.getName()); 958 } 959 assertActivitiesEqual( AndroidPackage aPkg, ParsedActivity a, AndroidPackage bPkg, ParsedActivity b )960 private static void assertActivitiesEqual( 961 AndroidPackage aPkg, 962 ParsedActivity a, 963 AndroidPackage bPkg, 964 ParsedActivity b 965 ) { 966 assertComponentsEqual(a, b); 967 968 // Validity check for ActivityInfo. 969 ActivityInfo aInfo = PackageInfoUtils.generateActivityInfo(aPkg, a, 0, 970 PackageUserStateInternal.DEFAULT, 0, mockPkgSetting(aPkg)); 971 ActivityInfo bInfo = PackageInfoUtils.generateActivityInfo(bPkg, b, 0, 972 PackageUserStateInternal.DEFAULT, 0, mockPkgSetting(bPkg)); 973 assertApplicationInfoEqual(aInfo.applicationInfo, bInfo.applicationInfo); 974 assertEquals(a.getName(), b.getName()); 975 } 976 assertPermissionGroupsEqual(ParsedPermissionGroup a, ParsedPermissionGroup b)977 private static void assertPermissionGroupsEqual(ParsedPermissionGroup a, 978 ParsedPermissionGroup b) { 979 assertComponentsEqual(a, b); 980 981 // Validity check for PermissionGroupInfo. 982 assertEquals(a.getName(), b.getName()); 983 assertEquals(a.getDescriptionRes(), b.getDescriptionRes()); 984 } 985 assertApplicationInfoEqual(ApplicationInfo a, ApplicationInfo that)986 private static void assertApplicationInfoEqual(ApplicationInfo a, ApplicationInfo that) { 987 assertEquals(a.descriptionRes, that.descriptionRes); 988 assertEquals(a.theme, that.theme); 989 assertEquals(a.fullBackupContent, that.fullBackupContent); 990 assertEquals(a.uiOptions, that.uiOptions); 991 assertEquals(Integer.toBinaryString(a.flags), Integer.toBinaryString(that.flags)); 992 assertEquals(a.privateFlags, that.privateFlags); 993 assertEquals(a.requiresSmallestWidthDp, that.requiresSmallestWidthDp); 994 assertEquals(a.compatibleWidthLimitDp, that.compatibleWidthLimitDp); 995 assertEquals(a.largestWidthLimitDp, that.largestWidthLimitDp); 996 assertEquals(a.nativeLibraryRootRequiresIsa, that.nativeLibraryRootRequiresIsa); 997 assertEquals(a.uid, that.uid); 998 assertEquals(a.minSdkVersion, that.minSdkVersion); 999 assertEquals(a.targetSdkVersion, that.targetSdkVersion); 1000 assertEquals(a.versionCode, that.versionCode); 1001 assertEquals(a.enabled, that.enabled); 1002 assertEquals(a.enabledSetting, that.enabledSetting); 1003 assertEquals(a.installLocation, that.installLocation); 1004 assertEquals(a.networkSecurityConfigRes, that.networkSecurityConfigRes); 1005 assertEquals(a.taskAffinity, that.taskAffinity); 1006 assertEquals(a.permission, that.permission); 1007 assertEquals(a.getKnownActivityEmbeddingCerts(), that.getKnownActivityEmbeddingCerts()); 1008 assertEquals(a.processName, that.processName); 1009 assertEquals(a.className, that.className); 1010 assertEquals(a.manageSpaceActivityName, that.manageSpaceActivityName); 1011 assertEquals(a.backupAgentName, that.backupAgentName); 1012 assertEquals(a.volumeUuid, that.volumeUuid); 1013 assertEquals(a.scanSourceDir, that.scanSourceDir); 1014 assertEquals(a.scanPublicSourceDir, that.scanPublicSourceDir); 1015 assertEquals(a.sourceDir, that.sourceDir); 1016 assertEquals(a.publicSourceDir, that.publicSourceDir); 1017 assertArrayEquals(a.splitSourceDirs, that.splitSourceDirs); 1018 assertArrayEquals(a.splitPublicSourceDirs, that.splitPublicSourceDirs); 1019 assertArrayEquals(a.resourceDirs, that.resourceDirs); 1020 assertArrayEquals(a.overlayPaths, that.overlayPaths); 1021 assertEquals(a.seInfo, that.seInfo); 1022 assertArrayEquals(a.sharedLibraryFiles, that.sharedLibraryFiles); 1023 assertEquals(a.dataDir, that.dataDir); 1024 assertEquals(a.deviceProtectedDataDir, that.deviceProtectedDataDir); 1025 assertEquals(a.credentialProtectedDataDir, that.credentialProtectedDataDir); 1026 assertEquals(a.nativeLibraryDir, that.nativeLibraryDir); 1027 assertEquals(a.secondaryNativeLibraryDir, that.secondaryNativeLibraryDir); 1028 assertEquals(a.nativeLibraryRootDir, that.nativeLibraryRootDir); 1029 assertEquals(a.primaryCpuAbi, that.primaryCpuAbi); 1030 assertEquals(a.secondaryCpuAbi, that.secondaryCpuAbi); 1031 } 1032 setKnownFields(ParsingPackage pkg)1033 public static void setKnownFields(ParsingPackage pkg) { 1034 Bundle bundle = new Bundle(); 1035 bundle.putString("key", "value"); 1036 1037 ParsedPermissionImpl permission = new ParsedPermissionImpl(); 1038 permission.setParsedPermissionGroup(new ParsedPermissionGroupImpl()); 1039 1040 ((ParsedPackage) pkg.setBaseRevisionCode(100) 1041 .setHardwareAccelerated(true) 1042 .setSharedUserLabelResourceId(100) 1043 .setInstallLocation(100) 1044 .setRequiredForAllUsers(true) 1045 .asSplit( 1046 new String[]{"foo2"}, 1047 new String[]{"foo6"}, 1048 new int[]{100}, 1049 null 1050 ) 1051 .set32BitAbiPreferred(true) 1052 .setVolumeUuid("d52ef59a-7def-4541-bf21-4c28ed4b65a0") 1053 .addPermission(permission) 1054 .addPermissionGroup(new ParsedPermissionGroupImpl()) 1055 .addActivity(new ParsedActivityImpl()) 1056 .addReceiver(new ParsedActivityImpl()) 1057 .addProvider(new ParsedProviderImpl()) 1058 .addService(new ParsedServiceImpl()) 1059 .addInstrumentation(new ParsedInstrumentationImpl()) 1060 .addUsesPermission(new ParsedUsesPermissionImpl("foo7", 0)) 1061 .addImplicitPermission("foo25") 1062 .addProtectedBroadcast("foo8") 1063 .setSdkLibraryName("sdk12") 1064 .setSdkLibVersionMajor(42) 1065 .addUsesSdkLibrary("sdk23", 200, new String[]{"digest2"}) 1066 .setStaticSharedLibraryName("foo23") 1067 .setStaticSharedLibraryVersion(100) 1068 .addUsesStaticLibrary("foo23", 100, new String[]{"digest"}) 1069 .addLibraryName("foo10") 1070 .addUsesLibrary("foo11") 1071 .addUsesOptionalLibrary("foo12") 1072 .addOriginalPackage("foo14") 1073 .addAdoptPermission("foo16") 1074 .setMetaData(bundle) 1075 .setVersionName("foo17") 1076 .setSharedUserId("foo18") 1077 .setSigningDetails( 1078 new SigningDetails( 1079 new Signature[]{new Signature(new byte[16])}, 1080 SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2, 1081 new ArraySet<>(), 1082 null) 1083 ) 1084 .setRestrictedAccountType("foo19") 1085 .setRequiredAccountType("foo20") 1086 .setOverlayTarget("foo21") 1087 .setOverlayPriority(100) 1088 .setUpgradeKeySets(new ArraySet<>()) 1089 .addPreferredActivityFilter("className", new ParsedIntentInfoImpl()) 1090 .addConfigPreference(new ConfigurationInfo()) 1091 .addReqFeature(new FeatureInfo()) 1092 .addFeatureGroup(new FeatureGroupInfo()) 1093 .setCompileSdkVersionCodeName("foo23") 1094 .setCompileSdkVersion(100) 1095 .setOverlayCategory("foo24") 1096 .setOverlayIsStatic(true) 1097 .setOverlayTargetOverlayableName("foo26") 1098 .setVisibleToInstantApps(true) 1099 .setSplitHasCode(0, true) 1100 .hideAsParsed()) 1101 .setBaseApkPath("foo5") 1102 .setPath("foo4") 1103 .setVersionCode(100) 1104 .setRestrictUpdateHash(new byte[16]) 1105 .setVersionCodeMajor(100) 1106 .setCoreApp(true) 1107 .hideAsFinal(); 1108 } 1109 assertAllFieldsExist(ParsedPackage pkg)1110 private static void assertAllFieldsExist(ParsedPackage pkg) throws Exception { 1111 Field[] fields = ParsedPackage.class.getDeclaredFields(); 1112 1113 Set<String> nonSerializedFields = new HashSet<>(); 1114 nonSerializedFields.add("mExtras"); 1115 nonSerializedFields.add("packageUsageTimeMillis"); 1116 nonSerializedFields.add("isStub"); 1117 1118 for (Field f : fields) { 1119 final Class<?> fieldType = f.getType(); 1120 1121 if (nonSerializedFields.contains(f.getName())) { 1122 continue; 1123 } 1124 1125 if (List.class.isAssignableFrom(fieldType)) { 1126 // Validity check for list fields: Assume they're non-null and contain precisely 1127 // one element. 1128 List<?> list = (List<?>) f.get(pkg); 1129 assertNotNull("List was null: " + f, list); 1130 assertEquals(1, list.size()); 1131 } else if (fieldType.getComponentType() != null) { 1132 // Validity check for array fields: Assume they're non-null and contain precisely 1133 // one element. 1134 Object array = f.get(pkg); 1135 assertNotNull(Array.get(array, 0)); 1136 } else if (fieldType == String.class) { 1137 // String fields: Check that they're set to "foo". 1138 String value = (String) f.get(pkg); 1139 1140 assertTrue("Bad value for field: " + f, value != null && value.startsWith("foo")); 1141 } else if (fieldType == int.class) { 1142 // int fields: Check that they're set to 100. 1143 int value = (int) f.get(pkg); 1144 assertEquals("Bad value for field: " + f, 100, value); 1145 } else if (fieldType == boolean.class) { 1146 // boolean fields: Check that they're set to true. 1147 boolean value = (boolean) f.get(pkg); 1148 assertTrue("Bad value for field: " + f, value); 1149 } else { 1150 // All other fields: Check that they're set. 1151 Object o = f.get(pkg); 1152 assertNotNull("Field was null: " + f, o); 1153 } 1154 } 1155 } 1156 } 1157 1158