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