Merge "Add parsing class parcelling tests"

This commit is contained in:
Winson Chiu
2021-08-05 21:43:58 +00:00
committed by Android (Google) Code Review
36 changed files with 2116 additions and 75 deletions

View File

@@ -55,6 +55,8 @@ import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.overlay.OverlayPaths;
import android.content.pm.parsing.ParsingPackageUtils;
import android.content.pm.split.SplitAssetLoader;
import android.content.pm.parsing.result.ParseResult;
import android.content.pm.parsing.result.ParseTypeImpl;
import android.content.res.ApkAssets;
@@ -7425,7 +7427,7 @@ public class PackageParser {
mCompileSdkVersionCodename = dest.readString();
mUpgradeKeySets = (ArraySet<String>) dest.readArraySet(boot);
mKeySetMapping = readKeySetMapping(dest);
mKeySetMapping = ParsingPackageUtils.readKeySetMapping(dest);
cpuAbiOverride = dest.readString();
use32bitAbi = (dest.readInt() == 1);
@@ -7551,73 +7553,13 @@ public class PackageParser {
dest.writeInt(mCompileSdkVersion);
dest.writeString(mCompileSdkVersionCodename);
dest.writeArraySet(mUpgradeKeySets);
writeKeySetMapping(dest, mKeySetMapping);
ParsingPackageUtils.writeKeySetMapping(dest, mKeySetMapping);
dest.writeString(cpuAbiOverride);
dest.writeInt(use32bitAbi ? 1 : 0);
dest.writeByteArray(restrictUpdateHash);
dest.writeInt(visibleToInstantApps ? 1 : 0);
}
/**
* Writes the keyset mapping to the provided package. {@code null} mappings are permitted.
*/
private static void writeKeySetMapping(
Parcel dest, ArrayMap<String, ArraySet<PublicKey>> keySetMapping) {
if (keySetMapping == null) {
dest.writeInt(-1);
return;
}
final int N = keySetMapping.size();
dest.writeInt(N);
for (int i = 0; i < N; i++) {
dest.writeString(keySetMapping.keyAt(i));
ArraySet<PublicKey> keys = keySetMapping.valueAt(i);
if (keys == null) {
dest.writeInt(-1);
continue;
}
final int M = keys.size();
dest.writeInt(M);
for (int j = 0; j < M; j++) {
dest.writeSerializable(keys.valueAt(j));
}
}
}
/**
* Reads a keyset mapping from the given parcel at the given data position. May return
* {@code null} if the serialized mapping was {@code null}.
*/
private static ArrayMap<String, ArraySet<PublicKey>> readKeySetMapping(Parcel in) {
final int N = in.readInt();
if (N == -1) {
return null;
}
ArrayMap<String, ArraySet<PublicKey>> keySetMapping = new ArrayMap<>();
for (int i = 0; i < N; ++i) {
String key = in.readString();
final int M = in.readInt();
if (M == -1) {
keySetMapping.put(key, null);
continue;
}
ArraySet<PublicKey> keys = new ArraySet<>(M);
for (int j = 0; j < M; ++j) {
PublicKey pk = (PublicKey) in.readSerializable();
keys.add(pk);
}
keySetMapping.put(key, keys);
}
return keySetMapping;
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Package>() {
public Package createFromParcel(Parcel in) {
return new Package(in);

View File

@@ -535,7 +535,7 @@ public class PackageInfoWithoutStateUtils {
ai.setMaxAspectRatio(maxAspectRatio != null ? maxAspectRatio : 0f);
Float minAspectRatio = a.getMinAspectRatio();
ai.setMinAspectRatio(minAspectRatio != null ? minAspectRatio : 0f);
ai.supportsSizeChanges = a.getSupportsSizeChanges();
ai.supportsSizeChanges = a.isSupportsSizeChanges();
ai.requestedVrComponent = a.getRequestedVrComponent();
ai.rotationAnimation = a.getRotationAnimation();
ai.colorMode = a.getColorMode();

View File

@@ -360,7 +360,7 @@ public interface ParsingPackage extends ParsingPackageRead {
ParsingPackage setCompileSdkVersion(int compileSdkVersion);
ParsingPackage setCompileSdkVersionCodename(String compileSdkVersionCodename);
ParsingPackage setCompileSdkVersionCodeName(String compileSdkVersionCodeName);
ParsingPackage setAttributionsAreUserVisible(boolean attributionsAreUserVisible);

View File

@@ -553,7 +553,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
setCompileSdkVersion(manifestArray.getInteger(
R.styleable.AndroidManifest_compileSdkVersion, 0));
setCompileSdkVersionCodename(manifestArray.getNonConfigurationString(
setCompileSdkVersionCodeName(manifestArray.getNonConfigurationString(
R.styleable.AndroidManifest_compileSdkVersionCodename, 0));
setIsolatedSplitLoading(manifestArray.getBoolean(
@@ -2686,8 +2686,8 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
}
@Override
public ParsingPackage setCompileSdkVersionCodename(String compileSdkVersionCodename) {
this.compileSdkVersionCodeName = compileSdkVersionCodename;
public ParsingPackage setCompileSdkVersionCodeName(String compileSdkVersionCodeName) {
this.compileSdkVersionCodeName = compileSdkVersionCodeName;
return this;
}

View File

@@ -23,6 +23,7 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.pm.parsing.ParsingPackageImpl.sForInternedString;
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityTaskManager;
import android.content.ComponentName;
@@ -423,6 +424,7 @@ public class ParsedActivity extends ParsedMainComponent {
}
}
@NonNull
public static final Parcelable.Creator<ParsedActivity> CREATOR = new Creator<ParsedActivity>() {
@Override
public ParsedActivity createFromParcel(Parcel source) {
@@ -513,10 +515,6 @@ public class ParsedActivity extends ParsedMainComponent {
return minAspectRatio;
}
public boolean getSupportsSizeChanges() {
return supportsSizeChanges;
}
@Nullable
public String getRequestedVrComponent() {
return requestedVrComponent;

View File

@@ -43,8 +43,8 @@ import java.util.Map;
/** @hide */
public abstract class ParsedComponent implements Parcelable {
private static ParsedIntentInfo.ListParceler sForIntentInfos = Parcelling.Cache.getOrCreate(
ParsedIntentInfo.ListParceler.class);
private static final ParsedIntentInfo.ListParceler sForIntentInfos =
Parcelling.Cache.getOrCreate(ParsedIntentInfo.ListParceler.class);
@NonNull
@DataClass.ParcelWith(ForInternedString.class)

View File

@@ -18,6 +18,7 @@ package android.content.pm.parsing.component;
import static android.content.pm.parsing.ParsingPackageImpl.sForInternedString;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.os.Parcel;
@@ -94,6 +95,7 @@ public class ParsedInstrumentation extends ParsedComponent {
this.functionalTest = in.readByte() != 0;
}
@NonNull
public static final Parcelable.Creator<ParsedInstrumentation> CREATOR =
new Parcelable.Creator<ParsedInstrumentation>() {
@Override

View File

@@ -16,6 +16,7 @@
package android.content.pm.parsing.component;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.IntentFilter;
import android.os.Parcel;
@@ -58,6 +59,7 @@ public final class ParsedIntentInfo extends IntentFilter {
item.writeIntentInfoToParcel(dest, parcelFlags);
}
@NonNull
@Override
public ParsedIntentInfo unparcel(Parcel source) {
return new ParsedIntentInfo(source);

View File

@@ -16,6 +16,7 @@
package android.content.pm.parsing.component;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.pm.PermissionInfo;
import android.os.Parcel;
@@ -167,6 +168,7 @@ public class ParsedPermission extends ParsedComponent {
this.knownCerts = sForStringSet.unparcel(in);
}
@NonNull
public static final Parcelable.Creator<ParsedPermission> CREATOR =
new Parcelable.Creator<ParsedPermission>() {
@Override

View File

@@ -19,7 +19,6 @@ package android.content.pm.parsing.component;
import static java.util.Collections.emptySet;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.pm.ApplicationInfo;
import android.os.Parcel;
import android.os.Parcelable;

View File

@@ -169,6 +169,7 @@ public class ParsedProvider extends ParsedMainComponent {
this.pathPermissions = in.createTypedArray(PathPermission.CREATOR);
}
@NonNull
public static final Parcelable.Creator<ParsedProvider> CREATOR = new Creator<ParsedProvider>() {
@Override
public ParsedProvider createFromParcel(Parcel source) {

View File

@@ -18,6 +18,7 @@ package android.content.pm.parsing.component;
import static android.content.pm.parsing.ParsingPackageImpl.sForInternedString;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.os.Parcel;
@@ -83,6 +84,7 @@ public class ParsedService extends ParsedMainComponent {
this.permission = sForInternedString.unparcel(in);
}
@NonNull
public static final Parcelable.Creator<ParsedService> CREATOR = new Creator<ParsedService>() {
@Override
public ParsedService createFromParcel(Parcel source) {

View File

@@ -55,6 +55,7 @@ import java.util.UUID;
*/
public final class PackageImpl extends ParsingPackageImpl implements ParsedPackage, AndroidPackage {
@NonNull
public static PackageImpl forParsing(@NonNull String packageName, @NonNull String baseCodePath,
@NonNull String codePath, @NonNull TypedArray manifestArray, boolean isCoreApp) {
return new PackageImpl(packageName, baseCodePath, codePath, manifestArray, isCoreApp);
@@ -70,6 +71,7 @@ public final class PackageImpl extends ParsingPackageImpl implements ParsedPacka
* this case only cares about
* volumeUuid, just fake it rather than having separate method paths.
*/
@NonNull
public static AndroidPackage buildFakeForDeletion(String packageName, String volumeUuid) {
return ((ParsedPackage) PackageImpl.forTesting(packageName)
.setVolumeUuid(volumeUuid)
@@ -77,11 +79,13 @@ public final class PackageImpl extends ParsingPackageImpl implements ParsedPacka
.hideAsFinal();
}
@NonNull
@VisibleForTesting
public static ParsingPackage forTesting(String packageName) {
return forTesting(packageName, "");
}
@NonNull
@VisibleForTesting
public static ParsingPackage forTesting(String packageName, String baseCodePath) {
return new PackageImpl(packageName, baseCodePath, baseCodePath, null, false);
@@ -568,6 +572,7 @@ public final class PackageImpl extends ParsingPackageImpl implements ParsedPacka
assignDerivedFields();
}
@NonNull
public static final Creator<PackageImpl> CREATOR = new Creator<PackageImpl>() {
@Override
public PackageImpl createFromParcel(Parcel source) {

View File

@@ -32,6 +32,7 @@ android_test {
"androidx.test.runner",
"junit",
"kotlin-test",
"kotlin-reflect",
"services.core",
"servicestests-utils",
"truth-prebuilt",

View File

@@ -0,0 +1,7 @@
{
"presubmit": [
{
"name": "PackageManagerServiceUnitTests"
}
]
}

View File

@@ -0,0 +1,572 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.pm.test.parsing.parcelling
import android.content.Intent
import android.content.pm.ApplicationInfo
import android.content.pm.ConfigurationInfo
import android.content.pm.FeatureGroupInfo
import android.content.pm.FeatureInfo
import android.content.pm.PackageManager
import android.content.pm.SigningDetails
import android.content.pm.parsing.ParsingPackage
import android.content.pm.parsing.component.ParsedActivity
import android.content.pm.parsing.component.ParsedAttribution
import android.content.pm.parsing.component.ParsedComponent
import android.content.pm.parsing.component.ParsedInstrumentation
import android.content.pm.parsing.component.ParsedIntentInfo
import android.content.pm.parsing.component.ParsedPermission
import android.content.pm.parsing.component.ParsedPermissionGroup
import android.content.pm.parsing.component.ParsedProcess
import android.content.pm.parsing.component.ParsedProvider
import android.content.pm.parsing.component.ParsedService
import android.content.pm.parsing.component.ParsedUsesPermission
import android.net.Uri
import android.os.Bundle
import android.os.Parcelable
import android.util.ArraySet
import android.util.SparseArray
import android.util.SparseIntArray
import com.android.internal.R
import com.android.server.pm.parsing.pkg.AndroidPackage
import com.android.server.pm.parsing.pkg.PackageImpl
import com.android.server.testutils.mockThrowOnUnmocked
import com.android.server.testutils.whenever
import java.security.KeyPairGenerator
import java.security.PublicKey
import kotlin.contracts.ExperimentalContracts
@ExperimentalContracts
class AndroidPackageTest : ParcelableComponentTest(AndroidPackage::class, PackageImpl::class) {
override val defaultImpl = PackageImpl.forTesting("com.example.test")
override val creator = PackageImpl.CREATOR
override val excludedMethods = listOf(
// Internal methods
"toAppInfoToString",
"toAppInfoWithoutState",
"toAppInfoWithoutStateWithoutFlags",
"assignDerivedFields",
"buildFakeForDeletion",
"capPermissionPriorities",
"forParsing",
"forTesting",
"getBaseAppDataCredentialProtectedDirForSystemUser",
"getBaseAppDataDeviceProtectedDirForSystemUser",
"getBoolean",
"setBoolean",
"hideAsFinal",
"hideAsParsed",
"markNotActivitiesAsNotExportedIfSingleUser",
"sortActivities",
"sortReceivers",
"sortServices",
"setAllComponentsDirectBootAware",
// Tested through setting minor/major manually
"setLongVersionCode",
"getLongVersionCode",
// Tested through constructor
"getManifestPackageName",
"setManifestPackageName",
// Utility methods
"getStorageUuid",
// Removal not tested, irrelevant for parcelling concerns
"removeUsesOptionalLibrary",
"clearAdoptPermissions",
"clearOriginalPackages",
"clearProtectedBroadcasts",
"removePermission",
"removeUsesLibrary",
"removeUsesOptionalNativeLibrary",
// Tested manually
"getMimeGroups",
"getRequestedPermissions",
// Tested through asSplit
"asSplit",
"getSplitNames",
"getSplitCodePaths",
"getSplitRevisionCodes",
"getSplitFlags",
"getSplitClassLoaderNames",
"getSplitDependencies",
"setSplitCodePaths",
"setSplitClassLoaderName",
"setSplitHasCode",
)
override val baseParams = listOf(
AndroidPackage::getAppComponentFactory,
AndroidPackage::getAutoRevokePermissions,
AndroidPackage::getBackupAgentName,
AndroidPackage::getBanner,
AndroidPackage::getBaseApkPath,
AndroidPackage::getBaseRevisionCode,
AndroidPackage::getCategory,
AndroidPackage::getClassLoaderName,
AndroidPackage::getClassName,
AndroidPackage::getCompatibleWidthLimitDp,
AndroidPackage::getCompileSdkVersion,
AndroidPackage::getCompileSdkVersionCodeName,
AndroidPackage::getDataExtractionRules,
AndroidPackage::getDescriptionRes,
AndroidPackage::getFullBackupContent,
AndroidPackage::getGwpAsanMode,
AndroidPackage::getIconRes,
AndroidPackage::getInstallLocation,
AndroidPackage::getLabelRes,
AndroidPackage::getLargestWidthLimitDp,
AndroidPackage::getLogo,
AndroidPackage::getManageSpaceActivityName,
AndroidPackage::getMemtagMode,
AndroidPackage::getMinSdkVersion,
AndroidPackage::getNativeHeapZeroInitialized,
AndroidPackage::getNativeLibraryDir,
AndroidPackage::getNativeLibraryRootDir,
AndroidPackage::getNetworkSecurityConfigRes,
AndroidPackage::getNonLocalizedLabel,
AndroidPackage::getOverlayCategory,
AndroidPackage::getOverlayPriority,
AndroidPackage::getOverlayTarget,
AndroidPackage::getOverlayTargetName,
AndroidPackage::getPackageName,
AndroidPackage::getPath,
AndroidPackage::getPermission,
AndroidPackage::getPrimaryCpuAbi,
AndroidPackage::getProcessName,
AndroidPackage::getRealPackage,
AndroidPackage::getRequiredAccountType,
AndroidPackage::getRequiresSmallestWidthDp,
AndroidPackage::getResizeableActivity,
AndroidPackage::getRestrictedAccountType,
AndroidPackage::getRoundIconRes,
AndroidPackage::getSeInfo,
AndroidPackage::getSeInfoUser,
AndroidPackage::getSecondaryCpuAbi,
AndroidPackage::getSecondaryNativeLibraryDir,
AndroidPackage::getSharedUserId,
AndroidPackage::getSharedUserLabel,
AndroidPackage::getStaticSharedLibName,
AndroidPackage::getStaticSharedLibVersion,
AndroidPackage::getTargetSandboxVersion,
AndroidPackage::getTargetSdkVersion,
AndroidPackage::getTaskAffinity,
AndroidPackage::getTheme,
AndroidPackage::getUiOptions,
AndroidPackage::getUid,
AndroidPackage::getVersionName,
AndroidPackage::getZygotePreloadName,
AndroidPackage::isAllowAudioPlaybackCapture,
AndroidPackage::isAllowBackup,
AndroidPackage::isAllowClearUserData,
AndroidPackage::isAllowClearUserDataOnFailedRestore,
AndroidPackage::isAllowNativeHeapPointerTagging,
AndroidPackage::isAllowTaskReparenting,
AndroidPackage::isBackupInForeground,
AndroidPackage::isBaseHardwareAccelerated,
AndroidPackage::isCantSaveState,
AndroidPackage::isCoreApp,
AndroidPackage::isCrossProfile,
AndroidPackage::isDebuggable,
AndroidPackage::isDefaultToDeviceProtectedStorage,
AndroidPackage::isDirectBootAware,
AndroidPackage::isEnabled,
AndroidPackage::isExternalStorage,
AndroidPackage::isExtractNativeLibs,
AndroidPackage::isFactoryTest,
AndroidPackage::isForceQueryable,
AndroidPackage::isFullBackupOnly,
AndroidPackage::isGame,
AndroidPackage::isHasCode,
AndroidPackage::isHasDomainUrls,
AndroidPackage::isHasFragileUserData,
AndroidPackage::isIsolatedSplitLoading,
AndroidPackage::isKillAfterRestore,
AndroidPackage::isLargeHeap,
AndroidPackage::isMultiArch,
AndroidPackage::isNativeLibraryRootRequiresIsa,
AndroidPackage::isOdm,
AndroidPackage::isOem,
AndroidPackage::isOverlay,
AndroidPackage::isOverlayIsStatic,
AndroidPackage::isPartiallyDirectBootAware,
AndroidPackage::isPersistent,
AndroidPackage::isPrivileged,
AndroidPackage::isProduct,
AndroidPackage::isProfileableByShell,
AndroidPackage::isRequestLegacyExternalStorage,
AndroidPackage::isRequiredForAllUsers,
AndroidPackage::isResizeableActivityViaSdkVersion,
AndroidPackage::isRestoreAnyVersion,
AndroidPackage::isSignedWithPlatformKey,
AndroidPackage::isStaticSharedLibrary,
AndroidPackage::isStub,
AndroidPackage::isSupportsRtl,
AndroidPackage::isSystem,
AndroidPackage::isSystemExt,
AndroidPackage::isTestOnly,
AndroidPackage::isUse32BitAbi,
AndroidPackage::isUseEmbeddedDex,
AndroidPackage::isUsesCleartextTraffic,
AndroidPackage::isUsesNonSdkApi,
AndroidPackage::isVendor,
AndroidPackage::isVisibleToInstantApps,
AndroidPackage::isVmSafeMode,
AndroidPackage::getMaxAspectRatio,
AndroidPackage::getMinAspectRatio,
AndroidPackage::hasPreserveLegacyExternalStorage,
AndroidPackage::hasRequestForegroundServiceExemption,
AndroidPackage::hasRequestRawExternalStorageAccess,
)
override fun extraParams() = listOf(
getter(AndroidPackage::getVolumeUuid, "57554103-df3e-4475-ae7a-8feba49353ac"),
getter(AndroidPackage::isProfileable, true),
getter(AndroidPackage::getVersionCode, 3),
getter(AndroidPackage::getVersionCodeMajor, 9),
getter(AndroidPackage::getUpgradeKeySets, setOf("testUpgradeKeySet")),
getter(AndroidPackage::isAnyDensity, false, 0),
getter(AndroidPackage::isResizeable, false, 0),
getter(AndroidPackage::isSupportsSmallScreens, false, 0),
getter(AndroidPackage::isSupportsNormalScreens, false, 0),
getter(AndroidPackage::isSupportsLargeScreens, false, 0),
getter(AndroidPackage::isSupportsExtraLargeScreens, false, 0),
adder(AndroidPackage::getAdoptPermissions, "test.adopt.PERMISSION"),
adder(AndroidPackage::getOriginalPackages, "com.test.original"),
adder(AndroidPackage::getImplicitPermissions, "test.implicit.PERMISSION"),
adder(AndroidPackage::getLibraryNames, "testLibraryName"),
adder(AndroidPackage::getProtectedBroadcasts, "test.protected.BROADCAST"),
adder(AndroidPackage::getQueriesPackages, "com.test.package.queries"),
adder(AndroidPackage::getQueriesProviders, "com.test.package.queries.provider"),
adder(AndroidPackage::getUsesLibraries, "testUsesLibrary"),
adder(AndroidPackage::getUsesNativeLibraries, "testUsesNativeLibrary"),
adder(AndroidPackage::getUsesOptionalLibraries, "testUsesOptionalLibrary"),
adder(AndroidPackage::getUsesOptionalNativeLibraries, "testUsesOptionalNativeLibrary"),
adder(AndroidPackage::getUsesStaticLibraries, "testUsesStaticLibrary"),
getSetByValue(
AndroidPackage::getUsesStaticLibrariesVersions,
PackageImpl::addUsesStaticLibraryVersion,
(testCounter++).toLong(),
transformGet = { it?.singleOrNull() }
),
getSetByValue(
AndroidPackage::areAttributionsUserVisible,
ParsingPackage::setAttributionsAreUserVisible,
true
),
getSetByValue2(
AndroidPackage::getOverlayables,
PackageImpl::addOverlayable,
"testOverlayableName" to "testActorName",
transformGet = { "testOverlayableName" to it["testOverlayableName"] }
),
getSetByValue(
AndroidPackage::getMetaData,
PackageImpl::setMetaData,
"testBundleKey" to "testBundleValue",
transformGet = { "testBundleKey" to it?.getString("testBundleKey") },
transformSet = { Bundle().apply { putString(it.first, it.second) } }
),
getSetByValue(
AndroidPackage::getAttributions,
PackageImpl::addAttribution,
Triple("testTag", 13, listOf("testInherit")),
transformGet = { it.singleOrNull()?.let { Triple(it.tag, it.label, it.inheritFrom) } },
transformSet = { it?.let { ParsedAttribution(it.first, it.second, it.third) } }
),
getSetByValue2(
AndroidPackage::getKeySetMapping,
PackageImpl::addKeySet,
"testKeySetName" to testKey(),
transformGet = { "testKeySetName" to it["testKeySetName"]?.singleOrNull() },
),
getSetByValue(
AndroidPackage::getPermissionGroups,
PackageImpl::addPermissionGroup,
"test.permission.GROUP",
transformGet = { it.singleOrNull()?.name },
transformSet = { ParsedPermissionGroup().apply { setName(it) } }
),
getSetByValue2(
AndroidPackage::getPreferredActivityFilters,
PackageImpl::addPreferredActivityFilter,
"TestClassName" to ParsedIntentInfo().apply {
addDataScheme("http")
addDataAuthority("test.pm.server.android.com", null)
},
transformGet = { it.singleOrNull()?.let { it.first to it.second } },
compare = { first, second ->
equalBy(
first, second,
{ it.first },
{ it.second.schemesIterator().asSequence().singleOrNull() },
{ it.second.authoritiesIterator().asSequence().singleOrNull()?.host },
)
}
),
getSetByValue(
AndroidPackage::getQueriesIntents,
PackageImpl::addQueriesIntent,
Intent(Intent.ACTION_VIEW, Uri.parse("https://test.pm.server.android.com")),
transformGet = { it.singleOrNull() },
compare = { first, second -> first?.filterEquals(second) },
),
getSetByValue(
AndroidPackage::getRestrictUpdateHash,
PackageImpl::setRestrictUpdateHash,
byteArrayOf(0, 1, 2, 3, 4),
compare = ByteArray::contentEquals
),
getSetByValue(
AndroidPackage::getSigningDetails,
PackageImpl::setSigningDetails,
testKey(),
transformGet = { it.publicKeys?.takeIf { it.size > 0 }?.valueAt(0) },
transformSet = {
SigningDetails(
null,
SigningDetails.SignatureSchemeVersion.UNKNOWN,
ArraySet<PublicKey>().apply { add(it) },
null
)
}
),
getSetByValue(
AndroidPackage::getUsesStaticLibrariesCertDigests,
PackageImpl::addUsesStaticLibraryCertDigests,
arrayOf("testCertDigest"),
transformGet = { it?.singleOrNull() },
compare = Array<String?>?::contentEquals
),
getSetByValue(
AndroidPackage::getActivities,
PackageImpl::addActivity,
"TestActivityName",
transformGet = { it.singleOrNull()?.name.orEmpty() },
transformSet = { ParsedActivity().apply { name = it }.withMimeGroups() }
),
getSetByValue(
AndroidPackage::getReceivers,
PackageImpl::addReceiver,
"TestReceiverName",
transformGet = { it.singleOrNull()?.name.orEmpty() },
transformSet = { ParsedActivity().apply { name = it }.withMimeGroups() }
),
getSetByValue(
AndroidPackage::getServices,
PackageImpl::addService,
"TestServiceName",
transformGet = { it.singleOrNull()?.name.orEmpty() },
transformSet = { ParsedService().apply { name = it }.withMimeGroups() }
),
getSetByValue(
AndroidPackage::getProviders,
PackageImpl::addProvider,
"TestProviderName",
transformGet = { it.singleOrNull()?.name.orEmpty() },
transformSet = { ParsedProvider().apply { name = it }.withMimeGroups() }
),
getSetByValue(
AndroidPackage::getInstrumentations,
PackageImpl::addInstrumentation,
"TestInstrumentationName",
transformGet = { it.singleOrNull()?.name.orEmpty() },
transformSet = { ParsedInstrumentation().apply { name = it } }
),
getSetByValue(
AndroidPackage::getConfigPreferences,
PackageImpl::addConfigPreference,
testCounter++,
transformGet = { it.singleOrNull()?.reqGlEsVersion ?: -1 },
transformSet = { ConfigurationInfo().apply { reqGlEsVersion = it } }
),
getSetByValue(
AndroidPackage::getFeatureGroups,
PackageImpl::addFeatureGroup,
"test.feature.GROUP",
transformGet = { it.singleOrNull()?.features?.singleOrNull()?.name.orEmpty() },
transformSet = {
FeatureGroupInfo().apply {
features = arrayOf(FeatureInfo().apply { name = it })
}
}
),
getSetByValue(
AndroidPackage::getPermissions,
PackageImpl::addPermission,
"test.PERMISSION",
transformGet = { it.singleOrNull()?.name.orEmpty() },
transformSet = { ParsedPermission().apply { name = it } }
),
getSetByValue(
AndroidPackage::getUsesPermissions,
PackageImpl::addUsesPermission,
"test.USES_PERMISSION",
transformGet = {
// Need to strip implicit permission, which calls addUsesPermission when added
it.filterNot { it.name == "test.implicit.PERMISSION" }
.singleOrNull()?.name.orEmpty()
},
transformSet = { ParsedUsesPermission(it, 0) }
),
getSetByValue(
AndroidPackage::getReqFeatures,
PackageImpl::addReqFeature,
"test.feature.INFO",
transformGet = { it.singleOrNull()?.name.orEmpty() },
transformSet = { FeatureInfo().apply { name = it } }
),
getSetByValue(
AndroidPackage::getMinExtensionVersions,
PackageImpl::setMinExtensionVersions,
SparseIntArray().apply { put(testCounter++, testCounter++) },
compare = { first, second ->
equalBy(
first, second,
{ it.size() },
{ it.keyAt(0) },
{ it.valueAt(0) },
)
}
),
getSetByValue(
AndroidPackage::getProcesses,
PackageImpl::setProcesses,
mapOf("testProcess" to ParsedProcess().apply { name = "testProcessName" }),
compare = { first, second ->
equalBy(
first, second,
{ it["testProcess"]?.name },
)
}
),
getSetByValue(
AndroidPackage::getProperties,
PackageImpl::addProperty,
PackageManager.Property(
"testPropertyName",
"testPropertyValue",
"testPropertyClassName",
"testPropertyPackageName"
),
transformGet = { it["testPropertyName"] },
compare = { first, second ->
equalBy(
first, second,
PackageManager.Property::getName,
PackageManager.Property::getClassName,
PackageManager.Property::getPackageName,
PackageManager.Property::getString,
)
}
),
)
override fun initialObject() = PackageImpl.forParsing(
"com.example.test",
"/test/test/base.apk",
"/test/test",
mockThrowOnUnmocked {
whenever(getInteger(R.styleable.AndroidManifest_revisionCode, 0)) { 4 }
whenever(getBoolean(R.styleable.AndroidManifest_isolatedSplits, false)) { true }
// Return invalid values here so that the getter/setter is tested properly
whenever(getInteger(R.styleable.AndroidManifest_versionCode, 0)) { -1 }
whenever(getInteger(R.styleable.AndroidManifest_versionCodeMajor, 0)) { -1 }
whenever(
getNonConfigurationString(
R.styleable.AndroidManifest_versionName,
0
)
) { "" }
whenever(getInteger(R.styleable.AndroidManifest_compileSdkVersion, 0)) { 31 }
whenever(
getNonConfigurationString(
R.styleable.AndroidManifest_compileSdkVersionCodename,
0
)
) { "" }
},
true
)
.asSplit(
arrayOf("testSplitNameZero", "testSplitNameOne"),
arrayOf("/test/testSplitZero.apk", "/test/testSplitOne.apk"),
intArrayOf(10, 11),
SparseArray<IntArray>().apply {
put(0, intArrayOf(-1))
put(1, intArrayOf(0))
}
)
.setSplitHasCode(0, true)
.setSplitHasCode(1, false)
.setSplitClassLoaderName(0, "testSplitClassLoaderNameZero")
.setSplitClassLoaderName(1, "testSplitClassLoaderNameOne")
override fun extraAssertions(before: Parcelable, after: Parcelable) {
super.extraAssertions(before, after)
after as PackageImpl
expect.that(after.manifestPackageName).isEqualTo("com.example.test")
expect.that(after.isCoreApp).isTrue()
expect.that(after.isIsolatedSplitLoading).isEqualTo(true)
expect.that(after.longVersionCode).isEqualTo(38654705667)
expect.that(after.requestedPermissions)
.containsExactlyElementsIn(after.usesPermissions.map { it.name })
.inOrder()
expect.that(after.mimeGroups).containsExactly(
"TestActivityName/mimeGroup",
"TestReceiverName/mimeGroup",
"TestServiceName/mimeGroup",
"TestProviderName/mimeGroup"
)
expect.that(after.splitNames).asList()
.containsExactly("testSplitNameZero", "testSplitNameOne")
.inOrder()
expect.that(after.splitCodePaths).asList()
.containsExactly("/test/testSplitZero.apk", "/test/testSplitOne.apk")
.inOrder()
expect.that(after.splitRevisionCodes).asList()
.containsExactly(10, 11)
.inOrder()
expect.that(after.splitFlags).asList()
.containsExactly(ApplicationInfo.FLAG_HAS_CODE, 0)
.inOrder()
expect.that(after.splitClassLoaderNames).asList()
.containsExactly("testSplitClassLoaderNameZero", "testSplitClassLoaderNameOne")
.inOrder()
expect.that(after.splitDependencies).isNotNull()
after.splitDependencies?.let {
expect.that(it.size()).isEqualTo(2)
expect.that(it.get(0)).asList().containsExactly(-1)
expect.that(it.get(1)).asList().containsExactly(0)
}
}
private fun testKey() = KeyPairGenerator.getInstance("RSA")
.generateKeyPair()
.public
private fun <T : ParsedComponent> T.withMimeGroups() = apply {
val componentName = name
addIntent(ParsedIntentInfo().apply {
addMimeGroup("$componentName/mimeGroup")
})
}
}

View File

@@ -0,0 +1,413 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.pm.test.parsing.parcelling
import android.os.Parcel
import android.os.Parcelable
import com.android.server.pm.test.util.IgnoreableExpect
import com.google.common.truth.Expect
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TestRule
import java.util.Objects
import kotlin.contracts.ExperimentalContracts
import kotlin.reflect.KClass
import kotlin.reflect.KFunction
import kotlin.reflect.KFunction1
import kotlin.reflect.KFunction2
import kotlin.reflect.KFunction3
import kotlin.reflect.KVisibility
import kotlin.reflect.full.allSuperclasses
import kotlin.reflect.full.createInstance
import kotlin.reflect.full.isSubclassOf
import kotlin.reflect.full.memberFunctions
import kotlin.reflect.full.memberProperties
import kotlin.reflect.full.staticProperties
import kotlin.reflect.jvm.jvmErasure
@ExperimentalContracts
abstract class ParcelableComponentTest(
private val getterType: KClass<*>,
private val setterType: KClass<out Parcelable>
) {
companion object {
private val DEFAULT_EXCLUDED = listOf(
// Java
"toString",
"equals",
"hashCode",
// Parcelable
"getStability",
"describeContents",
"writeToParcel",
// @DataClass
"__metadata"
)
}
internal val ignoreableExpect = IgnoreableExpect()
// Hides internal type
@get:Rule
val ignoreableAsTestRule: TestRule = ignoreableExpect
val expect: Expect
get() = ignoreableExpect.expect
protected var testCounter = 1
protected abstract val defaultImpl: Any
protected abstract val creator: Parcelable.Creator<out Parcelable>
protected open val excludedMethods: Collection<String> = emptyList()
protected abstract val baseParams: Collection<KFunction1<*, Any?>>
private val getters = getterType.memberFunctions
.filterNot { DEFAULT_EXCLUDED.contains(it.name) }
private val setters = setterType.memberFunctions
.filterNot { DEFAULT_EXCLUDED.contains(it.name) }
constructor(kClass: KClass<out Parcelable>) : this(kClass, kClass)
@Before
fun checkNoPublicFields() {
// Fields are not currently testable, and the idea is to enforce interface access for
// immutability purposes, so disallow any public fields from existing.
expect.that(getterType.memberProperties.filter { it.visibility == KVisibility.PUBLIC }
.filterNot { DEFAULT_EXCLUDED.contains(it.name) })
.isEmpty()
}
@Suppress("UNCHECKED_CAST")
private fun <ObjectType, ReturnType> buildParams(
getFunction: KFunction1<ObjectType, ReturnType>,
): Param? {
return buildParams<ObjectType, ReturnType, ReturnType, ReturnType>(
getFunction,
autoValue(getFunction) as ReturnType ?: return null
)
}
@Suppress("UNCHECKED_CAST")
private fun <ObjectType, ReturnType, SetType : Any?, CompareType : Any?> buildParams(
getFunction: KFunction1<ObjectType, ReturnType>,
value: SetType,
): Param? {
return getSetByValue<ObjectType, ReturnType, SetType, Any?>(
getFunction,
findSetFunction(getFunction) ?: return null,
value
)
}
@Suppress("UNCHECKED_CAST")
private fun <ObjectType, ReturnType> findSetFunction(
getFunction: KFunction1<ObjectType, ReturnType>
): KFunction2<ObjectType, ReturnType, Any?>? {
val getFunctionName = getFunction.name
val prefix = when {
getFunctionName.startsWith("get") -> "get"
getFunctionName.startsWith("is") -> "is"
getFunctionName.startsWith("has") -> "has"
else -> throw IllegalArgumentException("Unsupported method name $getFunctionName")
}
val setFunctionName = "set" + getFunctionName.removePrefix(prefix)
val setFunction = setters.filter { it.name == setFunctionName }
.minByOrNull { it.parameters.size }
if (setFunction == null) {
expect.withMessage("$getFunctionName does not have corresponding $setFunctionName")
.fail()
return null
}
return setFunction as KFunction2<ObjectType, ReturnType, Any?>
}
@Suppress("UNCHECKED_CAST")
private fun <ObjectType, ReturnType, SetType> findAddFunction(
getFunction: KFunction1<ObjectType, ReturnType>
): KFunction2<ObjectType, SetType, Any?>? {
val getFunctionName = getFunction.name
if (!getFunctionName.startsWith("get")) {
throw IllegalArgumentException("Unsupported method name $getFunctionName")
}
val setFunctionName = "add" + getFunctionName.removePrefix("get").run {
// Remove plurality
when {
endsWith("ies") -> "${removeSuffix("ies")}y"
endsWith("s") -> removeSuffix("s")
else -> this
}
}
val setFunction = setters.filter { it.name == setFunctionName }
.minByOrNull { it.parameters.size }
if (setFunction == null) {
expect.withMessage("$getFunctionName does not have corresponding $setFunctionName")
.fail()
return null
}
return setFunction as KFunction2<ObjectType, SetType, Any?>
}
protected fun <ObjectType, ReturnType> getter(
getFunction: KFunction1<ObjectType, ReturnType>,
valueToSet: ReturnType
) = buildParams<ObjectType, ReturnType, ReturnType, ReturnType>(getFunction, valueToSet)
protected fun <ObjectType, ReturnType, SetType : Any?, CompareType : Any?> getter(
getFunction: KFunction1<ObjectType, ReturnType>,
expectedValue: CompareType,
valueToSet: SetType
): Param? {
return getSetByValue(
getFunction,
findSetFunction(getFunction) ?: return null,
value = expectedValue,
transformSet = { valueToSet }
)
}
@Suppress("UNCHECKED_CAST")
protected fun <ObjectType, ReturnType> adder(
getFunction: KFunction1<ObjectType, ReturnType>,
value: ReturnType,
): Param? {
return getSetByValue(
getFunction,
findAddFunction<ObjectType, Any?, ReturnType>(getFunction) ?: return null,
value,
transformGet = {
// Primitive arrays don't implement Iterable, so cast manually
when (it) {
is BooleanArray -> it.singleOrNull()
is IntArray -> it.singleOrNull()
is LongArray -> it.singleOrNull()
is Iterable<*> -> it.singleOrNull()
else -> null
}
},
)
}
/**
* Method to provide custom getter and setter logic for values which are not simple primitives
* or cannot be directly compared using [Objects.equals].
*
* @param getFunction the getter function which will be called and marked as tested
* @param setFunction the setter function which will be called and marked as tested
* @param value the value for comparison through the parcel-unparcel cycle, which can be
* anything, like the [String] ID of an inner object
* @param transformGet the function to transform the result of [getFunction] into [value]
* @param transformSet the function to transform [value] into an input for [setFunction]
* @param compare the function that compares the pre/post-parcel [value] objects
*/
@Suppress("UNCHECKED_CAST")
protected fun <ObjectType, ReturnType, SetType : Any?, CompareType : Any?> getSetByValue(
getFunction: KFunction1<ObjectType, ReturnType>,
setFunction: KFunction2<ObjectType, SetType, Any?>,
value: CompareType,
transformGet: (ReturnType) -> CompareType = { it as CompareType },
transformSet: (CompareType) -> SetType = { it as SetType },
compare: (CompareType, CompareType) -> Boolean? = Objects::equals
) = Param(
getFunction.name,
{ transformGet(getFunction.call(it as ObjectType)) },
setFunction.name,
{ setFunction.call(it.first() as ObjectType, transformSet(it[1] as CompareType)) },
{ value },
{ first, second -> compare(first as CompareType, second as CompareType) == true }
)
/**
* Variant of [getSetByValue] that allows specifying a [setFunction] with 2 inputs.
*/
@Suppress("UNCHECKED_CAST")
protected fun <ObjectType, ReturnType, SetType1 : Any?, SetType2 : Any?, CompareType : Any?>
getSetByValue2(
getFunction: KFunction1<ObjectType, ReturnType>,
setFunction: KFunction3<ObjectType, SetType1, SetType2, Any>,
value: CompareType,
transformGet: (ReturnType) -> CompareType = { it as CompareType },
transformSet: (CompareType) -> Pair<SetType1, SetType2> =
{ it as Pair<SetType1, SetType2> },
compare: (CompareType, CompareType) -> Boolean = Objects::equals
) = Param(
getFunction.name,
{ transformGet(getFunction.call(it as ObjectType)) },
setFunction.name,
{
val pair = transformSet(it[1] as CompareType)
setFunction.call(it.first() as ObjectType, pair.first, pair.second)
},
{ value },
{ first, second -> compare(first as CompareType, second as CompareType) }
)
protected fun autoValue(getFunction: KFunction<*>) = when (getFunction.returnType.jvmErasure) {
Boolean::class -> (getFunction.call(defaultImpl) as Boolean?)?.not() ?: true
CharSequence::class,
String::class -> getFunction.name + "TEST"
Int::class -> testCounter++
Long::class -> (testCounter++).toLong()
Float::class -> (testCounter++).toFloat()
else -> {
expect.withMessage("${getFunction.name} needs to provide value").fail()
null
}
}
/**
* Verifies two instances are equivalent via a series of properties. For use when a public API
* class has not implemented equals.
*/
@Suppress("UNCHECKED_CAST")
protected fun <T : Any> equalBy(
first: T?,
second: T?,
vararg properties: (T) -> Any?
) = properties.all { property ->
first?.let { property(it) } == second?.let { property(it) }
}
@Test
fun valueComparison() {
val params = baseParams.mapNotNull(::buildParams) + extraParams().filterNotNull()
val before = initialObject()
params.forEach { it.setFunction(arrayOf(before, it.value())) }
val parcel = Parcel.obtain()
writeToParcel(parcel, before)
val dataSize = parcel.dataSize()
parcel.setDataPosition(0)
val after = creator.createFromParcel(parcel)
expect.withMessage("Mismatched write and read data sizes")
.that(parcel.dataPosition())
.isEqualTo(dataSize)
parcel.recycle()
runAssertions(params, before, after)
}
@Test
open fun parcellingSize() {
val parcelOne = Parcel.obtain()
writeToParcel(parcelOne, initialObject())
val parcelTwo = Parcel.obtain()
initialObject().writeToParcel(parcelTwo, 0)
val superDataSizes = setterType.allSuperclasses
.filter { it.isSubclassOf(Parcelable::class) }
.mapNotNull { it.memberFunctions.find { it.name == "writeToParcel" } }
.filter { it.isFinal }
.map {
val parcel = Parcel.obtain()
initialObject().writeToParcel(parcel, 0)
parcel.dataSize().also { parcel.recycle() }
}
if ((superDataSizes + parcelOne.dataSize() + parcelTwo.dataSize()).distinct().size != 1) {
listOf(getterType, setterType).distinct().forEach {
val creatorProperties = it.staticProperties.filter { it.name == "CREATOR" }
if (creatorProperties.size > 1) {
expect.withMessage(
"Multiple matching CREATOR fields found for" +
it.qualifiedName
)
.that(creatorProperties)
.hasSize(1)
} else {
val creator = creatorProperties.single().get()
if (creator !is Parcelable.Creator<*>) {
expect.that(creator).isInstanceOf(Parcelable.Creator::class.java)
return
}
parcelTwo.setDataPosition(0)
val parcelable = creator.createFromParcel(parcelTwo)
if (parcelable::class.isSubclassOf(setterType)) {
expect.withMessage(
"${it.qualifiedName} which does not safely override writeToParcel " +
"cannot contain a subclass CREATOR field"
)
.fail()
}
}
}
}
parcelOne.recycle()
parcelTwo.recycle()
}
private fun runAssertions(params: List<Param>, before: Parcelable, after: Parcelable) {
params.forEach {
val actual = it.getFunction(after)
val expected = it.value()
val equal = it.compare(actual, expected)
expect.withMessage("${it.getFunctionName} was $actual, expected $expected")
.that(equal)
.isTrue()
}
extraAssertions(before, after)
// TODO: Handle method overloads?
val expectedFunctions = (getters.map { it.name }
+ setters.map { it.name }
- excludedMethods)
.distinct()
val allTestedFunctions = params.flatMap {
listOfNotNull(it.getFunctionName, it.setFunctionName)
}
expect.that(allTestedFunctions).containsExactlyElementsIn(expectedFunctions)
}
open fun extraParams(): Collection<Param?> = emptyList()
open fun initialObject(): Parcelable = setterType.createInstance()
open fun extraAssertions(before: Parcelable, after: Parcelable) {}
open fun writeToParcel(parcel: Parcel, value: Parcelable) = value.writeToParcel(parcel, 0)
data class Param(
val getFunctionName: String,
val getFunction: (Any?) -> Any?,
val setFunctionName: String?,
val setFunction: (Array<Any?>) -> Unit,
val value: () -> Any?,
val compare: (Any?, Any?) -> Boolean = Objects::equals
)
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.pm.test.parsing.parcelling
import android.os.Parcel
import android.os.Parcelable
import com.android.server.pm.test.parsing.parcelling.java.TestSubWithCreator
import com.android.server.pm.test.parsing.parcelling.java.TestSuperClass
import org.junit.Test
import kotlin.contracts.ExperimentalContracts
/**
* Verifies the failing side of [ParcelableCreatorValidTest]. The sole difference is the addition
* of [TestSubWithCreator.CREATOR].
*/
@ExperimentalContracts
class ParcelableCreatorInvalidTest :
ParcelableComponentTest(TestSuperClass::class, TestSubWithCreator::class) {
override val defaultImpl = TestSubWithCreator()
override val creator = object : Parcelable.Creator<Parcelable> {
override fun createFromParcel(source: Parcel) = TestSubWithCreator(source)
override fun newArray(size: Int) = Array<TestSubWithCreator?>(size) { null }
}
override val excludedMethods = listOf("writeSubToParcel")
override val baseParams = listOf(TestSuperClass::getSuperString)
override fun writeToParcel(parcel: Parcel, value: Parcelable) {
(value as TestSubWithCreator).writeSubToParcel(parcel, 0)
}
@Test
override fun parcellingSize() {
super.parcellingSize()
if (expect.hasFailures()) {
// This is a hack to ignore an expected failure result. Doing it this way, rather than
// adding a switch in the test itself, prevents it from accidentally passing through a
// programming error.
ignoreableExpect.ignore()
}
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.pm.test.parsing.parcelling
import android.os.Parcel
import android.os.Parcelable
import com.android.server.pm.test.parsing.parcelling.java.TestSubWithoutCreator
import com.android.server.pm.test.parsing.parcelling.java.TestSuperClass
import kotlin.contracts.ExperimentalContracts
/**
* Tests the [Parcelable] CREATOR verification by using a mock object with known differences to
* ensure that the method succeeds/fails.
*/
@ExperimentalContracts
class ParcelableCreatorValidTest :
ParcelableComponentTest(TestSuperClass::class, TestSubWithoutCreator::class) {
override val defaultImpl = TestSubWithoutCreator()
override val creator = object : Parcelable.Creator<Parcelable> {
override fun createFromParcel(source: Parcel) = TestSubWithoutCreator(source)
override fun newArray(size: Int) = Array<TestSubWithoutCreator?>(size) { null }
}
override val excludedMethods = listOf("writeSubToParcel")
override val baseParams = listOf(TestSuperClass::getSuperString)
override fun writeToParcel(parcel: Parcel, value: Parcelable) {
(value as TestSubWithoutCreator).writeSubToParcel(parcel, 0)
}
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.pm.test.parsing.parcelling
import android.content.pm.ActivityInfo
import android.content.pm.parsing.component.ParsedActivity
import kotlin.contracts.ExperimentalContracts
@ExperimentalContracts
class ParsedActivityTest : ParsedMainComponentTest(ParsedActivity::class) {
override val defaultImpl = ParsedActivity()
override val creator = ParsedActivity.CREATOR
override val mainComponentSubclassBaseParams = listOf(
ParsedActivity::getPermission,
ParsedActivity::getColorMode,
ParsedActivity::getConfigChanges,
ParsedActivity::getDocumentLaunchMode,
ParsedActivity::getLaunchMode,
ParsedActivity::getLockTaskLaunchMode,
ParsedActivity::getMaxAspectRatio,
ParsedActivity::getMaxRecents,
ParsedActivity::getMinAspectRatio,
ParsedActivity::getParentActivityName,
ParsedActivity::getPersistableMode,
ParsedActivity::getPrivateFlags,
ParsedActivity::getRequestedVrComponent,
ParsedActivity::getResizeMode,
ParsedActivity::getRotationAnimation,
ParsedActivity::getScreenOrientation,
ParsedActivity::getSoftInputMode,
ParsedActivity::getTargetActivity,
ParsedActivity::getTaskAffinity,
ParsedActivity::getTheme,
ParsedActivity::getUiOptions,
ParsedActivity::isSupportsSizeChanges,
)
override fun mainComponentSubclassExtraParams() = listOf(
getSetByValue(
ParsedActivity::getWindowLayout,
ParsedActivity::setWindowLayout,
ActivityInfo.WindowLayout(1, 1f, 2, 1f, 3, 4, 5),
compare = { first, second ->
equalBy(
first, second,
ActivityInfo.WindowLayout::width,
ActivityInfo.WindowLayout::widthFraction,
ActivityInfo.WindowLayout::height,
ActivityInfo.WindowLayout::heightFraction,
ActivityInfo.WindowLayout::gravity,
ActivityInfo.WindowLayout::minWidth,
ActivityInfo.WindowLayout::minHeight
)
}
)
)
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.pm.test.parsing.parcelling
import android.content.pm.parsing.component.ParsedAttribution
import kotlin.contracts.ExperimentalContracts
@ExperimentalContracts
class ParsedAttributionTest : ParcelableComponentTest(ParsedAttribution::class) {
override val defaultImpl = ParsedAttribution("", 0, emptyList())
override val creator = ParsedAttribution.CREATOR
override val baseParams = listOf(
ParsedAttribution::getTag,
ParsedAttribution::getLabel,
)
override fun extraParams() = listOf(
getter(ParsedAttribution::getInheritFrom, listOf("testInheritFrom"))
)
}

View File

@@ -0,0 +1,95 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.pm.test.parsing.parcelling
import android.content.pm.PackageManager
import android.content.pm.parsing.component.ParsedComponent
import android.content.pm.parsing.component.ParsedIntentInfo
import android.os.Bundle
import android.os.Parcelable
import kotlin.contracts.ExperimentalContracts
import kotlin.reflect.KClass
import kotlin.reflect.KFunction1
@ExperimentalContracts
abstract class ParsedComponentTest(kClass: KClass<out Parcelable>) :
ParcelableComponentTest(kClass) {
final override val excludedMethods
get() = subclassExcludedMethods + listOf(
// Method aliases/utilities
"getClassName",
"getComponentName",
"setProperties" // Tested though addProperty
)
open val subclassExcludedMethods: Collection<String> = emptyList()
final override val baseParams
get() = subclassBaseParams + listOf(
ParsedComponent::getBanner,
ParsedComponent::getDescriptionRes,
ParsedComponent::getFlags,
ParsedComponent::getIcon,
ParsedComponent::getLabelRes,
ParsedComponent::getLogo,
ParsedComponent::getName,
ParsedComponent::getNonLocalizedLabel,
ParsedComponent::getPackageName,
)
abstract val subclassBaseParams: Collection<KFunction1<*, Any?>>
final override fun extraParams() = subclassExtraParams() + listOf(
getSetByValue(
ParsedComponent::getIntents,
ParsedComponent::addIntent,
"TestLabel",
transformGet = { it.singleOrNull()?.nonLocalizedLabel },
transformSet = { ParsedIntentInfo().setNonLocalizedLabel(it) },
),
getSetByValue(
ParsedComponent::getProperties,
ParsedComponent::addProperty,
PackageManager.Property(
"testPropertyName",
"testPropertyValue",
"testPropertyClassName",
"testPropertyPackageName"
),
transformGet = { it["testPropertyName"] },
compare = { first, second ->
equalBy(
first, second,
PackageManager.Property::getName,
PackageManager.Property::getClassName,
PackageManager.Property::getPackageName,
PackageManager.Property::getString,
)
}
),
getSetByValue(
ParsedComponent::getMetaData,
ParsedComponent::setMetaData,
"testBundleKey" to "testBundleValue",
transformGet = { "testBundleKey" to it?.getString("testBundleKey") },
transformSet = { Bundle().apply { putString(it.first, it.second) } }
),
)
open fun subclassExtraParams(): Collection<Param?> = emptyList()
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.pm.test.parsing.parcelling
import android.content.pm.parsing.component.ParsedInstrumentation
import kotlin.contracts.ExperimentalContracts
@ExperimentalContracts
class ParsedInstrumentationTest : ParsedComponentTest(ParsedInstrumentation::class) {
override val defaultImpl = ParsedInstrumentation()
override val creator = ParsedInstrumentation.CREATOR
override val subclassBaseParams = listOf(
ParsedInstrumentation::getTargetPackage,
ParsedInstrumentation::getTargetProcesses,
ParsedInstrumentation::isFunctionalTest,
ParsedInstrumentation::isHandleProfiling,
)
}

View File

@@ -0,0 +1,152 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.pm.test.parsing.parcelling
import android.content.pm.parsing.component.ParsedIntentInfo
import android.os.Parcel
import android.os.Parcelable
import android.os.PatternMatcher
import kotlin.contracts.ExperimentalContracts
@ExperimentalContracts
class ParsedIntentInfoTest : ParcelableComponentTest(ParsedIntentInfo::class) {
override val defaultImpl = ParsedIntentInfo()
override val creator = object : Parcelable.Creator<ParsedIntentInfo> {
override fun createFromParcel(source: Parcel) = ParsedIntentInfo(source)
override fun newArray(size: Int) = Array<ParsedIntentInfo?>(size) { null }
}
override val excludedMethods = listOf(
// Used to parcel
"writeIntentInfoToParcel",
// All remaining IntentFilter methods, which are out of scope
"hasDataPath",
"hasDataSchemeSpecificPart",
"matchAction",
"matchData",
"actionsIterator",
"addAction",
"addCategory",
"addDataAuthority",
"addDataPath",
"addDataScheme",
"addDataSchemeSpecificPart",
"addDataType",
"addDynamicDataType",
"addMimeGroup",
"asPredicate",
"asPredicateWithTypeResolution",
"authoritiesIterator",
"categoriesIterator",
"clearDynamicDataTypes",
"countActions",
"countCategories",
"countDataAuthorities",
"countDataPaths",
"countDataSchemeSpecificParts",
"countDataSchemes",
"countDataTypes",
"countMimeGroups",
"countStaticDataTypes",
"dataTypes",
"debugCheck",
"dump",
"dumpDebug",
"getAction",
"getAutoVerify",
"getCategory",
"getDataAuthority",
"getDataPath",
"getDataScheme",
"getDataSchemeSpecificPart",
"getDataType",
"getHosts",
"getHostsList",
"getMimeGroup",
"getOrder",
"getPriority",
"getVisibilityToInstantApp",
"handleAllWebDataURI",
"handlesWebUris",
"hasAction",
"hasCategory",
"hasDataAuthority",
"hasDataScheme",
"hasDataType",
"hasExactDataType",
"hasExactDynamicDataType",
"hasExactStaticDataType",
"hasMimeGroup",
"isExplicitlyVisibleToInstantApp",
"isImplicitlyVisibleToInstantApp",
"isVerified",
"isVisibleToInstantApp",
"match",
"matchCategories",
"matchDataAuthority",
"mimeGroupsIterator",
"needsVerification",
"pathsIterator",
"readFromXml",
"schemeSpecificPartsIterator",
"schemesIterator",
"setAutoVerify",
"setOrder",
"setPriority",
"setVerified",
"setVisibilityToInstantApp",
"typesIterator",
"writeToXml",
)
override val baseParams = listOf(
ParsedIntentInfo::getIcon,
ParsedIntentInfo::getLabelRes,
ParsedIntentInfo::isHasDefault,
ParsedIntentInfo::getNonLocalizedLabel,
)
override fun initialObject() = ParsedIntentInfo().apply {
addAction("test.ACTION")
addDataAuthority("testAuthority", "404")
addCategory("test.CATEGORY")
addMimeGroup("testMime")
addDataPath("testPath", PatternMatcher.PATTERN_LITERAL)
}
override fun extraAssertions(before: Parcelable, after: Parcelable) {
super.extraAssertions(before, after)
after as ParsedIntentInfo
expect.that(after.actionsIterator().asSequence().singleOrNull())
.isEqualTo("test.ACTION")
val authority = after.authoritiesIterator().asSequence().singleOrNull()
expect.that(authority?.host).isEqualTo("testAuthority")
expect.that(authority?.port).isEqualTo(404)
expect.that(after.categoriesIterator().asSequence().singleOrNull())
.isEqualTo("test.CATEGORY")
expect.that(after.mimeGroupsIterator().asSequence().singleOrNull())
.isEqualTo("testMime")
expect.that(after.hasDataPath("testPath")).isTrue()
}
override fun writeToParcel(parcel: Parcel, value: Parcelable) =
ParsedIntentInfo.PARCELER.parcel(value as ParsedIntentInfo, parcel, 0)
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.pm.test.parsing.parcelling
import android.content.pm.parsing.component.ParsedMainComponent
import android.content.pm.parsing.component.ParsedService
import android.os.Parcelable
import java.util.Arrays
import kotlin.contracts.ExperimentalContracts
import kotlin.reflect.KClass
import kotlin.reflect.KFunction1
@ExperimentalContracts
abstract class ParsedMainComponentTest(kClass: KClass<out Parcelable>) :
ParsedComponentTest(kClass) {
final override val subclassBaseParams
get() = mainComponentSubclassBaseParams + listOf(
ParsedMainComponent::getOrder,
ParsedMainComponent::getProcessName,
ParsedMainComponent::getSplitName,
ParsedMainComponent::isDirectBootAware,
ParsedMainComponent::isEnabled,
ParsedMainComponent::isExported,
)
abstract val mainComponentSubclassBaseParams: Collection<KFunction1<*, Any?>>
final override fun subclassExtraParams() = mainComponentSubclassExtraParams() + listOf(
getSetByValue(
ParsedService::getAttributionTags,
ParsedService::setAttributionTags,
arrayOf("testAttributionTag"),
compare = Arrays::equals
),
)
open fun mainComponentSubclassExtraParams(): Collection<Param?> = emptyList()
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.pm.test.parsing.parcelling
import android.content.pm.parsing.component.ParsedPermissionGroup
import kotlin.contracts.ExperimentalContracts
@ExperimentalContracts
class ParsedPermissionGroupTest : ParsedComponentTest(ParsedPermissionGroup::class) {
override val defaultImpl = ParsedPermissionGroup()
override val creator = ParsedPermissionGroup.CREATOR
override val subclassBaseParams = listOf(
ParsedPermissionGroup::getRequestDetailResourceId,
ParsedPermissionGroup::getBackgroundRequestDetailResourceId,
ParsedPermissionGroup::getBackgroundRequestResourceId,
ParsedPermissionGroup::getRequestRes,
ParsedPermissionGroup::getPriority,
)
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.pm.test.parsing.parcelling
import android.content.pm.parsing.component.ParsedPermission
import android.content.pm.parsing.component.ParsedPermissionGroup
import kotlin.contracts.ExperimentalContracts
@ExperimentalContracts
class ParsedPermissionTest : ParsedComponentTest(ParsedPermission::class) {
override val defaultImpl = ParsedPermission()
override val creator = ParsedPermission.CREATOR
override val subclassExcludedMethods = listOf(
// Utility methods
"isAppOp",
"isRuntime",
"getProtection",
"getProtectionFlags",
"calculateFootprint",
"setKnownCert", // Tested through setKnownCerts
)
override val subclassBaseParams = listOf(
ParsedPermission::getBackgroundPermission,
ParsedPermission::getGroup,
ParsedPermission::getRequestRes,
ParsedPermission::getProtectionLevel,
ParsedPermission::isTree,
)
override fun subclassExtraParams() = listOf(
getter(ParsedPermission::getKnownCerts, setOf("testCert")),
getSetByValue(
ParsedPermission::getParsedPermissionGroup,
ParsedPermission::setParsedPermissionGroup,
ParsedPermissionGroup().apply { name = "test.permission.group" },
compare = { first, second -> equalBy(first, second, ParsedPermissionGroup::getName) }
),
)
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.pm.test.parsing.parcelling
import android.content.pm.parsing.component.ParsedProcess
import kotlin.contracts.ExperimentalContracts
@ExperimentalContracts
class ParsedProcessTest : ParcelableComponentTest(ParsedProcess::class) {
override val defaultImpl = ParsedProcess()
override val creator = ParsedProcess.CREATOR
override val excludedMethods = listOf(
// Copying method
"addStateFrom",
)
override val baseParams = listOf(
ParsedProcess::getName,
ParsedProcess::getGwpAsanMode,
ParsedProcess::getMemtagMode,
ParsedProcess::getNativeHeapZeroInitialized,
)
override fun extraParams() = listOf(
getter(ParsedProcess::getDeniedPermissions, setOf("testDeniedPermission"))
)
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.pm.test.parsing.parcelling
import android.content.pm.PathPermission
import android.content.pm.parsing.component.ParsedProvider
import android.os.PatternMatcher
import kotlin.contracts.ExperimentalContracts
@ExperimentalContracts
class ParsedProviderTest : ParsedMainComponentTest(ParsedProvider::class) {
override val defaultImpl = ParsedProvider()
override val creator = ParsedProvider.CREATOR
override val mainComponentSubclassBaseParams = listOf(
ParsedProvider::getAuthority,
ParsedProvider::isSyncable,
ParsedProvider::getReadPermission,
ParsedProvider::getWritePermission,
ParsedProvider::isGrantUriPermissions,
ParsedProvider::isForceUriPermissions,
ParsedProvider::isMultiProcess,
ParsedProvider::getInitOrder,
)
override fun mainComponentSubclassExtraParams() = listOf(
getSetByValue(
ParsedProvider::getUriPermissionPatterns,
ParsedProvider::setUriPermissionPatterns,
PatternMatcher("testPattern", PatternMatcher.PATTERN_LITERAL),
transformGet = { it?.singleOrNull() },
transformSet = { arrayOf(it) },
compare = { first, second ->
equalBy(
first, second,
PatternMatcher::getPath,
PatternMatcher::getType
)
}
),
getSetByValue(
ParsedProvider::getPathPermissions,
ParsedProvider::setPathPermissions,
PathPermission(
"testPermissionPattern",
PatternMatcher.PATTERN_LITERAL,
"test.READ_PERMISSION",
"test.WRITE_PERMISSION"
),
transformGet = { it?.singleOrNull() },
transformSet = { arrayOf(it) },
compare = { first, second ->
equalBy(
first, second,
PatternMatcher::getPath,
PatternMatcher::getType,
PathPermission::getReadPermission,
PathPermission::getWritePermission,
)
}
)
)
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.pm.test.parsing.parcelling
import android.content.pm.parsing.component.ParsedService
import kotlin.contracts.ExperimentalContracts
@ExperimentalContracts
class ParsedServiceTest : ParsedMainComponentTest(ParsedService::class) {
override val defaultImpl = ParsedService()
override val creator = ParsedService.CREATOR
override val mainComponentSubclassBaseParams = listOf(
ParsedService::getForegroundServiceType,
ParsedService::getPermission,
)
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.pm.test.parsing.parcelling
import android.content.pm.parsing.component.ParsedUsesPermission
import android.os.Parcelable
import kotlin.contracts.ExperimentalContracts
@ExperimentalContracts
class ParsedUsesPermissionTest : ParcelableComponentTest(ParsedUsesPermission::class) {
override val defaultImpl = ParsedUsesPermission("", 0)
override val creator = ParsedUsesPermission.CREATOR
override val baseParams = listOf(
ParsedUsesPermission::getName,
ParsedUsesPermission::getUsesPermissionFlags
)
override fun initialObject() = ParsedUsesPermission("", 0)
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.pm.test.parsing.parcelling.java;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
public class TestSubWithCreator extends TestSuperClass {
@NonNull
public static final Parcelable.Creator<TestSubWithCreator> CREATOR =
new Parcelable.Creator<TestSubWithCreator>() {
@Override
public TestSubWithCreator createFromParcel(Parcel source) {
return new TestSubWithCreator(source);
}
@Override
public TestSubWithCreator[] newArray(int size) {
return new TestSubWithCreator[size];
}
};
@Nullable
private String subString;
public TestSubWithCreator() {
}
public TestSubWithCreator(@NonNull Parcel in) {
super(in);
subString = in.readString();
}
public void writeSubToParcel(@NonNull Parcel parcel, int flags) {
super.writeToParcel(parcel, flags);
parcel.writeString(subString);
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.pm.test.parsing.parcelling.java;
import android.annotation.Nullable;
import android.os.Parcel;
import androidx.annotation.NonNull;
public class TestSubWithoutCreator extends TestSuperClass {
@Nullable
private String subString;
public TestSubWithoutCreator() {
}
public TestSubWithoutCreator(@NonNull Parcel in) {
super(in);
subString = in.readString();
}
public void writeSubToParcel(@NonNull Parcel parcel, int flags) {
super.writeToParcel(parcel, flags);
parcel.writeString(subString);
}
}

View File

@@ -0,0 +1,118 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.pm.test.parsing.parcelling.java;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcelable;
import com.android.internal.util.DataClass;
@DataClass(genGetters = true, genSetters = true, genBuilder = false, genAidl = false,
genParcelable = true, genConstructor = false)
public class TestSuperClass implements Parcelable {
@Nullable
private String superString;
public TestSuperClass() {
}
// Code below generated by codegen v1.0.23.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
//
// To regenerate run:
// $ codegen $ANDROID_BUILD_TOP/frameworks/base/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSuperClass.java
//
// To exclude the generated code from IntelliJ auto-formatting enable (one-time):
// Settings > Editor > Code Style > Formatter Control
//@formatter:off
@DataClass.Generated.Member
public @Nullable String getSuperString() {
return superString;
}
@DataClass.Generated.Member
public @NonNull TestSuperClass setSuperString(@NonNull String value) {
superString = value;
return this;
}
@Override
@DataClass.Generated.Member
public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
// You can override field parcelling by defining methods like:
// void parcelFieldName(Parcel dest, int flags) { ... }
byte flg = 0;
if (superString != null) flg |= 0x1;
dest.writeByte(flg);
if (superString != null) dest.writeString(superString);
}
@Override
@DataClass.Generated.Member
public int describeContents() { return 0; }
/** @hide */
@SuppressWarnings({"unchecked", "RedundantCast"})
@DataClass.Generated.Member
protected TestSuperClass(@NonNull android.os.Parcel in) {
// You can override field unparcelling by defining methods like:
// static FieldType unparcelFieldName(Parcel in) { ... }
byte flg = in.readByte();
String _superString = (flg & 0x1) == 0 ? null : in.readString();
this.superString = _superString;
// onConstructed(); // You can define this method to get a callback
}
@DataClass.Generated.Member
public static final @NonNull Parcelable.Creator<TestSuperClass> CREATOR
= new Parcelable.Creator<TestSuperClass>() {
@Override
public TestSuperClass[] newArray(int size) {
return new TestSuperClass[size];
}
@Override
public TestSuperClass createFromParcel(@NonNull android.os.Parcel in) {
return new TestSuperClass(in);
}
};
@DataClass.Generated(
time = 1624381019144L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSuperClass.java",
inputSignatures = "private @android.annotation.Nullable java.lang.String superString\nclass TestSuperClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=true, genBuilder=false, genAidl=false, genParcelable=true, genConstructor=false)")
@Deprecated
private void __metadata() {}
//@formatter:on
// End of generated code
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.pm.test.util
import com.google.common.truth.Expect
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
/**
* Wrapper for [Expect] which supports ignoring any failures. This should be used with caution, but
* it allows a base test to be written which doesn't switch success/failure in the test itself,
* preventing any logic errors from causing the test to accidentally succeed.
*/
internal class IgnoreableExpect : TestRule {
val expect = Expect.create()
private var ignore = false
override fun apply(base: Statement?, description: Description?): Statement {
return object : Statement() {
override fun evaluate() {
ignore = false
try {
expect.apply(base, description).evaluate()
} catch (t: Throwable) {
if (!ignore) {
throw t
}
}
}
}
}
fun ignore() {
ignore = true
}
}

View File

@@ -949,7 +949,7 @@ public class PackageParserTest {
.addConfigPreference(new ConfigurationInfo())
.addReqFeature(new FeatureInfo())
.addFeatureGroup(new FeatureGroupInfo())
.setCompileSdkVersionCodename("foo23")
.setCompileSdkVersionCodeName("foo23")
.setCompileSdkVersion(100)
.setOverlayCategory("foo24")
.setOverlayIsStatic(true)