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.app.PropertyInvalidatedCache 19 import android.content.Context 20 import android.content.Intent 21 import android.content.pm.ActivityInfo 22 import android.content.pm.ApplicationInfo 23 import android.content.pm.FallbackCategoryProvider 24 import android.content.pm.FeatureInfo 25 import android.content.pm.ResolveInfo 26 import android.content.pm.ServiceInfo 27 import android.content.pm.Signature 28 import android.content.pm.SigningDetails 29 import android.content.pm.UserInfo 30 import android.content.pm.parsing.result.ParseTypeImpl 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.anyLong 49 import com.android.dx.mockito.inline.extended.ExtendedMockito.anyString 50 import com.android.dx.mockito.inline.extended.ExtendedMockito.argThat 51 import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn 52 import com.android.dx.mockito.inline.extended.ExtendedMockito.eq 53 import com.android.dx.mockito.inline.extended.ExtendedMockito.spy 54 import com.android.dx.mockito.inline.extended.StaticMockitoSession 55 import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder 56 import com.android.internal.R 57 import com.android.server.LocalServices 58 import com.android.server.LockGuard 59 import com.android.server.SystemConfig 60 import com.android.server.SystemServerInitThreadPool 61 import com.android.server.compat.PlatformCompat 62 import com.android.server.extendedtestutils.wheneverStatic 63 import com.android.server.pm.dex.DexManager 64 import com.android.server.pm.parsing.PackageParser2 65 import com.android.server.pm.parsing.pkg.AndroidPackage 66 import com.android.server.pm.parsing.pkg.PackageImpl 67 import com.android.server.pm.parsing.pkg.ParsedPackage 68 import com.android.server.pm.permission.PermissionManagerServiceInternal 69 import com.android.server.pm.pkg.parsing.ParsingPackage 70 import com.android.server.pm.pkg.parsing.ParsingPackageUtils 71 import com.android.server.pm.resolution.ComponentResolver 72 import com.android.server.pm.snapshot.PackageDataSnapshot 73 import com.android.server.pm.verify.domain.DomainVerificationManagerInternal 74 import com.android.server.sdksandbox.SdkSandboxManagerLocal 75 import com.android.server.testutils.TestHandler 76 import com.android.server.testutils.mock 77 import com.android.server.testutils.nullable 78 import com.android.server.testutils.whenever 79 import com.android.server.utils.WatchedArrayMap 80 import libcore.util.HexEncoding 81 import org.junit.Assert 82 import org.junit.rules.TestRule 83 import org.junit.runner.Description 84 import org.junit.runners.model.Statement 85 import org.mockito.AdditionalMatchers.or 86 import org.mockito.quality.Strictness 87 import java.io.File 88 import java.io.IOException 89 import java.nio.file.Files 90 import java.security.PublicKey 91 import java.security.cert.CertificateException 92 import java.util.Arrays 93 import java.util.Random 94 import java.util.concurrent.FutureTask 95 96 /** 97 * A utility for mocking behavior of the system and dependencies when testing PackageManagerService 98 * 99 * Create one of these and call [stageNominalSystemState] as a basis for additional behavior in most 100 * tests. 101 */ 102 class MockSystem(withSession: (StaticMockitoSessionBuilder) -> Unit = {}) { 103 private val random = Random() 104 val mocks = Mocks() 105 val packageCacheDirectory: File = 106 Files.createTempDirectory("packageCache").toFile() 107 val rootDirectory: File = 108 Files.createTempDirectory("root").toFile() 109 val dataAppDirectory: File = 110 File(Files.createTempDirectory("data").toFile(), "app") 111 val frameworkSignature: SigningDetails = SigningDetails(arrayOf(generateSpySignature()), 3) 112 val systemPartitions: List<ScanPartition> = 113 redirectScanPartitions(PackageManagerService.SYSTEM_PARTITIONS) 114 val session: StaticMockitoSession 115 116 /** Tracks temporary files created by this class during the running of a test. */ 117 private val createdFiles = ArrayList<File>() 118 119 /** Settings that are expected to be added as part of the test */ 120 private val mPendingPackageAdds: MutableList<Pair<String, PackageSetting>> = ArrayList() 121 122 /** Settings simulated to be stored on disk */ 123 private val mPreExistingSettings = ArrayMap<String, PackageSetting>() 124 125 /** The active map simulating the in memory storage of Settings */ 126 private val mSettingsMap = WatchedArrayMap<String, PackageSetting>() 127 128 /** The shared libraries on the device */ 129 private lateinit var mSharedLibraries: SharedLibrariesImpl 130 131 init { 132 PropertyInvalidatedCache.disableForTestMode() 133 val apply = ExtendedMockito.mockitoSession() 134 .strictness(Strictness.LENIENT) 135 .mockStatic(SystemProperties::class.java) 136 .mockStatic(SystemConfig::class.java) 137 .mockStatic(SELinuxMMAC::class.java) 138 .mockStatic(FallbackCategoryProvider::class.java) 139 .mockStatic(PackageManagerServiceUtils::class.java) 140 .mockStatic(Environment::class.java) 141 .mockStatic(SystemServerInitThreadPool::class.java) 142 .mockStatic(ParsingPackageUtils::class.java) 143 .mockStatic(LockGuard::class.java) 144 .mockStatic(EventLog::class.java) 145 .mockStatic(LocalServices::class.java) 146 .mockStatic(DeviceConfig::class.java) 147 .mockStatic(HexEncoding::class.java) 148 .apply(withSession) 149 session = apply.startMocking() 150 whenever(mocks.settings.insertPackageSettingLPw( <lambda>null151 any(PackageSetting::class.java), any(AndroidPackage::class.java))) { 152 val name: String = (getArgument<Any>(0) as PackageSetting).name 153 val pendingAdd = 154 mPendingPackageAdds.firstOrNull { it.first == name } ?: return@whenever null 155 mPendingPackageAdds.remove(pendingAdd) 156 mSettingsMap[name] = pendingAdd.second 157 null 158 } 159 whenever(mocks.settings.addPackageLPw(nullable(), nullable(), nullable(), nullable(), 160 nullable(), nullable(), nullable(), nullable(), nullable(), nullable(), nullable(), <lambda>null161 nullable(), nullable(), nullable(), nullable(), nullable(), nullable())) { 162 val name: String = getArgument(0) 163 val pendingAdd = mPendingPackageAdds.firstOrNull { it.first == name } 164 ?: return@whenever null 165 mPendingPackageAdds.remove(pendingAdd) 166 mSettingsMap[name] = pendingAdd.second 167 pendingAdd.second 168 } 169 whenever(mocks.settings.packagesLocked).thenReturn(mSettingsMap) <lambda>null170 whenever(mocks.settings.getPackageLPr(anyString())) { mSettingsMap[getArgument<Any>(0)] } <lambda>null171 whenever(mocks.settings.readLPw(any(), nullable())) { 172 mSettingsMap.putAll(mPreExistingSettings) 173 !mPreExistingSettings.isEmpty() 174 } 175 } 176 177 /** Collection of mocks used for PackageManagerService tests. */ 178 179 class Mocks { 180 val lock = PackageManagerTracedLock() 181 val installLock = Any() 182 val injector: PackageManagerServiceInjector = mock() 183 val systemWrapper: PackageManagerServiceInjector.SystemWrapper = mock() 184 val context: Context = mock() 185 val userManagerService: UserManagerService = mock() 186 val componentResolver: ComponentResolver = mock() 187 val permissionManagerInternal: PermissionManagerServiceInternal = mock() 188 val incrementalManager: IncrementalManager = mock() 189 val platformCompat: PlatformCompat = mock() 190 val settings: Settings = mock() 191 val resources: Resources = mock() 192 val systemConfig: SystemConfig = mock() 193 val apexManager: ApexManager = mock() 194 val userManagerInternal: UserManagerInternal = mock() 195 val packageParser: PackageParser2 = mock() 196 val keySetManagerService: KeySetManagerService = mock() 197 val packageAbiHelper: PackageAbiHelper = mock() 198 val appsFilterSnapshot: AppsFilterSnapshotImpl = mock() <lambda>null199 val appsFilter: AppsFilterImpl = mock { 200 whenever(snapshot()) { appsFilterSnapshot } 201 } 202 val dexManager: DexManager = mock() 203 val installer: Installer = mock() 204 val displayMetrics: DisplayMetrics = mock() 205 val domainVerificationManagerInternal: DomainVerificationManagerInternal = mock() 206 val handler = TestHandler(null) 207 val defaultAppProvider: DefaultAppProvider = mock() 208 val backgroundHandler = TestHandler(null) 209 } 210 211 companion object { 212 private const val DEVICE_PROVISIONING_PACKAGE_NAME = 213 "com.example.android.device.provisioning" 214 private val DEFAULT_AVAILABLE_FEATURES_MAP = ArrayMap<String, FeatureInfo>() 215 private val DEFAULT_ACTIVE_APEX_INFO_LIST = emptyList<ApexManager.ActiveApexInfo>() 216 private val DEFAULT_SHARED_LIBRARIES_LIST = 217 ArrayMap<String, SystemConfig.SharedLibraryEntry>() 218 private val DEFAULT_USERS = Arrays.asList( 219 UserInfo(UserHandle.USER_SYSTEM, "primary", "", 220 UserInfo.FLAG_PRIMARY or UserInfo.FLAG_SYSTEM or UserInfo.FLAG_FULL, 221 UserManager.USER_TYPE_FULL_SYSTEM)) 222 public val DEFAULT_VERSION_INFO = Settings.VersionInfo() 223 224 init { 225 DEFAULT_VERSION_INFO.fingerprint = "abcdef" 226 DEFAULT_VERSION_INFO.sdkVersion = Build.VERSION_CODES.R 227 DEFAULT_VERSION_INFO.databaseVersion = Settings.CURRENT_DATABASE_VERSION 228 } 229 addDefaultSharedLibrarynull230 fun addDefaultSharedLibrary(libName: String, libEntry: SystemConfig.SharedLibraryEntry) { 231 DEFAULT_SHARED_LIBRARIES_LIST[libName] = libEntry 232 } 233 } 234 235 /** 236 * Clean up any potentially dangling state. This should be run at the end of every test to 237 * account for changes to static memory, such as [LocalServices] 238 */ cleanupnull239 fun cleanup() { 240 createdFiles.forEach(File::delete) 241 createdFiles.clear() 242 mSettingsMap.clear() 243 mPendingPackageAdds.clear() 244 mPreExistingSettings.clear() 245 session.finishMocking() 246 } 247 248 /** 249 * Run this method to ensure that all expected actions were executed, such as pending 250 * [Settings] adds. 251 */ validateFinalStatenull252 fun validateFinalState() { 253 if (mPendingPackageAdds.isNotEmpty()) { 254 Assert.fail( 255 "Not all expected settings were added: ${mPendingPackageAdds.map { it.first }}") 256 } 257 } 258 259 /** 260 * This method stages enough of system startup to execute the PackageManagerService constructor 261 * successfullly. 262 */ 263 @Throws(Exception::class) stageNominalSystemStatenull264 fun stageNominalSystemState() { 265 whenever(mocks.injector.context).thenReturn(mocks.context) 266 whenever(mocks.injector.lock).thenReturn(mocks.lock) 267 whenever(mocks.injector.installLock).thenReturn(mocks.installLock) 268 whenever(mocks.injector.systemWrapper).thenReturn(mocks.systemWrapper) 269 whenever(mocks.injector.userManagerService).thenReturn(mocks.userManagerService) 270 whenever(mocks.injector.componentResolver).thenReturn(mocks.componentResolver) 271 whenever(mocks.injector.permissionManagerServiceInternal) { 272 mocks.permissionManagerInternal 273 } 274 whenever(mocks.injector.incrementalManager).thenReturn(mocks.incrementalManager) 275 whenever(mocks.injector.compatibility).thenReturn(mocks.platformCompat) 276 whenever(mocks.injector.settings).thenReturn(mocks.settings) 277 whenever(mocks.injector.dexManager).thenReturn(mocks.dexManager) 278 whenever(mocks.injector.systemConfig).thenReturn(mocks.systemConfig) 279 whenever(mocks.injector.apexManager).thenReturn(mocks.apexManager) 280 whenever(mocks.injector.scanningCachingPackageParser).thenReturn(mocks.packageParser) 281 whenever(mocks.injector.scanningPackageParser).thenReturn(mocks.packageParser) 282 whenever(mocks.injector.systemPartitions).thenReturn(systemPartitions) 283 whenever(mocks.injector.appsFilter).thenReturn(mocks.appsFilter) 284 whenever(mocks.injector.abiHelper).thenReturn(mocks.packageAbiHelper) 285 whenever(mocks.injector.userManagerInternal).thenReturn(mocks.userManagerInternal) 286 whenever(mocks.injector.installer).thenReturn(mocks.installer) 287 whenever(mocks.injector.displayMetrics).thenReturn(mocks.displayMetrics) 288 whenever(mocks.injector.domainVerificationManagerInternal) 289 .thenReturn(mocks.domainVerificationManagerInternal) 290 whenever(mocks.injector.handler) { mocks.handler } 291 whenever(mocks.injector.defaultAppProvider) { mocks.defaultAppProvider } 292 whenever(mocks.injector.backgroundHandler) { mocks.backgroundHandler } 293 wheneverStatic { SystemConfig.getInstance() }.thenReturn(mocks.systemConfig) 294 whenever(mocks.systemConfig.availableFeatures).thenReturn(DEFAULT_AVAILABLE_FEATURES_MAP) 295 whenever(mocks.systemConfig.sharedLibraries).thenReturn(DEFAULT_SHARED_LIBRARIES_LIST) 296 wheneverStatic { SystemProperties.getBoolean("fw.free_cache_v2", true) }.thenReturn(true) 297 wheneverStatic { Environment.getPackageCacheDirectory() }.thenReturn(packageCacheDirectory) 298 wheneverStatic { SystemProperties.digestOf("ro.build.fingerprint") }.thenReturn("cacheName") 299 wheneverStatic { Environment.getRootDirectory() }.thenReturn(rootDirectory) 300 wheneverStatic { SystemServerInitThreadPool.submit(any(Runnable::class.java), anyString()) } 301 .thenAnswer { FutureTask<Any?>(it.getArgument(0), null) } 302 303 wheneverStatic { Environment.getDataDirectory() }.thenReturn(dataAppDirectory.parentFile) 304 wheneverStatic { Environment.getDataSystemDirectory() } 305 .thenReturn(File(dataAppDirectory.parentFile, "system")) 306 whenever(mocks.context.resources).thenReturn(mocks.resources) 307 whenever(mocks.resources.getString(R.string.config_deviceProvisioningPackage)) { 308 DEVICE_PROVISIONING_PACKAGE_NAME 309 } 310 whenever(mocks.apexManager.activeApexInfos).thenReturn(DEFAULT_ACTIVE_APEX_INFO_LIST) 311 whenever(mocks.settings.packagesLocked).thenReturn(mSettingsMap) 312 whenever(mocks.settings.internalVersion).thenReturn(DEFAULT_VERSION_INFO) 313 whenever(mocks.settings.keySetManagerService).thenReturn(mocks.keySetManagerService) 314 whenever(mocks.settings.keySetManagerService).thenReturn(mocks.keySetManagerService) 315 whenever(mocks.settings.snapshot()).thenReturn(mocks.settings) 316 whenever(mocks.packageAbiHelper.derivePackageAbi( 317 any(AndroidPackage::class.java), anyBoolean(), nullable(), any(File::class.java))) { 318 android.util.Pair(PackageAbiHelper.Abis("", ""), 319 PackageAbiHelper.NativeLibraryPaths("", false, "", "")) 320 } 321 whenever(mocks.userManagerInternal.getUsers(true, false, false)).thenReturn(DEFAULT_USERS) 322 whenever(mocks.userManagerService.userIds).thenReturn(intArrayOf(0)) 323 whenever(mocks.userManagerService.exists(0)).thenReturn(true) 324 whenever(mocks.packageAbiHelper.deriveNativeLibraryPaths( 325 any(AndroidPackage::class.java), anyBoolean(), any(File::class.java))) { 326 PackageAbiHelper.NativeLibraryPaths("", false, "", "") 327 } 328 whenever(mocks.injector.bootstrap(any(PackageManagerService::class.java))) { 329 mSharedLibraries = SharedLibrariesImpl( 330 getArgument<Any>(0) as PackageManagerService, mocks.injector) 331 } 332 whenever(mocks.injector.sharedLibrariesImpl) { mSharedLibraries } 333 // everything visible by default 334 whenever(mocks.appsFilter.shouldFilterApplication(any(PackageDataSnapshot::class.java), 335 anyInt(), nullable(), nullable(), anyInt())) { false } 336 whenever(mocks.appsFilterSnapshot.shouldFilterApplication( 337 any(PackageDataSnapshot::class.java), 338 anyInt(), nullable(), nullable(), anyInt())) { false } 339 340 val displayManager: DisplayManager = mock() 341 whenever(mocks.context.getSystemService(DisplayManager::class.java)) 342 .thenReturn(displayManager) 343 val display: Display = mock() 344 whenever(displayManager.getDisplay(Display.DEFAULT_DISPLAY)).thenReturn(display) 345 346 stageFrameworkScan() 347 stageInstallerScan() 348 stageServicesExtensionScan() 349 stageSystemSharedLibraryScan() 350 stagePermissionsControllerScan() 351 stageSupplementalProcessScan() 352 stageInstantAppResolverScan() 353 } 354 355 /** 356 * This method will stage the parsing and scanning of a package as well as add it to the 357 * [PackageSetting]s read from disk. 358 */ 359 @Throws(Exception::class) stageScanExistingPackagenull360 fun stageScanExistingPackage( 361 packageName: String, 362 versionCode: Long, 363 parent: File?, 364 withPackage: (PackageImpl) -> PackageImpl = { it }, 365 withSetting: <lambda>null366 (PackageSettingBuilder) -> PackageSettingBuilder = { it }, 367 withExistingSetting: <lambda>null368 (PackageSettingBuilder) -> PackageSettingBuilder = { it } 369 ) { 370 val existingSettingBuilderRef = arrayOfNulls<PackageSettingBuilder>(1) 371 stageScanNewPackage(packageName, versionCode, parent, withPackage, settingBuildernull372 withSetting = { settingBuilder -> 373 withSetting(settingBuilder) 374 existingSettingBuilderRef[0] = settingBuilder 375 settingBuilder 376 }) 377 existingSettingBuilderRef[0]?.setPackage(null) <lambda>null378 val packageSetting = existingSettingBuilderRef[0]?.let { withExistingSetting(it) }!!.build() 379 addPreExistingSetting(packageSetting.name, packageSetting) 380 } 381 382 /** 383 * This method will stage a [PackageSetting] read from disk, but does not stage any scanning 384 * or parsing of the package. 385 */ addPreExistingSettingnull386 fun addPreExistingSetting(packageName: String, packageSetting: PackageSetting) { 387 mPreExistingSettings[packageName] = packageSetting 388 } 389 390 /** 391 * This method will stage the parsing and scanning of a package but will not add it to the set 392 * of [PackageSetting]s read from disk. 393 */ 394 @Throws(Exception::class) stageScanNewPackagenull395 fun stageScanNewPackage( 396 packageName: String, 397 versionCode: Long, 398 parent: File?, 399 withPackage: (PackageImpl) -> PackageImpl = { it }, <lambda>null400 withSetting: (PackageSettingBuilder) -> PackageSettingBuilder = { it } 401 ) { 402 val pair = createBasicAndroidPackage(parent, packageName, versionCode) 403 val apkPath = pair.first 404 val pkg = withPackage(pair.second) 405 stageParse(apkPath, pkg) 406 val parentFile = apkPath.parentFile 407 val settingBuilder = withSetting(createBasicSettingBuilder(parentFile, pkg)) 408 val packageSetting = settingBuilder.build() 409 stageSettingInsert(packageSetting.name, packageSetting) 410 } 411 412 /** 413 * Creates a simple package that should reasonably parse for scan operations. This can be used 414 * as a basis for more complicated packages. 415 */ createBasicAndroidPackagenull416 fun createBasicAndroidPackage( 417 parent: File?, 418 packageName: String, 419 versionCode: Long, 420 signingDetails: SigningDetails = 421 createRandomSigningDetails() 422 ): Pair<File, PackageImpl> { 423 val apkPath = File(File(parent, packageName), "base.apk") 424 val pkg = PackageImpl.forTesting(packageName, apkPath.parentFile.path) as PackageImpl 425 pkg.signingDetails = signingDetails 426 val result = ParseTypeImpl.forDefaultParsing().success(signingDetails) 427 wheneverStatic { ParsingPackageUtils.getSigningDetails( 428 any(ParseTypeImpl::class.java), eq(pkg), anyBoolean()) } 429 .thenReturn(result) 430 pkg.versionCode = versionCode.toInt() 431 pkg.versionCodeMajor = (versionCode shr 32).toInt() 432 pkg.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT 433 return Pair(apkPath, pkg) 434 } 435 436 /** 437 * This method will create a spy of a [SigningDetails] object to be used when simulating the 438 * collection of signatures. 439 */ createRandomSigningDetailsnull440 fun createRandomSigningDetails(): SigningDetails { 441 val signingDetails = spy(SigningDetails(arrayOf(generateSpySignature()), 442 SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3)) 443 doReturn(true).whenever(signingDetails).checkCapability( 444 anyString(), anyInt()) 445 doReturn(true).whenever(signingDetails).checkCapability( 446 any(SigningDetails::class.java), anyInt()) 447 return signingDetails 448 } 449 450 /** 451 * This method will create a basic [PackageSettingBuilder] from an [AndroidPackage] with all of 452 * the necessary parameters to be returned by a simple scan. This can be used as a basis for 453 * more complicated settings. 454 */ createBasicSettingBuildernull455 fun createBasicSettingBuilder(parentFile: File, pkg: AndroidPackage): PackageSettingBuilder { 456 return createBasicSettingBuilder(parentFile, pkg.packageName, pkg.longVersionCode, 457 pkg.signingDetails) 458 .setPackage(pkg) 459 } 460 461 /** 462 * This method will create a basic [PackageSettingBuilder] with all of the necessary parameters 463 * to be returned by a simple scan. This can be used as a basis for more complicated settings. 464 */ createBasicSettingBuildernull465 fun createBasicSettingBuilder( 466 parentFile: File, 467 packageName: String, 468 versionCode: Long, 469 signingDetails: SigningDetails 470 ): PackageSettingBuilder { 471 return PackageSettingBuilder() 472 .setCodePath(parentFile.path) 473 .setName(packageName) 474 .setPVersionCode(versionCode) 475 .setSigningDetails(signingDetails) 476 } 477 createBasicApplicationInfonull478 fun createBasicApplicationInfo(pkg: ParsingPackage): ApplicationInfo { 479 val applicationInfo: ApplicationInfo = mock() 480 applicationInfo.packageName = pkg.packageName 481 return applicationInfo 482 } 483 createBasicActivityInfonull484 fun createBasicActivityInfo( 485 pkg: ParsingPackage, 486 applicationInfo: ApplicationInfo?, 487 className: String? 488 ): 489 ActivityInfo { 490 val activityInfo = ActivityInfo() 491 activityInfo.applicationInfo = applicationInfo 492 activityInfo.packageName = pkg.packageName 493 activityInfo.name = className 494 return activityInfo 495 } 496 createBasicServiceInfonull497 fun createBasicServiceInfo( 498 pkg: ParsingPackage, 499 applicationInfo: ApplicationInfo?, 500 className: String? 501 ): 502 ServiceInfo { 503 val serviceInfo = ServiceInfo() 504 serviceInfo.applicationInfo = applicationInfo 505 serviceInfo.packageName = pkg.packageName 506 serviceInfo.name = className 507 return serviceInfo 508 } 509 510 /** Finds the appropriate partition, if available, based on a scan flag unique to it. */ getPartitionFromFlagnull511 fun getPartitionFromFlag(scanFlagMask: Int): ScanPartition = 512 systemPartitions.first { (it.scanFlag and scanFlagMask) != 0 } 513 514 @Throws(Exception::class) stageParsenull515 private fun stageParse(path: File, parseResult: ParsingPackage): ParsedPackage { 516 val basePath = path.parentFile 517 basePath.mkdirs() 518 path.createNewFile() 519 createdFiles.add(path) 520 val parsedPackage = parseResult.hideAsParsed() as ParsedPackage 521 whenever(mocks.packageParser.parsePackage( 522 or(eq(path), eq(basePath)), anyInt(), anyBoolean())) { parsedPackage } 523 whenever(mocks.packageParser.parsePackage( 524 or(eq(path), eq(basePath)), anyInt(), anyBoolean(), any())) { parsedPackage } 525 return parsedPackage 526 } 527 stageSettingInsertnull528 private fun stageSettingInsert(name: String, setting: PackageSetting): PackageSetting { 529 mPendingPackageAdds.add(Pair(name, setting)) 530 return setting 531 } 532 533 @Throws(Exception::class) stageFrameworkScannull534 private fun stageFrameworkScan() { 535 val apk = File(File(rootDirectory, "framework"), "framework-res.apk") 536 val frameworkPkg = PackageImpl.forTesting("android", 537 apk.parentFile.path) as PackageImpl 538 val result = ParseTypeImpl.forDefaultParsing().success(frameworkSignature) 539 wheneverStatic { ParsingPackageUtils.getSigningDetails( 540 any(ParseTypeImpl::class.java), eq(frameworkPkg), eq(true)) } 541 .thenReturn(result) 542 stageParse(apk, frameworkPkg) 543 stageSettingInsert("android", 544 PackageSettingBuilder().setCodePath(apk.path).setName( 545 "android").setPackage(frameworkPkg).build()) 546 } 547 548 @Throws(Exception::class) stageInstantAppResolverScannull549 private fun stageInstantAppResolverScan() { 550 whenever(mocks.resources.getStringArray(R.array.config_ephemeralResolverPackage)) { 551 arrayOf("com.android.test.ephemeral.resolver") 552 } 553 stageScanNewPackage("com.android.test.ephemeral.resolver", 554 1L, getPartitionFromFlag(PackageManagerService.SCAN_AS_PRODUCT).privAppFolder, 555 withPackage = { pkg: PackageImpl -> 556 val applicationInfo: ApplicationInfo = createBasicApplicationInfo(pkg) 557 whenever(applicationInfo.isPrivilegedApp).thenReturn(true) 558 mockQueryServices(Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE, 559 createBasicServiceInfo(pkg, applicationInfo, "test.EphemeralService")) 560 mockQueryActivities(Intent.ACTION_INSTANT_APP_RESOLVER_SETTINGS, 561 createBasicActivityInfo(pkg, applicationInfo, "test.SettingsActivity")) 562 pkg 563 }, 564 withSetting = { setting: PackageSettingBuilder -> 565 setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM) 566 }) 567 } 568 569 @Throws(Exception::class) stagePermissionsControllerScannull570 private fun stagePermissionsControllerScan() { 571 stageScanNewPackage("com.android.permissions.controller", 572 1L, systemPartitions[0].privAppFolder, 573 withPackage = { pkg: PackageImpl -> 574 val applicationInfo: ApplicationInfo = createBasicApplicationInfo(pkg) 575 whenever(applicationInfo.isPrivilegedApp).thenReturn(true) 576 mockQueryActivities(Intent.ACTION_MANAGE_PERMISSIONS, 577 createBasicActivityInfo( 578 pkg, applicationInfo, "test.PermissionActivity")) 579 pkg 580 }, 581 withSetting = { setting: PackageSettingBuilder -> 582 setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM) 583 }) 584 } 585 586 @Throws(Exception::class) stageSupplementalProcessScannull587 private fun stageSupplementalProcessScan() { 588 stageScanNewPackage("com.android.supplemental.process", 589 1L, systemPartitions[0].privAppFolder, 590 withPackage = { pkg: PackageImpl -> 591 val applicationInfo: ApplicationInfo = createBasicApplicationInfo(pkg) 592 mockQueryServices(SdkSandboxManagerLocal.SERVICE_INTERFACE, 593 createBasicServiceInfo( 594 pkg, applicationInfo, "SupplementalProcessService")) 595 pkg 596 }, 597 withSetting = { setting: PackageSettingBuilder -> 598 setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM) 599 }) 600 } 601 602 @Throws(Exception::class) stageSystemSharedLibraryScannull603 private fun stageSystemSharedLibraryScan() { 604 stageScanNewPackage("android.ext.shared", 605 1L, systemPartitions[0].appFolder, 606 withPackage = { it.addLibraryName("android.ext.shared") as PackageImpl }, 607 withSetting = { setting: PackageSettingBuilder -> 608 setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM) 609 } 610 ) 611 } 612 613 @Throws(Exception::class) stageServicesExtensionScannull614 private fun stageServicesExtensionScan() { 615 whenever(mocks.context.getString(R.string.config_servicesExtensionPackage)) { 616 "com.android.test.services.extension" 617 } 618 stageScanNewPackage("com.android.test.services.extension", 619 1L, getPartitionFromFlag(PackageManagerService.SCAN_AS_SYSTEM_EXT).privAppFolder, 620 withSetting = { setting: PackageSettingBuilder -> 621 setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM) 622 }) 623 } 624 625 @Throws(Exception::class) stageInstallerScannull626 private fun stageInstallerScan() { 627 stageScanNewPackage( 628 "com.android.test.installer", 629 1L, getPartitionFromFlag(PackageManagerService.SCAN_AS_PRODUCT).privAppFolder, 630 withPackage = { pkg: PackageImpl -> 631 val applicationInfo: ApplicationInfo = createBasicApplicationInfo(pkg) 632 whenever(applicationInfo.isPrivilegedApp).thenReturn(true) 633 val installerActivity: ActivityInfo = createBasicActivityInfo( 634 pkg, applicationInfo, "test.InstallerActivity") 635 mockQueryActivities(Intent.ACTION_INSTALL_PACKAGE, installerActivity) 636 mockQueryActivities(Intent.ACTION_UNINSTALL_PACKAGE, installerActivity) 637 mockQueryActivities(Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE, 638 installerActivity) 639 pkg 640 }, 641 withSetting = { setting: PackageSettingBuilder -> 642 setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM) 643 } 644 ) 645 } 646 mockQueryActivitiesnull647 private fun mockQueryActivities(action: String, vararg activities: ActivityInfo) { 648 whenever(mocks.componentResolver.queryActivities(any(), 649 argThat { intent: Intent? -> intent != null && (action == intent.action) }, 650 nullable(), anyLong(), anyInt())) { 651 ArrayList(activities.asList().map { info: ActivityInfo? -> 652 ResolveInfo().apply { activityInfo = info } 653 }) 654 } 655 } 656 mockQueryServicesnull657 private fun mockQueryServices(action: String, vararg services: ServiceInfo) { 658 whenever(mocks.componentResolver.queryServices(any(), 659 argThat { intent: Intent? -> intent != null && (action == intent.action) }, 660 nullable(), anyLong(), anyInt())) { 661 ArrayList(services.asList().map { info -> 662 ResolveInfo().apply { serviceInfo = info } 663 }) 664 } 665 } 666 generateSpySignaturenull667 fun generateSpySignature(): Signature { 668 val bytes = ByteArray(32) 669 random.nextBytes(bytes) 670 val signature = spy(Signature(bytes)) 671 try { 672 val mockPublicKey: PublicKey = mock() 673 doReturn(mockPublicKey).whenever(signature).getPublicKey() 674 } catch (e: CertificateException) { 675 throw RuntimeException(e) 676 } 677 return signature 678 } 679 680 /** Override get*Folder methods to point to temporary local directories */ 681 682 @Throws(IOException::class) redirectScanPartitionsnull683 private fun redirectScanPartitions(partitions: List<ScanPartition>): 684 List<ScanPartition> { 685 val spiedPartitions: MutableList<ScanPartition> = 686 ArrayList(partitions.size) 687 for (partition: ScanPartition in partitions) { 688 val spy = spy(partition) 689 val newRoot = Files.createTempDirectory(partition.folder.name).toFile() 690 whenever(spy.overlayFolder).thenReturn(File(newRoot, "overlay")) 691 whenever(spy.appFolder).thenReturn(File(newRoot, "app")) 692 whenever(spy.privAppFolder).thenReturn(File(newRoot, "priv-app")) 693 whenever(spy.folder).thenReturn(newRoot) 694 spiedPartitions.add(spy) 695 } 696 return spiedPartitions 697 } 698 } 699 700 /** 701 * Sets up a basic [MockSystem] for use in a test method. This will create a MockSystem before the 702 * test method and any [org.junit.Before] annotated methods. It can then be used to access the 703 * MockSystem via the [system] method or the mocks directly via [mocks]. 704 */ 705 class MockSystemRule : TestRule { 706 var mockSystem: MockSystem? = null applynull707 override fun apply(base: Statement?, description: Description?) = object : Statement() { 708 @Throws(Throwable::class) 709 override fun evaluate() { 710 mockSystem = MockSystem() 711 try { 712 base!!.evaluate() 713 } finally { 714 mockSystem?.cleanup() 715 mockSystem = null 716 } 717 } 718 } 719 720 /** Fetch the [MockSystem] instance prepared for this test */ systemnull721 fun system(): MockSystem = mockSystem!! 722 /** Fetch the [MockSystem.Mocks] prepared for this test */ 723 fun mocks(): MockSystem.Mocks = mockSystem!!.mocks 724 } 725