Example usage for android.content.pm PackageManager INSTALL_PARSE_FAILED_MANIFEST_MALFORMED

List of usage examples for android.content.pm PackageManager INSTALL_PARSE_FAILED_MANIFEST_MALFORMED

Introduction

In this page you can find the example usage for android.content.pm PackageManager INSTALL_PARSE_FAILED_MANIFEST_MALFORMED.

Prototype

int INSTALL_PARSE_FAILED_MANIFEST_MALFORMED

To view the source code for android.content.pm PackageManager INSTALL_PARSE_FAILED_MANIFEST_MALFORMED.

Click Source Link

Document

Installation parse return code: this is passed in the PackageInstaller#EXTRA_LEGACY_STATUS if the parser encountered some structural problem in the manifest.

Usage

From source file:android.content.pm.PackageParser.java

/**
 * Parse the manifest of a <em>split APK</em>.
 * <p>//from w w  w. ja v  a  2  s.c om
 * Note that split APKs have many more restrictions on what they're capable
 * of doing, so many valid features of a base APK have been carefully
 * omitted here.
 */
private Package parseSplitApk(Package pkg, Resources res, XmlResourceParser parser, int flags, int splitIndex,
        String[] outError) throws XmlPullParserException, IOException, PackageParserException {
    AttributeSet attrs = parser;

    // We parsed manifest tag earlier; just skip past it
    parsePackageSplitNames(parser, attrs, flags);

    mParseInstrumentationArgs = null;
    mParseActivityArgs = null;
    mParseServiceArgs = null;
    mParseProviderArgs = null;

    int type;

    boolean foundApp = false;

    int outerDepth = parser.getDepth();
    while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
            && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
        if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
            continue;
        }

        String tagName = parser.getName();
        if (tagName.equals("application")) {
            if (foundApp) {
                if (RIGID_PARSER) {
                    outError[0] = "<manifest> has more than one <application>";
                    mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                    return null;
                } else {
                    Slog.w(TAG, "<manifest> has more than one <application>");
                    XmlUtils.skipCurrentTag(parser);
                    continue;
                }
            }

            foundApp = true;
            if (!parseSplitApplication(pkg, res, parser, attrs, flags, splitIndex, outError)) {
                return null;
            }

        } else if (RIGID_PARSER) {
            outError[0] = "Bad element under <manifest>: " + parser.getName();
            mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
            return null;

        } else {
            Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName() + " at " + mArchiveSourcePath
                    + " " + parser.getPositionDescription());
            XmlUtils.skipCurrentTag(parser);
            continue;
        }
    }

    if (!foundApp) {
        outError[0] = "<manifest> does not contain an <application>";
        mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
    }

    return pkg;
}

From source file:android.content.pm.PackageParser.java

/**
 * Parse the manifest of a <em>base APK</em>.
 * <p>//w  w w . j av  a 2 s .c  om
 * When adding new features, carefully consider if they should also be
 * supported by split APKs.
 */
private Package parseBaseApk(Resources res, XmlResourceParser parser, int flags, String[] outError)
        throws XmlPullParserException, IOException {
    final boolean trustedOverlay = (flags & PARSE_TRUSTED_OVERLAY) != 0;

    AttributeSet attrs = parser;

    mParseInstrumentationArgs = null;
    mParseActivityArgs = null;
    mParseServiceArgs = null;
    mParseProviderArgs = null;

    final String pkgName;
    final String splitName;
    try {
        Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs, flags);
        pkgName = packageSplit.first;
        splitName = packageSplit.second;
    } catch (PackageParserException e) {
        mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
        return null;
    }

    int type;

    if (!TextUtils.isEmpty(splitName)) {
        outError[0] = "Expected base APK, but found split " + splitName;
        mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
        return null;
    }

    final Package pkg = new Package(pkgName);
    boolean foundApp = false;

    TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifest);
    pkg.mVersionCode = pkg.applicationInfo.versionCode = sa
            .getInteger(com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
    pkg.baseRevisionCode = sa.getInteger(com.android.internal.R.styleable.AndroidManifest_revisionCode, 0);
    pkg.mVersionName = sa
            .getNonConfigurationString(com.android.internal.R.styleable.AndroidManifest_versionName, 0);
    if (pkg.mVersionName != null) {
        pkg.mVersionName = pkg.mVersionName.intern();
    }
    String str = sa.getNonConfigurationString(com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
    if (str != null && str.length() > 0) {
        String nameError = validateName(str, true, false);
        if (nameError != null && !"android".equals(pkgName)) {
            outError[0] = "<manifest> specifies bad sharedUserId name \"" + str + "\": " + nameError;
            mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
            return null;
        }
        pkg.mSharedUserId = str.intern();
        pkg.mSharedUserLabel = sa
                .getResourceId(com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
    }

    pkg.installLocation = sa.getInteger(com.android.internal.R.styleable.AndroidManifest_installLocation,
            PARSE_DEFAULT_INSTALL_LOCATION);
    pkg.applicationInfo.installLocation = pkg.installLocation;

    pkg.coreApp = attrs.getAttributeBooleanValue(null, "coreApp", false);

    sa.recycle();

    /* Set the global "forward lock" flag */
    if ((flags & PARSE_FORWARD_LOCK) != 0) {
        pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK;
    }

    /* Set the global "on SD card" flag */
    if ((flags & PARSE_EXTERNAL_STORAGE) != 0) {
        pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
    }

    // Resource boolean are -1, so 1 means we don't know the value.
    int supportsSmallScreens = 1;
    int supportsNormalScreens = 1;
    int supportsLargeScreens = 1;
    int supportsXLargeScreens = 1;
    int resizeable = 1;
    int anyDensity = 1;

    int outerDepth = parser.getDepth();
    while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
            && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
        if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
            continue;
        }

        String tagName = parser.getName();
        if (tagName.equals("application")) {
            if (foundApp) {
                if (RIGID_PARSER) {
                    outError[0] = "<manifest> has more than one <application>";
                    mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                    return null;
                } else {
                    Slog.w(TAG, "<manifest> has more than one <application>");
                    XmlUtils.skipCurrentTag(parser);
                    continue;
                }
            }

            foundApp = true;
            if (!parseBaseApplication(pkg, res, parser, attrs, flags, outError)) {
                return null;
            }
        } else if (tagName.equals("overlay")) {
            pkg.mTrustedOverlay = trustedOverlay;

            sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestResourceOverlay);
            pkg.mOverlayTarget = sa
                    .getString(com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage);
            pkg.mOverlayPriority = sa
                    .getInt(com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority, -1);
            sa.recycle();

            if (pkg.mOverlayTarget == null) {
                outError[0] = "<overlay> does not specify a target package";
                mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                return null;
            }
            if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) {
                outError[0] = "<overlay> priority must be between 0 and 9999";
                mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                return null;
            }
            XmlUtils.skipCurrentTag(parser);

        } else if (tagName.equals("key-sets")) {
            if (!parseKeySets(pkg, res, parser, attrs, outError)) {
                return null;
            }
        } else if (tagName.equals("permission-group")) {
            if (parsePermissionGroup(pkg, flags, res, parser, attrs, outError) == null) {
                return null;
            }
        } else if (tagName.equals("permission")) {
            if (parsePermission(pkg, res, parser, attrs, outError) == null) {
                return null;
            }
        } else if (tagName.equals("permission-tree")) {
            if (parsePermissionTree(pkg, res, parser, attrs, outError) == null) {
                return null;
            }
        } else if (tagName.equals("uses-permission")) {
            if (!parseUsesPermission(pkg, res, parser, attrs)) {
                return null;
            }
        } else if (tagName.equals("uses-permission-sdk-m") || tagName.equals("uses-permission-sdk-23")) {
            if (!parseUsesPermission(pkg, res, parser, attrs)) {
                return null;
            }
        } else if (tagName.equals("uses-configuration")) {
            ConfigurationInfo cPref = new ConfigurationInfo();
            sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestUsesConfiguration);
            cPref.reqTouchScreen = sa.getInt(
                    com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen,
                    Configuration.TOUCHSCREEN_UNDEFINED);
            cPref.reqKeyboardType = sa.getInt(
                    com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType,
                    Configuration.KEYBOARD_UNDEFINED);
            if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard,
                    false)) {
                cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
            }
            cPref.reqNavigation = sa.getInt(
                    com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation,
                    Configuration.NAVIGATION_UNDEFINED);
            if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav,
                    false)) {
                cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
            }
            sa.recycle();
            pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);

            XmlUtils.skipCurrentTag(parser);

        } else if (tagName.equals("uses-feature")) {
            FeatureInfo fi = parseUsesFeature(res, attrs);
            pkg.reqFeatures = ArrayUtils.add(pkg.reqFeatures, fi);

            if (fi.name == null) {
                ConfigurationInfo cPref = new ConfigurationInfo();
                cPref.reqGlEsVersion = fi.reqGlEsVersion;
                pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
            }

            XmlUtils.skipCurrentTag(parser);

        } else if (tagName.equals("feature-group")) {
            FeatureGroupInfo group = new FeatureGroupInfo();
            ArrayList<FeatureInfo> features = null;
            final int innerDepth = parser.getDepth();
            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                    && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
                    continue;
                }

                final String innerTagName = parser.getName();
                if (innerTagName.equals("uses-feature")) {
                    FeatureInfo featureInfo = parseUsesFeature(res, attrs);
                    // FeatureGroups are stricter and mandate that
                    // any <uses-feature> declared are mandatory.
                    featureInfo.flags |= FeatureInfo.FLAG_REQUIRED;
                    features = ArrayUtils.add(features, featureInfo);
                } else {
                    Slog.w(TAG, "Unknown element under <feature-group>: " + innerTagName + " at "
                            + mArchiveSourcePath + " " + parser.getPositionDescription());
                }
                XmlUtils.skipCurrentTag(parser);
            }

            if (features != null) {
                group.features = new FeatureInfo[features.size()];
                group.features = features.toArray(group.features);
            }
            pkg.featureGroups = ArrayUtils.add(pkg.featureGroups, group);

        } else if (tagName.equals("uses-sdk")) {
            if (SDK_VERSION > 0) {
                sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestUsesSdk);

                int minVers = 0;
                String minCode = null;
                int targetVers = 0;
                String targetCode = null;

                TypedValue val = sa
                        .peekValue(com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
                if (val != null) {
                    if (val.type == TypedValue.TYPE_STRING && val.string != null) {
                        targetCode = minCode = val.string.toString();
                    } else {
                        // If it's not a string, it's an integer.
                        targetVers = minVers = val.data;
                    }
                }

                val = sa.peekValue(com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
                if (val != null) {
                    if (val.type == TypedValue.TYPE_STRING && val.string != null) {
                        targetCode = minCode = val.string.toString();
                    } else {
                        // If it's not a string, it's an integer.
                        targetVers = val.data;
                    }
                }

                sa.recycle();

                if (minCode != null) {
                    boolean allowedCodename = false;
                    for (String codename : SDK_CODENAMES) {
                        if (minCode.equals(codename)) {
                            allowedCodename = true;
                            break;
                        }
                    }
                    if (!allowedCodename) {
                        if (SDK_CODENAMES.length > 0) {
                            outError[0] = "Requires development platform " + minCode
                                    + " (current platform is any of " + Arrays.toString(SDK_CODENAMES) + ")";
                        } else {
                            outError[0] = "Requires development platform " + minCode
                                    + " but this is a release platform.";
                        }
                        mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
                        return null;
                    }
                } else if (minVers > SDK_VERSION) {
                    outError[0] = "Requires newer sdk version #" + minVers + " (current version is #"
                            + SDK_VERSION + ")";
                    mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
                    return null;
                }

                if (targetCode != null) {
                    boolean allowedCodename = false;
                    for (String codename : SDK_CODENAMES) {
                        if (targetCode.equals(codename)) {
                            allowedCodename = true;
                            break;
                        }
                    }
                    if (!allowedCodename) {
                        if (SDK_CODENAMES.length > 0) {
                            outError[0] = "Requires development platform " + targetCode
                                    + " (current platform is any of " + Arrays.toString(SDK_CODENAMES) + ")";
                        } else {
                            outError[0] = "Requires development platform " + targetCode
                                    + " but this is a release platform.";
                        }
                        mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
                        return null;
                    }
                    // If the code matches, it definitely targets this SDK.
                    pkg.applicationInfo.targetSdkVersion = android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
                } else {
                    pkg.applicationInfo.targetSdkVersion = targetVers;
                }
            }

            XmlUtils.skipCurrentTag(parser);

        } else if (tagName.equals("supports-screens")) {
            sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestSupportsScreens);

            pkg.applicationInfo.requiresSmallestWidthDp = sa.getInteger(
                    com.android.internal.R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp, 0);
            pkg.applicationInfo.compatibleWidthLimitDp = sa.getInteger(
                    com.android.internal.R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp, 0);
            pkg.applicationInfo.largestWidthLimitDp = sa.getInteger(
                    com.android.internal.R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp, 0);

            // This is a trick to get a boolean and still able to detect
            // if a value was actually set.
            supportsSmallScreens = sa.getInteger(
                    com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens,
                    supportsSmallScreens);
            supportsNormalScreens = sa.getInteger(
                    com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens,
                    supportsNormalScreens);
            supportsLargeScreens = sa.getInteger(
                    com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens,
                    supportsLargeScreens);
            supportsXLargeScreens = sa.getInteger(
                    com.android.internal.R.styleable.AndroidManifestSupportsScreens_xlargeScreens,
                    supportsXLargeScreens);
            resizeable = sa.getInteger(
                    com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable, resizeable);
            anyDensity = sa.getInteger(
                    com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity, anyDensity);

            sa.recycle();

            XmlUtils.skipCurrentTag(parser);

        } else if (tagName.equals("protected-broadcast")) {
            sa = res.obtainAttributes(attrs,
                    com.android.internal.R.styleable.AndroidManifestProtectedBroadcast);

            // Note: don't allow this value to be a reference to a resource
            // that may change.
            String name = sa.getNonResourceString(
                    com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name);

            sa.recycle();

            if (name != null && (flags & PARSE_IS_SYSTEM) != 0) {
                if (pkg.protectedBroadcasts == null) {
                    pkg.protectedBroadcasts = new ArrayList<String>();
                }
                if (!pkg.protectedBroadcasts.contains(name)) {
                    pkg.protectedBroadcasts.add(name.intern());
                }
            }

            XmlUtils.skipCurrentTag(parser);

        } else if (tagName.equals("instrumentation")) {
            if (parseInstrumentation(pkg, res, parser, attrs, outError) == null) {
                return null;
            }

        } else if (tagName.equals("original-package")) {
            sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestOriginalPackage);

            String orig = sa.getNonConfigurationString(
                    com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
            if (!pkg.packageName.equals(orig)) {
                if (pkg.mOriginalPackages == null) {
                    pkg.mOriginalPackages = new ArrayList<String>();
                    pkg.mRealPackage = pkg.packageName;
                }
                pkg.mOriginalPackages.add(orig);
            }

            sa.recycle();

            XmlUtils.skipCurrentTag(parser);

        } else if (tagName.equals("adopt-permissions")) {
            sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestOriginalPackage);

            String name = sa.getNonConfigurationString(
                    com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);

            sa.recycle();

            if (name != null) {
                if (pkg.mAdoptPermissions == null) {
                    pkg.mAdoptPermissions = new ArrayList<String>();
                }
                pkg.mAdoptPermissions.add(name);
            }

            XmlUtils.skipCurrentTag(parser);

        } else if (tagName.equals("uses-gl-texture")) {
            // Just skip this tag
            XmlUtils.skipCurrentTag(parser);
            continue;

        } else if (tagName.equals("compatible-screens")) {
            // Just skip this tag
            XmlUtils.skipCurrentTag(parser);
            continue;
        } else if (tagName.equals("supports-input")) {
            XmlUtils.skipCurrentTag(parser);
            continue;

        } else if (tagName.equals("eat-comment")) {
            // Just skip this tag
            XmlUtils.skipCurrentTag(parser);
            continue;

        } else if (RIGID_PARSER) {
            outError[0] = "Bad element under <manifest>: " + parser.getName();
            mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
            return null;

        } else {
            Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName() + " at " + mArchiveSourcePath
                    + " " + parser.getPositionDescription());
            XmlUtils.skipCurrentTag(parser);
            continue;
        }
    }

    if (!foundApp && pkg.instrumentation.size() == 0) {
        outError[0] = "<manifest> does not contain an <application> or <instrumentation>";
        mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
    }

    final int NP = PackageParser.NEW_PERMISSIONS.length;
    StringBuilder implicitPerms = null;
    for (int ip = 0; ip < NP; ip++) {
        final PackageParser.NewPermissionInfo npi = PackageParser.NEW_PERMISSIONS[ip];
        if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) {
            break;
        }
        if (!pkg.requestedPermissions.contains(npi.name)) {
            if (implicitPerms == null) {
                implicitPerms = new StringBuilder(128);
                implicitPerms.append(pkg.packageName);
                implicitPerms.append(": compat added ");
            } else {
                implicitPerms.append(' ');
            }
            implicitPerms.append(npi.name);
            pkg.requestedPermissions.add(npi.name);
        }
    }
    if (implicitPerms != null) {
        Slog.i(TAG, implicitPerms.toString());
    }

    final int NS = PackageParser.SPLIT_PERMISSIONS.length;
    for (int is = 0; is < NS; is++) {
        final PackageParser.SplitPermissionInfo spi = PackageParser.SPLIT_PERMISSIONS[is];
        if (pkg.applicationInfo.targetSdkVersion >= spi.targetSdk
                || !pkg.requestedPermissions.contains(spi.rootPerm)) {
            continue;
        }
        for (int in = 0; in < spi.newPerms.length; in++) {
            final String perm = spi.newPerms[in];
            if (!pkg.requestedPermissions.contains(perm)) {
                pkg.requestedPermissions.add(perm);
            }
        }
    }

    if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
            && pkg.applicationInfo.targetSdkVersion >= android.os.Build.VERSION_CODES.DONUT)) {
        pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
    }
    if (supportsNormalScreens != 0) {
        pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
    }
    if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
            && pkg.applicationInfo.targetSdkVersion >= android.os.Build.VERSION_CODES.DONUT)) {
        pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
    }
    if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0
            && pkg.applicationInfo.targetSdkVersion >= android.os.Build.VERSION_CODES.GINGERBREAD)) {
        pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
    }
    if (resizeable < 0 || (resizeable > 0
            && pkg.applicationInfo.targetSdkVersion >= android.os.Build.VERSION_CODES.DONUT)) {
        pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
    }
    if (anyDensity < 0 || (anyDensity > 0
            && pkg.applicationInfo.targetSdkVersion >= android.os.Build.VERSION_CODES.DONUT)) {
        pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
    }

    return pkg;
}

From source file:android.content.pm.PackageParser.java

private boolean parseKeySets(Package owner, Resources res, XmlPullParser parser, AttributeSet attrs,
        String[] outError) throws XmlPullParserException, IOException {
    // we've encountered the 'key-sets' tag
    // all the keys and keysets that we want must be defined here
    // so we're going to iterate over the parser and pull out the things we want
    int outerDepth = parser.getDepth();
    int currentKeySetDepth = -1;
    int type;/*from   w  ww .j av a  2 s.  co m*/
    String currentKeySet = null;
    ArrayMap<String, PublicKey> publicKeys = new ArrayMap<String, PublicKey>();
    ArraySet<String> upgradeKeySets = new ArraySet<String>();
    ArrayMap<String, ArraySet<String>> definedKeySets = new ArrayMap<String, ArraySet<String>>();
    ArraySet<String> improperKeySets = new ArraySet<String>();
    while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
            && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
        if (type == XmlPullParser.END_TAG) {
            if (parser.getDepth() == currentKeySetDepth) {
                currentKeySet = null;
                currentKeySetDepth = -1;
            }
            continue;
        }
        String tagName = parser.getName();
        if (tagName.equals("key-set")) {
            if (currentKeySet != null) {
                outError[0] = "Improperly nested 'key-set' tag at " + parser.getPositionDescription();
                mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                return false;
            }
            final TypedArray sa = res.obtainAttributes(attrs,
                    com.android.internal.R.styleable.AndroidManifestKeySet);
            final String keysetName = sa
                    .getNonResourceString(com.android.internal.R.styleable.AndroidManifestKeySet_name);
            definedKeySets.put(keysetName, new ArraySet<String>());
            currentKeySet = keysetName;
            currentKeySetDepth = parser.getDepth();
            sa.recycle();
        } else if (tagName.equals("public-key")) {
            if (currentKeySet == null) {
                outError[0] = "Improperly nested 'key-set' tag at " + parser.getPositionDescription();
                mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                return false;
            }
            final TypedArray sa = res.obtainAttributes(attrs,
                    com.android.internal.R.styleable.AndroidManifestPublicKey);
            final String publicKeyName = sa
                    .getNonResourceString(com.android.internal.R.styleable.AndroidManifestPublicKey_name);
            final String encodedKey = sa
                    .getNonResourceString(com.android.internal.R.styleable.AndroidManifestPublicKey_value);
            if (encodedKey == null && publicKeys.get(publicKeyName) == null) {
                outError[0] = "'public-key' " + publicKeyName + " must define a public-key value"
                        + " on first use at " + parser.getPositionDescription();
                mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                sa.recycle();
                return false;
            } else if (encodedKey != null) {
                PublicKey currentKey = parsePublicKey(encodedKey);
                if (currentKey == null) {
                    Slog.w(TAG,
                            "No recognized valid key in 'public-key' tag at " + parser.getPositionDescription()
                                    + " key-set " + currentKeySet
                                    + " will not be added to the package's defined key-sets.");
                    sa.recycle();
                    improperKeySets.add(currentKeySet);
                    XmlUtils.skipCurrentTag(parser);
                    continue;
                }
                if (publicKeys.get(publicKeyName) == null || publicKeys.get(publicKeyName).equals(currentKey)) {

                    /* public-key first definition, or matches old definition */
                    publicKeys.put(publicKeyName, currentKey);
                } else {
                    outError[0] = "Value of 'public-key' " + publicKeyName
                            + " conflicts with previously defined value at " + parser.getPositionDescription();
                    mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                    sa.recycle();
                    return false;
                }
            }
            definedKeySets.get(currentKeySet).add(publicKeyName);
            sa.recycle();
            XmlUtils.skipCurrentTag(parser);
        } else if (tagName.equals("upgrade-key-set")) {
            final TypedArray sa = res.obtainAttributes(attrs,
                    com.android.internal.R.styleable.AndroidManifestUpgradeKeySet);
            String name = sa
                    .getNonResourceString(com.android.internal.R.styleable.AndroidManifestUpgradeKeySet_name);
            upgradeKeySets.add(name);
            sa.recycle();
            XmlUtils.skipCurrentTag(parser);
        } else if (RIGID_PARSER) {
            outError[0] = "Bad element under <key-sets>: " + parser.getName() + " at " + mArchiveSourcePath
                    + " " + parser.getPositionDescription();
            mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
            return false;
        } else {
            Slog.w(TAG, "Unknown element under <key-sets>: " + parser.getName() + " at " + mArchiveSourcePath
                    + " " + parser.getPositionDescription());
            XmlUtils.skipCurrentTag(parser);
            continue;
        }
    }
    Set<String> publicKeyNames = publicKeys.keySet();
    if (publicKeyNames.removeAll(definedKeySets.keySet())) {
        outError[0] = "Package" + owner.packageName + " AndroidManifext.xml "
                + "'key-set' and 'public-key' names must be distinct.";
        mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
        return false;
    }
    owner.mKeySetMapping = new ArrayMap<String, ArraySet<PublicKey>>();
    for (ArrayMap.Entry<String, ArraySet<String>> e : definedKeySets.entrySet()) {
        final String keySetName = e.getKey();
        if (e.getValue().size() == 0) {
            Slog.w(TAG,
                    "Package" + owner.packageName + " AndroidManifext.xml " + "'key-set' " + keySetName
                            + " has no valid associated 'public-key'."
                            + " Not including in package's defined key-sets.");
            continue;
        } else if (improperKeySets.contains(keySetName)) {
            Slog.w(TAG,
                    "Package" + owner.packageName + " AndroidManifext.xml " + "'key-set' " + keySetName
                            + " contained improper 'public-key'"
                            + " tags. Not including in package's defined key-sets.");
            continue;
        }
        owner.mKeySetMapping.put(keySetName, new ArraySet<PublicKey>());
        for (String s : e.getValue()) {
            owner.mKeySetMapping.get(keySetName).add(publicKeys.get(s));
        }
    }
    if (owner.mKeySetMapping.keySet().containsAll(upgradeKeySets)) {
        owner.mUpgradeKeySets = upgradeKeySets;
    } else {
        outError[0] = "Package" + owner.packageName + " AndroidManifext.xml "
                + "does not define all 'upgrade-key-set's .";
        mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
        return false;
    }
    return true;
}

From source file:android.content.pm.PackageParser.java

private PermissionGroup parsePermissionGroup(Package owner, int flags, Resources res, XmlPullParser parser,
        AttributeSet attrs, String[] outError) throws XmlPullParserException, IOException {
    PermissionGroup perm = new PermissionGroup(owner);

    TypedArray sa = res.obtainAttributes(attrs,
            com.android.internal.R.styleable.AndroidManifestPermissionGroup);

    if (!parsePackageItemInfo(owner, perm.info, outError, "<permission-group>", sa,
            com.android.internal.R.styleable.AndroidManifestPermissionGroup_name,
            com.android.internal.R.styleable.AndroidManifestPermissionGroup_label,
            com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon,
            com.android.internal.R.styleable.AndroidManifestPermissionGroup_logo,
            com.android.internal.R.styleable.AndroidManifestPermissionGroup_banner)) {
        sa.recycle();//from  ww  w .  j  a  va2 s .com
        mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
        return null;
    }

    perm.info.descriptionRes = sa
            .getResourceId(com.android.internal.R.styleable.AndroidManifestPermissionGroup_description, 0);
    perm.info.flags = sa
            .getInt(com.android.internal.R.styleable.AndroidManifestPermissionGroup_permissionGroupFlags, 0);
    perm.info.priority = sa.getInt(com.android.internal.R.styleable.AndroidManifestPermissionGroup_priority, 0);
    if (perm.info.priority > 0 && (flags & PARSE_IS_SYSTEM) == 0) {
        perm.info.priority = 0;
    }

    sa.recycle();

    if (!parseAllMetaData(res, parser, attrs, "<permission-group>", perm, outError)) {
        mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
        return null;
    }

    owner.permissionGroups.add(perm);

    return perm;
}

From source file:android.content.pm.PackageParser.java

private Permission parsePermission(Package owner, Resources res, XmlPullParser parser, AttributeSet attrs,
        String[] outError) throws XmlPullParserException, IOException {
    Permission perm = new Permission(owner);

    TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestPermission);

    if (!parsePackageItemInfo(owner, perm.info, outError, "<permission>", sa,
            com.android.internal.R.styleable.AndroidManifestPermission_name,
            com.android.internal.R.styleable.AndroidManifestPermission_label,
            com.android.internal.R.styleable.AndroidManifestPermission_icon,
            com.android.internal.R.styleable.AndroidManifestPermission_logo,
            com.android.internal.R.styleable.AndroidManifestPermission_banner)) {
        sa.recycle();/*from www  .  ja  v  a2  s  . c o  m*/
        mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
        return null;
    }

    // Note: don't allow this value to be a reference to a resource
    // that may change.
    perm.info.group = sa
            .getNonResourceString(com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup);
    if (perm.info.group != null) {
        perm.info.group = perm.info.group.intern();
    }

    perm.info.descriptionRes = sa
            .getResourceId(com.android.internal.R.styleable.AndroidManifestPermission_description, 0);

    perm.info.protectionLevel = sa.getInt(
            com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel,
            PermissionInfo.PROTECTION_NORMAL);

    perm.info.flags = sa.getInt(com.android.internal.R.styleable.AndroidManifestPermission_permissionFlags, 0);

    sa.recycle();

    if (perm.info.protectionLevel == -1) {
        outError[0] = "<permission> does not specify protectionLevel";
        mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
        return null;
    }

    perm.info.protectionLevel = PermissionInfo.fixProtectionLevel(perm.info.protectionLevel);

    if ((perm.info.protectionLevel & PermissionInfo.PROTECTION_MASK_FLAGS) != 0) {
        if ((perm.info.protectionLevel
                & PermissionInfo.PROTECTION_MASK_BASE) != PermissionInfo.PROTECTION_SIGNATURE) {
            outError[0] = "<permission>  protectionLevel specifies a flag but is "
                    + "not based on signature type";
            mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
            return null;
        }
    }

    if (!parseAllMetaData(res, parser, attrs, "<permission>", perm, outError)) {
        mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
        return null;
    }

    owner.permissions.add(perm);

    return perm;
}

From source file:android.content.pm.PackageParser.java

private Permission parsePermissionTree(Package owner, Resources res, XmlPullParser parser, AttributeSet attrs,
        String[] outError) throws XmlPullParserException, IOException {
    Permission perm = new Permission(owner);

    TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestPermissionTree);

    if (!parsePackageItemInfo(owner, perm.info, outError, "<permission-tree>", sa,
            com.android.internal.R.styleable.AndroidManifestPermissionTree_name,
            com.android.internal.R.styleable.AndroidManifestPermissionTree_label,
            com.android.internal.R.styleable.AndroidManifestPermissionTree_icon,
            com.android.internal.R.styleable.AndroidManifestPermissionTree_logo,
            com.android.internal.R.styleable.AndroidManifestPermissionTree_banner)) {
        sa.recycle();// ww w  . j  a  v a2  s  .c o m
        mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
        return null;
    }

    sa.recycle();

    int index = perm.info.name.indexOf('.');
    if (index > 0) {
        index = perm.info.name.indexOf('.', index + 1);
    }
    if (index < 0) {
        outError[0] = "<permission-tree> name has less than three segments: " + perm.info.name;
        mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
        return null;
    }

    perm.info.descriptionRes = 0;
    perm.info.protectionLevel = PermissionInfo.PROTECTION_NORMAL;
    perm.tree = true;

    if (!parseAllMetaData(res, parser, attrs, "<permission-tree>", perm, outError)) {
        mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
        return null;
    }

    owner.permissions.add(perm);

    return perm;
}

From source file:android.content.pm.PackageParser.java

private Instrumentation parseInstrumentation(Package owner, Resources res, XmlPullParser parser,
        AttributeSet attrs, String[] outError) throws XmlPullParserException, IOException {
    TypedArray sa = res.obtainAttributes(attrs,
            com.android.internal.R.styleable.AndroidManifestInstrumentation);

    if (mParseInstrumentationArgs == null) {
        mParseInstrumentationArgs = new ParsePackageItemArgs(owner, outError,
                com.android.internal.R.styleable.AndroidManifestInstrumentation_name,
                com.android.internal.R.styleable.AndroidManifestInstrumentation_label,
                com.android.internal.R.styleable.AndroidManifestInstrumentation_icon,
                com.android.internal.R.styleable.AndroidManifestInstrumentation_logo,
                com.android.internal.R.styleable.AndroidManifestInstrumentation_banner);
        mParseInstrumentationArgs.tag = "<instrumentation>";
    }//from w w  w . j a  v  a2s  . c  om

    mParseInstrumentationArgs.sa = sa;

    Instrumentation a = new Instrumentation(mParseInstrumentationArgs, new InstrumentationInfo());
    if (outError[0] != null) {
        sa.recycle();
        mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
        return null;
    }

    String str;
    // Note: don't allow this value to be a reference to a resource
    // that may change.
    str = sa.getNonResourceString(
            com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage);
    a.info.targetPackage = str != null ? str.intern() : null;

    a.info.handleProfiling = sa
            .getBoolean(com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling, false);

    a.info.functionalTest = sa
            .getBoolean(com.android.internal.R.styleable.AndroidManifestInstrumentation_functionalTest, false);

    sa.recycle();

    if (a.info.targetPackage == null) {
        outError[0] = "<instrumentation> does not specify targetPackage";
        mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
        return null;
    }

    if (!parseAllMetaData(res, parser, attrs, "<instrumentation>", a, outError)) {
        mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
        return null;
    }

    owner.instrumentation.add(a);

    return a;
}

From source file:android.content.pm.PackageParser.java

/**
 * Parse the {@code application} XML tree at the current parse location in a
 * <em>base APK</em> manifest.
 * <p>/*w ww  . j  a v  a  2 s  .  c o m*/
 * When adding new features, carefully consider if they should also be
 * supported by split APKs.
 */
private boolean parseBaseApplication(Package owner, Resources res, XmlPullParser parser, AttributeSet attrs,
        int flags, String[] outError) throws XmlPullParserException, IOException {
    final ApplicationInfo ai = owner.applicationInfo;
    final String pkgName = owner.applicationInfo.packageName;

    TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestApplication);

    String name = sa.getNonConfigurationString(com.android.internal.R.styleable.AndroidManifestApplication_name,
            0);
    if (name != null) {
        ai.className = buildClassName(pkgName, name, outError);
        if (ai.className == null) {
            sa.recycle();
            mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
            return false;
        }
    }

    String manageSpaceActivity = sa.getNonConfigurationString(
            com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity,
            Configuration.NATIVE_CONFIG_VERSION);
    if (manageSpaceActivity != null) {
        ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity, outError);
    }

    boolean allowBackup = sa.getBoolean(com.android.internal.R.styleable.AndroidManifestApplication_allowBackup,
            true);
    if (allowBackup) {
        ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;

        // backupAgent, killAfterRestore, fullBackupContent and restoreAnyVersion are only
        // relevant if backup is possible for the given application.
        String backupAgent = sa.getNonConfigurationString(
                com.android.internal.R.styleable.AndroidManifestApplication_backupAgent,
                Configuration.NATIVE_CONFIG_VERSION);
        if (backupAgent != null) {
            ai.backupAgentName = buildClassName(pkgName, backupAgent, outError);
            if (DEBUG_BACKUP) {
                Slog.v(TAG,
                        "android:backupAgent = " + ai.backupAgentName + " from " + pkgName + "+" + backupAgent);
            }

            if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifestApplication_killAfterRestore,
                    true)) {
                ai.flags |= ApplicationInfo.FLAG_KILL_AFTER_RESTORE;
            }
            if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifestApplication_restoreAnyVersion,
                    false)) {
                ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
            }
            if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifestApplication_fullBackupOnly,
                    false)) {
                ai.flags |= ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
            }
        }

        TypedValue v = sa
                .peekValue(com.android.internal.R.styleable.AndroidManifestApplication_fullBackupContent);
        if (v != null && (ai.fullBackupContent = v.resourceId) == 0) {
            if (DEBUG_BACKUP) {
                Slog.v(TAG, "fullBackupContent specified as boolean=" + (v.data == 0 ? "false" : "true"));
            }
            // "false" => -1, "true" => 0
            ai.fullBackupContent = (v.data == 0 ? -1 : 0);
        }
        if (DEBUG_BACKUP) {
            Slog.v(TAG, "fullBackupContent=" + ai.fullBackupContent + " for " + pkgName);
        }
    }

    TypedValue v = sa.peekValue(com.android.internal.R.styleable.AndroidManifestApplication_label);
    if (v != null && (ai.labelRes = v.resourceId) == 0) {
        ai.nonLocalizedLabel = v.coerceToString();
    }

    ai.icon = sa.getResourceId(com.android.internal.R.styleable.AndroidManifestApplication_icon, 0);
    ai.logo = sa.getResourceId(com.android.internal.R.styleable.AndroidManifestApplication_logo, 0);
    ai.banner = sa.getResourceId(com.android.internal.R.styleable.AndroidManifestApplication_banner, 0);
    ai.theme = sa.getResourceId(com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
    ai.descriptionRes = sa
            .getResourceId(com.android.internal.R.styleable.AndroidManifestApplication_description, 0);

    if ((flags & PARSE_IS_SYSTEM) != 0) {
        if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifestApplication_persistent, false)) {
            ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
        }
    }

    if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifestApplication_requiredForAllUsers, false)) {
        owner.mRequiredForAllUsers = true;
    }

    String restrictedAccountType = sa
            .getString(com.android.internal.R.styleable.AndroidManifestApplication_restrictedAccountType);
    if (restrictedAccountType != null && restrictedAccountType.length() > 0) {
        owner.mRestrictedAccountType = restrictedAccountType;
    }

    String requiredAccountType = sa
            .getString(com.android.internal.R.styleable.AndroidManifestApplication_requiredAccountType);
    if (requiredAccountType != null && requiredAccountType.length() > 0) {
        owner.mRequiredAccountType = requiredAccountType;
    }

    if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifestApplication_debuggable, false)) {
        ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE;
    }

    if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifestApplication_vmSafeMode, false)) {
        ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE;
    }

    owner.baseHardwareAccelerated = sa.getBoolean(
            com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
            owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
    if (owner.baseHardwareAccelerated) {
        ai.flags |= ApplicationInfo.FLAG_HARDWARE_ACCELERATED;
    }

    if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifestApplication_hasCode, true)) {
        ai.flags |= ApplicationInfo.FLAG_HAS_CODE;
    }

    if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting,
            false)) {
        ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING;
    }

    if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData, true)) {
        ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
    }

    if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifestApplication_testOnly, false)) {
        ai.flags |= ApplicationInfo.FLAG_TEST_ONLY;
    }

    if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifestApplication_largeHeap, false)) {
        ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
    }

    if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifestApplication_usesCleartextTraffic, true)) {
        ai.flags |= ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC;
    }

    if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifestApplication_supportsRtl,
            false /* default is no RTL support*/)) {
        ai.flags |= ApplicationInfo.FLAG_SUPPORTS_RTL;
    }

    if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifestApplication_multiArch, false)) {
        ai.flags |= ApplicationInfo.FLAG_MULTIARCH;
    }

    if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs, true)) {
        ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
    }

    String str;
    str = sa.getNonConfigurationString(com.android.internal.R.styleable.AndroidManifestApplication_permission,
            0);
    ai.permission = (str != null && str.length() > 0) ? str.intern() : null;

    if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
        str = sa.getNonConfigurationString(
                com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity,
                Configuration.NATIVE_CONFIG_VERSION);
    } else {
        // Some older apps have been seen to use a resource reference
        // here that on older builds was ignored (with a warning).  We
        // need to continue to do this for them so they don't break.
        str = sa.getNonResourceString(com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity);
    }
    ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName, str, outError);

    if (outError[0] == null) {
        CharSequence pname;
        if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
            pname = sa.getNonConfigurationString(
                    com.android.internal.R.styleable.AndroidManifestApplication_process,
                    Configuration.NATIVE_CONFIG_VERSION);
        } else {
            // Some older apps have been seen to use a resource reference
            // here that on older builds was ignored (with a warning).  We
            // need to continue to do this for them so they don't break.
            pname = sa
                    .getNonResourceString(com.android.internal.R.styleable.AndroidManifestApplication_process);
        }
        ai.processName = buildProcessName(ai.packageName, null, pname, flags, mSeparateProcesses, outError);

        ai.enabled = sa.getBoolean(com.android.internal.R.styleable.AndroidManifestApplication_enabled, true);

        if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifestApplication_isGame, false)) {
            ai.flags |= ApplicationInfo.FLAG_IS_GAME;
        }

        if (false) {
            if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifestApplication_cantSaveState,
                    false)) {
                ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE;

                // A heavy-weight application can not be in a custom process.
                // We can do direct compare because we intern all strings.
                if (ai.processName != null && ai.processName != ai.packageName) {
                    outError[0] = "cantSaveState applications can not use custom processes";
                }
            }
        }
    }

    ai.uiOptions = sa.getInt(com.android.internal.R.styleable.AndroidManifestApplication_uiOptions, 0);

    sa.recycle();

    if (outError[0] != null) {
        mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
        return false;
    }

    final int innerDepth = parser.getDepth();
    int type;
    while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
            && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
        if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
            continue;
        }

        String tagName = parser.getName();
        if (tagName.equals("activity")) {
            Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false,
                    owner.baseHardwareAccelerated);
            if (a == null) {
                mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                return false;
            }

            owner.activities.add(a);

        } else if (tagName.equals("receiver")) {
            Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true, false);
            if (a == null) {
                mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                return false;
            }

            owner.receivers.add(a);

        } else if (tagName.equals("service")) {
            Service s = parseService(owner, res, parser, attrs, flags, outError);
            if (s == null) {
                mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                return false;
            }

            owner.services.add(s);

        } else if (tagName.equals("provider")) {
            Provider p = parseProvider(owner, res, parser, attrs, flags, outError);
            if (p == null) {
                mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                return false;
            }

            owner.providers.add(p);

        } else if (tagName.equals("activity-alias")) {
            Activity a = parseActivityAlias(owner, res, parser, attrs, flags, outError);
            if (a == null) {
                mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                return false;
            }

            owner.activities.add(a);

        } else if (parser.getName().equals("meta-data")) {
            // note: application meta-data is stored off to the side, so it can
            // remain null in the primary copy (we like to avoid extra copies because
            // it can be large)
            if ((owner.mAppMetaData = parseMetaData(res, parser, attrs, owner.mAppMetaData,
                    outError)) == null) {
                mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                return false;
            }

        } else if (tagName.equals("library")) {
            sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestLibrary);

            // Note: don't allow this value to be a reference to a resource
            // that may change.
            String lname = sa
                    .getNonResourceString(com.android.internal.R.styleable.AndroidManifestLibrary_name);

            sa.recycle();

            if (lname != null) {
                lname = lname.intern();
                if (!ArrayUtils.contains(owner.libraryNames, lname)) {
                    owner.libraryNames = ArrayUtils.add(owner.libraryNames, lname);
                }
            }

            XmlUtils.skipCurrentTag(parser);

        } else if (tagName.equals("uses-library")) {
            sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestUsesLibrary);

            // Note: don't allow this value to be a reference to a resource
            // that may change.
            String lname = sa
                    .getNonResourceString(com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
            boolean req = sa.getBoolean(com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
                    true);

            sa.recycle();

            if (lname != null) {
                lname = lname.intern();
                if (req) {
                    owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
                } else {
                    owner.usesOptionalLibraries = ArrayUtils.add(owner.usesOptionalLibraries, lname);
                }
            }

            XmlUtils.skipCurrentTag(parser);

        } else if (tagName.equals("uses-package")) {
            // Dependencies for app installers; we don't currently try to
            // enforce this.
            XmlUtils.skipCurrentTag(parser);

        } else {
            if (!RIGID_PARSER) {
                Slog.w(TAG, "Unknown element under <application>: " + tagName + " at " + mArchiveSourcePath
                        + " " + parser.getPositionDescription());
                XmlUtils.skipCurrentTag(parser);
                continue;
            } else {
                outError[0] = "Bad element under <application>: " + tagName;
                mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                return false;
            }
        }
    }

    modifySharedLibrariesForBackwardCompatibility(owner);

    if (hasDomainURLs(owner)) {
        owner.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
    } else {
        owner.applicationInfo.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
    }

    return true;
}

From source file:android.content.pm.PackageParser.java

/**
 * Parse the {@code application} XML tree at the current parse location in a
 * <em>split APK</em> manifest.
 * <p>//from   w  w w  . j a  va  2s  . c o  m
 * Note that split APKs have many more restrictions on what they're capable
 * of doing, so many valid features of a base APK have been carefully
 * omitted here.
 */
private boolean parseSplitApplication(Package owner, Resources res, XmlPullParser parser, AttributeSet attrs,
        int flags, int splitIndex, String[] outError) throws XmlPullParserException, IOException {
    TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestApplication);

    if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifestApplication_hasCode, true)) {
        owner.splitFlags[splitIndex] |= ApplicationInfo.FLAG_HAS_CODE;
    }

    final int innerDepth = parser.getDepth();
    int type;
    while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
            && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
        if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
            continue;
        }

        String tagName = parser.getName();
        if (tagName.equals("activity")) {
            Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false,
                    owner.baseHardwareAccelerated);
            if (a == null) {
                mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                return false;
            }

            owner.activities.add(a);

        } else if (tagName.equals("receiver")) {
            Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true, false);
            if (a == null) {
                mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                return false;
            }

            owner.receivers.add(a);

        } else if (tagName.equals("service")) {
            Service s = parseService(owner, res, parser, attrs, flags, outError);
            if (s == null) {
                mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                return false;
            }

            owner.services.add(s);

        } else if (tagName.equals("provider")) {
            Provider p = parseProvider(owner, res, parser, attrs, flags, outError);
            if (p == null) {
                mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                return false;
            }

            owner.providers.add(p);

        } else if (tagName.equals("activity-alias")) {
            Activity a = parseActivityAlias(owner, res, parser, attrs, flags, outError);
            if (a == null) {
                mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                return false;
            }

            owner.activities.add(a);

        } else if (parser.getName().equals("meta-data")) {
            // note: application meta-data is stored off to the side, so it can
            // remain null in the primary copy (we like to avoid extra copies because
            // it can be large)
            if ((owner.mAppMetaData = parseMetaData(res, parser, attrs, owner.mAppMetaData,
                    outError)) == null) {
                mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                return false;
            }

        } else if (tagName.equals("uses-library")) {
            sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestUsesLibrary);

            // Note: don't allow this value to be a reference to a resource
            // that may change.
            String lname = sa
                    .getNonResourceString(com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
            boolean req = sa.getBoolean(com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
                    true);

            sa.recycle();

            if (lname != null) {
                lname = lname.intern();
                if (req) {
                    // Upgrade to treat as stronger constraint
                    owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
                    owner.usesOptionalLibraries = ArrayUtils.remove(owner.usesOptionalLibraries, lname);
                } else {
                    // Ignore if someone already defined as required
                    if (!ArrayUtils.contains(owner.usesLibraries, lname)) {
                        owner.usesOptionalLibraries = ArrayUtils.add(owner.usesOptionalLibraries, lname);
                    }
                }
            }

            XmlUtils.skipCurrentTag(parser);

        } else if (tagName.equals("uses-package")) {
            // Dependencies for app installers; we don't currently try to
            // enforce this.
            XmlUtils.skipCurrentTag(parser);

        } else {
            if (!RIGID_PARSER) {
                Slog.w(TAG, "Unknown element under <application>: " + tagName + " at " + mArchiveSourcePath
                        + " " + parser.getPositionDescription());
                XmlUtils.skipCurrentTag(parser);
                continue;
            } else {
                outError[0] = "Bad element under <application>: " + tagName;
                mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                return false;
            }
        }
    }

    return true;
}