xref: /aosp_15_r20/frameworks/base/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
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