Android 8.0 dexopt记录

这里先初步看一下做odex优化的几个地方,以后再补充详细过程

一、installd的变化

首先回忆一下在7.0中installd是如何启动的:
在installd.rc中:

service installd /system/bin/installd
    class main
    socket installd stream 600 system system

这里启动installd的同时还启动了一个socket,在installd.cpp中有获取这个socket的地方android_get_control_socket

由于已经过时,其它的不再说了,下面看看8.0中是如何启动的:
在installd.rc中:

service installd /system/bin/installd
    class main

只是启动installd,进入installd看一下

[installd.cpp]
int main(const int argc, char *argv[]) {
    return android::installd::installd_main(argc, argv);
}

static int installd_main(const int argc ATTRIBUTE_UNUSED, char *argv[]) {
    ……
    if ((ret = InstalldNativeService::start()) != android::OK) {
        SLOGE("Unable to start InstalldNativeService: %d", ret);
        exit(1);
    }

    IPCThreadState::self()->joinThreadPool();

    LOG(INFO) << "installd shutting down";

    return 0;
}

看看这个InstalldNativeService是什么,InstalldNativeService .h中定义如下:

class InstalldNativeService : public BinderService<InstalldNativeService>, public os::BnInstalld

看到这是否有熟悉的感觉?之前在实现Native Service的时候,我们自己定义的TestPlayService就是这样定义的:

class TestPlayService : public BinderService<TestPlayService>, public BnTestPlayService

这说明installd和客户端是通过binder来通信的

那么肯定就有把这个service加入到servicemanager中的地方,继续看start()方法:

[InstalldNativeService.cpp]
status_t InstalldNativeService::start() {
    IPCThreadState::self()->disableBackgroundScheduling(true);
    status_t ret = BinderService<InstalldNativeService>::publish();
    if (ret != android::OK) {
        return ret;
    }
    sp<ProcessState> ps(ProcessState::self());
    ps->startThreadPool();
    ps->giveThreadPoolName();
    return android::OK;
}

明显,就是通过publish()这个方法的,可以看下它的定义

[BinderService.h]
static status_t publish(bool allowIsolated = false) {
    sp sm(defaultServiceManager());
    return sm->addService(
            String16(SERVICE::getServiceName()),
            new SERVICE(), allowIsolated);
}

那这个InstalldNativeService是不是我们要找到的installd呢,看一下它加入到servicemanager中的名字,

static char const* getServiceName() { return "installd"; }

就是installd !

二、odex优化的地方

1.首次开机或者升级

在SystemServer.java 中有mPackageManagerService.updatePackagesIfNeeded()
这里先列举流程,具体步骤有空再贴上
updatePackagesIfNeeded->performDexOptUpgrade->performDexOptTraced->performDexOptInternal->performDexOptInternalWithDependenciesLI->PackageDexOptimizer.performDexOpt->performDexOptLI->dexOptPath->Installer.dexopt->InstalldNativeService.dexopt->dexopt.dexopt

2.安装应用:

在PKMS.installPackageLI函数中有:
mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles,
null /* instructionSets /, false / checkProfiles */,
getCompilerFilterForReason(REASON_INSTALL),
getOrCreateCompilerPackageStats(pkg),
mDexManager.isUsedByOtherApps(pkg.packageName));

3.IPackageManager.aidl提供了performDexOpt方法

在PKMS中有实现的地方,但是没找到调用的地方

4.IPackageManager.aidl提供了performDexOptMode方法

在PKMS中有实现的地方,在PackageManagerShellCommand中会被调用,应该是提供给shell命令调用

5.OTA升级后:

在SystemServer.java 中有OtaDexoptService.main(mSystemContext, mPackageManagerService);

public static OtaDexoptService main(Context context,
        PackageManagerService packageManagerService) {
    OtaDexoptService ota = new OtaDexoptService(context, packageManagerService);
    ServiceManager.addService("otadexopt", ota);

    // Now it's time to check whether we need to move any A/B artifacts.
    ota.moveAbArtifacts(packageManagerService.mInstaller);

    return ota;
}
private void moveAbArtifacts(Installer installer) {
    if (mDexoptCommands != null) {
        throw new IllegalStateException("Should not be ota-dexopting when trying to move.");
    }
    //如果不是升级上来的,就return掉
    if (!mPackageManagerService.isUpgrade()) {
        Slog.d(TAG, "No upgrade, skipping A/B artifacts check.");
        return;
    }

        installer.moveAb(path, dexCodeInstructionSet, oatDir);
}

moveAbArtifacts函数的逻辑:
1.判断是否升级
2.判断扫描过的package是否有code,没有则跳过
3.判断package的code路径是否为空,为空则跳过
4.如果package的code在system或者vendor目录下,跳过
5.满足上述条件,调用Installer.java中的moveAb方法
最终是调用dexopt.cpp的move_ab方法

OtaDexoptService也提供给shell命令一些方法来调用

6.在系统空闲的时候:

是通过BackgroundDexOptService来实现的,BackgroundDexOptService继承了JobService
这里启动了两个任务
1.开机的时候执行odex优化 JOB_POST_BOOT_UPDATE
执行条件:开机一分钟内
2.在系统休眠的时候执行优化 JOB_IDLE_OPTIMIZE
执行条件:设备处于空闲,插入充电器,且每隔一分钟或者一天就检查一次(根据debug开关控制)

你可能感兴趣的:(Android,源码分析)