AB升级之odex文件首次开机处理

1 篇文章 0 订阅

开启AB升级方案的项目,因为很多需要升级的镜像都有两份,所以存储空间比较浪费。为缓解此问题,有个针对odex的优化方案。

编译版本会生成两个system镜像:system.img和system_other.img,其中,system_other.img中存储的就是odex文件,这样system.img就能小很多,意味着可以为system分区划分较小的空间。

在首次开机时,假设system.img镜像存储在A slot,那么此时的B slot是闲置的。所以可以把system.img刷入A slot的system分区,把system_other.img刷入B slot的system分区。在首次开机时,再把system_other.img中的odex文件拷贝到data分区。

https://source.android.com/devices/tech/dalvik/configure.html#other_odex

开机后copy odex文件的相关代码

/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public PackageManagerService(Context context, Installer installer,
              boolean factoryTest, boolean onlyCore) {
    ...
    // 首次开机时才执行
    if (!mOnlyCore && mFirstBoot) {
        requestCopyPreoptedFiles();
    }
    ...
}

/**
 * Requests that files preopted on a secondary system partition be copied to the data partition
 * if possible.  Note that the actual copying of the files is accomplished by init for security
 * reasons. This simply requests that the copy takes place and awaits confirmation of its
 * completion. See platform/system/extras/cppreopt/ for the implementation of the actual copy.
 */
private static void requestCopyPreoptedFiles() {
    final int WAIT_TIME_MS = 100;
    final String CP_PREOPT_PROPERTY = "sys.cppreopt";
    if (SystemProperties.getInt("ro.cp_system_other_odex", 0) == 1) {
        SystemProperties.set(CP_PREOPT_PROPERTY, "requested");
        // We will wait for up to 100 seconds.
        final long timeStart = SystemClock.uptimeMillis();
        final long timeEnd = timeStart + 100 * 1000;
        long timeNow = timeStart;
        while (!SystemProperties.get(CP_PREOPT_PROPERTY).equals("finished")) {
            try {
                Thread.sleep(WAIT_TIME_MS);
            } catch (InterruptedException e) {
                // Do nothing
            }
            timeNow = SystemClock.uptimeMillis();
            if (timeNow > timeEnd) {
                SystemProperties.set(CP_PREOPT_PROPERTY, "timed-out");
                Slog.wtf(TAG, "cppreopt did not finish!");
                break;
            }
        }

        Slog.i(TAG, "cppreopts took " + (timeNow - timeStart) + " ms");
    }
}

这里是在PSM初始化时,PMS_scan_START之前进行copy动作,且只在首次开机执行。

有开关控制此功能:ro.cp_system_other_odex=1则打开,默认为0

如注释中提到的,PMS并不负责真正的copy,因为它没有相关权限,而是由init进程来执行。

PMS和init的交互是通过系统属性:sys.cppreopt

PMS将其设置为requested,来请求init去copy;每隔一段时间检测下是否已经变更为finished。

当sys.cppreopt=requested时,触发copy;结束后,设置为finished

如下是对应rc文件,相关操作会在init进程中执行。

这个代码给我们提供了一个普通进程和init进程交互的方法:透过property通信

/system/extras/cppreopts/cppreopts.rc
on property:sys.cppreopt=requested && property:ro.boot.slot_suffix=_a
    mount ext4 /dev/block/by-name/system_b /postinstall ro nosuid nodev noexec
    exec - root -- /system/bin/cppreopts.sh /postinstall
    # Optional script to copy additional preloaded content to data directory
    exec - system system -- /system/bin/preloads_copy.sh /postinstall
    umount /postinstall
    setprop sys.cppreopt finished

on property:sys.cppreopt=requested && property:ro.boot.slot_suffix=_b
    mount ext4 /dev/block/by-name/system_a /postinstall ro nosuid nodev noexec
    exec - root -- /system/bin/cppreopts.sh /postinstall
    # Optional script to copy additional preloaded content to data directory
    exec - system system -- /system/bin/preloads_copy.sh /postinstall
    umount /postinstall
    setprop sys.cppreopt finished

具体copy流程:

把system_other.img镜像mount到/postinstall,然后运行/system/bin/cppreopts.sh,之后umount。这个sh脚步在/system/extras/cppreopts/cppreopts.sh

在copy时,需要用到preopt2cachename来生成目标文件路径和名称:system/extras/preopt2cachename/,这个bin档会输出一个string

std::cout << output_file_location;

 

一般地,system/app和system/priv-app/目录下的odex文件会生成到system_other.img

/build/make/core/dex_preopt.mk

# The default filter for which files go into the system_other image (if it is
# being used). To bundle everything one should set this to '%'
SYSTEM_OTHER_ODEX_FILTER ?= app/% priv-app/%

 

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值