系统服务Installer的启动 您所在的位置:网站首页 packagename翻译 系统服务Installer的启动

系统服务Installer的启动

2023-05-21 15:05| 来源: 网络整理| 查看: 265

目录

1 Java层Installer和native层Installd服务概述

2 Installers服务启动

2.1 SystemServer.startBootstrapServices()

2.2  Installer构造方法

2.3 Installer.onStart()

2.4 Installer.connect()

2.5 Installer.invalidateMounts()

3 Installers服务其他功能

3.1 Installers.createAppData()

3.2 Installer.Batch.createAppData()和execute()

3.3 和AppData相关的其他方法 

3.4 获取App/User空间大小的方法

3.5 Dex文件相关的方法

3.6 安装apk的方法

3.7 创建OAT目录

1 Java层Installer和native层Installd服务概述

PackageManagerService的中负责Application安装、卸载等工作,实际上是由Java层系统Intaller通过Binder调用native层的installd守护进程来实现的,而Installer与installd是通过AIDL进行通信的。

因为SystemServer进程是以system用户运行,所以由它启动的系统服务包括PackageManagerService都是以system用户运行,而创建关键目录如/data/user等需要root用户权限、dex文件的优化和转化等需要installd进程完成。

主要涉及的文件有:

Java层:/frameworks/base/services/core/java/com/android/server/pm/Installer.java,代码参考地址:Installer.java。 native层installd主要在目录:/frameworks/native/cmds/installd,代码参考地址:installd - OpenGrok cross reference for /frameworks/native/cmds/installd/,部分文件如下 AIDL文件:/frameworks/native/cmds/installd/binder/android/os/IInstalld.aidl /frameworks/native/cmds/installd/InstalldNativeService.cpp /frameworks/native/cmds/installd/installd.cpp

2 Installers服务启动

2.1 SystemServer.startBootstrapServices() public final class SystemServer implements Dumpable { private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) { //启动Installer服务,以便有机会使用合适的权限创建关键目录,例如/data/user. //在初始化其他Services之前需要完成Install的加载. t.traceBegin("StartInstaller"); Installer installer = mSystemServiceManager.startService(Installer.class); t.traceEnd(); ... } }

SystemServiceManager.startService()会通过反射创建Installer实例,进而调用Installers.onStart()方法 

2.2  Installer构造方法

SystemServiceManager.startService()通过反射创建的Installer实例时,只有一个参数context是mSystemContext,所以mIsolated=false,默认不会与native层的installd服务建立连接。

public class Installer extends SystemService { private final boolean mIsolated; public Installer(Context context) { this(context, false); } //参数isolated表示这个object是否不应该与installd连接. 除非extends该类 //并intercept(拦截)他们,否则所有的远程调用都会被忽略 public Installer(Context context, boolean isolated) { super(context); mIsolated = isolated; } } 2.3 Installer.onStart()

该方法中mIsolated默认是false,所以不会与native层的installd服务连接。

之前我们介绍过的AMS、ATMS、PMS等其他系统服务都会在重写的onStart()中调用publishBinderService(),把自身注册到ServiceManager中。而Installer服务却不没有调用publishBinderService(),而是直接通过Binder调用native层的Installd服务,这是因为Installd服务已经在native层注册到ServiceManager中了,所以Java层的Installer不需要再注册同样功能的服务,connect()在下部分介绍。

public class Installer extends SystemService { private final boolean mIsolated; private volatile IInstalld mInstalld; @Override public void onStart() { if (mIsolated) { //正如构造方法中介绍的,当mIsolated=false,则不会和Installd服务建立连接, //需要通过Injector才能与installd连接. mInstalld = null; } else { connect(); } } } 2.4 Installer.connect()

native层的installd服务已经在ServiceManager中注册过,所以直接通过name=installd就可以通过Binder与installd通信。

如果获取不到installd服务,则发延迟消息,1s后再次调用connect();

如果获取到installd服务,一方面注册它的死亡回调,收到binderDied()回调后再次connect();另一方面获取installd binder客户端,调用invalidateMounts()。

public class Installer extends SystemService { private volatile IInstalld mInstalld; private void connect() { IBinder binder = ServiceManager.getService("installd"); if (binder != null) { try { binder.linkToDeath(new DeathRecipient() { @Override public void binderDied() { //接收installd的死亡通知,再次建立连接。 Slog.w(TAG, "installd died; reconnecting"); connect(); } }, 0); } catch (RemoteException e) { binder = null; } } if (binder != null) { //获取Installd服务的客户端 mInstalld = IInstalld.Stub.asInterface(binder); try { invalidateMounts(); } catch (InstallerException ignored) { } } else { //如果binder=null,则没有获取到installd服务,发送延迟消息,1s后再次调用connect() Slog.w(TAG, "installd not found; trying again"); BackgroundThread.getHandler().postDelayed(() -> { connect(); }, DateUtils.SECOND_IN_MILLIS); } } } 2.5 Installer.invalidateMounts()

该方法调用native层installd.invalidateMounts(),主要是先清空mStorageMounts,从"/proc/mounts"读取重新构建mStorageMounts。

public class Installer extends SystemService { private volatile IInstalld mInstalld; public void invalidateMounts() throws InstallerException { //判断mInstalld是true or false if (!checkBeforeRemote()) return; try { //调用native层installd的方法 mInstalld.invalidateMounts(); } catch (Exception e) { throw InstallerException.from(e); } } } 3 Installers服务其他功能 3.1 Installers.createAppData()

该方法实质也是调用installd守护进程来创建应用数据,参数包括UUID、应用的包名、userId、flags、appId应用进程ID、seInfo和targetSdkVersion。

public class Installer extends SystemService { public long createAppData(String uuid, String packageName, int userId, int flags, int appId, String seInfo, int targetSdkVersion) throws InstallerException { //组装参数,组装成CreateAppDataArgs结构 final CreateAppDataArgs args = buildCreateAppDataArgs(uuid, packageName, userId, flags, appId, seInfo, targetSdkVersion); final CreateAppDataResult result = createAppData(args); if (result.exceptionCode == 0) { return result.ceDataInode; } else { throw new InstallerException(result.exceptionMessage); } } public @NonNull CreateAppDataResult createAppData(@NonNull CreateAppDataArgs args) throws InstallerException { if (!checkBeforeRemote()) { return buildPlaceholderCreateAppDataResult(); } try { //调用installd的createAppData() return mInstalld.createAppData(args); } catch (Exception e) { throw InstallerException.from(e); } } } 3.2 Installer.Batch.createAppData()和execute()

该方法是批量执行创建应用数据,推荐使用该方法,效率更高而且线程安全,因为它使用了synchronized。

Batch内部有两个数组:mArgs数组存储创建app数据需要的参数;mFutures保存参数对应的任务。Batch.createAppData()就是向这两个数组添加元素,Batch.execute()就是从数据中取出创建应用数据的所需的参数,它实质也是调用installd.createAppDataBatched()。

private final List mArgs = new ArrayList(); private final List mFutures = new ArrayList(); 3.3 和AppData相关的其他方法 

public void restoreconAppData(String uuid, String packageName, int userId, int flags, int appId, String seInfo)、 public void migrateAppData(String uuid, String packageName, int userId, int flags) public void clearAppData(String uuid, String packageName, int userId, int flags, long ceDataInode) public void destroyAppData(String uuid, String packageName, int userId, int flags, long ceDataInode) public void fixupAppData(String uuid, int flags) public void moveCompleteApp(String fromUuid, String toUuid, String packageName,             int appId, String seInfo, int targetSdkVersion, String fromCodePath)

以上方法都是调用installd对应方法,之后有空再介绍。

3.4 获取App/User空间大小的方法

public void getAppSize(String uuid, String[] packageNames, int userId, int flags, int appId,             long[] ceDataInodes, String[] codePaths, PackageStats stats) public void getUserSize(String uuid, int userId, int flags, int[] appIds, PackageStats stats) public long[] getExternalSize(String uuid, int userId, int flags, int[] appIds)

3.5 Dex文件相关的方法

public void dexopt(String apkPath, int uid, @Nullable String pkgName, String instructionSet,             int dexoptNeeded, @Nullable String outputPath, int dexFlags,             String compilerFilter, @Nullable String volumeUuid, @Nullable String sharedLibraries,             @Nullable String seInfo, boolean downgrade, int targetSdkVersion,             @Nullable String profileName, @Nullable String dexMetadataPath,             @Nullable String compilationReason) public void rmdex(String codePath, String instructionSet) public long deleteOdex(String apkPath, String instructionSet, String outputPath) public byte[] hashSecondaryDexFile(String dexPath, String packageName, int uid,             @Nullable String volumeUuid, int flags)

3.6 安装apk的方法

public void installApkVerity(String filePath, FileDescriptor verityInput, int contentSize)

3.7 创建OAT目录

public void createOatDir(String oatDir, String dexInstructionSet)



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有