1 /* 2 * Copyright (C) 2019 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; 18 19 import static android.content.pm.SharedLibraryInfo.TYPE_DYNAMIC; 20 import static android.content.pm.SharedLibraryInfo.TYPE_SDK_PACKAGE; 21 import static android.content.pm.SharedLibraryInfo.TYPE_STATIC; 22 import static android.content.pm.SharedLibraryInfo.VERSION_UNDEFINED; 23 24 import static com.android.server.pm.PackageManagerService.SCAN_AS_APEX; 25 import static com.android.server.pm.PackageManagerService.SCAN_AS_FULL_APP; 26 import static com.android.server.pm.PackageManagerService.SCAN_AS_INSTANT_APP; 27 import static com.android.server.pm.PackageManagerService.SCAN_FIRST_BOOT_OR_UPGRADE; 28 import static com.android.server.pm.PackageManagerService.SCAN_NEW_INSTALL; 29 30 import static org.hamcrest.MatcherAssert.assertThat; 31 import static org.hamcrest.Matchers.empty; 32 import static org.hamcrest.Matchers.hasItems; 33 import static org.hamcrest.Matchers.nullValue; 34 import static org.hamcrest.collection.IsArrayContainingInOrder.arrayContaining; 35 import static org.hamcrest.core.Is.is; 36 import static org.junit.Assert.assertNotSame; 37 import static org.mockito.ArgumentMatchers.any; 38 import static org.mockito.ArgumentMatchers.anyBoolean; 39 import static org.mockito.ArgumentMatchers.nullable; 40 import static org.mockito.Mockito.mock; 41 import static org.mockito.Mockito.when; 42 43 import android.Manifest; 44 import android.content.pm.ApplicationInfo; 45 import android.content.pm.PackageInfo; 46 import android.content.pm.SharedLibraryInfo; 47 import android.content.res.TypedArray; 48 import android.os.Environment; 49 import android.os.UserHandle; 50 import android.platform.test.annotations.Presubmit; 51 import android.util.Pair; 52 53 import com.android.internal.pm.parsing.pkg.PackageImpl; 54 import com.android.internal.pm.parsing.pkg.ParsedPackage; 55 import com.android.internal.pm.pkg.component.ParsedUsesPermissionImpl; 56 import com.android.internal.pm.pkg.parsing.ParsingPackage; 57 import com.android.server.compat.PlatformCompat; 58 import com.android.server.pm.parsing.PackageInfoUtils; 59 import com.android.server.pm.pkg.AndroidPackage; 60 import com.android.server.pm.verify.domain.DomainVerificationManagerInternal; 61 62 import org.hamcrest.BaseMatcher; 63 import org.hamcrest.Description; 64 import org.hamcrest.Matcher; 65 import org.junit.Before; 66 import org.junit.Test; 67 import org.junit.runner.RunWith; 68 import org.mockito.Mock; 69 import org.mockito.junit.MockitoJUnitRunner; 70 71 import java.io.File; 72 import java.util.UUID; 73 74 @RunWith(MockitoJUnitRunner.class) 75 @Presubmit 76 // TODO: shared user tests 77 public class ScanTests { 78 79 private static final String DUMMY_PACKAGE_NAME = "some.app.to.test"; 80 81 private static final UUID UUID_ONE = UUID.randomUUID(); 82 private static final UUID UUID_TWO = UUID.randomUUID(); 83 84 @Mock 85 PackageAbiHelper mMockPackageAbiHelper; 86 @Mock 87 UserManagerInternal mMockUserManager; 88 @Mock 89 PlatformCompat mMockCompatibility; 90 @Mock 91 PackageManagerServiceInjector mMockInjector; 92 @Mock 93 PackageManagerService mMockPackageManager; 94 @Mock 95 Installer mMockInstaller; 96 97 @Before setupInjector()98 public void setupInjector() { 99 when(mMockInjector.getAbiHelper()).thenReturn(mMockPackageAbiHelper); 100 when(mMockInjector.getUserManagerInternal()).thenReturn(mMockUserManager); 101 when(mMockInjector.getCompatibility()).thenReturn(mMockCompatibility); 102 103 DomainVerificationManagerInternal domainVerificationManager = 104 mock(DomainVerificationManagerInternal.class); 105 when(domainVerificationManager.generateNewId()) 106 .thenAnswer(invocation -> UUID.randomUUID()); 107 108 when(mMockInjector.getDomainVerificationManagerInternal()) 109 .thenReturn(domainVerificationManager); 110 when(mMockInjector.getInstaller()).thenReturn(mMockInstaller); 111 } 112 113 @Before setupDefaultUser()114 public void setupDefaultUser() { 115 when(mMockUserManager.getUserIds()).thenReturn(new int[]{0}); 116 } 117 118 @Before setupDefaultAbiBehavior()119 public void setupDefaultAbiBehavior() throws Exception { 120 when(mMockPackageAbiHelper.derivePackageAbi( 121 any(AndroidPackage.class), anyBoolean(), anyBoolean(), nullable(String.class), 122 any(File.class))) 123 .thenReturn(new Pair<>( 124 new PackageAbiHelper.Abis("derivedPrimary", "derivedSecondary"), 125 new PackageAbiHelper.NativeLibraryPaths( 126 "derivedRootDir", true, "derivedNativeDir", "derivedNativeDir2"))); 127 when(mMockPackageAbiHelper.deriveNativeLibraryPaths( 128 any(AndroidPackage.class), anyBoolean(), anyBoolean(), any(File.class))) 129 .thenReturn(new PackageAbiHelper.NativeLibraryPaths( 130 "getRootDir", true, "getNativeDir", "getNativeDir2" 131 )); 132 when(mMockPackageAbiHelper.getBundledAppAbis( 133 any(AndroidPackage.class))) 134 .thenReturn(new PackageAbiHelper.Abis("bundledPrimary", "bundledSecondary")); 135 } 136 137 @Test newInstallSimpleAllNominal()138 public void newInstallSimpleAllNominal() throws Exception { 139 final ScanRequest scanRequest = 140 createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME)) 141 .addScanFlag(PackageManagerService.SCAN_NEW_INSTALL) 142 .addScanFlag(PackageManagerService.SCAN_AS_FULL_APP) 143 .build(); 144 145 final ScanResult scanResult = executeScan(scanRequest); 146 147 assertBasicPackageScanResult(scanResult, DUMMY_PACKAGE_NAME, false /*isInstant*/); 148 assertThat(scanResult.mExistingSettingCopied, is(false)); 149 assertPathsNotDerived(scanResult); 150 } 151 152 @Test newInstallForAllUsers()153 public void newInstallForAllUsers() throws Exception { 154 final int[] userIds = {0, 10, 11}; 155 when(mMockUserManager.getUserIds()).thenReturn(userIds); 156 157 final ScanRequest scanRequest = 158 createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME)) 159 .setRealPkgName(null) 160 .addScanFlag(PackageManagerService.SCAN_NEW_INSTALL) 161 .addScanFlag(PackageManagerService.SCAN_AS_FULL_APP) 162 .build(); 163 final ScanResult scanResult = executeScan(scanRequest); 164 165 for (int uid : userIds) { 166 assertThat(scanResult.mPkgSetting.readUserState(uid).isInstalled(), is(true)); 167 } 168 } 169 170 @Test installRealPackageName()171 public void installRealPackageName() throws Exception { 172 final ScanRequest scanRequest = 173 createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME)) 174 .setRealPkgName("com.package.real") 175 .build(); 176 177 final ScanResult scanResult = executeScan(scanRequest); 178 179 assertThat(scanResult.mPkgSetting.getRealName(), is("com.package.real")); 180 181 final ScanRequest scanRequestNoRealPkg = 182 createBasicScanRequestBuilder( 183 createBasicPackage(DUMMY_PACKAGE_NAME) 184 .addOriginalPackage("com.package.real")) 185 .build(); 186 187 final ScanResult scanResultNoReal = executeScan(scanRequestNoRealPkg); 188 assertThat(scanResultNoReal.mPkgSetting.getRealName(), nullValue()); 189 } 190 191 @Test updateSimpleNominal()192 public void updateSimpleNominal() throws Exception { 193 when(mMockUserManager.getUserIds()).thenReturn(new int[]{0}); 194 195 final PackageSetting pkgSetting = createBasicPackageSettingBuilder(DUMMY_PACKAGE_NAME) 196 .setPrimaryCpuAbiString("primaryCpuAbi") 197 .setSecondaryCpuAbiString("secondaryCpuAbi") 198 .build(); 199 final ScanRequest scanRequest = 200 createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME)) 201 .addScanFlag(PackageManagerService.SCAN_AS_FULL_APP) 202 .setPkgSetting(pkgSetting) 203 .build(); 204 205 206 final ScanResult scanResult = executeScan(scanRequest); 207 208 assertThat(scanResult.mExistingSettingCopied, is(true)); 209 210 // ensure we don't overwrite the existing pkgSetting, in case something post-scan fails 211 assertNotSame(pkgSetting, scanResult.mPkgSetting); 212 213 assertBasicPackageScanResult(scanResult, DUMMY_PACKAGE_NAME, false /*isInstant*/); 214 215 assertThat(scanResult.mPkgSetting.getPrimaryCpuAbiLegacy(), is("primaryCpuAbi")); 216 assertThat(scanResult.mPkgSetting.getSecondaryCpuAbiLegacy(), is("secondaryCpuAbi")); 217 assertThat(scanResult.mPkgSetting.getCpuAbiOverride(), nullValue()); 218 219 assertPathsNotDerived(scanResult); 220 } 221 222 @Test updateInstantSimpleNominal()223 public void updateInstantSimpleNominal() throws Exception { 224 when(mMockUserManager.getUserIds()).thenReturn(new int[]{0}); 225 226 final PackageSetting existingPkgSetting = 227 createBasicPackageSettingBuilder(DUMMY_PACKAGE_NAME) 228 .setInstantAppUserState(0, true) 229 .build(); 230 231 final ScanRequest scanRequest = 232 createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME)) 233 .setPkgSetting(existingPkgSetting) 234 .build(); 235 236 237 final ScanResult scanResult = executeScan(scanRequest); 238 239 assertBasicPackageScanResult(scanResult, DUMMY_PACKAGE_NAME, true /*isInstant*/); 240 } 241 242 @Test installSdkLibrary()243 public void installSdkLibrary() throws Exception { 244 final ParsedPackage pkg = ((ParsedPackage) createBasicPackage("ogl.sdk_123") 245 .setSdkLibraryName("ogl.sdk") 246 .setSdkLibVersionMajor(123) 247 .hideAsParsed()) 248 .setPackageName("ogl.sdk_123") 249 .setVersionCodeMajor(5) 250 .setVersionCode(678) 251 .setBaseApkPath("/some/path.apk") 252 .setSplitCodePaths(new String[] {"/some/other/path.apk"}); 253 254 final ScanRequest scanRequest = new ScanRequestBuilder(pkg) 255 .setUser(UserHandle.of(0)).build(); 256 257 final ScanResult scanResult = executeScan(scanRequest); 258 259 assertThat(scanResult.mSdkSharedLibraryInfo.getPackageName(), is("ogl.sdk_123")); 260 assertThat(scanResult.mSdkSharedLibraryInfo.getName(), is("ogl.sdk")); 261 assertThat(scanResult.mSdkSharedLibraryInfo.getLongVersion(), is(123L)); 262 assertThat(scanResult.mSdkSharedLibraryInfo.getType(), is(TYPE_SDK_PACKAGE)); 263 assertThat(scanResult.mSdkSharedLibraryInfo.getDeclaringPackage().getPackageName(), 264 is("ogl.sdk_123")); 265 assertThat(scanResult.mSdkSharedLibraryInfo.getDeclaringPackage().getLongVersionCode(), 266 is(pkg.getLongVersionCode())); 267 assertThat(scanResult.mSdkSharedLibraryInfo.getAllCodePaths(), 268 hasItems("/some/path.apk", "/some/other/path.apk")); 269 assertThat(scanResult.mSdkSharedLibraryInfo.getDependencies(), nullValue()); 270 assertThat(scanResult.mSdkSharedLibraryInfo.getDependentPackages(), empty()); 271 } 272 273 @Test installStaticSharedLibrary()274 public void installStaticSharedLibrary() throws Exception { 275 final ParsedPackage pkg = ((ParsedPackage) createBasicPackage("static.lib.pkg") 276 .setStaticSharedLibraryName("static.lib") 277 .setStaticSharedLibraryVersion(123L) 278 .hideAsParsed()) 279 .setPackageName("static.lib.pkg.123") 280 .setVersionCodeMajor(1) 281 .setVersionCode(234) 282 .setBaseApkPath("/some/path.apk") 283 .setSplitCodePaths(new String[] {"/some/other/path.apk"}); 284 285 final ScanRequest scanRequest = new ScanRequestBuilder(pkg) 286 .setUser(UserHandle.of(0)).build(); 287 288 289 final ScanResult scanResult = executeScan(scanRequest); 290 291 assertThat(scanResult.mStaticSharedLibraryInfo.getPackageName(), is("static.lib.pkg.123")); 292 assertThat(scanResult.mStaticSharedLibraryInfo.getName(), is("static.lib")); 293 assertThat(scanResult.mStaticSharedLibraryInfo.getLongVersion(), is(123L)); 294 assertThat(scanResult.mStaticSharedLibraryInfo.getType(), is(TYPE_STATIC)); 295 assertThat(scanResult.mStaticSharedLibraryInfo.getDeclaringPackage().getPackageName(), 296 is("static.lib.pkg")); 297 assertThat(scanResult.mStaticSharedLibraryInfo.getDeclaringPackage().getLongVersionCode(), 298 is(pkg.getLongVersionCode())); 299 assertThat(scanResult.mStaticSharedLibraryInfo.getAllCodePaths(), 300 hasItems("/some/path.apk", "/some/other/path.apk")); 301 assertThat(scanResult.mStaticSharedLibraryInfo.getDependencies(), nullValue()); 302 assertThat(scanResult.mStaticSharedLibraryInfo.getDependentPackages(), empty()); 303 } 304 305 @Test installDynamicLibraries()306 public void installDynamicLibraries() throws Exception { 307 final ParsedPackage pkg = ((ParsedPackage) createBasicPackage( 308 "dynamic.lib.pkg") 309 .addLibraryName("liba") 310 .addLibraryName("libb") 311 .hideAsParsed()) 312 .setVersionCodeMajor(1) 313 .setVersionCode(234) 314 .setBaseApkPath("/some/path.apk") 315 .setSplitCodePaths(new String[] {"/some/other/path.apk"}); 316 317 final ScanRequest scanRequest = 318 new ScanRequestBuilder(pkg).setUser(UserHandle.of(0)).build(); 319 320 321 final ScanResult scanResult = executeScan(scanRequest); 322 323 final SharedLibraryInfo dynamicLib0 = scanResult.mDynamicSharedLibraryInfos.get(0); 324 assertThat(dynamicLib0.getPackageName(), is("dynamic.lib.pkg")); 325 assertThat(dynamicLib0.getName(), is("liba")); 326 assertThat(dynamicLib0.getLongVersion(), is((long) VERSION_UNDEFINED)); 327 assertThat(dynamicLib0.getType(), is(TYPE_DYNAMIC)); 328 assertThat(dynamicLib0.getDeclaringPackage().getPackageName(), is("dynamic.lib.pkg")); 329 assertThat(dynamicLib0.getDeclaringPackage().getLongVersionCode(), 330 is(pkg.getLongVersionCode())); 331 assertThat(dynamicLib0.getAllCodePaths(), 332 hasItems("/some/path.apk", "/some/other/path.apk")); 333 assertThat(dynamicLib0.getDependencies(), nullValue()); 334 assertThat(dynamicLib0.getDependentPackages(), empty()); 335 336 final SharedLibraryInfo dynamicLib1 = scanResult.mDynamicSharedLibraryInfos.get(1); 337 assertThat(dynamicLib1.getPackageName(), is("dynamic.lib.pkg")); 338 assertThat(dynamicLib1.getName(), is("libb")); 339 assertThat(dynamicLib1.getLongVersion(), is((long) VERSION_UNDEFINED)); 340 assertThat(dynamicLib1.getType(), is(TYPE_DYNAMIC)); 341 assertThat(dynamicLib1.getDeclaringPackage().getPackageName(), is("dynamic.lib.pkg")); 342 assertThat(dynamicLib1.getDeclaringPackage().getLongVersionCode(), 343 is(pkg.getLongVersionCode())); 344 assertThat(dynamicLib1.getAllCodePaths(), 345 hasItems("/some/path.apk", "/some/other/path.apk")); 346 assertThat(dynamicLib1.getDependencies(), nullValue()); 347 assertThat(dynamicLib1.getDependentPackages(), empty()); 348 } 349 350 @Test volumeUuidChangesOnUpdate()351 public void volumeUuidChangesOnUpdate() throws Exception { 352 final PackageSetting pkgSetting = 353 createBasicPackageSettingBuilder(DUMMY_PACKAGE_NAME) 354 .setVolumeUuid("someUuid") 355 .build(); 356 357 final ParsedPackage basicPackage = ((ParsedPackage) createBasicPackage(DUMMY_PACKAGE_NAME) 358 .setVolumeUuid(UUID_TWO.toString()) 359 .hideAsParsed()); 360 361 362 final ScanResult scanResult = executeScan( 363 new ScanRequestBuilder(basicPackage).setPkgSetting(pkgSetting).build()); 364 365 assertThat(scanResult.mPkgSetting.getVolumeUuid(), is(UUID_TWO.toString())); 366 } 367 368 @Test scanFirstBoot_apexDontDeriveAbis()369 public void scanFirstBoot_apexDontDeriveAbis() throws Exception { 370 final PackageSetting pkgSetting = 371 createBasicPackageSettingBuilder(DUMMY_PACKAGE_NAME) 372 .setPkgFlags(ApplicationInfo.FLAG_SYSTEM).build(); 373 374 final String codePath = "/data/apex/" + DUMMY_PACKAGE_NAME + ".apex"; 375 376 // Create the ParsedPackage for the apex 377 final ParsedPackage basicPackage = 378 ((ParsedPackage) new PackageImpl(DUMMY_PACKAGE_NAME, codePath, codePath, 379 mock(TypedArray.class), false, null) 380 .setVolumeUuid(UUID_ONE.toString()) 381 .hideAsParsed()) 382 .setVersionCodeMajor(1) 383 .setVersionCode(2345) 384 .setSystem(true); 385 386 when(mMockInjector.getAbiHelper()).thenReturn(new PackageAbiHelperImpl()); 387 388 // prepare the scan request with the scanflag (SCAN_FIRST_BOOT_OR_UPGRADE | SCAN_AS_APEX) 389 final ScanResult scanResult = executeScan(new ScanRequestBuilder(basicPackage) 390 .setPkgSetting(pkgSetting) 391 .addScanFlag(SCAN_FIRST_BOOT_OR_UPGRADE | SCAN_AS_APEX) 392 .build()); 393 394 final PackageSetting resultSetting = scanResult.mPkgSetting; 395 final ApplicationInfo applicationInfo = PackageInfoUtils.generateApplicationInfo( 396 resultSetting.getPkg(), 0, pkgSetting.getUserStateOrDefault(0), 0, resultSetting); 397 assertThat(applicationInfo.primaryCpuAbi, nullValue()); 398 assertThat(applicationInfo.primaryCpuAbi, nullValue()); 399 assertThat(applicationInfo.secondaryCpuAbi, nullValue()); 400 401 assertThat(applicationInfo.nativeLibraryRootDir, nullValue()); 402 assertThat(pkgSetting.getLegacyNativeLibraryPath(), nullValue()); 403 assertThat(applicationInfo.nativeLibraryRootRequiresIsa, is(false)); 404 assertThat(applicationInfo.nativeLibraryDir, nullValue()); 405 assertThat(applicationInfo.secondaryNativeLibraryDir, nullValue()); 406 } 407 408 @Test scanFirstBoot_derivesAbis()409 public void scanFirstBoot_derivesAbis() throws Exception { 410 final PackageSetting pkgSetting = 411 createBasicPackageSettingBuilder(DUMMY_PACKAGE_NAME).build(); 412 413 final ParsedPackage basicPackage = 414 ((ParsedPackage) createBasicPackage(DUMMY_PACKAGE_NAME) 415 .hideAsParsed()); 416 417 418 final ScanResult scanResult = executeScan(new ScanRequestBuilder( 419 basicPackage) 420 .setPkgSetting(pkgSetting) 421 .addScanFlag(SCAN_FIRST_BOOT_OR_UPGRADE) 422 .build()); 423 424 assertAbiAndPathssDerived(scanResult); 425 } 426 427 @Test scanWithOriginalPkgSetting_packageNameChanges()428 public void scanWithOriginalPkgSetting_packageNameChanges() throws Exception { 429 final PackageSetting originalPkgSetting = 430 createBasicPackageSettingBuilder("original.package").build(); 431 432 final ParsedPackage basicPackage = 433 (ParsedPackage) createBasicPackage(DUMMY_PACKAGE_NAME) 434 .hideAsParsed(); 435 436 437 final ScanResult result = 438 executeScan(new ScanRequestBuilder(basicPackage) 439 .setOriginalPkgSetting(originalPkgSetting) 440 .build()); 441 442 assertThat(result.mRequest.mParsedPackage.getPackageName(), is("original.package")); 443 } 444 445 @Test updateInstant_changeToFull()446 public void updateInstant_changeToFull() throws Exception { 447 when(mMockUserManager.getUserIds()).thenReturn(new int[]{0}); 448 449 final PackageSetting existingPkgSetting = 450 createBasicPackageSettingBuilder(DUMMY_PACKAGE_NAME) 451 .setInstantAppUserState(0, true) 452 .build(); 453 454 final ScanRequest scanRequest = 455 createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME)) 456 .setPkgSetting(existingPkgSetting) 457 .addScanFlag(SCAN_AS_FULL_APP) 458 .build(); 459 460 461 final ScanResult scanResult = executeScan(scanRequest); 462 463 assertBasicPackageScanResult(scanResult, DUMMY_PACKAGE_NAME, false /*isInstant*/); 464 } 465 466 @Test updateFull_changeToInstant()467 public void updateFull_changeToInstant() throws Exception { 468 when(mMockUserManager.getUserIds()).thenReturn(new int[]{0}); 469 470 final PackageSetting existingPkgSetting = 471 createBasicPackageSettingBuilder(DUMMY_PACKAGE_NAME) 472 .setInstantAppUserState(0, false) 473 .build(); 474 475 final ScanRequest scanRequest = 476 createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME)) 477 .setPkgSetting(existingPkgSetting) 478 .addScanFlag(SCAN_AS_INSTANT_APP) 479 .build(); 480 481 482 final ScanResult scanResult = executeScan(scanRequest); 483 484 assertBasicPackageScanResult(scanResult, DUMMY_PACKAGE_NAME, true /*isInstant*/); 485 } 486 487 @Test updateSystemApp_applicationInfoFlagSet()488 public void updateSystemApp_applicationInfoFlagSet() throws Exception { 489 final PackageSetting existingPkgSetting = 490 createBasicPackageSettingBuilder(DUMMY_PACKAGE_NAME) 491 .setPkgFlags(ApplicationInfo.FLAG_SYSTEM) 492 .build(); 493 494 final ScanRequest scanRequest = 495 createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME)) 496 .setPkgSetting(existingPkgSetting) 497 .setDisabledPkgSetting(existingPkgSetting) 498 .addScanFlag(SCAN_NEW_INSTALL) 499 .build(); 500 501 final ScanResult scanResult = executeScan(scanRequest); 502 503 int appInfoFlags = PackageInfoUtils.appInfoFlags(scanResult.mRequest.mParsedPackage, 504 scanResult.mPkgSetting); 505 assertThat(appInfoFlags, hasFlag(ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)); 506 } 507 508 @Test factoryTestFlagSet()509 public void factoryTestFlagSet() throws Exception { 510 final ParsingPackage basicPackage = createBasicPackage(DUMMY_PACKAGE_NAME) 511 .addUsesPermission( 512 new ParsedUsesPermissionImpl(Manifest.permission.FACTORY_TEST, 0)); 513 514 final ScanResult scanResult = ScanPackageUtils.scanPackageOnly( 515 createBasicScanRequestBuilder(basicPackage).build(), 516 mMockInjector, 517 true /*isUnderFactoryTest*/, 518 System.currentTimeMillis()); 519 520 int appInfoFlags = PackageInfoUtils.appInfoFlags(scanResult.mRequest.mParsedPackage, 521 scanResult.mRequest.mPkgSetting); 522 assertThat(appInfoFlags, hasFlag(ApplicationInfo.FLAG_FACTORY_TEST)); 523 } 524 525 @Test scanSystemApp_isOrphanedTrue()526 public void scanSystemApp_isOrphanedTrue() throws Exception { 527 final ParsedPackage pkg = ((ParsedPackage) createBasicPackage(DUMMY_PACKAGE_NAME) 528 .hideAsParsed()) 529 .setSystem(true); 530 531 final ScanRequest scanRequest = 532 createBasicScanRequestBuilder(pkg) 533 .build(); 534 535 final ScanResult scanResult = executeScan(scanRequest); 536 537 assertThat(scanResult.mPkgSetting.getInstallSource().mIsOrphaned, is(true)); 538 } 539 hasFlag(final int flag)540 private static Matcher<Integer> hasFlag(final int flag) { 541 return new BaseMatcher<Integer>() { 542 @Override public void describeTo(Description description) { 543 description.appendText("flags "); 544 } 545 546 @Override public boolean matches(Object item) { 547 return ((int) item & flag) != 0; 548 } 549 550 @Override 551 public void describeMismatch(Object item, Description mismatchDescription) { 552 mismatchDescription 553 .appendValue(item) 554 .appendText(" does not contain flag ") 555 .appendValue(flag); 556 } 557 }; 558 } 559 560 private ScanResult executeScan( 561 ScanRequest scanRequest) throws PackageManagerException { 562 ScanResult result = ScanPackageUtils.scanPackageOnly( 563 scanRequest, 564 mMockInjector, 565 false /*isUnderFactoryTest*/, 566 System.currentTimeMillis()); 567 568 // Need to call hideAsFinal to cache derived fields. This is normally done in PMS, but not 569 // in this cut down flow used for the test. 570 ((ParsedPackage) result.mPkgSetting.getPkg()).hideAsFinal(); 571 return result; 572 } 573 574 private static String createCodePath(String packageName) { 575 return "/data/app/" + packageName + "-randompath"; 576 } 577 578 private static PackageSettingBuilder createBasicPackageSettingBuilder(String packageName) { 579 return new PackageSettingBuilder() 580 .setName(packageName) 581 .setCodePath(createCodePath(packageName)); 582 } 583 584 private static ScanRequestBuilder createBasicScanRequestBuilder(ParsingPackage pkg) { 585 return new ScanRequestBuilder((ParsedPackage) pkg.hideAsParsed()) 586 .setUser(UserHandle.of(0)); 587 } 588 589 private static ScanRequestBuilder createBasicScanRequestBuilder(ParsedPackage pkg) { 590 return new ScanRequestBuilder(pkg) 591 .setUser(UserHandle.of(0)); 592 } 593 594 private static ParsingPackage createBasicPackage(String packageName) { 595 // TODO(b/135203078): Make this use PackageImpl.forParsing and separate the steps 596 return (ParsingPackage) ((ParsedPackage) new PackageImpl(packageName, 597 "/data/tmp/randompath/base.apk", createCodePath(packageName), 598 mock(TypedArray.class), false, null) 599 .setVolumeUuid(UUID_ONE.toString()) 600 .addUsesStaticLibrary("some.static.library", 234L, new String[]{"testCert1"}) 601 .addUsesStaticLibrary("some.other.static.library", 456L, new String[]{"testCert2"}) 602 .addUsesSdkLibrary("some.sdk.library", 123L, new String[]{"testCert3"}, false) 603 .addUsesSdkLibrary("some.other.sdk.library", 789L, new String[]{"testCert4"}, true) 604 .hideAsParsed()) 605 .setNativeLibraryRootDir("/data/tmp/randompath/base.apk:/lib") 606 .setVersionCodeMajor(1) 607 .setVersionCode(2345); 608 } 609 610 private static void assertBasicPackageScanResult( 611 ScanResult scanResult, String packageName, boolean isInstant) { 612 613 final PackageSetting pkgSetting = scanResult.mPkgSetting; 614 assertBasicPackageSetting(scanResult, packageName, isInstant, pkgSetting); 615 616 final ApplicationInfo applicationInfo = PackageInfoUtils.generateApplicationInfo( 617 pkgSetting.getPkg(), 0, pkgSetting.getUserStateOrDefault(0), 0, pkgSetting); 618 assertBasicApplicationInfo(scanResult, applicationInfo); 619 } 620 621 private static void assertBasicPackageSetting(ScanResult scanResult, 622 String packageName, boolean isInstant, PackageSetting pkgSetting) { 623 assertThat(pkgSetting.getPkg().getPackageName(), is(packageName)); 624 assertThat(pkgSetting.getInstantApp(0), is(isInstant)); 625 assertThat(pkgSetting.getUsesStaticLibraries(), 626 arrayContaining("some.static.library", "some.other.static.library")); 627 assertThat(pkgSetting.getUsesStaticLibrariesVersions(), is(new long[]{234L, 456L})); 628 assertThat(pkgSetting.getUsesSdkLibraries(), 629 arrayContaining("some.sdk.library", "some.other.sdk.library")); 630 assertThat(pkgSetting.getUsesSdkLibrariesVersionsMajor(), is(new long[]{123L, 789L})); 631 assertThat(pkgSetting.getUsesSdkLibrariesOptional(), is(new boolean[]{false, true})); 632 assertThat(pkgSetting.getPkg(), is(scanResult.mRequest.mParsedPackage)); 633 assertThat(pkgSetting.getPath(), is(new File(createCodePath(packageName)))); 634 assertThat(pkgSetting.getVersionCode(), 635 is(PackageInfo.composeLongVersionCode(1, 2345))); 636 } 637 638 private static void assertBasicApplicationInfo(ScanResult scanResult, 639 ApplicationInfo applicationInfo) { 640 assertThat(applicationInfo.processName, 641 is(scanResult.mRequest.mParsedPackage.getPackageName())); 642 643 final int uid = applicationInfo.uid; 644 assertThat(UserHandle.getUserId(uid), is(UserHandle.USER_SYSTEM)); 645 646 final String calculatedCredentialId = Environment.getDataUserCePackageDirectory( 647 applicationInfo.volumeUuid, UserHandle.USER_SYSTEM, 648 scanResult.mRequest.mParsedPackage.getPackageName()).getAbsolutePath(); 649 assertThat(applicationInfo.credentialProtectedDataDir, is(calculatedCredentialId)); 650 assertThat(applicationInfo.dataDir, is(applicationInfo.credentialProtectedDataDir)); 651 } 652 653 private static void assertAbiAndPathssDerived(ScanResult scanResult) { 654 PackageSetting pkgSetting = scanResult.mPkgSetting; 655 final ApplicationInfo applicationInfo = PackageInfoUtils.generateApplicationInfo( 656 pkgSetting.getPkg(), 0, pkgSetting.getUserStateOrDefault(0), 0, pkgSetting); 657 assertThat(applicationInfo.primaryCpuAbi, is("derivedPrimary")); 658 assertThat(applicationInfo.secondaryCpuAbi, is("derivedSecondary")); 659 660 assertThat(applicationInfo.nativeLibraryRootDir, is("derivedRootDir")); 661 assertThat(pkgSetting.getLegacyNativeLibraryPath(), is("derivedRootDir")); 662 assertThat(applicationInfo.nativeLibraryRootRequiresIsa, is(true)); 663 assertThat(applicationInfo.nativeLibraryDir, is("derivedNativeDir")); 664 assertThat(applicationInfo.secondaryNativeLibraryDir, is("derivedNativeDir2")); 665 } 666 667 private static void assertPathsNotDerived(ScanResult scanResult) { 668 PackageSetting pkgSetting = scanResult.mPkgSetting; 669 final ApplicationInfo applicationInfo = PackageInfoUtils.generateApplicationInfo( 670 pkgSetting.getPkg(), 0, pkgSetting.getUserStateOrDefault(0), 0, pkgSetting); 671 assertThat(applicationInfo.nativeLibraryRootDir, is("getRootDir")); 672 assertThat(pkgSetting.getLegacyNativeLibraryPath(), is("getRootDir")); 673 assertThat(applicationInfo.nativeLibraryRootRequiresIsa, is(true)); 674 assertThat(applicationInfo.nativeLibraryDir, is("getNativeDir")); 675 assertThat(applicationInfo.secondaryNativeLibraryDir, is("getNativeDir2")); 676 } 677 } 678