Example usage for android.content.pm ConfigurationInfo ConfigurationInfo

List of usage examples for android.content.pm ConfigurationInfo ConfigurationInfo

Introduction

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

Prototype

public ConfigurationInfo() 

Source Link

Usage

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

/**
 * Parse the manifest of a <em>base APK</em>.
 * <p>/*ww w. j  a va 2  s .c o m*/
 * 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;
}