apk文件在开机过程中的解析流程

涉及文件:

frameworks\base\core\java\android\content\pm\PackageParser.java

frameworks\base\core\res\res\values\attrs_manifest.xml

两个涉及重要内部类:

public final static class Package implements Parcelable {
//省略其余manifest文件中相关属性
public ApplicationInfo applicationInfo = new ApplicationInfo();
public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
public final ArrayList<Service> services = new ArrayList<Service>(0);
public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
public final ArrayList<String> requestedPermissions = new ArrayList<String>();
public ArrayList<String> protectedBroadcasts;
public Package parentPackage;
public ArrayList<Package> childPackages;
//省略其余manifest文件中相关属性 
}


//轻量级的package类,只有部分以上属性
public static class PackageLite {
    public final String packageName;
public final int versionCode;
public final int versionCodeMajor;
public final int installLocation;
public final VerifierInfo[] verifiers;
/** Names of any split APKs, ordered by parsed splitName */
public final String[] splitNames;
/** Names of any split APKs that are features. Ordered by splitName */
public final boolean[] isFeatureSplits;
/** Dependencies of any split APKs, ordered by parsed splitName */
public final String[] usesSplitNames;
public final String[] configForSplit;
public final String codePath;
/** Path of base APK */
public final String baseCodePath;
/** Paths of any split APKs, ordered by parsed splitName */
public final String[] splitCodePaths;
/** Revision code of base APK */
public final int baseRevisionCode;
/** Revision codes of any split APKs, ordered by parsed splitName */
public final int[] splitRevisionCodes;
public final boolean coreApp;
public final boolean debuggable;
public final boolean multiArch;
public final boolean use32bitAbi;
public final boolean extractNativeLibs;
public final boolean isolatedSplits;    
    
}
public final static class Package implements Parcelable {
//省略其余manifest文件中相关属性
public ApplicationInfo applicationInfo = new ApplicationInfo();
public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
public final ArrayList<Service> services = new ArrayList<Service>(0);
public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
public final ArrayList<String> requestedPermissions = new ArrayList<String>();
public ArrayList<String> protectedBroadcasts;
public Package parentPackage;
public ArrayList<Package> childPackages;
//省略其余manifest文件中相关属性 
}


//轻量级的package类,只有部分以上属性
public static class PackageLite {
    public final String packageName;
public final int versionCode;
public final int versionCodeMajor;
public final int installLocation;
public final VerifierInfo[] verifiers;
/** Names of any split APKs, ordered by parsed splitName */
public final String[] splitNames;
/** Names of any split APKs that are features. Ordered by splitName */
public final boolean[] isFeatureSplits;
/** Dependencies of any split APKs, ordered by parsed splitName */
public final String[] usesSplitNames;
public final String[] configForSplit;
public final String codePath;
/** Path of base APK */
public final String baseCodePath;
/** Paths of any split APKs, ordered by parsed splitName */
public final String[] splitCodePaths;
/** Revision code of base APK */
public final int baseRevisionCode;
/** Revision codes of any split APKs, ordered by parsed splitName */
public final int[] splitRevisionCodes;
public final boolean coreApp;
public final boolean debuggable;

apk文件中manifest文件解析流程图如下:

 

parsePackage代码如下:

public Package parsePackage(File packageFile, int flags, boolean useCaches)
        throws PackageParserException {
    //从pms启动时候创建的cacheDir:/data/system/package_cache/1,中查看该包是否已经解析过
    //如果已经解析过,则直接返回已经解析好的数据
    Package parsed = useCaches ? getCachedResult(packageFile, flags) : null;
    if (parsed != null) {
        return parsed;
    }

    long parseTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
    //解析文件或者目录得到pakcage类
    if (packageFile.isDirectory()) {
        parsed = parseClusterPackage(packageFile, flags);
    } else {
        parsed = parseMonolithicPackage(packageFile, flags);
    }
    long cacheTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
    //将本次解析得到的package类以parceable形式写入到/data/system/package_cache/1目录下
    cacheResult(packageFile, flags, parsed);
    if (LOG_PARSE_TIMINGS) {
        parseTime = cacheTime - parseTime;
        cacheTime = SystemClock.uptimeMillis() - cacheTime;
        if (parseTime + cacheTime > LOG_PARSE_TIMINGS_THRESHOLD_MS) {
            Slog.i(TAG, "Parse times for '" + packageFile + "': parse=" + parseTime
                    + "ms, update_cache=" + cacheTime + " ms");
        }
    }
    return parsed;
}

直接进入到文件的解析分析,目录的解析分析绕过,因最终都会归结到对apk文件的解析操作中:

@Deprecated
public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
    //得到轻量级packagelite实体
    final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
    if (mOnlyCoreApps) {
        if (!lite.coreApp) {
            throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
                    "Not a coreApp: " + apkFile);
        }
    }
    //得到asset用于获取apk解析manifest文件
    final SplitAssetLoader assetLoader = new DefaultSplitAssetLoader(lite, flags);
    try {
        final Package pkg = parseBaseApk(apkFile, assetLoader.getBaseAssetManager(), flags);
        pkg.setCodePath(apkFile.getCanonicalPath());
        pkg.setUse32bitAbi(lite.use32bitAbi);
        return pkg;
    } catch (IOException e) {
        throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
                "Failed to get path: " + apkFile, e);
    } finally {
        IoUtils.closeQuietly(assetLoader);
    }
}

private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
        throws PackageParserException {
    final String apkPath = apkFile.getAbsolutePath();

    String volumeUuid = null;
    if (apkPath.startsWith(MNT_EXPAND)) {
        final int end = apkPath.indexOf('/', MNT_EXPAND.length());
        volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
    }

    mParseError = PackageManager.INSTALL_SUCCEEDED;
    mArchiveSourcePath = apkFile.getAbsolutePath();

    if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);

    XmlResourceParser parser = null;
    try {
        final int cookie = assets.findCookieForPath(apkPath);
        if (cookie == 0) {
            throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
                    "Failed adding asset path: " + apkPath);
        }
        parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
        final Resources res = new Resources(assets, mMetrics, null);

        final String[] outError = new String[1];
        final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
        if (pkg == null) {
            throw new PackageParserException(mParseError,
                    apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
        }

        pkg.setVolumeUuid(volumeUuid);
        pkg.setApplicationVolumeUuid(volumeUuid);
        pkg.setBaseCodePath(apkPath);
        pkg.setSigningDetails(SigningDetails.UNKNOWN);

        return pkg;

    } catch (PackageParserException e) {
        throw e;
    } catch (Exception e) {
        throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
                "Failed to read manifest from " + apkPath, e);
    } finally {
        IoUtils.closeQuietly(parser);
    }
}

parseBaseApkCommon完成manifest文件中所有信息的解析,涉及一重要文件:frameworks\base\core\res\res\values\attrs_manifest.xml

所有解析用到的属性都在该文件中定义

private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res,
        XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException,
        IOException {
    mParseInstrumentationArgs = null;

    int type;
    boolean foundApp = false;

    TypedArray sa = res.obtainAttributes(parser,
            com.android.internal.R.styleable.AndroidManifest);

    String str = sa.getNonConfigurationString(
            com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
    
    //......

    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 (acceptedTags != null && !acceptedTags.contains(tagName)) {
            Slog.w(TAG, "Skipping unsupported element under <manifest>: "
                    + tagName + " at " + mArchiveSourcePath + " "
                    + parser.getPositionDescription());
            XmlUtils.skipCurrentTag(parser);
            continue;
        }

        if (tagName.equals(TAG_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;
            //解析application标签下的内容
            if (!parseBaseApplication(pkg, res, parser, flags, outError)) {
                return null;
            }
        } 
    //省略多数tag解析过程
    return pkg;
}

parseBaseApplication解析application标签

private boolean parseBaseApplication(Package owner, Resources res,
        XmlResourceParser parser, int flags, String[] outError)
    throws XmlPullParserException, IOException {
    final ApplicationInfo ai = owner.applicationInfo;
    final String pkgName = owner.applicationInfo.packageName;

    //.......
    
    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")) {
            //解析antivity
            Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
                    owner.baseHardwareAccelerated);
            if (a == null) {
                mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                return false;
            }

            hasActivityOrder |= (a.order != 0);
            //将该activity信息加入到package类的列表中
            owner.activities.add(a);

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

            hasReceiverOrder |= (a.order != 0);
            //将该activity信息加入到package类的列表中
            owner.receivers.add(a);

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

            hasServiceOrder |= (s.order != 0);
            owner.services.add(s);

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

            owner.providers.add(p);

        } 
        //......

    return true;
}

activity、service、receiver、provider的解析分别在parseActivity、parseService、parseProvider中完成,完成后加入到package类的列表中,这样开机后所有安装的应用的

activity、receiver、service就能够通过queryIntent从PMS服务中进行查找了

猜你喜欢

转载自blog.csdn.net/thh159/article/details/88378941