1 /* <lambda>null2 * Copyright (C) 2021 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 17 package com.android.server.pm 18 19 import android.content.pm.ApplicationInfo 20 import android.content.pm.PackageManager 21 import android.content.pm.SharedLibraryInfo 22 import android.content.pm.VersionedPackage 23 import android.os.Build 24 import android.os.storage.StorageManager 25 import android.util.ArrayMap 26 import android.util.PackageUtils 27 import com.android.server.SystemConfig.SharedLibraryEntry 28 import com.android.server.compat.PlatformCompat 29 import com.android.server.extendedtestutils.wheneverStatic 30 import com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME 31 import com.android.server.pm.parsing.pkg.AndroidPackage 32 import com.android.server.pm.parsing.pkg.PackageImpl 33 import com.android.server.pm.parsing.pkg.ParsedPackage 34 import com.android.server.testutils.any 35 import com.android.server.testutils.eq 36 import com.android.server.testutils.mock 37 import com.android.server.testutils.nullable 38 import com.android.server.testutils.spy 39 import com.android.server.testutils.whenever 40 import com.android.server.utils.WatchedLongSparseArray 41 import com.google.common.truth.Truth.assertThat 42 import libcore.util.HexEncoding 43 import org.junit.Before 44 import org.junit.Rule 45 import org.junit.Test 46 import org.junit.rules.RuleChain 47 import org.junit.rules.TemporaryFolder 48 import org.junit.runner.RunWith 49 import org.junit.runners.JUnit4 50 import org.mockito.Mock 51 import org.mockito.Mockito.doAnswer 52 import org.mockito.Mockito.verify 53 import org.mockito.MockitoAnnotations 54 import java.io.File 55 import kotlin.test.assertFailsWith 56 import kotlin.test.assertFalse 57 import kotlin.test.assertTrue 58 59 @RunWith(JUnit4::class) 60 class SharedLibrariesImplTest { 61 62 companion object { 63 const val TEST_LIB_NAME = "test.lib" 64 const val TEST_LIB_PACKAGE_NAME = "com.android.lib.test" 65 const val BUILTIN_LIB_NAME = "builtin.lib" 66 const val STATIC_LIB_NAME = "static.lib" 67 const val STATIC_LIB_VERSION = 7L 68 const val STATIC_LIB_DECLARING_PACKAGE_NAME = "com.android.lib.static.provider" 69 const val STATIC_LIB_PACKAGE_NAME = "com.android.lib.static.provider_7" 70 const val DYNAMIC_LIB_NAME = "dynamic.lib" 71 const val DYNAMIC_LIB_PACKAGE_NAME = "com.android.lib.dynamic.provider" 72 const val CONSUMER_PACKAGE_NAME = "com.android.lib.consumer" 73 const val VERSION_UNDEFINED = SharedLibraryInfo.VERSION_UNDEFINED.toLong() 74 } 75 76 private val mMockSystem = MockSystemRule() 77 private val mTempFolder = TemporaryFolder() 78 79 @Rule 80 @JvmField 81 val mRules = RuleChain.outerRule(mTempFolder).around(mMockSystem)!! 82 83 private lateinit var mSharedLibrariesImpl: SharedLibrariesImpl 84 private lateinit var mPms: PackageManagerService 85 private lateinit var mSettings: Settings 86 private lateinit var mComputer: Computer 87 private lateinit var mExistingPackages: ArrayMap<String, AndroidPackage> 88 private lateinit var builtinLibDirectory: File 89 90 @Mock 91 private lateinit var mDeletePackageHelper: DeletePackageHelper 92 @Mock 93 private lateinit var mStorageManager: StorageManager 94 @Mock 95 private lateinit var mFile: File 96 @Mock 97 private lateinit var mPlatformCompat: PlatformCompat 98 99 @Before 100 fun setup() { 101 MockitoAnnotations.initMocks(this) 102 mMockSystem.system().stageNominalSystemState() 103 stageBuiltinLibrary(mTempFolder.newFolder()) 104 stageScanExistingPackages() 105 106 mPms = spy(PackageManagerService(mMockSystem.mocks().injector, 107 false /*coreOnly*/, 108 false /*factoryTest*/, 109 MockSystem.DEFAULT_VERSION_INFO.fingerprint, 110 false /*isEngBuild*/, 111 false /*isUserDebugBuild*/, 112 Build.VERSION_CODES.CUR_DEVELOPMENT, 113 Build.VERSION.INCREMENTAL)) 114 mMockSystem.system().validateFinalState() 115 mSettings = mMockSystem.mocks().injector.settings 116 mSharedLibrariesImpl = mMockSystem.mocks().injector.sharedLibrariesImpl 117 mSharedLibrariesImpl.setDeletePackageHelper(mDeletePackageHelper) 118 mComputer = spy(mPms.snapshotComputer()) 119 mExistingPackages = getExistingPackages( 120 DYNAMIC_LIB_PACKAGE_NAME, STATIC_LIB_PACKAGE_NAME, CONSUMER_PACKAGE_NAME) 121 122 whenever(mMockSystem.mocks().injector.getSystemService(StorageManager::class.java)) 123 .thenReturn(mStorageManager) 124 whenever(mStorageManager.findPathForUuid(nullable())).thenReturn(mFile) 125 doAnswer { mComputer }.`when`(mPms).snapshotComputer() 126 doAnswer { STATIC_LIB_PACKAGE_NAME }.`when`(mComputer).resolveInternalPackageName( 127 eq(STATIC_LIB_DECLARING_PACKAGE_NAME), eq(STATIC_LIB_VERSION)) 128 whenever(mDeletePackageHelper.deletePackageX(any(), any(), any(), any(), any())) 129 .thenReturn(PackageManager.DELETE_SUCCEEDED) 130 whenever(mMockSystem.mocks().injector.compatibility).thenReturn(mPlatformCompat) 131 wheneverStatic { HexEncoding.decode(STATIC_LIB_NAME, false) } 132 .thenReturn(PackageUtils.computeSha256DigestBytes( 133 mSettings.getPackageLPr(STATIC_LIB_PACKAGE_NAME) 134 .pkg.signingDetails.signatures!![0].toByteArray())) 135 } 136 137 @Test 138 fun snapshot_shouldSealed() { 139 val builtinLibs = mSharedLibrariesImpl.snapshot().all[BUILTIN_LIB_NAME] 140 assertThat(builtinLibs).isNotNull() 141 142 assertFailsWith(IllegalStateException::class) { 143 mSharedLibrariesImpl.snapshot().all[BUILTIN_LIB_NAME] = WatchedLongSparseArray() 144 } 145 assertFailsWith(IllegalStateException::class) { 146 builtinLibs!!.put(VERSION_UNDEFINED, libOfBuiltin(BUILTIN_LIB_NAME)) 147 } 148 } 149 150 @Test 151 fun addBuiltInSharedLibrary() { 152 mSharedLibrariesImpl.addBuiltInSharedLibraryLPw(libEntry(TEST_LIB_NAME)) 153 154 assertThat(mSharedLibrariesImpl.getSharedLibraryInfos(TEST_LIB_NAME)).isNotNull() 155 assertThat(mSharedLibrariesImpl.getSharedLibraryInfo(TEST_LIB_NAME, VERSION_UNDEFINED)) 156 .isNotNull() 157 } 158 159 @Test 160 fun addBuiltInSharedLibrary_withDuplicateLibName() { 161 val duplicate = libEntry(BUILTIN_LIB_NAME, "duplicate.path") 162 mSharedLibrariesImpl.addBuiltInSharedLibraryLPw(duplicate) 163 val sharedLibInfo = mSharedLibrariesImpl 164 .getSharedLibraryInfo(BUILTIN_LIB_NAME, VERSION_UNDEFINED) 165 166 assertThat(sharedLibInfo).isNotNull() 167 assertThat(sharedLibInfo!!.path).isNotEqualTo(duplicate.filename) 168 } 169 170 @Test 171 fun commitSharedLibraryInfo_withStaticSharedLib() { 172 val testInfo = libOfStatic(TEST_LIB_PACKAGE_NAME, TEST_LIB_NAME, 1L) 173 mSharedLibrariesImpl.commitSharedLibraryInfoLPw(testInfo) 174 val sharedLibInfos = mSharedLibrariesImpl 175 .getStaticLibraryInfos(testInfo.declaringPackage.packageName) 176 177 assertThat(mSharedLibrariesImpl.getSharedLibraryInfos(TEST_LIB_NAME)) 178 .isNotNull() 179 assertThat(mSharedLibrariesImpl.getSharedLibraryInfo(testInfo.name, testInfo.longVersion)) 180 .isNotNull() 181 assertThat(sharedLibInfos).isNotNull() 182 assertThat(sharedLibInfos.get(testInfo.longVersion)).isNotNull() 183 } 184 185 @Test 186 fun removeSharedLibrary() { 187 val staticInfo = mSharedLibrariesImpl 188 .getSharedLibraryInfo(STATIC_LIB_NAME, STATIC_LIB_VERSION)!! 189 190 mSharedLibrariesImpl.removeSharedLibraryLPw(STATIC_LIB_NAME, STATIC_LIB_VERSION) 191 192 assertThat(mSharedLibrariesImpl.getSharedLibraryInfos(STATIC_LIB_NAME)).isNull() 193 assertThat(mSharedLibrariesImpl 194 .getStaticLibraryInfos(staticInfo.declaringPackage.packageName)).isNull() 195 } 196 197 @Test 198 fun pruneUnusedStaticSharedLibraries() { 199 mSharedLibrariesImpl.pruneUnusedStaticSharedLibraries(mPms.snapshotComputer(), 200 Long.MAX_VALUE, 0) 201 202 verify(mDeletePackageHelper) 203 .deletePackageX(eq(STATIC_LIB_PACKAGE_NAME), any(), any(), any(), any()) 204 } 205 206 @Test 207 fun getLatestSharedLibraVersion() { 208 val pair = createBasicAndroidPackage(STATIC_LIB_PACKAGE_NAME + "_" + 10, 10L, 209 staticLibrary = STATIC_LIB_NAME, staticLibraryVersion = 10L) 210 211 val latestInfo = 212 mSharedLibrariesImpl.getLatestStaticSharedLibraVersionLPr(pair.second)!! 213 214 assertThat(latestInfo).isNotNull() 215 assertThat(latestInfo.name).isEqualTo(STATIC_LIB_NAME) 216 assertThat(latestInfo.longVersion).isEqualTo(STATIC_LIB_VERSION) 217 } 218 219 @Test 220 fun getStaticSharedLibLatestVersionSetting() { 221 val pair = createBasicAndroidPackage(STATIC_LIB_PACKAGE_NAME + "_" + 10, 10L, 222 staticLibrary = STATIC_LIB_NAME, staticLibraryVersion = 10L) 223 val parsedPackage = pair.second as ParsedPackage 224 val scanRequest = ScanRequest(parsedPackage, null, null, null, null, 225 null, null, null, 0, 0, false, null, null) 226 val scanResult = ScanResult(scanRequest, true, null, null, false, 0, null, null, null) 227 228 val latestInfoSetting = 229 mSharedLibrariesImpl.getStaticSharedLibLatestVersionSetting(scanResult)!! 230 231 assertThat(latestInfoSetting).isNotNull() 232 assertThat(latestInfoSetting.packageName).isEqualTo(STATIC_LIB_PACKAGE_NAME) 233 } 234 235 @Test 236 fun updateSharedLibraries_withDynamicLibPackage() { 237 val testPackageSetting = mSettings.getPackageLPr(DYNAMIC_LIB_PACKAGE_NAME) 238 testPackageSetting.setPkgStateLibraryFiles(listOf()) 239 assertThat(testPackageSetting.usesLibraryFiles).isEmpty() 240 241 mSharedLibrariesImpl.updateSharedLibrariesLPw(testPackageSetting.pkg, testPackageSetting, 242 null /* changingLib */, null /* changingLibSetting */, mExistingPackages) 243 244 assertThat(testPackageSetting.usesLibraryFiles).hasSize(1) 245 assertThat(testPackageSetting.usesLibraryFiles).contains(builtinLibPath(BUILTIN_LIB_NAME)) 246 } 247 248 @Test 249 fun updateSharedLibraries_withStaticLibPackage() { 250 val testPackageSetting = mSettings.getPackageLPr(STATIC_LIB_PACKAGE_NAME) 251 testPackageSetting.setPkgStateLibraryFiles(listOf()) 252 assertThat(testPackageSetting.usesLibraryFiles).isEmpty() 253 254 mSharedLibrariesImpl.updateSharedLibrariesLPw(testPackageSetting.pkg, testPackageSetting, 255 null /* changingLib */, null /* changingLibSetting */, mExistingPackages) 256 257 assertThat(testPackageSetting.usesLibraryFiles).hasSize(2) 258 assertThat(testPackageSetting.usesLibraryFiles).contains(builtinLibPath(BUILTIN_LIB_NAME)) 259 assertThat(testPackageSetting.usesLibraryFiles).contains(apkPath(DYNAMIC_LIB_PACKAGE_NAME)) 260 } 261 262 @Test 263 fun updateSharedLibraries_withConsumerPackage() { 264 val testPackageSetting = mSettings.getPackageLPr(CONSUMER_PACKAGE_NAME) 265 testPackageSetting.setPkgStateLibraryFiles(listOf()) 266 assertThat(testPackageSetting.usesLibraryFiles).isEmpty() 267 268 mSharedLibrariesImpl.updateSharedLibrariesLPw(testPackageSetting.pkg, testPackageSetting, 269 null /* changingLib */, null /* changingLibSetting */, mExistingPackages) 270 271 assertThat(testPackageSetting.usesLibraryFiles).hasSize(3) 272 assertThat(testPackageSetting.usesLibraryFiles).contains(builtinLibPath(BUILTIN_LIB_NAME)) 273 assertThat(testPackageSetting.usesLibraryFiles).contains(apkPath(DYNAMIC_LIB_PACKAGE_NAME)) 274 assertThat(testPackageSetting.usesLibraryFiles) 275 .contains(apkPath(STATIC_LIB_DECLARING_PACKAGE_NAME)) 276 } 277 278 @Test 279 fun updateAllSharedLibraries() { 280 mExistingPackages.forEach { 281 val setting = mSettings.getPackageLPr(it.key) 282 setting.setPkgStateLibraryFiles(listOf()) 283 assertThat(setting.usesLibraryFiles).isEmpty() 284 } 285 286 mSharedLibrariesImpl.updateAllSharedLibrariesLPw( 287 null /* updatedPkg */, null /* updatedPkgSetting */, mExistingPackages) 288 289 var testPackageSetting = mSettings.getPackageLPr(DYNAMIC_LIB_PACKAGE_NAME) 290 assertThat(testPackageSetting.usesLibraryFiles).hasSize(1) 291 assertThat(testPackageSetting.usesLibraryFiles).contains(builtinLibPath(BUILTIN_LIB_NAME)) 292 293 testPackageSetting = mSettings.getPackageLPr(STATIC_LIB_PACKAGE_NAME) 294 assertThat(testPackageSetting.usesLibraryFiles).hasSize(2) 295 assertThat(testPackageSetting.usesLibraryFiles).contains(builtinLibPath(BUILTIN_LIB_NAME)) 296 assertThat(testPackageSetting.usesLibraryFiles).contains(apkPath(DYNAMIC_LIB_PACKAGE_NAME)) 297 298 testPackageSetting = mSettings.getPackageLPr(CONSUMER_PACKAGE_NAME) 299 assertThat(testPackageSetting.usesLibraryFiles).hasSize(3) 300 assertThat(testPackageSetting.usesLibraryFiles).contains(builtinLibPath(BUILTIN_LIB_NAME)) 301 assertThat(testPackageSetting.usesLibraryFiles).contains(apkPath(DYNAMIC_LIB_PACKAGE_NAME)) 302 assertThat(testPackageSetting.usesLibraryFiles) 303 .contains(apkPath(STATIC_LIB_DECLARING_PACKAGE_NAME)) 304 } 305 306 @Test 307 fun getAllowedSharedLibInfos_withStaticSharedLibInfo() { 308 val testInfo = libOfStatic(TEST_LIB_PACKAGE_NAME, TEST_LIB_NAME, 1L) 309 val scanResult = ScanResult(mock(), true, null, null, 310 false, 0, null, testInfo, null) 311 312 val allowedInfos = mSharedLibrariesImpl.getAllowedSharedLibInfos(scanResult) 313 314 assertThat(allowedInfos).hasSize(1) 315 assertThat(allowedInfos[0].name).isEqualTo(TEST_LIB_NAME) 316 } 317 318 @Test 319 fun getAllowedSharedLibInfos_withDynamicSharedLibInfo() { 320 val testInfo = libOfDynamic(TEST_LIB_PACKAGE_NAME, TEST_LIB_NAME) 321 val pair = createBasicAndroidPackage( 322 TEST_LIB_PACKAGE_NAME, 10L, libraries = arrayOf(TEST_LIB_NAME)) 323 val parsedPackage = pair.second.apply { 324 isSystem = true 325 } as ParsedPackage 326 val packageSetting = mMockSystem.system() 327 .createBasicSettingBuilder(pair.first.parentFile, parsedPackage.hideAsFinal()) 328 .setPkgFlags(ApplicationInfo.FLAG_SYSTEM).build() 329 val scanRequest = ScanRequest(parsedPackage, null, null, null, null, 330 null, null, null, 0, 0, false, null, null) 331 val scanResult = ScanResult(scanRequest, true, packageSetting, null, 332 false, 0, null, null, listOf(testInfo)) 333 334 val allowedInfos = mSharedLibrariesImpl.getAllowedSharedLibInfos(scanResult) 335 336 assertThat(allowedInfos).hasSize(1) 337 assertThat(allowedInfos[0].name).isEqualTo(TEST_LIB_NAME) 338 } 339 340 private fun getExistingPackages(vararg args: String): ArrayMap<String, AndroidPackage> { 341 val existingPackages = ArrayMap<String, AndroidPackage>() 342 args.forEach { 343 existingPackages[it] = mSettings.getPackageLPr(it).pkg 344 } 345 return existingPackages 346 } 347 348 private fun stageBuiltinLibrary(folder: File) { 349 builtinLibDirectory = folder 350 val libPath = File(builtinLibPath(BUILTIN_LIB_NAME)) 351 libPath.createNewFile() 352 MockSystem.addDefaultSharedLibrary(BUILTIN_LIB_NAME, libEntry(BUILTIN_LIB_NAME)) 353 } 354 355 private fun stageScanExistingPackages() { 356 // add a dynamic shared library that is using the builtin library 357 stageScanExistingPackage(DYNAMIC_LIB_PACKAGE_NAME, 1L, 358 libraries = arrayOf(DYNAMIC_LIB_NAME), 359 usesLibraries = arrayOf(BUILTIN_LIB_NAME)) 360 361 // add a static shared library v7 that is using the dynamic shared library 362 stageScanExistingPackage(STATIC_LIB_DECLARING_PACKAGE_NAME, STATIC_LIB_VERSION, 363 staticLibrary = STATIC_LIB_NAME, staticLibraryVersion = STATIC_LIB_VERSION, 364 usesLibraries = arrayOf(DYNAMIC_LIB_NAME)) 365 366 // add a consumer package that is using the dynamic and static shared library 367 stageScanExistingPackage(CONSUMER_PACKAGE_NAME, 1L, 368 isSystem = true, 369 usesLibraries = arrayOf(DYNAMIC_LIB_NAME), 370 usesStaticLibraries = arrayOf(STATIC_LIB_NAME), 371 usesStaticLibraryVersions = arrayOf(STATIC_LIB_VERSION)) 372 } 373 374 private fun stageScanExistingPackage( 375 packageName: String, 376 version: Long, 377 isSystem: Boolean = false, 378 libraries: Array<String>? = null, 379 staticLibrary: String? = null, 380 staticLibraryVersion: Long = 0L, 381 usesLibraries: Array<String>? = null, 382 usesStaticLibraries: Array<String>? = null, 383 usesStaticLibraryVersions: Array<Long>? = null 384 ) { 385 val withPackage = { pkg: PackageImpl -> 386 pkg.setSystem(isSystem || libraries != null) 387 pkg.setTargetSdkVersion(Build.VERSION_CODES.S) 388 libraries?.forEach { pkg.addLibraryName(it) } 389 staticLibrary?.let { 390 pkg.setStaticSharedLibName(it) 391 pkg.setStaticSharedLibVersion(staticLibraryVersion) 392 pkg.setStaticSharedLibrary(true) 393 } 394 usesLibraries?.forEach { pkg.addUsesLibrary(it) } 395 usesStaticLibraries?.forEachIndexed { index, s -> 396 pkg.addUsesStaticLibrary(s, 397 usesStaticLibraryVersions?.get(index) ?: 0L, 398 arrayOf(s)) 399 } 400 pkg 401 } 402 val withSetting = { settingBuilder: PackageSettingBuilder -> 403 if (staticLibrary != null) { 404 settingBuilder.setName(getStaticSharedLibInternalPackageName(packageName, version)) 405 } 406 if (isSystem || libraries != null) { 407 settingBuilder.setPkgFlags(ApplicationInfo.FLAG_SYSTEM) 408 } 409 settingBuilder 410 } 411 mMockSystem.system().stageScanExistingPackage( 412 packageName, version, mMockSystem.system().dataAppDirectory, withPackage, withSetting) 413 } 414 415 private fun createBasicAndroidPackage( 416 packageName: String, 417 version: Long, 418 libraries: Array<String>? = null, 419 staticLibrary: String? = null, 420 staticLibraryVersion: Long = 0L, 421 usesLibraries: Array<String>? = null, 422 usesStaticLibraries: Array<String>? = null, 423 usesStaticLibraryVersions: Array<Long>? = null 424 ): Pair<File, PackageImpl> { 425 assertFalse { libraries != null && staticLibrary != null } 426 assertTrue { (usesStaticLibraries?.size ?: -1) == (usesStaticLibraryVersions?.size ?: -1) } 427 428 val pair = mMockSystem.system() 429 .createBasicAndroidPackage(mMockSystem.system().dataAppDirectory, packageName, version) 430 pair.second.apply { 431 setTargetSdkVersion(Build.VERSION_CODES.S) 432 libraries?.forEach { addLibraryName(it) } 433 staticLibrary?.let { 434 setStaticSharedLibName(it) 435 setStaticSharedLibVersion(staticLibraryVersion) 436 setStaticSharedLibrary(true) 437 } 438 usesLibraries?.forEach { addUsesLibrary(it) } 439 usesStaticLibraries?.forEachIndexed { index, s -> 440 addUsesStaticLibrary(s, 441 usesStaticLibraryVersions?.get(index) ?: 0L, 442 arrayOf(s)) 443 } 444 } 445 return pair 446 } 447 448 private fun libEntry(libName: String, path: String? = null): SharedLibraryEntry = 449 SharedLibraryEntry(libName, path ?: builtinLibPath(libName), 450 arrayOfNulls(0), false /* isNative */) 451 452 private fun libOfBuiltin(libName: String): SharedLibraryInfo = 453 SharedLibraryInfo(builtinLibPath(libName), 454 null /* packageName */, 455 null /* codePaths */, 456 libName, 457 VERSION_UNDEFINED, 458 SharedLibraryInfo.TYPE_BUILTIN, 459 VersionedPackage(PLATFORM_PACKAGE_NAME, 0L /* versionCode */), 460 null /* dependentPackages */, 461 null /* dependencies */, 462 false /* isNative */) 463 464 private fun libOfStatic( 465 declaringPackageName: String, 466 libName: String, 467 version: Long 468 ): SharedLibraryInfo = 469 SharedLibraryInfo(null /* path */, 470 getStaticSharedLibInternalPackageName(declaringPackageName, version), 471 listOf(apkPath(declaringPackageName)), 472 libName, 473 version, 474 SharedLibraryInfo.TYPE_STATIC, 475 VersionedPackage(declaringPackageName, version /* versionCode */), 476 null /* dependentPackages */, 477 null /* dependencies */, 478 false /* isNative */) 479 480 private fun libOfDynamic(packageName: String, libName: String): SharedLibraryInfo = 481 SharedLibraryInfo(null /* path */, 482 packageName, 483 listOf(apkPath(packageName)), 484 libName, 485 VERSION_UNDEFINED, 486 SharedLibraryInfo.TYPE_DYNAMIC, 487 VersionedPackage(packageName, 1L /* versionCode */), 488 null /* dependentPackages */, 489 null /* dependencies */, 490 false /* isNative */) 491 492 private fun builtinLibPath(libName: String) = 493 File(builtinLibDirectory, "$libName.jar").path 494 495 private fun apkPath(packageName: String) = 496 File(mMockSystem.system().dataAppDirectory, packageName).path 497 498 private fun getStaticSharedLibInternalPackageName( 499 declaringPackageName: String, 500 version: Long 501 ) = "${declaringPackageName}_$version" 502 } 503