Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 16e84e61 authored by Jackal Guo's avatar Jackal Guo Committed by Android (Google) Code Review
Browse files

Merge "Fail install if required split type is missing"

parents d027f6bb dfd7a656
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -1194,6 +1194,7 @@ package android {
    field public static final int requiredFeature = 16844116; // 0x1010554
    field public static final int requiredForAllUsers = 16843728; // 0x10103d0
    field public static final int requiredNotFeature = 16844117; // 0x1010555
    field public static final int requiredSplitTypes;
    field public static final int requiresFadingEdge = 16843685; // 0x10103a5
    field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364
    field public static final int resizeClip = 16843983; // 0x10104cf
@@ -1329,6 +1330,7 @@ package android {
    field public static final int splitMotionEvents = 16843503; // 0x10102ef
    field public static final int splitName = 16844105; // 0x1010549
    field public static final int splitTrack = 16843852; // 0x101044c
    field public static final int splitTypes;
    field public static final int spotShadowAlpha = 16843967; // 0x10104bf
    field public static final int src = 16843033; // 0x1010119
    field public static final int ssp = 16843747; // 0x10103e3
+45 −12
Original line number Diff line number Diff line
@@ -19,12 +19,15 @@ package android.content.pm.parsing;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.SigningDetails;
import android.content.pm.VerifierInfo;

import com.android.internal.util.CollectionUtils;
import com.android.internal.util.DataClass;

import java.util.List;
import java.util.Set;

/**
 * Lightweight parsed details about a single APK file.
@@ -44,6 +47,10 @@ public class ApkLite {
    private final @Nullable String mUsesSplitName;
    /** Name of the split APK that this APK is a configuration for */
    private final @Nullable String mConfigForSplit;
    /** Indicate the types of the required split are necessary for this package to run */
    private final @Nullable Set<String> mRequiredSplitTypes;
    /** Split types of this APK */
    private final @Nullable Set<String> mSplitTypes;

    /** Major version number of this package */
    private final int mVersionCodeMajor;
@@ -105,9 +112,9 @@ public class ApkLite {
    /**
     * Indicate the policy to deal with user data when rollback is committed
     *
     * @see {@link android.content.pm.PackageManager.RollbackDataPolicy#RESTORE}
     * @see {@link android.content.pm.PackageManager.RollbackDataPolicy#WIPE}
     * @see {@link android.content.pm.PackageManager.RollbackDataPolicy#RETAIN}
     * @see {@link PackageManager#ROLLBACK_DATA_POLICY_RESTORE}
     * @see {@link PackageManager#ROLLBACK_DATA_POLICY_WIPE}
     * @see {@link PackageManager#ROLLBACK_DATA_POLICY_RETAIN}
     */
    private final int mRollbackDataPolicy;

@@ -118,14 +125,17 @@ public class ApkLite {
            boolean debuggable, boolean profileableByShell, boolean multiArch, boolean use32bitAbi,
            boolean useEmbeddedDex, boolean extractNativeLibs, boolean isolatedSplits,
            String targetPackageName, boolean overlayIsStatic, int overlayPriority,
            int minSdkVersion, int targetSdkVersion, int rollbackDataPolicy) {
            int minSdkVersion, int targetSdkVersion, int rollbackDataPolicy,
            Set<String> requiredSplitTypes, Set<String> splitTypes) {
        mPath = path;
        mPackageName = packageName;
        mSplitName = splitName;
        mSplitTypes = splitTypes;
        mFeatureSplit = isFeatureSplit;
        mConfigForSplit = configForSplit;
        mUsesSplitName = usesSplitName;
        mSplitRequired = isSplitRequired;
        mRequiredSplitTypes = requiredSplitTypes;
        mSplitRequired = (isSplitRequired || hasAnyRequiredSplitTypes());
        mVersionCode = versionCode;
        mVersionCodeMajor = versionCodeMajor;
        mRevisionCode = revisionCode;
@@ -156,9 +166,16 @@ public class ApkLite {
        return PackageInfo.composeLongVersionCode(mVersionCodeMajor, mVersionCode);
    }

    /**
     * Return if requiredSplitTypes presents.
     */
    private boolean hasAnyRequiredSplitTypes() {
        return !CollectionUtils.isEmpty(mRequiredSplitTypes);
    }



    // Code below generated by codegen v1.0.22.
    // Code below generated by codegen v1.0.23.
    //
    // DO NOT MODIFY!
    // CHECKSTYLE:OFF Generated code
@@ -211,6 +228,22 @@ public class ApkLite {
        return mConfigForSplit;
    }

    /**
     * Indicate the types of the required split are necessary for this package to run
     */
    @DataClass.Generated.Member
    public @Nullable Set<String> getRequiredSplitTypes() {
        return mRequiredSplitTypes;
    }

    /**
     * Split types of this APK
     */
    @DataClass.Generated.Member
    public @Nullable Set<String> getSplitTypes() {
        return mSplitTypes;
    }

    /**
     * Major version number of this package
     */
@@ -388,9 +421,9 @@ public class ApkLite {
    /**
     * Indicate the policy to deal with user data when rollback is committed
     *
     * @see {@link android.content.pm.PackageManager.RollbackDataPolicy#RESTORE}
     * @see {@link android.content.pm.PackageManager.RollbackDataPolicy#WIPE}
     * @see {@link android.content.pm.PackageManager.RollbackDataPolicy#RETAIN}
     * @see {@link PackageManager#ROLLBACK_DATA_POLICY_RESTORE}
     * @see {@link PackageManager#ROLLBACK_DATA_POLICY_WIPE}
     * @see {@link PackageManager#ROLLBACK_DATA_POLICY_RETAIN}
     */
    @DataClass.Generated.Member
    public int getRollbackDataPolicy() {
@@ -398,10 +431,10 @@ public class ApkLite {
    }

    @DataClass.Generated(
            time = 1616985847981L,
            codegenVersion = "1.0.22",
            time = 1628562554893L,
            codegenVersion = "1.0.23",
            sourceFile = "frameworks/base/core/java/android/content/pm/parsing/ApkLite.java",
            inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.lang.String mPath\nprivate final @android.annotation.Nullable java.lang.String mSplitName\nprivate final @android.annotation.Nullable java.lang.String mUsesSplitName\nprivate final @android.annotation.Nullable java.lang.String mConfigForSplit\nprivate final  int mVersionCodeMajor\nprivate final  int mVersionCode\nprivate final  int mRevisionCode\nprivate final  int mInstallLocation\nprivate final  int mMinSdkVersion\nprivate final  int mTargetSdkVersion\nprivate final @android.annotation.NonNull android.content.pm.VerifierInfo[] mVerifiers\nprivate final @android.annotation.NonNull android.content.pm.SigningDetails mSigningDetails\nprivate final  boolean mFeatureSplit\nprivate final  boolean mIsolatedSplits\nprivate final  boolean mSplitRequired\nprivate final  boolean mCoreApp\nprivate final  boolean mDebuggable\nprivate final  boolean mProfileableByShell\nprivate final  boolean mMultiArch\nprivate final  boolean mUse32bitAbi\nprivate final  boolean mExtractNativeLibs\nprivate final  boolean mUseEmbeddedDex\nprivate final @android.annotation.Nullable java.lang.String mTargetPackageName\nprivate final  boolean mOverlayIsStatic\nprivate final  int mOverlayPriority\nprivate final  int mRollbackDataPolicy\npublic  long getLongVersionCode()\nclass ApkLite extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genConstDefs=false)")
            inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.lang.String mPath\nprivate final @android.annotation.Nullable java.lang.String mSplitName\nprivate final @android.annotation.Nullable java.lang.String mUsesSplitName\nprivate final @android.annotation.Nullable java.lang.String mConfigForSplit\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String> mRequiredSplitTypes\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String> mSplitTypes\nprivate final  int mVersionCodeMajor\nprivate final  int mVersionCode\nprivate final  int mRevisionCode\nprivate final  int mInstallLocation\nprivate final  int mMinSdkVersion\nprivate final  int mTargetSdkVersion\nprivate final @android.annotation.NonNull android.content.pm.VerifierInfo[] mVerifiers\nprivate final @android.annotation.NonNull android.content.pm.SigningDetails mSigningDetails\nprivate final  boolean mFeatureSplit\nprivate final  boolean mIsolatedSplits\nprivate final  boolean mSplitRequired\nprivate final  boolean mCoreApp\nprivate final  boolean mDebuggable\nprivate final  boolean mProfileableByShell\nprivate final  boolean mMultiArch\nprivate final  boolean mUse32bitAbi\nprivate final  boolean mExtractNativeLibs\nprivate final  boolean mUseEmbeddedDex\nprivate final @android.annotation.Nullable java.lang.String mTargetPackageName\nprivate final  boolean mOverlayIsStatic\nprivate final  int mOverlayPriority\nprivate final  int mRollbackDataPolicy\npublic  long getLongVersionCode()\nprivate  boolean hasAnyRequiredSplitTypes()\nclass ApkLite extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genConstDefs=false)")
    @Deprecated
    private void __metadata() {}

+70 −5
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import android.content.res.XmlResourceParser;
import android.os.Trace;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.Pair;
import android.util.Slog;
@@ -58,6 +59,7 @@ import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/** @hide */
public class ApkLiteParseUtils {
@@ -104,8 +106,11 @@ public class ApkLiteParseUtils {
            final ApkLite baseApk = result.getResult();
            final String packagePath = packageFile.getAbsolutePath();
            return input.success(
                    new PackageLite(packagePath, baseApk.getPath(), baseApk, null,
                            null, null, null, null, null, baseApk.getTargetSdkVersion()));
                    new PackageLite(packagePath, baseApk.getPath(), baseApk, null /* splitNames */,
                            null /* isFeatureSplits */, null /* usesSplitNames */,
                            null /* configForSplit */, null /* splitApkPaths */,
                            null /* splitRevisionCodes */, baseApk.getTargetSdkVersion(),
                            null /* requiredSplitTypes */, null /* splitTypes */));
        } finally {
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }
@@ -209,6 +214,8 @@ public class ApkLiteParseUtils {
        final int size = ArrayUtils.size(splitApks);

        String[] splitNames = null;
        Set<String>[] requiredSplitTypes = null;
        Set<String>[] splitTypes = null;
        boolean[] isFeatureSplits = null;
        String[] usesSplitNames = null;
        String[] configForSplits = null;
@@ -216,6 +223,8 @@ public class ApkLiteParseUtils {
        int[] splitRevisionCodes = null;
        if (size > 0) {
            splitNames = new String[size];
            requiredSplitTypes = new Set[size];
            splitTypes = new Set[size];
            isFeatureSplits = new boolean[size];
            usesSplitNames = new String[size];
            configForSplits = new String[size];
@@ -227,6 +236,8 @@ public class ApkLiteParseUtils {

            for (int i = 0; i < size; i++) {
                final ApkLite apk = splitApks.get(splitNames[i]);
                requiredSplitTypes[i] = apk.getRequiredSplitTypes();
                splitTypes[i] = apk.getSplitTypes();
                usesSplitNames[i] = apk.getUsesSplitName();
                isFeatureSplits[i] = apk.isFeatureSplit();
                configForSplits[i] = apk.getConfigForSplit();
@@ -242,7 +253,7 @@ public class ApkLiteParseUtils {
        return input.success(
                new PackageLite(codePath, baseCodePath, baseApk, splitNames, isFeatureSplits,
                        usesSplitNames, configForSplits, splitCodePaths, splitRevisionCodes,
                        baseApk.getTargetSdkVersion()));
                        baseApk.getTargetSdkVersion(), requiredSplitTypes, splitTypes));
    }

    /**
@@ -345,9 +356,15 @@ public class ApkLiteParseUtils {
        if (result.isError()) {
            return input.error(result);
        }

        Pair<String, String> packageSplit = result.getResult();

        final ParseResult<Pair<Set<String>, Set<String>>> requiredSplitTypesResult =
                parseRequiredSplitTypes(input, parser);
        if (requiredSplitTypesResult.isError()) {
            return input.error(result);
        }
        Pair<Set<String>, Set<String>> requiredSplitTypes = requiredSplitTypesResult.getResult();

        int installLocation = parser.getAttributeIntValue(ANDROID_RES_NAMESPACE,
                "installLocation", PARSE_DEFAULT_INSTALL_LOCATION);
        int versionCode = parser.getAttributeIntValue(ANDROID_RES_NAMESPACE, "versionCode", 0);
@@ -522,7 +539,7 @@ public class ApkLiteParseUtils {
                        coreApp, debuggable, profilableByShell, multiArch, use32bitAbi,
                        useEmbeddedDex, extractNativeLibs, isolatedSplits, targetPackage,
                        overlayIsStatic, overlayPriority, minSdkVersion, targetSdkVersion,
                        rollbackDataPolicy));
                        rollbackDataPolicy, requiredSplitTypes.first, requiredSplitTypes.second));
    }

    public static ParseResult<Pair<String, String>> parsePackageSplitNames(ParseInput input,
@@ -567,6 +584,54 @@ public class ApkLiteParseUtils {
                (splitName != null) ? splitName.intern() : splitName));
    }

    /**
     * Utility method that parses attributes android:requiredSplitTypes and android:splitTypes.
     */
    public static ParseResult<Pair<Set<String>, Set<String>>> parseRequiredSplitTypes(
            ParseInput input, XmlResourceParser parser) {
        Set<String> requiredSplitTypes = null;
        Set<String> splitTypes = null;
        String value = parser.getAttributeValue(ANDROID_RES_NAMESPACE, "requiredSplitTypes");
        if (!TextUtils.isEmpty(value)) {
            final ParseResult<Set<String>> result = separateAndValidateSplitTypes(input, value);
            if (result.isError()) {
                return input.error(result);
            }
            requiredSplitTypes = result.getResult();
        }

        value = parser.getAttributeValue(ANDROID_RES_NAMESPACE, "splitTypes");
        if (!TextUtils.isEmpty(value)) {
            final ParseResult<Set<String>> result = separateAndValidateSplitTypes(input, value);
            if (result.isError()) {
                return input.error(result);
            }
            splitTypes = result.getResult();
        }

        return input.success(Pair.create(requiredSplitTypes, splitTypes));
    }

    private static ParseResult<Set<String>> separateAndValidateSplitTypes(ParseInput input,
            String values) {
        final Set<String> ret = new ArraySet<>();
        for (String value : values.trim().split(",")) {
            final String type = value.trim();
            // Using requireFilename as true because it limits length of the name to the
            // {@link #MAX_FILE_NAME_SIZE}.
            final ParseResult<?> nameResult = validateName(input, type,
                    false /* requireSeparator */, true /* requireFilename */);
            if (nameResult.isError()) {
                return input.error(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
                        "Invalid manifest split types: " + nameResult.getErrorMessage());
            }
            if (!ret.add(type)) {
                Slog.w(TAG, type + " was defined multiple times");
            }
        }
        return input.success(ret);
    }

    public static VerifierInfo parseVerifier(AttributeSet attrs) {
        String packageName = attrs.getAttributeValue(ANDROID_RES_NAMESPACE, "name");
        String encodedPublicKey = attrs.getAttributeValue(ANDROID_RES_NAMESPACE, "publicKey");
+51 −6
Original line number Diff line number Diff line
@@ -22,11 +22,13 @@ import android.content.pm.PackageInfo;
import android.content.pm.VerifierInfo;

import com.android.internal.util.ArrayUtils;
import com.android.internal.util.CollectionUtils;
import com.android.internal.util.DataClass;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
 * Lightweight parsed details about a single package.
@@ -52,6 +54,12 @@ public class PackageLite {
    /** Dependencies of any split APKs, ordered by parsed splitName */
    private final @Nullable String[] mUsesSplitNames;
    private final @Nullable String[] mConfigForSplit;
    /** Indicate the types of the required split are necessary for base APK to run */
    private final @Nullable Set<String> mBaseRequiredSplitTypes;
    /** Indicate the types of the required split are necessary for split APKs to run */
    private final @Nullable Set<String>[] mRequiredSplitTypes;
    /** Split type of any split APKs, ordered by parsed splitName */
    private final @Nullable Set<String>[] mSplitTypes;
    /** Major and minor version number of this package */
    private final int mVersionCodeMajor;
    private final int mVersionCode;
@@ -101,7 +109,7 @@ public class PackageLite {
    public PackageLite(String path, String baseApkPath, ApkLite baseApk,
            String[] splitNames, boolean[] isFeatureSplits, String[] usesSplitNames,
            String[] configForSplit, String[] splitApkPaths, int[] splitRevisionCodes,
            int targetSdk) {
            int targetSdk, Set<String>[] requiredSplitTypes, Set<String>[] splitTypes) {
        // The following paths may be different from the path in ApkLite because we
        // move or rename the APK files. Use parameters to indicate the correct paths.
        mPath = path;
@@ -119,9 +127,12 @@ public class PackageLite {
        mExtractNativeLibs = baseApk.isExtractNativeLibs();
        mIsolatedSplits = baseApk.isIsolatedSplits();
        mUseEmbeddedDex = baseApk.isUseEmbeddedDex();
        mSplitRequired = baseApk.isSplitRequired();
        mBaseRequiredSplitTypes = baseApk.getRequiredSplitTypes();
        mRequiredSplitTypes = requiredSplitTypes;
        mSplitRequired = (baseApk.isSplitRequired() || hasAnyRequiredSplitTypes());
        mProfileableByShell = baseApk.isProfileableByShell();
        mSplitNames = splitNames;
        mSplitTypes = splitTypes;
        mIsFeatureSplits = isFeatureSplits;
        mUsesSplitNames = usesSplitNames;
        mConfigForSplit = configForSplit;
@@ -150,9 +161,19 @@ public class PackageLite {
        return PackageInfo.composeLongVersionCode(mVersionCodeMajor, mVersionCode);
    }

    /**
     * Return if requiredSplitTypes presents in the package.
     */
    private boolean hasAnyRequiredSplitTypes() {
        if (!CollectionUtils.isEmpty(mBaseRequiredSplitTypes)) {
            return true;
        }
        return ArrayUtils.find(mRequiredSplitTypes, r -> !CollectionUtils.isEmpty(r)) != null;
    }



    // Code below generated by codegen v1.0.22.
    // Code below generated by codegen v1.0.23.
    //
    // DO NOT MODIFY!
    // CHECKSTYLE:OFF Generated code
@@ -220,6 +241,30 @@ public class PackageLite {
        return mConfigForSplit;
    }

    /**
     * Indicate the types of the required split are necessary for base APK to run
     */
    @DataClass.Generated.Member
    public @Nullable Set<String> getBaseRequiredSplitTypes() {
        return mBaseRequiredSplitTypes;
    }

    /**
     * Indicate the types of the required split are necessary for split APKs to run
     */
    @DataClass.Generated.Member
    public @Nullable Set<String>[] getRequiredSplitTypes() {
        return mRequiredSplitTypes;
    }

    /**
     * Split type of any split APKs, ordered by parsed splitName
     */
    @DataClass.Generated.Member
    public @Nullable Set<String>[] getSplitTypes() {
        return mSplitTypes;
    }

    /**
     * Major and minor version number of this package
     */
@@ -357,10 +402,10 @@ public class PackageLite {
    }

    @DataClass.Generated(
            time = 1615914120261L,
            codegenVersion = "1.0.22",
            time = 1628562559343L,
            codegenVersion = "1.0.23",
            sourceFile = "frameworks/base/core/java/android/content/pm/parsing/PackageLite.java",
            inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.lang.String mPath\nprivate final @android.annotation.NonNull java.lang.String mBaseApkPath\nprivate final @android.annotation.Nullable java.lang.String[] mSplitApkPaths\nprivate final @android.annotation.Nullable java.lang.String[] mSplitNames\nprivate final @android.annotation.Nullable java.lang.String[] mUsesSplitNames\nprivate final @android.annotation.Nullable java.lang.String[] mConfigForSplit\nprivate final  int mVersionCodeMajor\nprivate final  int mVersionCode\nprivate final  int mTargetSdk\nprivate final  int mBaseRevisionCode\nprivate final @android.annotation.Nullable int[] mSplitRevisionCodes\nprivate final  int mInstallLocation\nprivate final @android.annotation.NonNull android.content.pm.VerifierInfo[] mVerifiers\nprivate final @android.annotation.Nullable boolean[] mIsFeatureSplits\nprivate final  boolean mIsolatedSplits\nprivate final  boolean mSplitRequired\nprivate final  boolean mCoreApp\nprivate final  boolean mDebuggable\nprivate final  boolean mMultiArch\nprivate final  boolean mUse32bitAbi\nprivate final  boolean mExtractNativeLibs\nprivate final  boolean mProfileableByShell\nprivate final  boolean mUseEmbeddedDex\npublic  java.util.List<java.lang.String> getAllApkPaths()\npublic  long getLongVersionCode()\nclass PackageLite extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genConstDefs=false)")
            inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.lang.String mPath\nprivate final @android.annotation.NonNull java.lang.String mBaseApkPath\nprivate final @android.annotation.Nullable java.lang.String[] mSplitApkPaths\nprivate final @android.annotation.Nullable java.lang.String[] mSplitNames\nprivate final @android.annotation.Nullable java.lang.String[] mUsesSplitNames\nprivate final @android.annotation.Nullable java.lang.String[] mConfigForSplit\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String> mBaseRequiredSplitTypes\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String>[] mRequiredSplitTypes\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String>[] mSplitTypes\nprivate final  int mVersionCodeMajor\nprivate final  int mVersionCode\nprivate final  int mTargetSdk\nprivate final  int mBaseRevisionCode\nprivate final @android.annotation.Nullable int[] mSplitRevisionCodes\nprivate final  int mInstallLocation\nprivate final @android.annotation.NonNull android.content.pm.VerifierInfo[] mVerifiers\nprivate final @android.annotation.Nullable boolean[] mIsFeatureSplits\nprivate final  boolean mIsolatedSplits\nprivate final  boolean mSplitRequired\nprivate final  boolean mCoreApp\nprivate final  boolean mDebuggable\nprivate final  boolean mMultiArch\nprivate final  boolean mUse32bitAbi\nprivate final  boolean mExtractNativeLibs\nprivate final  boolean mProfileableByShell\nprivate final  boolean mUseEmbeddedDex\npublic  java.util.List<java.lang.String> getAllApkPaths()\npublic  long getLongVersionCode()\nprivate  boolean hasAnyRequiredSplitTypes()\nclass PackageLite extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genConstDefs=false)")
    @Deprecated
    private void __metadata() {}

+1 −1
Original line number Diff line number Diff line
@@ -234,7 +234,7 @@ public class ParsingPackageUtils {
     * For those names would be used as a part of the file name. Limits size to 223 and reserves 32
     * for the OS.
     */
    private static final int MAX_FILE_NAME_SIZE = 223;
    static final int MAX_FILE_NAME_SIZE = 223;

    /**
     * @see #parseDefault(ParseInput, File, int, List, boolean)
Loading