美文网首页
第一章:Installer

第一章:Installer

作者: momxmo | 来源:发表于2020-04-01 10:51 被阅读0次
功能概述

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构造函数中;


image.png

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牛

相关文章

网友评论

      本文标题:第一章:Installer

      本文链接:https://www.haomeiwen.com/subject/pihwuhtx.html