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 packageInstallerService: PackageInstallerService = mock() 222 val installDependencyHelper: InstallDependencyHelper = mock() 223 val updateOwnershipHelper: UpdateOwnershipHelper = mock() 224 } 225 226 companion object { 227 private const val DEVICE_PROVISIONING_PACKAGE_NAME = 228 "com.example.android.device.provisioning" 229 private val DEFAULT_AVAILABLE_FEATURES_MAP = ArrayMap<String, FeatureInfo>() 230 private val DEFAULT_ACTIVE_APEX_INFO_LIST = emptyList<ApexManager.ActiveApexInfo>() 231 private val DEFAULT_SHARED_LIBRARIES_LIST = 232 ArrayMap<String, SystemConfig.SharedLibraryEntry>() 233 private val DEFAULT_USERS = Arrays.asList( 234 UserInfo(UserHandle.USER_SYSTEM, "primary", "", 235 UserInfo.FLAG_PRIMARY or UserInfo.FLAG_SYSTEM or UserInfo.FLAG_FULL, 236 UserManager.USER_TYPE_FULL_SYSTEM)) 237 public val DEFAULT_VERSION_INFO = Settings.VersionInfo() 238 239 init { 240 DEFAULT_VERSION_INFO.fingerprint = "abcdef" 241 DEFAULT_VERSION_INFO.sdkVersion = Build.VERSION_CODES.R 242 DEFAULT_VERSION_INFO.databaseVersion = Settings.CURRENT_DATABASE_VERSION 243 } 244 addDefaultSharedLibrarynull245 fun addDefaultSharedLibrary(libName: String, libEntry: SystemConfig.SharedLibraryEntry) { 246 DEFAULT_SHARED_LIBRARIES_LIST[libName] = libEntry 247 } 248 } 249 250 /** 251 * Clean up any potentially dangling state. This should be run at the end of every test to 252 * account for changes to static memory, such as [LocalServices] 253 */ cleanupnull254 fun cleanup() { 255 createdFiles.forEach(File::delete) 256 createdFiles.clear() 257 mSettingsMap.clear() 258 mPendingPackageAdds.clear() 259 mPreExistingSettings.clear() 260 session.finishMocking() 261 } 262 263 /** 264 * Run this method to ensure that all expected actions were executed, such as pending 265 * [Settings] adds. 266 */ validateFinalStatenull267 fun validateFinalState() { 268 if (mPendingPackageAdds.isNotEmpty()) { 269 Assert.fail( 270 "Not all expected settings were added: ${mPendingPackageAdds.map { it.first }}") 271 } 272 } 273 274 /** 275 * This method stages enough of system startup to execute the PackageManagerService constructor 276 * successfullly. 277 */ 278 @Throws(Exception::class) stageNominalSystemStatenull279 fun stageNominalSystemState() { 280 whenever(mocks.injector.context).thenReturn(mocks.context) 281 whenever(mocks.injector.lock).thenReturn(mocks.lock) 282 whenever(mocks.injector.installLock).thenReturn(mocks.installLock) 283 whenever(mocks.injector.systemWrapper).thenReturn(mocks.systemWrapper) 284 whenever(mocks.injector.userManagerService).thenReturn(mocks.userManagerService) 285 whenever(mocks.injector.componentResolver).thenReturn(mocks.componentResolver) 286 whenever(mocks.injector.permissionManagerServiceInternal) { 287 mocks.permissionManagerInternal 288 } 289 whenever(mocks.injector.incrementalManager).thenReturn(mocks.incrementalManager) 290 whenever(mocks.injector.compatibility).thenReturn(mocks.platformCompat) 291 whenever(mocks.injector.settings).thenReturn(mocks.settings) 292 whenever(mocks.injector.crossProfileIntentFilterHelper) 293 .thenReturn(mocks.crossProfileIntentFilterHelper) 294 whenever(mocks.injector.dexManager).thenReturn(mocks.dexManager) 295 whenever(mocks.injector.dynamicCodeLogger).thenReturn(mocks.dynamicCodeLogger) 296 whenever(mocks.injector.systemConfig).thenReturn(mocks.systemConfig) 297 whenever(mocks.injector.apexManager).thenReturn(mocks.apexManager) 298 whenever(mocks.injector.scanningCachingPackageParser).thenReturn(mocks.packageParser) 299 whenever(mocks.injector.scanningPackageParser).thenReturn(mocks.packageParser) 300 whenever(mocks.injector.systemPartitions).thenReturn(systemPartitions) 301 whenever(mocks.injector.appsFilter).thenReturn(mocks.appsFilter) 302 whenever(mocks.injector.abiHelper).thenReturn(mocks.packageAbiHelper) 303 whenever(mocks.injector.userManagerInternal).thenReturn(mocks.userManagerInternal) 304 whenever(mocks.injector.installer).thenReturn(mocks.installer) 305 whenever(mocks.injector.displayMetrics).thenReturn(mocks.displayMetrics) 306 whenever(mocks.injector.domainVerificationManagerInternal) 307 .thenReturn(mocks.domainVerificationManagerInternal) 308 whenever(mocks.injector.handler) { mocks.handler } 309 whenever(mocks.injector.defaultAppProvider) { mocks.defaultAppProvider } 310 whenever(mocks.injector.backgroundHandler) { mocks.backgroundHandler } 311 whenever(mocks.injector.packageInstallerService) { mocks.packageInstallerService } 312 whenever(mocks.injector.updateOwnershipHelper) { mocks.updateOwnershipHelper } 313 whenever(mocks.injector.getSystemService(AppOpsManager::class.java)) { mocks.appOpsManager } 314 wheneverStatic { SystemConfig.getInstance() }.thenReturn(mocks.systemConfig) 315 whenever(mocks.systemConfig.availableFeatures).thenReturn(DEFAULT_AVAILABLE_FEATURES_MAP) 316 whenever(mocks.systemConfig.sharedLibraries).thenReturn(DEFAULT_SHARED_LIBRARIES_LIST) 317 whenever(mocks.systemConfig.defaultVrComponents).thenReturn(ArraySet()) 318 whenever(mocks.systemConfig.hiddenApiWhitelistedApps).thenReturn(ArraySet()) 319 whenever(mocks.systemConfig.appMetadataFilePaths).thenReturn(ArrayMap()) 320 whenever(mocks.systemConfig.oemDefinedUids).thenReturn(ArrayMap()) 321 wheneverStatic { SystemProperties.set(anyString(), anyString()) }.thenDoNothing() 322 wheneverStatic { SystemProperties.getBoolean("fw.free_cache_v2", true) }.thenReturn(true) 323 wheneverStatic { Environment.getApexDirectory() }.thenReturn(apexDirectory) 324 wheneverStatic { Environment.getPackageCacheDirectory() }.thenReturn(packageCacheDirectory) 325 wheneverStatic { SystemProperties.digestOf("ro.build.fingerprint") }.thenReturn("cacheName") 326 wheneverStatic { Environment.getRootDirectory() }.thenReturn(rootDirectory) 327 wheneverStatic { SystemServerInitThreadPool.submit(any(Runnable::class.java), anyString()) } 328 .thenAnswer { FutureTask<Any?>(it.getArgument(0), null) } 329 330 wheneverStatic { Environment.getDataDirectory() }.thenReturn(dataAppDirectory.parentFile) 331 wheneverStatic { Environment.getDataSystemDirectory() } 332 .thenReturn(File(dataAppDirectory.parentFile, "system")) 333 whenever(mocks.context.resources).thenReturn(mocks.resources) 334 whenever(mocks.resources.getString(R.string.config_deviceProvisioningPackage)) { 335 DEVICE_PROVISIONING_PACKAGE_NAME 336 } 337 whenever(mocks.apexManager.activeApexInfos).thenReturn(DEFAULT_ACTIVE_APEX_INFO_LIST) 338 whenever(mocks.packageInstallerService.installDependencyHelper).thenReturn( 339 mocks.installDependencyHelper) 340 whenever(mocks.settings.packagesLocked).thenReturn(mSettingsMap) 341 whenever(mocks.settings.internalVersion).thenReturn(DEFAULT_VERSION_INFO) 342 whenever(mocks.settings.keySetManagerService).thenReturn(mocks.keySetManagerService) 343 whenever(mocks.settings.keySetManagerService).thenReturn(mocks.keySetManagerService) 344 whenever(mocks.settings.snapshot()).thenReturn(mocks.settings) 345 whenever(mocks.packageAbiHelper.derivePackageAbi(any(AndroidPackage::class.java), 346 anyBoolean(), anyBoolean(), nullable(), any(File::class.java))) { 347 android.util.Pair(PackageAbiHelper.Abis("", ""), 348 PackageAbiHelper.NativeLibraryPaths("", false, "", "")) 349 } 350 whenever(mocks.userManagerInternal.getUsers(true, false, false)).thenReturn(DEFAULT_USERS) 351 whenever(mocks.userManagerService.userIds).thenReturn(intArrayOf(0)) 352 whenever(mocks.userManagerService.exists(0)).thenReturn(true) 353 whenever(mocks.packageAbiHelper.deriveNativeLibraryPaths(any(AndroidPackage::class.java), 354 anyBoolean(), anyBoolean(), any(File::class.java))) { 355 PackageAbiHelper.NativeLibraryPaths("", false, "", "") 356 } 357 whenever(mocks.injector.bootstrap(any(PackageManagerService::class.java))) { 358 mSharedLibraries = SharedLibrariesImpl( 359 getArgument<Any>(0) as PackageManagerService, mocks.injector) 360 } 361 whenever(mocks.injector.sharedLibrariesImpl) { mSharedLibraries } 362 // everything visible by default 363 whenever(mocks.appsFilter.shouldFilterApplication(any(PackageDataSnapshot::class.java), 364 anyInt(), nullable(), nullable(), anyInt())) { false } 365 whenever(mocks.appsFilterSnapshot.shouldFilterApplication( 366 any(PackageDataSnapshot::class.java), 367 anyInt(), nullable(), nullable(), anyInt())) { false } 368 369 val displayManager: DisplayManager = mock() 370 whenever(mocks.context.getSystemService(DisplayManager::class.java)) 371 .thenReturn(displayManager) 372 val display: Display = mock() 373 whenever(displayManager.getDisplay(Display.DEFAULT_DISPLAY)).thenReturn(display) 374 375 stageFrameworkScan() 376 stageInstallerScan() 377 stageServicesExtensionScan() 378 stageSystemSharedLibraryScan() 379 stagePermissionsControllerScan() 380 stageSupplementalProcessScan() 381 stageInstantAppResolverScan() 382 } 383 384 /** 385 * This method will stage the parsing and scanning of a package as well as add it to the 386 * [PackageSetting]s read from disk. 387 */ 388 @Throws(Exception::class) stageScanExistingPackagenull389 fun stageScanExistingPackage( 390 packageName: String, 391 versionCode: Long, 392 parent: File?, 393 withPackage: (PackageImpl) -> PackageImpl = { it }, 394 withSetting: <lambda>null395 (PackageSettingBuilder) -> PackageSettingBuilder = { it }, 396 withExistingSetting: <lambda>null397 (PackageSettingBuilder) -> PackageSettingBuilder = { it } 398 ) { 399 val existingSettingBuilderRef = arrayOfNulls<PackageSettingBuilder>(1) 400 stageScanNewPackage(packageName, versionCode, parent, withPackage, settingBuildernull401 withSetting = { settingBuilder -> 402 withSetting(settingBuilder) 403 existingSettingBuilderRef[0] = settingBuilder 404 settingBuilder 405 }) 406 existingSettingBuilderRef[0]?.setPackage(null) <lambda>null407 val packageSetting = existingSettingBuilderRef[0]?.let { withExistingSetting(it) }!!.build() 408 addPreExistingSetting(packageSetting.name, packageSetting) 409 } 410 411 /** 412 * This method will stage a [PackageSetting] read from disk, but does not stage any scanning 413 * or parsing of the package. 414 */ addPreExistingSettingnull415 fun addPreExistingSetting(packageName: String, packageSetting: PackageSetting) { 416 mPreExistingSettings[packageName] = packageSetting 417 } 418 419 /** 420 * This method will stage the parsing and scanning of a package but will not add it to the set 421 * of [PackageSetting]s read from disk. 422 */ 423 @Throws(Exception::class) stageScanNewPackagenull424 fun stageScanNewPackage( 425 packageName: String, 426 versionCode: Long, 427 parent: File?, 428 withPackage: (PackageImpl) -> PackageImpl = { it }, <lambda>null429 withSetting: (PackageSettingBuilder) -> PackageSettingBuilder = { it } 430 ) { 431 val pair = createBasicAndroidPackage(parent, packageName, versionCode) 432 val apkPath = pair.first 433 val pkg = withPackage(pair.second) 434 stageParse(apkPath, pkg) 435 val parentFile = apkPath.parentFile 436 val settingBuilder = withSetting(createBasicSettingBuilder(parentFile, pkg)) 437 val packageSetting = settingBuilder.build() 438 stageSettingInsert(packageSetting.name, packageSetting) 439 } 440 441 /** 442 * Creates a simple package that should reasonably parse for scan operations. This can be used 443 * as a basis for more complicated packages. 444 */ createBasicAndroidPackagenull445 fun createBasicAndroidPackage( 446 parent: File?, 447 packageName: String, 448 versionCode: Long, 449 signingDetails: SigningDetails = 450 createRandomSigningDetails() 451 ): Pair<File, PackageImpl> { 452 val apkPath = File(File(parent, packageName), "base.apk") 453 val pkg = PackageImpl.forTesting(packageName, apkPath.parentFile.path) as PackageImpl 454 pkg.signingDetails = signingDetails 455 val result = ParseTypeImpl.forDefaultParsing().success(signingDetails) 456 wheneverStatic { ParsingPackageUtils.getSigningDetails( 457 any(ParseTypeImpl::class.java), eq(pkg), anyBoolean()) } 458 .thenReturn(result) 459 pkg.versionCode = versionCode.toInt() 460 pkg.versionCodeMajor = (versionCode shr 32).toInt() 461 pkg.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT 462 return Pair(apkPath, pkg) 463 } 464 465 /** 466 * This method will create a spy of a [SigningDetails] object to be used when simulating the 467 * collection of signatures. 468 */ createRandomSigningDetailsnull469 fun createRandomSigningDetails(): SigningDetails { 470 val signingDetails = spy(SigningDetails(arrayOf(generateSpySignature()), 471 SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3)) 472 doReturn(true).whenever(signingDetails).checkCapability( 473 anyString(), anyInt()) 474 doReturn(true).whenever(signingDetails).checkCapability( 475 any(SigningDetails::class.java), anyInt()) 476 return signingDetails 477 } 478 479 /** 480 * This method will create a basic [PackageSettingBuilder] from an [AndroidPackage] with all of 481 * the necessary parameters to be returned by a simple scan. This can be used as a basis for 482 * more complicated settings. 483 */ createBasicSettingBuildernull484 fun createBasicSettingBuilder(parentFile: File, pkg: AndroidPackage): PackageSettingBuilder { 485 return createBasicSettingBuilder(parentFile, pkg.packageName, pkg.longVersionCode, 486 pkg.signingDetails) 487 .setPackage(pkg) 488 } 489 490 /** 491 * This method will create a basic [PackageSettingBuilder] with all of the necessary parameters 492 * to be returned by a simple scan. This can be used as a basis for more complicated settings. 493 */ createBasicSettingBuildernull494 fun createBasicSettingBuilder( 495 parentFile: File, 496 packageName: String, 497 versionCode: Long, 498 signingDetails: SigningDetails 499 ): PackageSettingBuilder { 500 return PackageSettingBuilder() 501 .setCodePath(parentFile.path) 502 .setName(packageName) 503 .setPVersionCode(versionCode) 504 .setSigningDetails(signingDetails) 505 } 506 createBasicApplicationInfonull507 fun createBasicApplicationInfo(pkg: ParsingPackage): ApplicationInfo { 508 val applicationInfo: ApplicationInfo = mock() 509 applicationInfo.packageName = pkg.packageName 510 return applicationInfo 511 } 512 createBasicActivityInfonull513 fun createBasicActivityInfo( 514 pkg: ParsingPackage, 515 applicationInfo: ApplicationInfo?, 516 className: String? 517 ): ActivityInfo { 518 val activityInfo = ActivityInfo() 519 activityInfo.applicationInfo = applicationInfo 520 activityInfo.packageName = pkg.packageName 521 activityInfo.name = className 522 return activityInfo 523 } 524 createBasicServiceInfonull525 fun createBasicServiceInfo( 526 pkg: ParsingPackage, 527 applicationInfo: ApplicationInfo?, 528 className: String? 529 ): ServiceInfo { 530 val serviceInfo = ServiceInfo() 531 serviceInfo.applicationInfo = applicationInfo 532 serviceInfo.packageName = pkg.packageName 533 serviceInfo.name = className 534 return serviceInfo 535 } 536 537 /** Finds the appropriate partition, if available, based on a scan flag unique to it. */ getPartitionFromFlagnull538 fun getPartitionFromFlag(scanFlagMask: Int): ScanPartition = 539 systemPartitions.first { (it.scanFlag and scanFlagMask) != 0 } 540 541 @Throws(Exception::class) stageParsenull542 private fun stageParse(path: File, parseResult: ParsingPackage): ParsedPackage { 543 val basePath = path.parentFile 544 basePath.mkdirs() 545 path.createNewFile() 546 createdFiles.add(path) 547 val parsedPackage = parseResult.hideAsParsed() as ParsedPackage 548 whenever(mocks.packageParser.parsePackage( 549 or(eq(path), eq(basePath)), anyInt(), anyBoolean())) { parsedPackage } 550 whenever(mocks.packageParser.parsePackage( 551 or(eq(path), eq(basePath)), anyInt(), anyBoolean())) { parsedPackage } 552 return parsedPackage 553 } 554 stageSettingInsertnull555 private fun stageSettingInsert(name: String, setting: PackageSetting): PackageSetting { 556 mPendingPackageAdds.add(Pair(name, setting)) 557 return setting 558 } 559 560 @Throws(Exception::class) stageFrameworkScannull561 private fun stageFrameworkScan() { 562 val apk = File(File(rootDirectory, "framework"), "framework-res.apk") 563 val frameworkPkg = PackageImpl.forTesting("android", 564 apk.parentFile.path) as PackageImpl 565 val result = ParseTypeImpl.forDefaultParsing().success(frameworkSignature) 566 wheneverStatic { ParsingPackageUtils.getSigningDetails( 567 any(ParseTypeImpl::class.java), eq(frameworkPkg), eq(true)) } 568 .thenReturn(result) 569 stageParse(apk, frameworkPkg) 570 stageSettingInsert("android", 571 PackageSettingBuilder().setCodePath(apk.path).setName( 572 "android").setPackage(frameworkPkg).build()) 573 } 574 575 @Throws(Exception::class) stageInstantAppResolverScannull576 private fun stageInstantAppResolverScan() { 577 doReturn(arrayOf("com.android.test.ephemeral.resolver")) 578 .whenever(mocks.resources).getStringArray(R.array.config_ephemeralResolverPackage) 579 stageScanNewPackage("com.android.test.ephemeral.resolver", 580 1L, getPartitionFromFlag(PackageManagerService.SCAN_AS_PRODUCT).privAppFolder, 581 withPackage = { pkg: PackageImpl -> 582 val applicationInfo: ApplicationInfo = createBasicApplicationInfo(pkg) 583 whenever(applicationInfo.isPrivilegedApp).thenReturn(true) 584 mockQueryServices(Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE, 585 createBasicServiceInfo(pkg, applicationInfo, "test.EphemeralService")) 586 mockQueryActivities(Intent.ACTION_INSTANT_APP_RESOLVER_SETTINGS, 587 createBasicActivityInfo(pkg, applicationInfo, "test.SettingsActivity")) 588 pkg 589 }, 590 withSetting = { setting: PackageSettingBuilder -> 591 setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM) 592 }) 593 } 594 595 @Throws(Exception::class) stagePermissionsControllerScannull596 private fun stagePermissionsControllerScan() { 597 stageScanNewPackage("com.android.permissions.controller", 598 1L, systemPartitions[0].privAppFolder, 599 withPackage = { pkg: PackageImpl -> 600 val applicationInfo: ApplicationInfo = createBasicApplicationInfo(pkg) 601 whenever(applicationInfo.isPrivilegedApp).thenReturn(true) 602 mockQueryActivities(Intent.ACTION_MANAGE_PERMISSIONS, 603 createBasicActivityInfo( 604 pkg, applicationInfo, "test.PermissionActivity")) 605 pkg 606 }, 607 withSetting = { setting: PackageSettingBuilder -> 608 setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM) 609 }) 610 } 611 612 @Throws(Exception::class) stageSupplementalProcessScannull613 private fun stageSupplementalProcessScan() { 614 stageScanNewPackage("com.android.supplemental.process", 615 1L, systemPartitions[0].privAppFolder, 616 withPackage = { pkg: PackageImpl -> 617 val applicationInfo: ApplicationInfo = createBasicApplicationInfo(pkg) 618 mockQueryServices(SdkSandboxManagerLocal.SERVICE_INTERFACE, 619 createBasicServiceInfo( 620 pkg, applicationInfo, "SupplementalProcessService")) 621 pkg 622 }, 623 withSetting = { setting: PackageSettingBuilder -> 624 setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM) 625 }) 626 } 627 628 @Throws(Exception::class) stageSystemSharedLibraryScannull629 private fun stageSystemSharedLibraryScan() { 630 stageScanNewPackage("android.ext.shared", 631 1L, systemPartitions[0].appFolder, 632 withPackage = { it.addLibraryName("android.ext.shared") as PackageImpl }, 633 withSetting = { setting: PackageSettingBuilder -> 634 setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM) 635 } 636 ) 637 } 638 639 @Throws(Exception::class) stageServicesExtensionScannull640 private fun stageServicesExtensionScan() { 641 whenever(mocks.context.getString(R.string.config_servicesExtensionPackage)) { 642 "com.android.test.services.extension" 643 } 644 stageScanNewPackage("com.android.test.services.extension", 645 1L, getPartitionFromFlag(PackageManagerService.SCAN_AS_SYSTEM_EXT).privAppFolder, 646 withSetting = { setting: PackageSettingBuilder -> 647 setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM) 648 }) 649 } 650 651 @Throws(Exception::class) stageInstallerScannull652 private fun stageInstallerScan() { 653 stageScanNewPackage( 654 "com.android.test.installer", 655 1L, getPartitionFromFlag(PackageManagerService.SCAN_AS_PRODUCT).privAppFolder, 656 withPackage = { pkg: PackageImpl -> 657 val applicationInfo: ApplicationInfo = createBasicApplicationInfo(pkg) 658 whenever(applicationInfo.isPrivilegedApp).thenReturn(true) 659 val installerActivity: ActivityInfo = createBasicActivityInfo( 660 pkg, applicationInfo, "test.InstallerActivity") 661 mockQueryActivities(Intent.ACTION_INSTALL_PACKAGE, installerActivity) 662 mockQueryActivities(Intent.ACTION_UNINSTALL_PACKAGE, installerActivity) 663 mockQueryActivities(Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE, 664 installerActivity) 665 pkg 666 }, 667 withSetting = { setting: PackageSettingBuilder -> 668 setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM) 669 } 670 ) 671 } 672 mockQueryActivitiesnull673 private fun mockQueryActivities(action: String, vararg activities: ActivityInfo) { 674 whenever(mocks.componentResolver.queryActivities(any(), 675 argThat { intent: Intent? -> intent != null && (action == intent.action) }, 676 nullable(), anyLong(), anyInt())) { 677 ArrayList(activities.asList().map { info: ActivityInfo? -> 678 ResolveInfo().apply { activityInfo = info } 679 }) 680 } 681 } 682 mockQueryServicesnull683 private fun mockQueryServices(action: String, vararg services: ServiceInfo) { 684 whenever(mocks.componentResolver.queryServices(any(), 685 argThat { intent: Intent? -> intent != null && (action == intent.action) }, 686 nullable(), anyLong(), anyInt())) { 687 ArrayList(services.asList().map { info -> 688 ResolveInfo().apply { serviceInfo = info } 689 }) 690 } 691 } 692 generateSpySignaturenull693 fun generateSpySignature(): Signature { 694 val bytes = ByteArray(32) 695 random.nextBytes(bytes) 696 val signature = spy(Signature(bytes)) 697 try { 698 val mockPublicKey: PublicKey = mock() 699 doReturn(mockPublicKey).whenever(signature).getPublicKey() 700 } catch (e: CertificateException) { 701 throw RuntimeException(e) 702 } 703 return signature 704 } 705 706 /** Override get*Folder methods to point to temporary local directories */ 707 708 @Throws(IOException::class) redirectScanPartitionsnull709 private fun redirectScanPartitions(partitions: List<ScanPartition>): List<ScanPartition> { 710 val spiedPartitions: MutableList<ScanPartition> = 711 ArrayList(partitions.size) 712 for (partition: ScanPartition in partitions) { 713 val spy = spy(partition) 714 val newRoot = Files.createTempDirectory(partition.folder.name).toFile() 715 whenever(spy.overlayFolder).thenReturn(File(newRoot, "overlay")) 716 whenever(spy.appFolder).thenReturn(File(newRoot, "app")) 717 whenever(spy.privAppFolder).thenReturn(File(newRoot, "priv-app")) 718 whenever(spy.folder).thenReturn(newRoot) 719 spiedPartitions.add(spy) 720 } 721 return spiedPartitions 722 } 723 } 724 725 /** 726 * Sets up a basic [MockSystem] for use in a test method. This will create a MockSystem before the 727 * test method and any [org.junit.Before] annotated methods. It can then be used to access the 728 * MockSystem via the [system] method or the mocks directly via [mocks]. 729 */ 730 class MockSystemRule : TestRule { 731 var mockSystem: MockSystem? = null applynull732 override fun apply(base: Statement?, description: Description?) = object : Statement() { 733 @Throws(Throwable::class) 734 override fun evaluate() { 735 mockSystem = MockSystem() 736 try { 737 base!!.evaluate() 738 } finally { 739 mockSystem?.cleanup() 740 mockSystem = null 741 Mockito.framework().clearInlineMocks() 742 } 743 } 744 } 745 746 /** Fetch the [MockSystem] instance prepared for this test */ systemnull747 fun system(): MockSystem = mockSystem!! 748 /** Fetch the [MockSystem.Mocks] prepared for this test */ 749 fun mocks(): MockSystem.Mocks = mockSystem!!.mocks 750 } 751