1 /* <lambda>null2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.server.pm 17 18 import android.content.Context 19 import android.content.Intent 20 import android.content.pm.ActivityInfo 21 import android.content.pm.ApplicationInfo 22 import android.content.pm.FallbackCategoryProvider 23 import android.content.pm.FeatureInfo 24 import android.content.pm.PackageParser.SigningDetails 25 import android.content.pm.ResolveInfo 26 import android.content.pm.ServiceInfo 27 import android.content.pm.Signature 28 import android.content.pm.UserInfo 29 import android.content.pm.parsing.ParsingPackage 30 import android.content.pm.parsing.ParsingPackageUtils 31 import android.content.res.Resources 32 import android.hardware.display.DisplayManager 33 import android.os.Build 34 import android.os.Environment 35 import android.os.SystemProperties 36 import android.os.UserHandle 37 import android.os.UserManager 38 import android.os.incremental.IncrementalManager 39 import android.provider.DeviceConfig 40 import android.util.ArrayMap 41 import android.util.DisplayMetrics 42 import android.util.EventLog 43 import android.view.Display 44 import com.android.dx.mockito.inline.extended.ExtendedMockito 45 import com.android.dx.mockito.inline.extended.ExtendedMockito.any 46 import com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean 47 import com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt 48 import com.android.dx.mockito.inline.extended.ExtendedMockito.anyString 49 import com.android.dx.mockito.inline.extended.ExtendedMockito.argThat 50 import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn 51 import com.android.dx.mockito.inline.extended.ExtendedMockito.eq 52 import com.android.dx.mockito.inline.extended.ExtendedMockito.spy 53 import com.android.dx.mockito.inline.extended.StaticMockitoSession 54 import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder 55 import com.android.internal.R 56 import com.android.server.LocalServices 57 import com.android.server.LockGuard 58 import com.android.server.SystemConfig 59 import com.android.server.SystemServerInitThreadPool 60 import com.android.server.compat.PlatformCompat 61 import com.android.server.extendedtestutils.wheneverStatic 62 import com.android.server.pm.dex.DexManager 63 import com.android.server.pm.parsing.PackageParser2 64 import com.android.server.pm.parsing.pkg.AndroidPackage 65 import com.android.server.pm.parsing.pkg.PackageImpl 66 import com.android.server.pm.parsing.pkg.ParsedPackage 67 import com.android.server.pm.permission.PermissionManagerServiceInternal 68 import com.android.server.pm.verify.domain.DomainVerificationManagerInternal 69 import com.android.server.testutils.TestHandler 70 import com.android.server.testutils.mock 71 import com.android.server.testutils.nullable 72 import com.android.server.testutils.whenever 73 import com.android.server.utils.WatchedArrayMap 74 import org.junit.Assert 75 import org.junit.rules.TestRule 76 import org.junit.runner.Description 77 import org.junit.runners.model.Statement 78 import org.mockito.AdditionalMatchers.or 79 import org.mockito.quality.Strictness 80 import java.io.File 81 import java.io.IOException 82 import java.nio.file.Files 83 import java.security.PublicKey 84 import java.security.cert.CertificateException 85 import java.util.Arrays 86 import java.util.Random 87 import java.util.concurrent.FutureTask 88 89 /** 90 * A utility for mocking behavior of the system and dependencies when testing PackageManagerService 91 * 92 * Create one of these and call [stageNominalSystemState] as a basis for additional behavior in most 93 * tests. 94 */ 95 class MockSystem(withSession: (StaticMockitoSessionBuilder) -> Unit = {}) { 96 private val random = Random() 97 val mocks = Mocks() 98 val packageCacheDirectory: File = 99 Files.createTempDirectory("packageCache").toFile() 100 val rootDirectory: File = 101 Files.createTempDirectory("root").toFile() 102 val dataAppDirectory: File = 103 File(Files.createTempDirectory("data").toFile(), "app") 104 val frameworkSignature: SigningDetails = SigningDetails(arrayOf(generateSpySignature()), 3) 105 val systemPartitions: List<PackageManagerService.ScanPartition> = 106 redirectScanPartitions(PackageManagerService.SYSTEM_PARTITIONS) 107 val session: StaticMockitoSession 108 109 /** Tracks temporary files created by this class during the running of a test. */ 110 private val createdFiles = ArrayList<File>() 111 112 /** Settings that are expected to be added as part of the test */ 113 private val mPendingPackageAdds: MutableList<Pair<String, PackageSetting>> = ArrayList() 114 115 /** Settings simulated to be stored on disk */ 116 private val mPreExistingSettings = ArrayMap<String, PackageSetting>() 117 118 /** The active map simulating the in memory storage of Settings */ 119 private val mSettingsMap = WatchedArrayMap<String, PackageSetting>() 120 121 init { 122 val apply = ExtendedMockito.mockitoSession() 123 .strictness(Strictness.LENIENT) 124 .mockStatic(SystemProperties::class.java) 125 .mockStatic(SystemConfig::class.java) 126 .mockStatic(SELinuxMMAC::class.java) 127 .mockStatic(FallbackCategoryProvider::class.java) 128 .mockStatic(PackageManagerServiceUtils::class.java) 129 .mockStatic(Environment::class.java) 130 .mockStatic(SystemServerInitThreadPool::class.java) 131 .mockStatic(ParsingPackageUtils::class.java) 132 .mockStatic(LockGuard::class.java) 133 .mockStatic(EventLog::class.java) 134 .mockStatic(LocalServices::class.java) 135 .mockStatic(DeviceConfig::class.java) 136 .apply(withSession) 137 session = apply.startMocking() 138 whenever(mocks.settings.insertPackageSettingLPw( <lambda>null139 any(PackageSetting::class.java), any(AndroidPackage::class.java))) { 140 val name: String = (getArgument<Any>(0) as PackageSetting).name 141 val pendingAdd = 142 mPendingPackageAdds.firstOrNull { it.first == name } ?: return@whenever null 143 mPendingPackageAdds.remove(pendingAdd) 144 mSettingsMap[name] = pendingAdd.second 145 null 146 } 147 whenever(mocks.settings.addPackageLPw(nullable(), nullable(), nullable(), nullable(), 148 nullable(), nullable(), nullable(), nullable(), nullable(), nullable(), nullable(), <lambda>null149 nullable(), nullable(), nullable(), nullable())) { 150 val name: String = getArgument(0) 151 val pendingAdd = mPendingPackageAdds.firstOrNull { it.first == name } 152 ?: return@whenever null 153 mPendingPackageAdds.remove(pendingAdd) 154 mSettingsMap[name] = pendingAdd.second 155 pendingAdd.second 156 } 157 whenever(mocks.settings.packagesLocked).thenReturn(mSettingsMap) <lambda>null158 whenever(mocks.settings.getPackageLPr(anyString())) { mSettingsMap[getArgument<Any>(0)] } <lambda>null159 whenever(mocks.settings.readLPw(nullable())) { 160 mSettingsMap.putAll(mPreExistingSettings) 161 !mPreExistingSettings.isEmpty() 162 } 163 } 164 165 /** Collection of mocks used for PackageManagerService tests. */ 166 167 class Mocks { 168 val lock = PackageManagerTracedLock() 169 val installLock = Any() 170 val injector: PackageManagerService.Injector = mock() 171 val systemWrapper: PackageManagerService.SystemWrapper = mock() 172 val context: Context = mock() 173 val userManagerService: UserManagerService = mock() 174 val componentResolver: ComponentResolver = mock() 175 val permissionManagerInternal: PermissionManagerServiceInternal = mock() 176 val incrementalManager: IncrementalManager = mock() 177 val platformCompat: PlatformCompat = mock() 178 val settings: Settings = mock() 179 val resources: Resources = mock() 180 val systemConfig: SystemConfig = mock() 181 val apexManager: ApexManager = mock() 182 val userManagerInternal: UserManagerInternal = mock() 183 val packageParser: PackageParser2 = mock() 184 val keySetManagerService: KeySetManagerService = mock() 185 val packageAbiHelper: PackageAbiHelper = mock() 186 val appsFilter: AppsFilter = mock() 187 val dexManager: DexManager = mock() 188 val installer: Installer = mock() 189 val displayMetrics: DisplayMetrics = mock() 190 val domainVerificationManagerInternal: DomainVerificationManagerInternal = mock() 191 val handler = TestHandler(null) 192 } 193 194 companion object { 195 private const val DEVICE_PROVISIONING_PACKAGE_NAME = 196 "com.example.android.device.provisioning" 197 private val DEFAULT_AVAILABLE_FEATURES_MAP = ArrayMap<String, FeatureInfo>() 198 private val DEFAULT_ACTIVE_APEX_INFO_LIST = emptyList<ApexManager.ActiveApexInfo>() 199 private val DEFAULT_SHARED_LIBRARIES_LIST = 200 ArrayMap<String, SystemConfig.SharedLibraryEntry>() 201 private val DEFAULT_USERS = Arrays.asList( 202 UserInfo(UserHandle.USER_SYSTEM, "primary", "", 203 UserInfo.FLAG_PRIMARY or UserInfo.FLAG_SYSTEM or UserInfo.FLAG_FULL, 204 UserManager.USER_TYPE_FULL_SYSTEM)) 205 public val DEFAULT_VERSION_INFO = Settings.VersionInfo() 206 207 init { 208 DEFAULT_VERSION_INFO.fingerprint = "abcdef" 209 DEFAULT_VERSION_INFO.sdkVersion = Build.VERSION_CODES.R 210 DEFAULT_VERSION_INFO.databaseVersion = Settings.CURRENT_DATABASE_VERSION 211 } 212 } 213 214 /** 215 * Clean up any potentially dangling state. This should be run at the end of every test to 216 * account for changes to static memory, such as [LocalServices] 217 */ cleanupnull218 fun cleanup() { 219 createdFiles.forEach(File::delete) 220 createdFiles.clear() 221 mSettingsMap.clear() 222 mPendingPackageAdds.clear() 223 mPreExistingSettings.clear() 224 session.finishMocking() 225 } 226 227 /** 228 * Run this method to ensure that all expected actions were executed, such as pending 229 * [Settings] adds. 230 */ validateFinalStatenull231 fun validateFinalState() { 232 if (mPendingPackageAdds.isNotEmpty()) { 233 Assert.fail( 234 "Not all expected settings were added: ${mPendingPackageAdds.map { it.first }}") 235 } 236 } 237 238 /** 239 * This method stages enough of system startup to execute the PackageManagerService constructor 240 * successfullly. 241 */ 242 @Throws(Exception::class) stageNominalSystemStatenull243 fun stageNominalSystemState() { 244 whenever(mocks.injector.context).thenReturn(mocks.context) 245 whenever(mocks.injector.lock).thenReturn(mocks.lock) 246 whenever(mocks.injector.installLock).thenReturn(mocks.installLock) 247 whenever(mocks.injector.systemWrapper).thenReturn(mocks.systemWrapper) 248 whenever(mocks.injector.userManagerService).thenReturn(mocks.userManagerService) 249 whenever(mocks.injector.componentResolver).thenReturn(mocks.componentResolver) 250 whenever(mocks.injector.permissionManagerServiceInternal) { 251 mocks.permissionManagerInternal 252 } 253 whenever(mocks.injector.incrementalManager).thenReturn(mocks.incrementalManager) 254 whenever(mocks.injector.compatibility).thenReturn(mocks.platformCompat) 255 whenever(mocks.injector.settings).thenReturn(mocks.settings) 256 whenever(mocks.injector.dexManager).thenReturn(mocks.dexManager) 257 whenever(mocks.injector.systemConfig).thenReturn(mocks.systemConfig) 258 whenever(mocks.injector.apexManager).thenReturn(mocks.apexManager) 259 whenever(mocks.injector.scanningCachingPackageParser).thenReturn(mocks.packageParser) 260 whenever(mocks.injector.scanningPackageParser).thenReturn(mocks.packageParser) 261 whenever(mocks.injector.systemPartitions).thenReturn(systemPartitions) 262 whenever(mocks.injector.appsFilter).thenReturn(mocks.appsFilter) 263 whenever(mocks.injector.abiHelper).thenReturn(mocks.packageAbiHelper) 264 whenever(mocks.injector.userManagerInternal).thenReturn(mocks.userManagerInternal) 265 whenever(mocks.injector.installer).thenReturn(mocks.installer) 266 whenever(mocks.injector.displayMetrics).thenReturn(mocks.displayMetrics) 267 whenever(mocks.injector.domainVerificationManagerInternal) 268 .thenReturn(mocks.domainVerificationManagerInternal) 269 whenever(mocks.injector.handler) { mocks.handler } 270 wheneverStatic { SystemConfig.getInstance() }.thenReturn(mocks.systemConfig) 271 whenever(mocks.systemConfig.availableFeatures).thenReturn(DEFAULT_AVAILABLE_FEATURES_MAP) 272 whenever(mocks.systemConfig.sharedLibraries).thenReturn(DEFAULT_SHARED_LIBRARIES_LIST) 273 wheneverStatic { SystemProperties.getBoolean("fw.free_cache_v2", true) }.thenReturn(true) 274 wheneverStatic { Environment.getPackageCacheDirectory() }.thenReturn(packageCacheDirectory) 275 wheneverStatic { SystemProperties.digestOf("ro.build.fingerprint") }.thenReturn("cacheName") 276 wheneverStatic { Environment.getRootDirectory() }.thenReturn(rootDirectory) 277 wheneverStatic { SystemServerInitThreadPool.submit(any(Runnable::class.java), anyString()) } 278 .thenAnswer { FutureTask<Any?>(it.getArgument(0), null) } 279 280 wheneverStatic { Environment.getDataDirectory() }.thenReturn(dataAppDirectory.parentFile) 281 wheneverStatic { Environment.getDataSystemDirectory() } 282 .thenReturn(File(dataAppDirectory.parentFile, "system")) 283 whenever(mocks.context.resources).thenReturn(mocks.resources) 284 whenever(mocks.resources.getString(R.string.config_deviceProvisioningPackage)) { 285 DEVICE_PROVISIONING_PACKAGE_NAME 286 } 287 whenever(mocks.apexManager.activeApexInfos).thenReturn(DEFAULT_ACTIVE_APEX_INFO_LIST) 288 whenever(mocks.settings.packagesLocked).thenReturn(mSettingsMap) 289 whenever(mocks.settings.internalVersion).thenReturn(DEFAULT_VERSION_INFO) 290 whenever(mocks.settings.keySetManagerService).thenReturn(mocks.keySetManagerService) 291 whenever(mocks.settings.keySetManagerService).thenReturn(mocks.keySetManagerService) 292 whenever(mocks.settings.snapshot()).thenReturn(mocks.settings) 293 whenever(mocks.packageAbiHelper.derivePackageAbi( 294 any(AndroidPackage::class.java), anyBoolean(), nullable(), any(File::class.java))) { 295 android.util.Pair(PackageAbiHelper.Abis("", ""), 296 PackageAbiHelper.NativeLibraryPaths("", false, "", "")) 297 } 298 whenever(mocks.userManagerInternal.getUsers(true, false, false)).thenReturn(DEFAULT_USERS) 299 whenever(mocks.userManagerService.userIds).thenReturn(intArrayOf(0)) 300 whenever(mocks.userManagerService.exists(0)).thenReturn(true) 301 whenever(mocks.packageAbiHelper.deriveNativeLibraryPaths( 302 any(AndroidPackage::class.java), anyBoolean(), any(File::class.java))) { 303 PackageAbiHelper.NativeLibraryPaths("", false, "", "") 304 } 305 // everything visible by default 306 whenever(mocks.appsFilter.shouldFilterApplication( 307 anyInt(), nullable(), nullable(), anyInt())) { false } 308 309 val displayManager: DisplayManager = mock() 310 whenever(mocks.context.getSystemService(DisplayManager::class.java)) 311 .thenReturn(displayManager) 312 val display: Display = mock() 313 whenever(displayManager.getDisplay(Display.DEFAULT_DISPLAY)).thenReturn(display) 314 315 stageFrameworkScan() 316 stageInstallerScan() 317 stageServicesExtensionScan() 318 stageSystemSharedLibraryScan() 319 stagePermissionsControllerScan() 320 stageInstantAppResolverScan() 321 } 322 323 /** 324 * This method will stage the parsing and scanning of a package as well as add it to the 325 * [PackageSetting]s read from disk. 326 */ 327 @Throws(Exception::class) stageScanExistingPackagenull328 fun stageScanExistingPackage( 329 packageName: String, 330 versionCode: Long, 331 parent: File?, 332 withPackage: (PackageImpl) -> PackageImpl = { it }, 333 withSetting: <lambda>null334 (PackageSettingBuilder) -> PackageSettingBuilder = { it }, 335 withExistingSetting: <lambda>null336 (PackageSettingBuilder) -> PackageSettingBuilder = { it } 337 ) { 338 val existingSettingBuilderRef = arrayOfNulls<PackageSettingBuilder>(1) 339 stageScanNewPackage(packageName, versionCode, parent, withPackage, settingBuildernull340 withSetting = { settingBuilder -> 341 withSetting(settingBuilder) 342 existingSettingBuilderRef[0] = settingBuilder 343 settingBuilder 344 }) 345 existingSettingBuilderRef[0]?.setPackage(null) <lambda>null346 val packageSetting = existingSettingBuilderRef[0]?.let { withExistingSetting(it) }!!.build() 347 addPreExistingSetting(packageName, packageSetting) 348 } 349 350 /** 351 * This method will stage a [PackageSetting] read from disk, but does not stage any scanning 352 * or parsing of the package. 353 */ addPreExistingSettingnull354 fun addPreExistingSetting(packageName: String, packageSetting: PackageSetting) { 355 mPreExistingSettings[packageName] = packageSetting 356 } 357 358 /** 359 * This method will stage the parsing and scanning of a package but will not add it to the set 360 * of [PackageSetting]s read from disk. 361 */ 362 @Throws(Exception::class) stageScanNewPackagenull363 fun stageScanNewPackage( 364 packageName: String, 365 versionCode: Long, 366 parent: File?, 367 withPackage: (PackageImpl) -> PackageImpl = { it }, <lambda>null368 withSetting: (PackageSettingBuilder) -> PackageSettingBuilder = { it } 369 ) { 370 val pair = createBasicAndroidPackage(parent, packageName, versionCode) 371 val apkPath = pair.first 372 val pkg = withPackage(pair.second) 373 stageParse(apkPath, pkg) 374 val parentFile = apkPath.parentFile 375 val settingBuilder = withSetting(createBasicSettingBuilder(parentFile, pkg)) 376 stageSettingInsert(packageName, settingBuilder.build()) 377 } 378 379 /** 380 * Creates a simple package that should reasonably parse for scan operations. This can be used 381 * as a basis for more complicated packages. 382 */ createBasicAndroidPackagenull383 fun createBasicAndroidPackage( 384 parent: File?, 385 packageName: String, 386 versionCode: Long, 387 signingDetails: SigningDetails = 388 createRandomSigningDetails() 389 ): Pair<File, PackageImpl> { 390 val apkPath = File(File(parent, packageName), "base.apk") 391 val pkg = PackageImpl.forTesting(packageName, apkPath.parentFile.path) as PackageImpl 392 pkg.signingDetails = signingDetails 393 wheneverStatic { ParsingPackageUtils.getSigningDetails(eq(pkg), anyBoolean()) } 394 .thenReturn(signingDetails) 395 pkg.versionCode = versionCode.toInt() 396 pkg.versionCodeMajor = (versionCode shr 32).toInt() 397 pkg.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT 398 return Pair(apkPath, pkg) 399 } 400 401 /** 402 * This method will create a spy of a [SigningDetails] object to be used when simulating the 403 * collection of signatures. 404 */ createRandomSigningDetailsnull405 fun createRandomSigningDetails(): SigningDetails { 406 val signingDetails = spy(SigningDetails(arrayOf(generateSpySignature()), 407 SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3)) 408 doReturn(true).whenever(signingDetails).checkCapability( 409 anyString(), anyInt()) 410 doReturn(true).whenever(signingDetails).checkCapability( 411 any(SigningDetails::class.java), anyInt()) 412 return signingDetails 413 } 414 415 /** 416 * This method will create a basic [PackageSettingBuilder] from an [AndroidPackage] with all of 417 * the necessary parameters to be returned by a simple scan. This can be used as a basis for 418 * more complicated settings. 419 */ createBasicSettingBuildernull420 fun createBasicSettingBuilder(parentFile: File, pkg: AndroidPackage): PackageSettingBuilder { 421 return createBasicSettingBuilder(parentFile, pkg.packageName, pkg.longVersionCode, 422 pkg.signingDetails) 423 .setPackage(pkg) 424 } 425 426 /** 427 * This method will create a basic [PackageSettingBuilder] with all of the necessary parameters 428 * to be returned by a simple scan. This can be used as a basis for more complicated settings. 429 */ createBasicSettingBuildernull430 fun createBasicSettingBuilder( 431 parentFile: File, 432 packageName: String, 433 versionCode: Long, 434 signingDetails: SigningDetails 435 ): PackageSettingBuilder { 436 return PackageSettingBuilder() 437 .setCodePath(parentFile.path) 438 .setName(packageName) 439 .setPVersionCode(versionCode) 440 .setSigningDetails(signingDetails) 441 } 442 createBasicApplicationInfonull443 fun createBasicApplicationInfo(pkg: ParsingPackage): ApplicationInfo { 444 val applicationInfo: ApplicationInfo = mock() 445 applicationInfo.packageName = pkg.packageName 446 return applicationInfo 447 } 448 createBasicActivityInfonull449 fun createBasicActivityInfo( 450 pkg: ParsingPackage, 451 applicationInfo: ApplicationInfo?, 452 className: String? 453 ): 454 ActivityInfo { 455 val activityInfo = ActivityInfo() 456 activityInfo.applicationInfo = applicationInfo 457 activityInfo.packageName = pkg.packageName 458 activityInfo.name = className 459 return activityInfo 460 } 461 createBasicServiceInfonull462 fun createBasicServiceInfo( 463 pkg: ParsingPackage, 464 applicationInfo: ApplicationInfo?, 465 className: String? 466 ): 467 ServiceInfo { 468 val serviceInfo = ServiceInfo() 469 serviceInfo.applicationInfo = applicationInfo 470 serviceInfo.packageName = pkg.packageName 471 serviceInfo.name = className 472 return serviceInfo 473 } 474 475 /** Finds the appropriate partition, if available, based on a scan flag unique to it. */ getPartitionFromFlagnull476 fun getPartitionFromFlag(scanFlagMask: Int): PackageManagerService.ScanPartition = 477 systemPartitions.first { (it.scanFlag and scanFlagMask) != 0 } 478 479 @Throws(Exception::class) stageParsenull480 private fun stageParse(path: File, parseResult: ParsingPackage): ParsedPackage { 481 val basePath = path.parentFile 482 basePath.mkdirs() 483 path.createNewFile() 484 createdFiles.add(path) 485 val parsedPackage = parseResult.hideAsParsed() as ParsedPackage 486 whenever(mocks.packageParser.parsePackage( 487 or(eq(path), eq(basePath)), anyInt(), anyBoolean())) { parsedPackage } 488 return parsedPackage 489 } 490 stageSettingInsertnull491 private fun stageSettingInsert(name: String, setting: PackageSetting): PackageSetting { 492 mPendingPackageAdds.add(Pair(name, setting)) 493 return setting 494 } 495 496 @Throws(Exception::class) stageFrameworkScannull497 private fun stageFrameworkScan() { 498 val apk = File(File(rootDirectory, "framework"), "framework-res.apk") 499 val frameworkPkg = PackageImpl.forTesting("android", 500 apk.parentFile.path) as PackageImpl 501 wheneverStatic { ParsingPackageUtils.getSigningDetails(frameworkPkg, true) } 502 .thenReturn(frameworkSignature) 503 stageParse(apk, frameworkPkg) 504 stageSettingInsert("android", 505 PackageSettingBuilder().setCodePath(apk.path).setName( 506 "android").setPackage(frameworkPkg).build()) 507 } 508 509 @Throws(Exception::class) stageInstantAppResolverScannull510 private fun stageInstantAppResolverScan() { 511 whenever(mocks.resources.getStringArray(R.array.config_ephemeralResolverPackage)) { 512 arrayOf("com.android.test.ephemeral.resolver") 513 } 514 stageScanNewPackage("com.android.test.ephemeral.resolver", 515 1L, getPartitionFromFlag(PackageManagerService.SCAN_AS_PRODUCT).privAppFolder, 516 withPackage = { pkg: PackageImpl -> 517 val applicationInfo: ApplicationInfo = createBasicApplicationInfo(pkg) 518 whenever(applicationInfo.isPrivilegedApp).thenReturn(true) 519 mockQueryServices(Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE, 520 createBasicServiceInfo(pkg, applicationInfo, "test.EphemeralService")) 521 mockQueryActivities(Intent.ACTION_INSTANT_APP_RESOLVER_SETTINGS, 522 createBasicActivityInfo(pkg, applicationInfo, "test.SettingsActivity")) 523 pkg 524 }, 525 withSetting = { setting: PackageSettingBuilder -> 526 setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM) 527 }) 528 } 529 530 @Throws(Exception::class) stagePermissionsControllerScannull531 private fun stagePermissionsControllerScan() { 532 stageScanNewPackage("com.android.permissions.controller", 533 1L, systemPartitions[0].privAppFolder, 534 withPackage = { pkg: PackageImpl -> 535 val applicationInfo: ApplicationInfo = createBasicApplicationInfo(pkg) 536 whenever(applicationInfo.isPrivilegedApp).thenReturn(true) 537 mockQueryActivities(Intent.ACTION_MANAGE_PERMISSIONS, 538 createBasicActivityInfo( 539 pkg, applicationInfo, "test.PermissionActivity")) 540 pkg 541 }, 542 withSetting = { setting: PackageSettingBuilder -> 543 setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM) 544 }) 545 } 546 547 @Throws(Exception::class) stageSystemSharedLibraryScannull548 private fun stageSystemSharedLibraryScan() { 549 stageScanNewPackage("android.ext.shared", 550 1L, systemPartitions[0].appFolder, 551 withPackage = { it.addLibraryName("android.ext.shared") as PackageImpl }, 552 withSetting = { setting: PackageSettingBuilder -> 553 setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM) 554 } 555 ) 556 } 557 558 @Throws(Exception::class) stageServicesExtensionScannull559 private fun stageServicesExtensionScan() { 560 whenever(mocks.context.getString(R.string.config_servicesExtensionPackage)) { 561 "com.android.test.services.extension" 562 } 563 stageScanNewPackage("com.android.test.services.extension", 564 1L, getPartitionFromFlag(PackageManagerService.SCAN_AS_SYSTEM_EXT).privAppFolder, 565 withSetting = { setting: PackageSettingBuilder -> 566 setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM) 567 }) 568 } 569 570 @Throws(Exception::class) stageInstallerScannull571 private fun stageInstallerScan() { 572 stageScanNewPackage( 573 "com.android.test.installer", 574 1L, getPartitionFromFlag(PackageManagerService.SCAN_AS_PRODUCT).privAppFolder, 575 withPackage = { pkg: PackageImpl -> 576 val applicationInfo: ApplicationInfo = createBasicApplicationInfo(pkg) 577 whenever(applicationInfo.isPrivilegedApp).thenReturn(true) 578 val installerActivity: ActivityInfo = createBasicActivityInfo( 579 pkg, applicationInfo, "test.InstallerActivity") 580 mockQueryActivities(Intent.ACTION_INSTALL_PACKAGE, installerActivity) 581 mockQueryActivities(Intent.ACTION_UNINSTALL_PACKAGE, installerActivity) 582 mockQueryActivities(Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE, 583 installerActivity) 584 pkg 585 }, 586 withSetting = { setting: PackageSettingBuilder -> 587 setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM) 588 } 589 ) 590 } 591 mockQueryActivitiesnull592 private fun mockQueryActivities(action: String, vararg activities: ActivityInfo) { 593 whenever(mocks.componentResolver.queryActivities( 594 argThat { intent: Intent? -> intent != null && (action == intent.action) }, 595 nullable(), anyInt(), anyInt())) { 596 ArrayList(activities.asList().map { info: ActivityInfo? -> 597 ResolveInfo().apply { activityInfo = info } 598 }) 599 } 600 } 601 mockQueryServicesnull602 private fun mockQueryServices(action: String, vararg services: ServiceInfo) { 603 whenever(mocks.componentResolver.queryServices( 604 argThat { intent: Intent? -> intent != null && (action == intent.action) }, 605 nullable(), anyInt(), anyInt())) { 606 ArrayList(services.asList().map { info -> 607 ResolveInfo().apply { serviceInfo = info } 608 }) 609 } 610 } 611 generateSpySignaturenull612 fun generateSpySignature(): Signature { 613 val bytes = ByteArray(32) 614 random.nextBytes(bytes) 615 val signature = spy(Signature(bytes)) 616 try { 617 val mockPublicKey: PublicKey = mock() 618 doReturn(mockPublicKey).whenever(signature).getPublicKey() 619 } catch (e: CertificateException) { 620 throw RuntimeException(e) 621 } 622 return signature 623 } 624 625 /** Override get*Folder methods to point to temporary local directories */ 626 627 @Throws(IOException::class) redirectScanPartitionsnull628 private fun redirectScanPartitions(partitions: List<PackageManagerService.ScanPartition>): 629 List<PackageManagerService.ScanPartition> { 630 val spiedPartitions: MutableList<PackageManagerService.ScanPartition> = 631 ArrayList(partitions.size) 632 for (partition: PackageManagerService.ScanPartition in partitions) { 633 val spy = spy(partition) 634 val newRoot = Files.createTempDirectory(partition.folder.name).toFile() 635 whenever(spy.overlayFolder).thenReturn(File(newRoot, "overlay")) 636 whenever(spy.appFolder).thenReturn(File(newRoot, "app")) 637 whenever(spy.privAppFolder).thenReturn(File(newRoot, "priv-app")) 638 whenever(spy.folder).thenReturn(newRoot) 639 spiedPartitions.add(spy) 640 } 641 return spiedPartitions 642 } 643 } 644 645 /** 646 * Sets up a basic [MockSystem] for use in a test method. This will create a MockSystem before the 647 * test method and any [org.junit.Before] annotated methods. It can then be used to access the 648 * MockSystem via the [system] method or the mocks directly via [mocks]. 649 */ 650 class MockSystemRule : TestRule { 651 var mockSystem: MockSystem? = null applynull652 override fun apply(base: Statement?, description: Description?) = object : Statement() { 653 @Throws(Throwable::class) 654 override fun evaluate() { 655 mockSystem = MockSystem() 656 try { 657 base!!.evaluate() 658 } finally { 659 mockSystem?.cleanup() 660 mockSystem = null 661 } 662 } 663 } 664 665 /** Fetch the [MockSystem] instance prepared for this test */ systemnull666 fun system(): MockSystem = mockSystem!! 667 /** Fetch the [MockSystem.Mocks] prepared for this test */ 668 fun mocks(): MockSystem.Mocks = mockSystem!!.mocks 669 } 670