功能概述
android apk应用的安装和卸载主要是由Installer和InstalldNativeService完成的。
Installer提供Java API接口,Installd则是init进程启动的Daemon Service(在root进程中,拥有root权限);Installer 和Installd进行Binder通信(android 8.1.0以前是通过Socket通信),Installer作为客户端,由位于nativie层的installd来完成具体的操作。nativie层调用installd启动InstalldNativeService服务实现。
1.启动流程
1.1Installer简介
public class Installer extends SystemService {
}
Installer继承自SystemService,在Android系统中有两个SystemServer,一个是os/SystemService.java,另一个是server/SystemService.java,这里Installer继承的是server/SystemService.java,所以我们可以说Installer其实是一个系统服务。
1.2 Installer的启动
在SystemServer.java代码中启动
private void startBootstrapServices() {
...
// Wait for installd to finish starting up so that it has a chance to
// create critical directories such as /data/user with the appropriate
// permissions. We need this to complete before we initialize other services.
//等待installd完成启动,以便有机会启动
//创建具有适当权限的关键目录,如/data/user。我们需要在初始化其他服务之前完成此任务。
traceBeginAndSlog("StartInstaller");
Installer installer = mSystemServiceManager.startService(Installer.class);
traceEnd();
...
}
1.3 Installer的onStart()方法
Installer继承自SystemService,所以我们看下Installer的onStart方法,在启动的时候通过ServiceManager获取installd对应的mInstalld服务(该服务运行在root进程中),后面的操作全部都通过mInstalld调用InstalldNativeService执行
@Override
public void onStart() {
if (mIsolated) {
mInstalld = null;
} else {
//进行Binder 进程间连接通信
connect();
}
}
private void connect() {
IBinder binder = ServiceManager.getService("installd");
if (binder != null) {
try {
binder.linkToDeath(new DeathRecipient() {
@Override
public void binderDied() {
Slog.w(TAG, "installd died; reconnecting");
connect();
}
}, 0);
} catch (RemoteException e) {
binder = null;
}
}
if (binder != null) {
mInstalld = IInstalld.Stub.asInterface(binder);
try {
invalidateMounts();
} catch (InstallerException ignored) {
}
} else {
Slog.w(TAG, "installd not found; trying again");
BackgroundThread.getHandler().postDelayed(() -> {
connect();
}, DateUtils.SECOND_IN_MILLIS);
}
}
1.4 IInstalld 观察AIDL有哪些方法
interface IInstalld {
void createUserData(@nullable @utf8InCpp String uuid, int userId, int userSerial, int flags);
void destroyUserData(@nullable @utf8InCpp String uuid, int userId, int flags);
long createAppData(@nullable @utf8InCpp String uuid, in @utf8InCpp String packageName,
int userId, int flags, int appId, in @utf8InCpp String seInfo, int targetSdkVersion);
void restoreconAppData(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName,
int userId, int flags, int appId, @utf8InCpp String seInfo);
void migrateAppData(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName,
int userId, int flags);
void clearAppData(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName,
int userId, int flags, long ceDataInode);
void destroyAppData(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName,
int userId, int flags, long ceDataInode);
void fixupAppData(@nullable @utf8InCpp String uuid, int flags);
long[] getAppSize(@nullable @utf8InCpp String uuid, in @utf8InCpp String[] packageNames,
int userId, int flags, int appId, in long[] ceDataInodes,
in @utf8InCpp String[] codePaths);
long[] getUserSize(@nullable @utf8InCpp String uuid, int userId, int flags, in int[] appIds);
long[] getExternalSize(@nullable @utf8InCpp String uuid, int userId, int flags, in int[] appIds);
void setAppQuota(@nullable @utf8InCpp String uuid, int userId, int appId, long cacheQuota);
void moveCompleteApp(@nullable @utf8InCpp String fromUuid, @nullable @utf8InCpp String toUuid,
@utf8InCpp String packageName, @utf8InCpp String dataAppName, int appId,
@utf8InCpp String seInfo, int targetSdkVersion);
void dexopt(@utf8InCpp String apkPath, int uid, @nullable @utf8InCpp String packageName,
@utf8InCpp String instructionSet, int dexoptNeeded,
@nullable @utf8InCpp String outputPath, int dexFlags,
@utf8InCpp String compilerFilter, @nullable @utf8InCpp String uuid,
@nullable @utf8InCpp String sharedLibraries,
@nullable @utf8InCpp String seInfo);
void rmdex(@utf8InCpp String codePath, @utf8InCpp String instructionSet);
boolean mergeProfiles(int uid, @utf8InCpp String packageName);
boolean dumpProfiles(int uid, @utf8InCpp String packageName, @utf8InCpp String codePaths);
void clearAppProfiles(@utf8InCpp String packageName);
void destroyAppProfiles(@utf8InCpp String packageName);
void idmap(@utf8InCpp String targetApkPath, @utf8InCpp String overlayApkPath, int uid);
void removeIdmap(@utf8InCpp String overlayApkPath);
void rmPackageDir(@utf8InCpp String packageDir);
void markBootComplete(@utf8InCpp String instructionSet);
void freeCache(@nullable @utf8InCpp String uuid, long targetFreeBytes,
long cacheReservedBytes, int flags);
void linkNativeLibraryDirectory(@nullable @utf8InCpp String uuid,
@utf8InCpp String packageName, @utf8InCpp String nativeLibPath32, int userId);
void createOatDir(@utf8InCpp String oatDir, @utf8InCpp String instructionSet);
void linkFile(@utf8InCpp String relativePath, @utf8InCpp String fromBase,
@utf8InCpp String toBase);
void moveAb(@utf8InCpp String apkPath, @utf8InCpp String instructionSet,
@utf8InCpp String outputPath);
void deleteOdex(@utf8InCpp String apkPath, @utf8InCpp String instructionSet,
@nullable @utf8InCpp String outputPath);
boolean reconcileSecondaryDexFile(@utf8InCpp String dexPath, @utf8InCpp String pkgName,
int uid, in @utf8InCpp String[] isas, @nullable @utf8InCpp String volume_uuid,
int storage_flag);
void invalidateMounts();
boolean isQuotaSupported(@nullable @utf8InCpp String uuid);
}
2. 分析其他调用Installer类的其他使用者
PackageManagerService类主要管理应用的安装、卸载、更新、解析以及权限等过程,运行过程中会经常调用Installer执行具体的操作,Installer会再次调用native层执行安装解析等操作;
所以SystemServer启动服务的先后顺序Installer在PackageManagerService服务前面;Installer作为参数传到PackageManagerService构造函数中;

3. installd守护进程
为什么不直接在PackageManagerServcie完成所有操作,还需要InstalldNativeService这个守护进程间接完成?
答:因为权限的问题,PackageManagerService只有system权限。installd却是具有root权限
3.1 bp配置文件
platform/frameworks/native/cmds/installd/Android.bp
...
cc_binary {
...
srcs: ["installd.cpp"],
...
init_rc: ["installd.rc"],
...
}
...
Android.bp文件中指定这个模块装载时候解析的init.rc文件为installd.rc,对外部提供的加载文件为installd.cpp
3.2 rc文件解析
platform/frameworks/native/cmds/installd/installd.rc
service installd /system/bin/installd
class main
....
3.3 installd启动
platform/frameworks/native/cmds/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[]) {
int ret;
...
//初始化 /data 、/system目录
if (!initialize_globals()) {
...
}
//初始化 /data/misc/user
if (initialize_directories() < 0) {
...
}
//selinux校验
if (selinux_enabled && selinux_status_open(true) < 0) {
...
}
...
//注册binder服务 InstalldNativeService
if ((ret = InstalldNativeService::start()) != android::OK) {
...
}
IPCThreadState::self()->joinThreadPool();
...
return 0;
}
这里首先调initialize_globals用初始化解析/data、/system下各种必要目录,然后通过initialize_directories去初始化/data/misc/user下用户组信息,这里会根据不同用户设置不同的id,默认只有一个用户则是0,之后会经过一个selinux的校验,最后会向binder注册一个InstalldNativeService类型的服务
3.4 InstalldNativeService初始化
platform/frameworks/native/cmds/installd/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;
}
这里很常规的进程初始化+binder服务注册,BinderService::publish()这个是个模板函数,定义在/frameworks/native/libs/binder/include/binder/BinderService.h展开后伪代码如下:
static status_t publish(bool allowIsolated = false,
int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT) {
sp<IServiceManager> sm(defaultServiceManager());
return sm->addService(String16(InstalldNativeService::getServiceName())
, new InstalldNativeService(), allowIsolated,dumpFlags);
}
这里实际上就是通过servce_manager去注册一个binder服务
至此,InstalldNativeService服务启动完成
本文参考:一只胖Wa牛
网友评论