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