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

Commit 4e54b521 authored by Victor Hsieh's avatar Victor Hsieh
Browse files

Flip default of extractNativeLibs if targets Q+

Test: Local in-progress CTS
Test: CtsDynamicLinkerTestCases
Bug: 112037137
Change-Id: I41289ec6bdfff13ef4aa551bf0a98bad73c9371e
parent a4ee2766
Loading
Loading
Loading
Loading
+156 −56
Original line number Diff line number Diff line
@@ -1621,7 +1621,7 @@ public class PackageParser {
            }

            final AttributeSet attrs = parser;
            return parseApkLite(apkPath, parser, attrs, signingDetails);
            return parseApkLite(apkPath, parser, attrs, signingDetails, flags);

        } catch (XmlPullParserException | IOException | RuntimeException e) {
            Slog.w(TAG, "Failed to parse " + apkPath, e);
@@ -1708,7 +1708,7 @@ public class PackageParser {
    }

    private static ApkLite parseApkLite(String codePath, XmlPullParser parser, AttributeSet attrs,
            SigningDetails signingDetails)
            SigningDetails signingDetails, int flags)
            throws IOException, XmlPullParserException, PackageParserException {
        final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs);

@@ -1716,11 +1716,12 @@ public class PackageParser {
        int versionCode = 0;
        int versionCodeMajor = 0;
        int revisionCode = 0;
        int targetSdkVersion = 0;
        boolean coreApp = false;
        boolean debuggable = false;
        boolean multiArch = false;
        boolean use32bitAbi = false;
        boolean extractNativeLibs = true;
        Boolean extractNativeLibsProvided = null;
        boolean isolatedSplits = false;
        boolean isFeatureSplit = false;
        boolean isSplitRequired = false;
@@ -1785,7 +1786,8 @@ public class PackageParser {
                        use32bitAbi = attrs.getAttributeBooleanValue(i, false);
                    }
                    if ("extractNativeLibs".equals(attr)) {
                        extractNativeLibs = attrs.getAttributeBooleanValue(i, true);
                        extractNativeLibsProvided = Boolean.valueOf(
                                attrs.getAttributeBooleanValue(i, true));
                    }
                    if ("preferCodeIntegrity".equals(attr)) {
                        preferCodeIntegrity = attrs.getAttributeBooleanValue(i, false);
@@ -1803,8 +1805,50 @@ public class PackageParser {
                            PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
                            "<uses-split> tag requires 'android:name' attribute");
                }
            } else if (TAG_USES_SDK.equals(parser.getName())) {
                final String[] errorMsg = new String[1];
                Pair<Integer, Integer> versions = deriveSdkVersions(new AbstractVersionsAccessor() {
                    @Override public String getMinSdkVersionCode() {
                        return getAttributeAsString("minSdkVersion");
                    }

                    @Override public int getMinSdkVersion() {
                        return getAttributeAsInt("minSdkVersion");
                    }

                    @Override public String getTargetSdkVersionCode() {
                        return getAttributeAsString("targetSdkVersion");
                    }

                    @Override public int getTargetSdkVersion() {
                        return getAttributeAsInt("targetSdkVersion");
                    }

                    private String getAttributeAsString(String name) {
                        return attrs.getAttributeValue(ANDROID_RESOURCES, name);
                    }

                    private int getAttributeAsInt(String name) {
                        try {
                            return attrs.getAttributeIntValue(ANDROID_RESOURCES, name, -1);
                        } catch (NumberFormatException e) {
                            return -1;
                        }
                    }
                }, flags, errorMsg);

                if (versions == null) {
                    throw new PackageParserException(
                            PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, errorMsg[0]);
                }

                targetSdkVersion = versions.second;
            }
        }

        final boolean extractNativeLibsDefault = targetSdkVersion < Build.VERSION_CODES.Q;
        final boolean extractNativeLibs = (extractNativeLibsProvided != null)
                ? extractNativeLibsProvided : extractNativeLibsDefault;

        if (preferCodeIntegrity && extractNativeLibs) {
            throw new PackageParserException(
@@ -2215,65 +2259,60 @@ public class PackageParser {

            } else if (tagName.equals(TAG_USES_SDK)) {
                if (SDK_VERSION > 0) {
                    sa = res.obtainAttributes(parser,
                            com.android.internal.R.styleable.AndroidManifestUsesSdk);
                    sa = res.obtainAttributes(parser, R.styleable.AndroidManifestUsesSdk);
                    final TypedArray saFinal = sa;
                    Pair<Integer, Integer> versions = deriveSdkVersions(
                            new AbstractVersionsAccessor() {
                                @Override public String getMinSdkVersionCode() {
                                    return getAttributeAsString(
                                            R.styleable.AndroidManifestUsesSdk_minSdkVersion);
                                }

                    int minVers = 1;
                    String minCode = null;
                    int targetVers = 0;
                    String targetCode = null;
                                @Override public int getMinSdkVersion() {
                                    return getAttributeAsInt(
                                            R.styleable.AndroidManifestUsesSdk_minSdkVersion);
                                }

                    TypedValue val = sa.peekValue(
                            com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
                    if (val != null) {
                        if (val.type == TypedValue.TYPE_STRING && val.string != null) {
                            minCode = val.string.toString();
                        } else {
                            // If it's not a string, it's an integer.
                            minVers = val.data;
                                @Override public String getTargetSdkVersionCode() {
                                    return getAttributeAsString(
                                            R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
                                }

                                @Override public int getTargetSdkVersion() {
                                    return getAttributeAsInt(
                                            R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
                                }

                    val = sa.peekValue(
                            com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
                    if (val != null) {
                        if (val.type == TypedValue.TYPE_STRING && val.string != null) {
                            targetCode = val.string.toString();
                            if (minCode == null) {
                                minCode = targetCode;
                                private String getAttributeAsString(int index) {
                                    TypedValue val = saFinal.peekValue(index);
                                    if (val != null && val.type == TypedValue.TYPE_STRING
                                            && val.string != null) {
                                        return val.string.toString();
                                    }
                        } else {
                                    return null;
                                }

                                private int getAttributeAsInt(int index) {
                                    TypedValue val = saFinal.peekValue(index);
                                    if (val != null && val.type != TypedValue.TYPE_STRING) {
                                        // If it's not a string, it's an integer.
                            targetVers = val.data;
                                        return val.data;
                                    }
                    } else {
                        targetVers = minVers;
                        targetCode = minCode;
                                    return -1;
                                }
                            }, flags, outError);

                    sa.recycle();

                    final int minSdkVersion = PackageParser.computeMinSdkVersion(minVers, minCode,
                            SDK_VERSION, SDK_CODENAMES, outError);
                    if (minSdkVersion < 0) {
                    if (versions == null) {
                        mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
                        return null;
                    }

                    boolean defaultToCurrentDevBranch = (flags & PARSE_FORCE_SDK) != 0;
                    final int targetSdkVersion = PackageParser.computeTargetSdkVersion(targetVers,
                            targetCode, SDK_CODENAMES, outError, defaultToCurrentDevBranch);
                    if (targetSdkVersion < 0) {
                        mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
                        return null;
                    }
                    pkg.applicationInfo.minSdkVersion = versions.first;
                    pkg.applicationInfo.targetSdkVersion = versions.second;

                    pkg.applicationInfo.minSdkVersion = minSdkVersion;
                    pkg.applicationInfo.targetSdkVersion = targetSdkVersion;
                    sa.recycle();
                }

                XmlUtils.skipCurrentTag(parser);

            } else if (tagName.equals(TAG_SUPPORT_SCREENS)) {
                sa = res.obtainAttributes(parser,
                        com.android.internal.R.styleable.AndroidManifestSupportsScreens);
@@ -2675,6 +2714,67 @@ public class PackageParser {
        return -1;
    }

    private interface AbstractVersionsAccessor {
        /** Returns minimum SDK version code string, or null if absent. */
        String getMinSdkVersionCode();

        /** Returns minimum SDK version code, or -1 if absent. */
        int getMinSdkVersion();

        /** Returns target SDK version code string, or null if absent. */
        String getTargetSdkVersionCode();

        /** Returns target SDK version code, or -1 if absent. */
        int getTargetSdkVersion();
    }

    private static @Nullable Pair<Integer, Integer> deriveSdkVersions(
            @NonNull AbstractVersionsAccessor accessor, int flags, String[] outError) {
        int minVers = 1;
        String minCode = null;
        int targetVers = 0;
        String targetCode = null;

        String code = accessor.getMinSdkVersionCode();
        int version = accessor.getMinSdkVersion();
        // Check integer first since code is almost never a null string (e.g. "28").
        if (version >= 0) {
            minVers = version;
        } else if (code != null) {
            minCode = code;
        }

        code = accessor.getTargetSdkVersionCode();
        version = accessor.getTargetSdkVersion();
        // Check integer first since code is almost never a null string (e.g. "28").
        if (version >= 0) {
            targetVers = version;
        } else if (code != null) {
            targetCode = code;
            if (minCode == null) {
                minCode = targetCode;
            }
        } else {
            targetVers = minVers;
            targetCode = minCode;
        }

        final int minSdkVersion = computeMinSdkVersion(minVers, minCode,
                SDK_VERSION, SDK_CODENAMES, outError);
        if (minSdkVersion < 0) {
            return null;
        }

        boolean defaultToCurrentDevBranch = (flags & PARSE_FORCE_SDK) != 0;
        final int targetSdkVersion = computeTargetSdkVersion(targetVers,
                targetCode, SDK_CODENAMES, outError, defaultToCurrentDevBranch);
        if (targetSdkVersion < 0) {
            return null;
        }

        return Pair.create(minSdkVersion, targetSdkVersion);
    }

    /**
     * Computes the minSdkVersion to use at runtime. If the package is not
     * compatible with this platform, populates {@code outError[0]} with an