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