这里先初步看一下做odex优化的几个地方,以后再补充详细过程
首先回忆一下在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 !
在SystemServer.java 中有mPackageManagerService.updatePackagesIfNeeded()
这里先列举流程,具体步骤有空再贴上
updatePackagesIfNeeded->performDexOptUpgrade->performDexOptTraced->performDexOptInternal->performDexOptInternalWithDependenciesLI->PackageDexOptimizer.performDexOpt->performDexOptLI->dexOptPath->Installer.dexopt->InstalldNativeService.dexopt->dexopt.dexopt
在PKMS.installPackageLI函数中有:
mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles,
null /* instructionSets /, false / checkProfiles */,
getCompilerFilterForReason(REASON_INSTALL),
getOrCreateCompilerPackageStats(pkg),
mDexManager.isUsedByOtherApps(pkg.packageName));
在PKMS中有实现的地方,但是没找到调用的地方
在PKMS中有实现的地方,在PackageManagerShellCommand中会被调用,应该是提供给shell命令调用
在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命令一些方法来调用
是通过BackgroundDexOptService来实现的,BackgroundDexOptService继承了JobService
这里启动了两个任务
1.开机的时候执行odex优化 JOB_POST_BOOT_UPDATE
执行条件:开机一分钟内
2.在系统休眠的时候执行优化 JOB_IDLE_OPTIMIZE
执行条件:设备处于空闲,插入充电器,且每隔一分钟或者一天就检查一次(根据debug开关控制)