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