1 /*
2  * 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.test.parsing.parcelling
18 
19 import android.content.Intent
20 import android.content.pm.ApplicationInfo
21 import android.content.pm.ConfigurationInfo
22 import android.content.pm.FeatureGroupInfo
23 import android.content.pm.FeatureInfo
24 import android.content.pm.PackageManager
25 import android.content.pm.SigningDetails
26 import android.net.Uri
27 import android.os.Bundle
28 import android.os.Parcelable
29 import android.util.ArraySet
30 import android.util.SparseArray
31 import android.util.SparseIntArray
32 import com.android.internal.R
33 import com.android.server.pm.parsing.pkg.AndroidPackageUtils
34 import com.android.server.pm.parsing.pkg.PackageImpl
35 import com.android.server.pm.pkg.AndroidPackage
36 import com.android.server.pm.pkg.component.ParsedActivityImpl
37 import com.android.server.pm.pkg.component.ParsedApexSystemServiceImpl
38 import com.android.server.pm.pkg.component.ParsedAttributionImpl
39 import com.android.server.pm.pkg.component.ParsedComponentImpl
40 import com.android.server.pm.pkg.component.ParsedInstrumentationImpl
41 import com.android.server.pm.pkg.component.ParsedIntentInfoImpl
42 import com.android.server.pm.pkg.component.ParsedPermissionGroupImpl
43 import com.android.server.pm.pkg.component.ParsedPermissionImpl
44 import com.android.server.pm.pkg.component.ParsedProcessImpl
45 import com.android.server.pm.pkg.component.ParsedProviderImpl
46 import com.android.server.pm.pkg.component.ParsedServiceImpl
47 import com.android.server.pm.pkg.component.ParsedUsesPermissionImpl
48 import com.android.server.testutils.mockThrowOnUnmocked
49 import com.android.server.testutils.whenever
50 import java.security.KeyPairGenerator
51 import java.security.PublicKey
52 import java.util.UUID
53 import kotlin.contracts.ExperimentalContracts
54 
55 @ExperimentalContracts
56 class AndroidPackageTest : ParcelableComponentTest(AndroidPackage::class, PackageImpl::class) {
57 
58     companion object {
59         private val TEST_UUID = UUID.fromString("57554103-df3e-4475-ae7a-8feba49353ac")
60     }
61 
62     override val defaultImpl = PackageImpl.forTesting("com.example.test")
63     override val creator = PackageImpl.CREATOR
64 
65     override val excludedMethods = listOf(
66         // Internal methods
67         "toAppInfoToString",
68         "toAppInfoWithoutState",
69         "toAppInfoWithoutStateWithoutFlags",
70         "addMimeGroupsFromComponent",
71         "assignDerivedFields",
72         "assignDerivedFields2",
73         "makeImmutable",
74         "buildFakeForDeletion",
75         "buildAppClassNamesByProcess",
76         "capPermissionPriorities",
77         "forParsing",
78         "forTesting",
79         "getBaseAppDataCredentialProtectedDirForSystemUser",
80         "getBaseAppDataDeviceProtectedDirForSystemUser",
81         "getBoolean",
82         "getBoolean2",
83         "setBoolean",
84         "setBoolean2",
85         "hideAsFinal",
86         "hideAsParsed",
87         "markNotActivitiesAsNotExportedIfSingleUser",
88         "sortActivities",
89         "sortReceivers",
90         "sortServices",
91         "setAllComponentsDirectBootAware",
92         "getUsesLibrariesSorted",
93         "getUsesOptionalLibrariesSorted",
94         "getUsesSdkLibrariesSorted",
95         "getUsesStaticLibrariesSorted",
96         // Tested through setting minor/major manually
97         "setLongVersionCode",
98         "getLongVersionCode",
99         // Tested through constructor
100         "getManifestPackageName",
101         // Removal not tested, irrelevant for parcelling concerns
102         "removeUsesOptionalLibrary",
103         "clearAdoptPermissions",
104         "clearOriginalPackages",
105         "clearProtectedBroadcasts",
106         "removePermission",
107         "removeUsesLibrary",
108         "removeUsesOptionalNativeLibrary",
109         // Tested manually
110         "getMimeGroups",
111         "getRequestedPermissions",
112         "getStorageUuid",
113         // Tested through asSplit
114         "asSplit",
115         "getSplits",
116         "getSplitNames",
117         "getSplitCodePaths",
118         "getSplitRevisionCodes",
119         "getSplitFlags",
120         "getSplitClassLoaderNames",
121         "getSplitDependencies",
122         "setSplitCodePaths",
123         "setSplitClassLoaderName",
124         "setSplitHasCode",
125         // Tested through addUsesSdkLibrary
126         "addUsesSdkLibrary",
127         "getUsesSdkLibraries",
128         "getUsesSdkLibrariesVersionsMajor",
129         "getUsesSdkLibrariesCertDigests",
130         // Tested through addUsesStaticLibrary
131         "addUsesStaticLibrary",
132         "getUsesStaticLibraries",
133         "getUsesStaticLibrariesVersions",
134         "getUsesStaticLibrariesCertDigests",
135 
136         // Tested through getSetByValue via AndroidPackageHidden APIs, to be removed eventually
137         "setOdm",
138         "setOem",
139         "setPrivileged",
140         "setProduct",
141         "setSystem",
142         "setSystemExt",
143         "setVendor",
144         "isOdm",
145         "isOem",
146         "isPrivileged",
147         "isProduct",
148         "isSystem",
149         "isSystemExt",
150         "isVendor",
151     )
152 
153     override val baseParams = listOf(
154         AndroidPackage::getApplicationClassName,
155         AndroidPackage::getAppComponentFactory,
156         AndroidPackage::getAutoRevokePermissions,
157         AndroidPackage::getBackupAgentName,
158         AndroidPackage::getBannerResourceId,
159         AndroidPackage::getBaseApkPath,
160         AndroidPackage::getBaseRevisionCode,
161         AndroidPackage::getCategory,
162         AndroidPackage::getClassLoaderName,
163         AndroidPackage::getCompatibleWidthLimitDp,
164         AndroidPackage::getCompileSdkVersion,
165         AndroidPackage::getCompileSdkVersionCodeName,
166         AndroidPackage::getDataExtractionRulesResourceId,
167         AndroidPackage::getDescriptionResourceId,
168         AndroidPackage::getFullBackupContentResourceId,
169         AndroidPackage::getGwpAsanMode,
170         AndroidPackage::getIconResourceId,
171         AndroidPackage::getInstallLocation,
172         AndroidPackage::getLabelResourceId,
173         AndroidPackage::getLargestWidthLimitDp,
174         AndroidPackage::getLogoResourceId,
175         AndroidPackage::getLocaleConfigResourceId,
176         AndroidPackage::getManageSpaceActivityName,
177         AndroidPackage::getMaxSdkVersion,
178         AndroidPackage::getMemtagMode,
179         AndroidPackage::getMinSdkVersion,
180         AndroidPackage::getNativeHeapZeroInitialized,
181         AndroidPackage::getNativeLibraryDir,
182         AndroidPackage::getNativeLibraryRootDir,
183         AndroidPackage::getNetworkSecurityConfigResourceId,
184         AndroidPackage::getNonLocalizedLabel,
185         AndroidPackage::getOverlayCategory,
186         AndroidPackage::getOverlayPriority,
187         AndroidPackage::getOverlayTarget,
188         AndroidPackage::getOverlayTargetOverlayableName,
189         AndroidPackage::getPackageName,
190         AndroidPackage::getPath,
191         AndroidPackage::getPermission,
192         PackageImpl::getPrimaryCpuAbi,
193         AndroidPackage::getProcessName,
194         AndroidPackage::getRequiredAccountType,
195         AndroidPackage::getRequiresSmallestWidthDp,
196         AndroidPackage::getResizeableActivity,
197         AndroidPackage::getRestrictedAccountType,
198         AndroidPackage::getRoundIconResourceId,
199         PackageImpl::getSecondaryCpuAbi,
200         AndroidPackage::getSecondaryNativeLibraryDir,
201         AndroidPackage::getSharedUserId,
202         AndroidPackage::getSharedUserLabelResourceId,
203         AndroidPackage::getSdkLibraryName,
204         AndroidPackage::getSdkLibVersionMajor,
205         AndroidPackage::getStaticSharedLibraryName,
206         AndroidPackage::getStaticSharedLibraryVersion,
207         AndroidPackage::getTargetSandboxVersion,
208         AndroidPackage::getTargetSdkVersion,
209         AndroidPackage::getTaskAffinity,
210         AndroidPackage::getThemeResourceId,
211         AndroidPackage::getUiOptions,
212         AndroidPackage::getUid,
213         AndroidPackage::getVersionName,
214         AndroidPackage::getZygotePreloadName,
215         AndroidPackage::isAllowAudioPlaybackCapture,
216         AndroidPackage::isBackupAllowed,
217         AndroidPackage::isClearUserDataAllowed,
218         AndroidPackage::isClearUserDataOnFailedRestoreAllowed,
219         AndroidPackage::isAllowNativeHeapPointerTagging,
220         AndroidPackage::isTaskReparentingAllowed,
221         AndroidPackage::isBackupInForeground,
222         AndroidPackage::isHardwareAccelerated,
223         AndroidPackage::isSaveStateDisallowed,
224         AndroidPackage::isCoreApp,
225         AndroidPackage::isCrossProfile,
226         AndroidPackage::isDebuggable,
227         AndroidPackage::isDefaultToDeviceProtectedStorage,
228         AndroidPackage::isDirectBootAware,
229         AndroidPackage::isEnabled,
230         AndroidPackage::isExternalStorage,
231         AndroidPackage::isExtractNativeLibrariesRequested,
232         AndroidPackage::isFactoryTest,
233         AndroidPackage::isApex,
234         AndroidPackage::isForceQueryable,
235         AndroidPackage::isFullBackupOnly,
236         AndroidPackage::isGame,
237         AndroidPackage::isDeclaredHavingCode,
238         AndroidPackage::isHasDomainUrls,
239         AndroidPackage::isUserDataFragile,
240         AndroidPackage::isIsolatedSplitLoading,
241         AndroidPackage::isKillAfterRestoreAllowed,
242         AndroidPackage::isLargeHeap,
243         AndroidPackage::isMultiArch,
244         AndroidPackage::isNativeLibraryRootRequiresIsa,
245         AndroidPackage::isOnBackInvokedCallbackEnabled,
246         AndroidPackage::isResourceOverlay,
247         AndroidPackage::isOverlayIsStatic,
248         AndroidPackage::isPartiallyDirectBootAware,
249         AndroidPackage::isPersistent,
250         AndroidPackage::isProfileableByShell,
251         AndroidPackage::isRequestLegacyExternalStorage,
252         AndroidPackage::isRequiredForAllUsers,
253         AndroidPackage::isResizeableActivityViaSdkVersion,
254         AndroidPackage::isRestoreAnyVersion,
255         AndroidPackage::isSignedWithPlatformKey,
256         AndroidPackage::isSdkLibrary,
257         AndroidPackage::isStaticSharedLibrary,
258         AndroidPackage::isStub,
259         AndroidPackage::isRtlSupported,
260         AndroidPackage::isTestOnly,
261         AndroidPackage::is32BitAbiPreferred,
262         AndroidPackage::isUseEmbeddedDex,
263         AndroidPackage::isCleartextTrafficAllowed,
264         AndroidPackage::isNonSdkApiRequested,
265         AndroidPackage::isVisibleToInstantApps,
266         AndroidPackage::isVmSafeMode,
267         AndroidPackage::isLeavingSharedUser,
268         AndroidPackage::isResetEnabledSettingsOnAppDataCleared,
269         AndroidPackage::getMaxAspectRatio,
270         AndroidPackage::getMinAspectRatio,
271         AndroidPackage::hasPreserveLegacyExternalStorage,
272         AndroidPackage::hasRequestForegroundServiceExemption,
273         AndroidPackage::hasRequestRawExternalStorageAccess
274     )
275 
276     override fun extraParams() = listOf(
277         getter(AndroidPackage::getVolumeUuid, TEST_UUID.toString()),
278         getter(AndroidPackage::isProfileable, true),
279         getter(PackageImpl::getVersionCode, 3),
280         getter(PackageImpl::getVersionCodeMajor, 9),
281         getter(AndroidPackage::getUpgradeKeySets, setOf("testUpgradeKeySet")),
282         getter(AndroidPackage::isAnyDensity, false, 0),
283         getter(AndroidPackage::isResizeable, false, 0),
284         getter(AndroidPackage::isSmallScreensSupported, false, 0),
285         getter(AndroidPackage::isNormalScreensSupported, false, 0),
286         getter(AndroidPackage::isLargeScreensSupported, false, 0),
287         getter(AndroidPackage::isExtraLargeScreensSupported, false, 0),
288         adder(AndroidPackage::getAdoptPermissions, "test.adopt.PERMISSION"),
289         adder(AndroidPackage::getOriginalPackages, "com.test.original"),
290         adder(AndroidPackage::getImplicitPermissions, "test.implicit.PERMISSION"),
291         adder(AndroidPackage::getLibraryNames, "testLibraryName"),
292         adder(AndroidPackage::getProtectedBroadcasts, "test.protected.BROADCAST"),
293         adder(AndroidPackage::getQueriesPackages, "com.test.package.queries"),
294         adder(AndroidPackage::getQueriesProviders, "com.test.package.queries.provider"),
295         adder(AndroidPackage::getUsesLibraries, "testUsesLibrary"),
296         adder(AndroidPackage::getUsesNativeLibraries, "testUsesNativeLibrary"),
297         adder(AndroidPackage::getUsesOptionalLibraries, "testUsesOptionalLibrary"),
298         adder(AndroidPackage::getUsesOptionalNativeLibraries, "testUsesOptionalNativeLibrary"),
299         getSetByValue(
300             AndroidPackage::isAttributionsUserVisible,
301             PackageImpl::setAttributionsAreUserVisible,
302             true
303         ),
304         getSetByValue2(
305             AndroidPackage::getOverlayables,
306             PackageImpl::addOverlayable,
307             "testOverlayableName" to "testActorName",
308             transformGet = { "testOverlayableName" to it["testOverlayableName"] }
309         ),
310         getSetByValue(
311             AndroidPackage::getMetaData,
312             PackageImpl::setMetaData,
313             "testBundleKey" to "testBundleValue",
314             transformGet = { "testBundleKey" to it?.getString("testBundleKey") },
315             transformSet = { Bundle().apply { putString(it.first, it.second) } }
316         ),
317         getSetByValue(
318             AndroidPackage::getAttributions,
319             PackageImpl::addAttribution,
320             Triple("testTag", 13, listOf("testInherit")),
321             transformGet = { it.singleOrNull()?.let { Triple(it.tag, it.label, it.inheritFrom) } },
322             transformSet = { it?.let {
323                 ParsedAttributionImpl(
324                     it.first,
325                     it.second,
326                     it.third
327                 )
328             } }
329         ),
330         getSetByValue2(
331             AndroidPackage::getKeySetMapping,
332             PackageImpl::addKeySet,
333             "testKeySetName" to testKey(),
334             transformGet = { "testKeySetName" to it["testKeySetName"]?.singleOrNull() }
335         ),
336         getSetByValue(
337             AndroidPackage::getPermissionGroups,
338             PackageImpl::addPermissionGroup,
339             "test.permission.GROUP",
340             transformGet = { it.singleOrNull()?.name },
341             transformSet = { ParsedPermissionGroupImpl()
342                 .apply { setName(it) } }
343         ),
344         getSetByValue2(
345             AndroidPackage::getPreferredActivityFilters,
346             PackageImpl::addPreferredActivityFilter,
347             "TestClassName" to ParsedIntentInfoImpl()
348                 .apply {
349                 intentFilter.apply {
350                     addDataScheme("http")
351                     addDataAuthority("test.pm.server.android.com", null)
352                 }
353             },
354             transformGet = { it.singleOrNull()?.let { it.first to it.second } },
355             compare = { first, second ->
356                 equalBy(
357                     first, second,
358                     { it.first },
359                     { it.second.intentFilter.schemesIterator().asSequence().singleOrNull() },
360                     { it.second.intentFilter.authoritiesIterator().asSequence()
361                         .singleOrNull()?.host }
362                 )
363             }
364         ),
365         getSetByValue(
366             AndroidPackage::getQueriesIntents,
367             PackageImpl::addQueriesIntent,
368             Intent(Intent.ACTION_VIEW, Uri.parse("https://test.pm.server.android.com")),
369             transformGet = { it.singleOrNull() },
370             compare = { first, second -> first?.filterEquals(second) }
371         ),
372         getSetByValue(
373             AndroidPackage::getRestrictUpdateHash,
374             PackageImpl::setRestrictUpdateHash,
375             byteArrayOf(0, 1, 2, 3, 4),
376             compare = ByteArray::contentEquals
377         ),
378         getSetByValue(
379             AndroidPackage::getSigningDetails,
380             PackageImpl::setSigningDetails,
381             testKey(),
382             transformGet = { it.publicKeys?.takeIf { it.size > 0 }?.valueAt(0) },
383             transformSet = {
384                 SigningDetails(
385                     null,
386                     SigningDetails.SignatureSchemeVersion.UNKNOWN,
387                     ArraySet<PublicKey>().apply { add(it) },
388                     null
389                 )
390             }
391         ),
392         getSetByValue(
393             AndroidPackage::getActivities,
394             PackageImpl::addActivity,
395             "TestActivityName",
396             transformGet = { it.singleOrNull()?.name.orEmpty() },
397             transformSet = { ParsedActivityImpl()
398                 .apply { name = it }.withMimeGroups() }
399         ),
400         getSetByValue(
401             AndroidPackage::getApexSystemServices,
402             PackageImpl::addApexSystemService,
403             "TestApexSystemServiceName",
404             transformGet = { it.singleOrNull()?.name.orEmpty() },
405             transformSet = { ParsedApexSystemServiceImpl()
406                 .apply { name = it } }
407         ),
408         getSetByValue(
409             AndroidPackage::getReceivers,
410             PackageImpl::addReceiver,
411             "TestReceiverName",
412             transformGet = { it.singleOrNull()?.name.orEmpty() },
413             transformSet = { ParsedActivityImpl()
414                 .apply { name = it }.withMimeGroups() }
415         ),
416         getSetByValue(
417             AndroidPackage::getServices,
418             PackageImpl::addService,
419             "TestServiceName",
420             transformGet = { it.singleOrNull()?.name.orEmpty() },
421             transformSet = { ParsedServiceImpl()
422                 .apply { name = it }.withMimeGroups() }
423         ),
424         getSetByValue(
425             AndroidPackage::getProviders,
426             PackageImpl::addProvider,
427             "TestProviderName",
428             transformGet = { it.singleOrNull()?.name.orEmpty() },
429             transformSet = { ParsedProviderImpl()
430                 .apply { name = it }.withMimeGroups() }
431         ),
432         getSetByValue(
433             AndroidPackage::getInstrumentations,
434             PackageImpl::addInstrumentation,
435             "TestInstrumentationName",
436             transformGet = { it.singleOrNull()?.name.orEmpty() },
437             transformSet = { ParsedInstrumentationImpl()
438                 .apply { name = it } }
439         ),
440         getSetByValue(
441             AndroidPackage::getConfigPreferences,
442             PackageImpl::addConfigPreference,
443             testCounter++,
444             transformGet = { it.singleOrNull()?.reqGlEsVersion ?: -1 },
445             transformSet = { ConfigurationInfo().apply { reqGlEsVersion = it } }
446         ),
447         getSetByValue(
448             AndroidPackage::getFeatureGroups,
449             PackageImpl::addFeatureGroup,
450             "test.feature.GROUP",
451             transformGet = { it.singleOrNull()?.features?.singleOrNull()?.name.orEmpty() },
452             transformSet = {
453                 FeatureGroupInfo().apply {
454                     features = arrayOf(FeatureInfo().apply { name = it })
455                 }
456             }
457         ),
458         getSetByValue(
459             AndroidPackage::getPermissions,
460             PackageImpl::addPermission,
461             "test.PERMISSION",
462             transformGet = { it.singleOrNull()?.name.orEmpty() },
463             transformSet = { ParsedPermissionImpl()
464                 .apply { name = it } }
465         ),
466         getSetByValue(
467             AndroidPackage::getUsesPermissions,
468             PackageImpl::addUsesPermission,
469             "test.USES_PERMISSION",
470             transformGet = {
471                 // Need to strip implicit permission, which calls addUsesPermission when added
472                 it.filterNot { it.name == "test.implicit.PERMISSION" }
473                     .singleOrNull()?.name.orEmpty()
474             },
475             transformSet = {
476                 ParsedUsesPermissionImpl(
477                     it,
478                     0
479                 )
480             }
481         ),
482         getSetByValue(
483             AndroidPackage::getRequestedFeatures,
484             PackageImpl::addReqFeature,
485             "test.feature.INFO",
486             transformGet = { it.singleOrNull()?.name.orEmpty() },
487             transformSet = { FeatureInfo().apply { name = it } }
488         ),
489         getSetByValue(
490             AndroidPackage::getMinExtensionVersions,
491             PackageImpl::setMinExtensionVersions,
492             SparseIntArray().apply { put(testCounter++, testCounter++) },
493             compare = { first, second ->
494                 equalBy(
495                     first, second,
496                     { it.size() },
497                     { it.keyAt(0) },
498                     { it.valueAt(0) }
499                 )
500             }
501         ),
502         getSetByValue(
503             AndroidPackage::getProcesses,
504             PackageImpl::setProcesses,
505             mapOf("testProcess" to ParsedProcessImpl()
506                 .apply { name = "testProcessName" }),
507             compare = { first, second ->
508                 equalBy(
509                     first, second,
510                     { it["testProcess"]?.name }
511                 )
512             }
513         ),
514         getSetByValue(
515             AndroidPackage::getProperties,
516             PackageImpl::addProperty,
517             PackageManager.Property(
518                 "testPropertyName",
519                 "testPropertyValue",
520                 "testPropertyClassName",
521                 "testPropertyPackageName"
522             ),
523             transformGet = { it["testPropertyName"] },
524             compare = { first, second ->
525                 equalBy(
526                     first, second,
527                     PackageManager.Property::getName,
528                     PackageManager.Property::getClassName,
529                     PackageManager.Property::getPackageName,
530                     PackageManager.Property::getString
531                 )
532             }
533         ),
534         getter(AndroidPackage::getKnownActivityEmbeddingCerts, setOf("TESTEMBEDDINGCERT")),
535         getSetByValue({ AndroidPackageUtils.isOdm(it) }, "isOdm", PackageImpl::setOdm, true),
536         getSetByValue({ AndroidPackageUtils.isOem(it) }, "isOem", PackageImpl::setOem, true),
537         getSetByValue(
538             { AndroidPackageUtils.isPrivileged(it) },
539             "isPrivileged",
540             PackageImpl::setPrivileged,
541             true
542         ),
543         getSetByValue(
544             { AndroidPackageUtils.isProduct(it) },
545             "isProduct",
546             PackageImpl::setProduct,
547             true
548         ),
549         getSetByValue(
550             { AndroidPackageUtils.isVendor(it) },
551             "isVendor",
552             PackageImpl::setVendor,
553             true
554         ),
555         getSetByValue(
556             { AndroidPackageUtils.isSystem(it) },
557             "isSystem",
558             PackageImpl::setSystem,
559             true
560         ),
561         getSetByValue(
562             { AndroidPackageUtils.isSystemExt(it) },
563             "isSystemExt",
564             PackageImpl::setSystemExt,
565             true
566         ),
567     )
568 
569     override fun initialObject() = PackageImpl.forParsing(
570         "com.example.test",
571         "/test/test/base.apk",
572         "/test/test",
573         mockThrowOnUnmocked {
574             whenever(getInteger(R.styleable.AndroidManifest_revisionCode, 0)) { 4 }
575             whenever(getBoolean(R.styleable.AndroidManifest_isolatedSplits, false)) { true }
576 
577             // Return invalid values here so that the getter/setter is tested properly
578             whenever(getInteger(R.styleable.AndroidManifest_versionCode, 0)) { -1 }
579             whenever(getInteger(R.styleable.AndroidManifest_versionCodeMajor, 0)) { -1 }
580             whenever(
581                 getNonConfigurationString(
582                     R.styleable.AndroidManifest_versionName,
583                     0
584                 )
585             ) { "" }
586             whenever(getInteger(R.styleable.AndroidManifest_compileSdkVersion, 0)) { 31 }
587             whenever(
588                 getNonConfigurationString(
589                     R.styleable.AndroidManifest_compileSdkVersionCodename,
590                     0
591                 )
592             ) { "" }
593         },
594         true
595     )
596         .asSplit(
597             arrayOf("testSplitNameZero", "testSplitNameOne"),
598             arrayOf("/test/testSplitZero.apk", "/test/testSplitOne.apk"),
599             intArrayOf(10, 11),
600             SparseArray<IntArray>().apply {
601                 put(0, intArrayOf(-1))
602                 put(1, intArrayOf(0))
603                 put(2, intArrayOf(1))
604             }
605         )
606         .setSplitHasCode(0, true)
607         .setSplitHasCode(1, false)
608         .setSplitClassLoaderName(0, "testSplitClassLoaderNameZero")
609         .setSplitClassLoaderName(1, "testSplitClassLoaderNameOne")
610         .addUsesSdkLibrary("testSdk", 2L, arrayOf("testCertDigest1"))
611         .addUsesStaticLibrary("testStatic", 3L, arrayOf("testCertDigest2"))
612 
613     override fun finalizeObject(parcelable: Parcelable) {
614         (parcelable as PackageImpl).hideAsParsed().hideAsFinal()
615     }
616 
617     override fun extraAssertions(before: Parcelable, after: Parcelable) {
618         super.extraAssertions(before, after)
619         after as PackageImpl
620         expect.that(after.manifestPackageName).isEqualTo("com.example.test")
621         expect.that(after.isCoreApp).isTrue()
622         expect.that(after.isIsolatedSplitLoading).isEqualTo(true)
623         expect.that(after.longVersionCode).isEqualTo(38654705667)
624         expect.that(after.requestedPermissions)
625             .containsExactlyElementsIn(after.usesPermissions.map { it.name })
626             .inOrder()
627 
628         expect.that(after.mimeGroups).containsExactly(
629             "TestActivityName/mimeGroup",
630             "TestReceiverName/mimeGroup",
631             "TestServiceName/mimeGroup",
632             "TestProviderName/mimeGroup"
633         )
634 
635         expect.that(after.splitNames).asList()
636             .containsExactly("testSplitNameZero", "testSplitNameOne")
637             .inOrder()
638         expect.that(after.splitCodePaths).asList()
639             .containsExactly("/test/testSplitZero.apk", "/test/testSplitOne.apk")
640             .inOrder()
641         expect.that(after.splitRevisionCodes).asList()
642             .containsExactly(10, 11)
643             .inOrder()
644         expect.that(after.splitFlags).asList()
645             .containsExactly(ApplicationInfo.FLAG_HAS_CODE, 0)
646             .inOrder()
647         expect.that(after.splitClassLoaderNames).asList()
648             .containsExactly("testSplitClassLoaderNameZero", "testSplitClassLoaderNameOne")
649             .inOrder()
650 
651         expect.that(after.splitDependencies).isNotNull()
652         after.splitDependencies?.let {
653             expect.that(it.size()).isEqualTo(3)
654             expect.that(it.get(0)).asList().containsExactly(-1)
655             expect.that(it.get(1)).asList().containsExactly(0)
656             expect.that(it.get(2)).asList().containsExactly(1)
657         }
658 
659         expect.that(after.usesSdkLibraries).containsExactly("testSdk")
660         expect.that(after.usesSdkLibrariesVersionsMajor).asList().containsExactly(2L)
661         expect.that(after.usesSdkLibrariesCertDigests!!.size).isEqualTo(1)
662         expect.that(after.usesSdkLibrariesCertDigests!![0]).asList()
663                 .containsExactly("testCertDigest1")
664 
665         expect.that(after.usesStaticLibraries).containsExactly("testStatic")
666         expect.that(after.usesStaticLibrariesVersions).asList().containsExactly(3L)
667         expect.that(after.usesStaticLibrariesCertDigests!!.size).isEqualTo(1)
668         expect.that(after.usesStaticLibrariesCertDigests!![0]).asList()
669                 .containsExactly("testCertDigest2")
670 
671         expect.that(after.storageUuid).isEqualTo(TEST_UUID)
672     }
673 
674     private fun testKey() = KeyPairGenerator.getInstance("RSA")
675         .generateKeyPair()
676         .public
677 
678     private fun <T : ParsedComponentImpl> T.withMimeGroups() = apply {
679         val componentName = name
680         addIntent(ParsedIntentInfoImpl().apply {
681             intentFilter.apply {
682                 addMimeGroup("$componentName/mimeGroup")
683             }
684         })
685     }
686 }
687