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