Android编程之Android 8.0 PKMS新变化:如何提取ABI
小标 2018-05-23 来源 : 阅读 2637 评论 0

摘要:Android编程中,在8.0之前,因为每次开机都要扫描APK,所以每次都要判断并设置ABI,这个过程比较花费时间,如果手机安装大量APK,势必会造成开机时间过慢,所以之前项目会对这一块做优化,将ABI信息写入一个xml文件中,首次开机或者安装删除APK就会更新这个文件,非首次开机就会直接读取里面的值,希望对大家学习Android编程有所帮助。

Android编程中,在8.0之前,因为每次开机都要扫描APK,所以每次都要判断并设置ABI,这个过程比较花费时间,如果手机安装大量APK,势必会造成开机时间过慢,所以之前项目会对这一块做优化,将ABI信息写入一个xml文件中,首次开机或者安装删除APK就会更新这个文件,非首次开机就会直接读取里面的值,希望对大家学习Android编程有所帮助。

这次Android 8.0内部优化这一过程,而且比之前的方案更简单,下面来看看是怎么实现的:

之前在分析PKMS开机初始化的时候,知道最终会进入scanPackageDirtyLI方法内:

if ((scanFlags & SCAN_FIRST_BOOT_OR_UPGRADE) == 0) {
    PackageSetting foundPs = mSettings.getPackageLPr(pkg.packageName);
    if (foundPs != null) {
        primaryCpuAbiFromSettings = foundPs.primaryCpuAbiString;
        secondaryCpuAbiFromSettings = foundPs.secondaryCpuAbiString;
    }
}

   

可以看到,这部分逻辑是,如果不是第一次开机或者升级,就从mSettings中读取PackageSetting类型的值,再将其中存储的关于ABI的值保存到临时变量中
再往下看

if ((scanFlags & SCAN_NEW_INSTALL) == 0) {
    if ((scanFlags & SCAN_FIRST_BOOT_OR_UPGRADE) != 0) {
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "derivePackageAbi");
        final boolean extractNativeLibs = !pkg.isLibrary();
        derivePackageAbi(pkg, scanFile, cpuAbiOverride, extractNativeLibs,
                mAppLib32InstallDir);
        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
 
        // Some system apps still use directory structure for native libraries
        // in which case we might end up not detecting abi solely based on apk
        // structure. Try to detect abi based on directory structure.
        if (isSystemApp(pkg) && !pkg.isUpdatedSystemApp() &&
                pkg.applicationInfo.primaryCpuAbi == null) {
            setBundledAppAbisAndRoots(pkg, pkgSetting);
            setNativeLibraryPaths(pkg, mAppLib32InstallDir);
        }
    } else {
        // This is not a first boot or an upgrade, don't bother deriving the
        // ABI during the scan. Instead, trust the value that was stored in the
        // package setting.
        pkg.applicationInfo.primaryCpuAbi = primaryCpuAbiFromSettings;
        pkg.applicationInfo.secondaryCpuAbi = secondaryCpuAbiFromSettings;
 
        setNativeLibraryPaths(pkg, mAppLib32InstallDir);
 
        if (DEBUG_ABI_SELECTION) {
            Slog.i(TAG, "Using ABIS and native lib paths from settings : " +
                pkg.packageName + " " + pkg.applicationInfo.primaryCpuAbi + ", " +
                pkg.applicationInfo.secondaryCpuAbi);
        }
    }
}

这里会再次判断是否第一次开机或者升级
如果是的话,调用derivePackageAbi方法解析abi路径等相关信息存到pkg中

pkg.applicationInfo.primaryCpuAbi
pkg.applicationInfo.secondaryCpuAbi

如果不是,将上面第一次判断得到的临时变量的值复制到pkg中

获取到ABI后肯定要保存起来:
在commitPackageSettings方法中会调用:mSettings.insertPackageSettingLPw(pkgSetting, pkg)

   

<code><code>[Settings.java]
void insertPackageSettingLPw(PackageSetting p, PackageParser.Package pkg) {
 
    addPackageSettingLPw(p, p.sharedUser);
}
 
private void addPackageSettingLPw(PackageSetting p, SharedUserSetting sharedUser) {
    //这里会加入到mPackages中
    mPackages.put(p.name, p);
}</code></code>

   

之前分析PKMS的构造函数时候说到,在构造函数最后会执行mSettings.writeLPr()
writeLPr函数会把mPackages相关信息写入到package.xml等文件中
而在package.xml中就记录了ABI的信息:


<code><code><code><package ......="" codepath="/system/app/YouTube" name="com.google.android.youtube" nativelibrarypath="/system/app/YouTube/lib" primarycpuabi="arm64-v8a"><package .......="" codepath="/system/app/Chrome" name="com.android.chrome" nativelibrarypath="/system/app/Chrome/lib" primarycpuabi="armeabi-v7a" secondarycpuabi="arm64-v8a"></package></package></code></code></code>

   

第一次判断的时候如果不是首次开机或者升级就从mSettings的mPackages中读取PackageSetting类型的值
下面看看packages.xml中的值是怎么读取到mPackages中的
在PKMS构造函数的开始,会调用mSettings.readLPw


<code><code><code><code>[Settings.java]
boolean readLPw(@NonNull List<userinfo> users) {
    //mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
    str = new FileInputStream(mBackupSettingsFilename);
    XmlPullParser parser = Xml.newPullParser();
    parser.setInput(str, StandardCharsets.UTF_8.name());
    if (tagName.equals("package")) {
        readPackageLPw(parser);
    }
}</userinfo></code></code></code></code>

   

readLPw的逻辑就是删除packages.xml,从packages-backup.xml中读取值
再按照不同的节点来来调用不同的方法解析,这里主要看readPackageLPw方法


<code><code><code><code>primaryCpuAbiString = parser.getAttributeValue(null, "primaryCpuAbi");
secondaryCpuAbiString = parser.getAttributeValue(null, "secondaryCpuAbi");
//读取一些值后调用addPackageLPw方法
packageSetting = addPackageLPw(......, primaryCpuAbiString,secondaryCpuAbiString,......);
 
PackageSettinga ddPackageLPw(......) {
    p = new PackageSetting(......, primaryCpuAbiString, secondaryCpuAbiString,......);
    mPackages.put(name, p);
}</code></code></code></code>

这样就加入到mPackages中了

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发Android频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved