/frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() { ... WindowManagerService wm = null; ... try { ... mActivityManagerService.installSystemProviders(); //1 ... wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore, new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager); ... mActivityManagerService.setWindowManager(wm); //2 ... } ... mActivityManagerService.systemReady(() -> { //3 ... mSystemServiceManager.startBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY); ... try { mActivityManagerService.startObservingNativeCrashes(); } ... try { startSystemUi(context, windowManagerF); } ... mSystemServiceManager.startBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START); ... }, BOOT_TIMINGS_TRACE_LOG); } /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public final void installSystemProviders() { List providers; synchronized (this) { ProcessRecord app = mProcessList.mProcessNames.get("system", SYSTEM_UID); providers = generateApplicationProvidersLocked(app); ... } if (providers != null) { mSystemThread.installSystemProviders(providers); } ... mConstants.start(mContext.getContentResolver()); mCoreSettingsObserver = new CoreSettingsObserver(this); mActivityTaskManager.installSystemProviders(); ... }
public void setWindowManager(WindowManagerService wm) { synchronized (this) { mWindowManager = wm; mActivityTaskManager.setWindowManager(wm); } }
public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) { //添加 AMS 服务,方便跨进程调用 ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true, DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO); ... synchronized(this) { ... mLocalDeviceIdleController = LocalServices.getService(DeviceIdleController.LocalService.class); mActivityTaskManager.onSystemReady(); mUserController.onSystemReady(); mAppOpsService.systemReady(); mSystemReady = true; } ... }
已通过 ServiceManager.addService() 将 Context.ACTIVITY_SERVICE 与 AMS 绑定,因此在其他进程中可以通过如下方式获取 AMS。
IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
IActivityManager am = IActivityManager.Stub.asInterface(b);
PMS篇
PackageManagerService(简称 PMS),是 Android 系统核心服务之一,处理包管理相关的工作,常见的比如安装、卸载应用等。PMS是系统服务,那么应用层肯定有个PackageManager作为binder call client端来供使用,但是这里要注意,PackageManager是个抽象类,一般使用的是它的实现类:ApplicationPackageManager。因此PackageManager功能的具体实现还是ApplicationPackageManager这个实现类
PMS的功能
1、安装、卸载应用
2、查询permission相关信息
3、查询Application相关信息(application、activity、receiver、service、provider及相应属性等)
4、查询已安装应用
5、增加、删除permission
6、清除用户数据、缓存、代码等
接口的讲解
1.PackaeManager.java ----------------------> ApplicationPackageManager.java------------------------------->PackageManagerService.java
- queryIntentActivities(intent, PackageManager.MATCH_ALL): 查询包含这个Intent的Activity
- resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) : 查询是否有满足这个Intent的Activity
- clearPackagePreferredActivities() : 清除默认的修改
- addPreferredActivity() : 修改默认的配置
- if (r.match > bestMatch) bestMatch = r.match;***
- replacePreferredActivity() : 替换Intent 匹配相同的Activity
- getPackageUid(String packageName) : 获取相应包的UID
- getPermissionInfo(String packageName, int flags (大部分默认为0)) : 通过包名获取权限
- getApplicationInfo(String packageName,int flags) : 检索出一个应用程序的所有信息
- getActivityInfo(ComponentName component,int flags) : 检索出一个特定的Activity类的所有信息`
- getPackageInfo(String packageName, int flags) : 包名获取该包名对应的应用程序的PackageInfo对象
- getInstalledPackages(int flags(一般传值为0)) : 返回设备上所有已经安装的应用程序集合
入参params flags 附加选项的标志位,你可以理解为筛选条件,可以使用的标志位为:
GET_ACTIVITIES :(packageInfo的标志)表示 返回包(packageInfo)中包含的所有Activity信息 GET_GIDS :(packageInfo的标志)表示 返回关联的GID(groupId) GET_CONFIGURATIONS :(packageInfo的标志)表示 配置选项信息 GET_INSTRUMENTATION :(PackageInfo的标志)表示 是否使用了instrumentation GET_PERMISSIONS :(PackageInfo的标志)表示 是否使用了permissions GET_PROVIDERS :(PackageInfo的标志)表示 是否使用了providers GET_RECEIVERS :(PackageInfo的标志)表示 是否使用了recevier GET_SERVICES :(PackageInfo的标志)表示 是否使用了service GET_SIGNATURES :(PackageInf的标志) 表示是否使用包的签名信息 GET_UNINSTALLED_PACKAGES:参数标志位,表示检索出所有有数据的目录的应用程序(主要是卸载的)的信息
安装过程
1.准备工作
前面说到 APK 的信息会提交给 PMS 进行安装的一系列工作,具体是通过 PackageHandler 发送消息来驱动 APK 的复制和安装,其时序图如下:
上相过程中有几点需要说明:
1、在 installStage 方法中创建了 InstallParams 对象,它对应于包的安装数据,并创建 INIT_COPY 消息并发送给 PackageHandler 进行处理;
2、PackageHandler 在处理 INIT_COPY 消息时,会先判断是否绑定了 DefaultContainerService ,这是用于检查和赋值可移动文件的服务,比较耗时,所以和 PMS 并没有运行在同一个进程中,它们之间通过 IMediaContainerService 进行 IPC 通信,没有绑定则会进行绑定,之后
DefaultContainerConnection 同样是定义在 PMS 中,执行链路如下:
PackageHandler -> doHandleMessage(INIT_COPY) -> connectToService() { 连接成功 mBound = true; } -> bindServiceAsUser() -> DefaultContainerConnection -> onServiceConnected() -> sendMessage(MCS_BOUND)
3、发送 MCS_BOUND 消息时,根据发送的 Message 是否带 Object 分为两种,如下所示:
void doHandleMessage(Message msg) { switch (msg.what) { case INIT_COPY: { ...... //mBound用于标识是否绑定了服务,默认值为false if (!mBound) { ...... if (!connectToService()) { // 绑定 DefaultContainerConnection 成功之后会发送 // mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, Object)); ...... //绑定服务失败则return return; } else { //绑定服务成功,将请求添加到ArrayList类型的mPendingInstalls中,等待处理 mPendingInstalls.add(idx, params); } } else { //已经绑定服务 mHandler.sendEmptyMessage(MCS_BOUND); } break; } ...... } } }
4、 MCS_BOUND 消息的处理:
case MCS_BOUND: {
if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound");
if (msg.obj != null) {
...
}
if (mContainerService == null) {//1
...
} elseif (mPendingInstalls.size() > 0) {//2
HandlerParams params = mPendingInstalls.get(0);//3
if (params != null) {
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
System.identityHashCode(params));
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "startCopy");
if (params.startCopy()) {//4
if (DEBUG_SD_INSTALL) Log.i(TAG,
"Checking for more work or unbind...");
//如果APK安装成功,删除本次安装请求
if (mPendingInstalls.size() > 0) {
mPendingInstalls.remove(0);
}
if (mPendingInstalls.size() == 0) {
if (mBound) {
//如果没有安装请求了,发送解绑服务的请求
if (DEBUG_SD_INSTALL) Log.i(TAG,
"Posting delayed MCS_UNBIND");
removeMessages(MCS_UNBIND);
Message ubmsg = obtainMessage(MCS_UNBIND);
sendMessageDelayed(ubmsg, 10000);
}
} else {
if (DEBUG_SD_INSTALL) Log.i(TAG,
"Posting MCS_BOUND for next work");
//如果还有其他的安装请求,接着发送MCS_BOUND消息继续处理剩余的安装请求
mHandler.sendEmptyMessage(MCS_BOUND);
}
}
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}else {
Slog.w(TAG, "Empty queue");
}
break;
}
2.复制APK
2.1 复制过程时序图
HandlerParams 是 PMS 中的抽象类,它的实现类为 PMS 的内部类 InstallParams。HandlerParams 的 startCopy 方法如下所示:
2.2 复制过程的源码分析
PackageManagerService.java#HandlerParams
final boolean startCopy() { boolean res; try { if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this); //startCopy方法尝试的次数,超过了4次,就放弃这个安装请求 if (++mRetries > MAX_RETRIES) { Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up"); //MCS_GIVE_UP类型消息,将本次安装请求从安装请求队列mPendingInstalls中移除掉 mHandler.sendEmptyMessage(MCS_GIVE_UP); handleServiceError(); returnfalse; } else { handleStartCopy(); // 注释① res = true; } } catch (RemoteException e) { if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT"); mHandler.sendEmptyMessage(MCS_RECONNECT); res = false; } handleReturnCode(); return res; }
在 注释① 处调用抽象方法 handleStartCopy ,具体实现在 InstallParams 中,如下所示:
PackageManagerService.java#InstallParams
public void handleStartCopy() throws RemoteException {
...
//确定APK的安装位置。onSd:安装到SD卡, onInt:内部存储即Data分区,ephemeral:安装到临时存储(Instant Apps安装)
finalboolean onSd = (installFlags & PackageManager.INSTALL_EXTERNAL) != 0;
finalboolean onInt = (installFlags & PackageManager.INSTALL_INTERNAL) != 0;
finalboolean ephemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
PackageInfoLite pkgLite = null;
if (onInt && onSd) {
// APK不能同时安装在SD卡和Data分区
Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
//安装标志冲突,Instant Apps不能安装到SD卡中
} elseif (onSd && ephemeral) {
Slog.w(TAG, "Conflicting flags specified for installing ephemeral on external");
ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
} else {
//获取APK的少量的信息
pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags,
packageAbiOverride);
if (DEBUG_EPHEMERAL && ephemeral) {
Slog.v(TAG, "pkgLite for install: " + pkgLite);
}
...
if (ret == PackageManager.INSTALL_SUCCEEDED) {
//判断安装的位置
int loc = pkgLite.recommendedInstallLocation;
if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION) {
ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
} elseif (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS) {
ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
}
...
}else{
loc = installLocationPolicy(pkgLite); // 注释①
...
}
}
//根据InstallParams创建InstallArgs对象
final InstallArgs args = createInstallArgs(this); // 注释②
mArgs = args;
if (ret == PackageManager.INSTALL_SUCCEEDED) {
...
if (!origin.existing && requiredUid != -1
&& isVerificationEnabled(
verifierUser.getIdentifier(), installFlags, installerUid)) {
...
} else{
ret = args.copyApk(mContainerService, true); // 注释③
}
}
mRet = ret;
}
- 注释① 处确定了 APK 的安装位置。
- 注释②处创建 InstallArgs 对象,此对象是一个抽象类,定义了 APK 的复制和重命名APK等安装逻辑,在 Android 8.x 及之前的版本中有三个子类:FileInstallArgs、AsecInstallArgs、MoveInstallArgs。其中 FileInstallArgs 用于处理安装到非ASEC的存储空间的APK,即内部存储空间(Data分区);AsecInstallArgs 用于处理安装到ASEC(mnt/asec)即SD卡中的APK;MoveInstallArgs 用于处理已安装APK的移动的逻辑;但在 Android 9.x 之后已经去掉了 AsecInstallArgs ,
- 注释③ 处调用 InstallArgs 的 copyApk 方法,这里以 FileInstallArgs 的实现为例,内部会调用 FileInstallArgs 的 doCopyApk 方法:
private int doCopyApk(IMediaContainerService imcs, boolean temp) throws RemoteException { ... try { finalboolean isEphemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0; //创建临时文件存储目录 final File tempDir = mInstallerService.allocateStageDirLegacy(volumeUuid, isEphemeral); // 注释① codeFile = tempDir; resourceFile = tempDir; } catch (IOException e) { Slog.w(TAG, "Failed to create copy file: " + e); return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; } ... int ret = PackageManager.INSTALL_SUCCEEDED; ret = imcs.copyPackage(origin.file.getAbsolutePath(), target); // 注释② ... return ret; }
- 注释① 处用于创建临时存储目录,比如 /data/app/vmdl18300388.tmp,其中 18300388 是安装的 sessionId;
- 注释②处通过 IMediaContainerService 跨进程调用 DefaultContainerService 的 copyPackage 方法,这个方法会在 DefaultContainerService 所在的进程中将 APK 复制到临时存储目录,比如 /data/app/vmdl18300388.tmp/base.apk ,至此 APK 的复制工作结束。
3.APK的安装
3.1 APK安装时序图
在上述 APK 的赋值调用链的过程中,在 HandlerParams 的 startCopy 方法中,会调用 handleReturnCode 方法,时序图如下:
3.2 安装源码分析
PackageManagerService#handleReturnCode:
void handleReturnCode() { if (mArgs != null) { processPendingInstall(mArgs, mRet); } }
private void processPendingInstall(final InstallArgs args, final int currentStatus) { mHandler.post(new Runnable() { public void run() { mHandler.removeCallbacks(this); PackageInstalledInfo res = new PackageInstalledInfo(); res.setReturnCode(currentStatus); res.uid = -1; res.pkg = null; res.removedInfo = null; if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) { //安装前处理 args.doPreInstall(res.returnCode); //注释① synchronized (mInstallLock) { installPackageTracedLI(args, res); //注释② } //安装后收尾 args.doPostInstall(res.returnCode, res.uid); //注释③ } ... // 安装结束发送消息 Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0); // 注释⑤ mHandler.sendMessage(msg); } }); }
- 注释① 处检查APK的状态,在安装前确保安装环境的可靠,如果不可靠会清除复制的APK文件,注释③ 处会检测是否安装成功,失败则删除安装相关的目录和文件。安装完成之后在 注释⑤ 处会发送 POST_INSALL 消息通知已安装完成,此处稍后会说明。
- 注释② 处的 installPackageTracedLI 会调用 PMS 的 installPackageLI 方法:
PackageManagerService.java#installPackageLI:
private void installPackageLI(InstallArgs args, PackageInstalledInfo res) { ... PackageParser pp = new PackageParser(); pp.setSeparateProcesses(mSeparateProcesses); pp.setDisplayMetrics(mMetrics); pp.setCallback(mPackageParserCallback); Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage"); final PackageParser.Package pkg; try { //解析APK pkg = pp.parsePackage(tmpPackageFile, parseFlags); //注释① } catch (PackageParserException e) { res.setError("Failed parse during installPackageLI", e); return; } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } ... pp = null; String oldCodePath = null; boolean systemApp = false; synchronized (mPackages) { // 检查APK是否存在 if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) { String oldName = mSettings.getRenamedPackageLPr(pkgName);//获取没被改名前的包名 if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName) && mPackages.containsKey(oldName)) { pkg.setPackageName(oldName); //注释② pkgName = pkg.packageName; replace = true;//设置标志位表示是替换安装 if (DEBUG_INSTALL) Slog.d(TAG, "Replacing existing renamed package: oldName="
- oldName + " pkgName=" + pkgName); } ... } PackageSetting ps = mSettings.mPackages.get(pkgName); //查看Settings中是否存有要安装的APK的信息,如果有就获取签名信息 if (ps != null) { //注释③ if (DEBUG_INSTALL) Slog.d(TAG, "Existing package: " + ps); PackageSetting signatureCheckPs = ps; if (pkg.applicationInfo.isStaticSharedLibrary()) { SharedLibraryEntry libraryEntry = getLatestSharedLibraVersionLPr(pkg); if (libraryEntry != null) { signatureCheckPs = mSettings.getPackageLPr(libraryEntry.apk); } } //检查签名的正确性 if (ksms.shouldCheckUpgradeKeySetLocked(signatureCheckPs, scanFlags)) { if (!ksms.checkUpgradeKeySetLocked(signatureCheckPs, pkg)) { res.setError(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package "
- pkg.packageName + " upgrade keys do not match the "
- "previously installed version"); return; } } ... }
int N = pkg.permissions.size(); for (int i = N-1; i >= 0; i--) { //遍历每个权限,对权限进行处理 PackageParser.Permission perm = pkg.permissions.get(i); BasePermission bp = mSettings.mPermissions.get(perm.info.name);
} } } if (systemApp) { if (onExternal) { //系统APP不能在SD卡上替换安装 res.setError(INSTALL_FAILED_INVALID_INSTALL_LOCATION, "Cannot install updates to system apps on sdcard"); return; } elseif (instantApp) { //系统APP不能被Instant App替换 res.setError(INSTALL_FAILED_INSTANT_APP_INVALID, "Cannot update a system app with an instant app"); return; } } ... //重命名临时文件 if (!args.doRename(res.returnCode, pkg, oldCodePath)) { //注释④ res.setError(INSTALL_FAILED_INSUFFICIENT_STORAGE, "Failed rename"); return; }
startIntentFilterVerifications(args.user.getIdentifier(), replace, pkg);
try (PackageFreezer freezer = freezePackageForInstall(pkgName, installFlags, "installPackageLI")) {
if (replace) { //注释⑤
//替换安装
...
replacePackageLIF(pkg, parseFlags, scanFlags | SCAN_REPLACING, args.user,
installerPackageName, res, args.installReason);
} else {
//安装新的APK
installNewPackageLIF(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,
args.user, installerPackageName, volumeUuid, res, args.installReason);
}
}
synchronized (mPackages) { final PackageSetting ps = mSettings.mPackages.get(pkgName); if (ps != null) { //更新应用程序所属的用户 res.newUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true); ps.setUpdateAvailable(false/updateAvailable/); } ... } }
这里需要说明几点:
1、注释③处,会先检测 Settings 中保存有要安装的 APK 信息,则说明安装该 APK ,因此需要检验APK 的签名信息,确保安全的进行替换。
2、注释④处,会对临时文件重新命名,例如 /data/app/vmdl18300388.tmp/base.apk,重命名为 /data/app/包名-oONlnRRPYyleU63AveqbYA==/base.apk。新的包名后面带上的一串字母和数字的混合字符串,是使用MD5的方式对随机生成的16个字符进行加密之后的产物。
3、注释⑤处,根据 replace 来做区分,如果是替换安装就会调用replacePackageLIF方法,其方法内部还会对系统APP和非系统APP进行区分处理,如果是新安装APK会调用installNewPackageLIF方法
PackageManagerService.java#installNewPackageLIF:
private void installNewPackageLIF(PackageParser.Package pkg, final int policyFlags, int scanFlags, UserHandle user, String installerPackageName, String volumeUuid, PackageInstalledInfo res, int installReason) { ... try { //扫描APK PackageParser.Package newPackage = scanPackageTracedLI(pkg, policyFlags, scanFlags, System.currentTimeMillis(), user); //更新Settings信息 updateSettingsLI(newPackage, installerPackageName, null, res, user, installReason); if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) { //安装成功后,为新安装的应用程序准备数据 prepareAppDataAfterInstallLIF(newPackage);
} else { //安装失败则删除APK deletePackageLIF(pkgName, UserHandle.ALL, false, null, PackageManager.DELETE_KEEP_DATA, res.removedInfo, true, null); } } catch (PackageManagerException e) { res.setError("Package couldn't be installed in " + pkg.codePath, e); } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); }
4.发送消息
在上面 processPendingInstall 方法的源码分析中,在 注释⑤ 处会发送 POST_INSTALL 消息通知安装完成,那么接下来就来具体看一看在 PackageHandler 中是怎么处理这个消息的。
class PackageHandler extends Handler { void doHandleMessage(Message msg) { switch (msg.what) { ... ...
case POST_INSTALL: { ... ... handlePackagePostInstall(); ... ... break; } } } }
private void handlePackagePostInstall(...){ // 如果已经成功的安装了应用,在发送广播之前先授予一些必要的权限 grantRequestedRuntimePermissions(res.pkg, args.user.getIdentifier(), args.installGrantPermissions);
// 安装完成之后发送"ACTION_PACKAGE_ADDED"广播 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras, null, null, firstUsers);
// 如果是升级更新安装,还会发送ACTION_PACKAGE_REPLACED和ACTION_MY_PACKAGE_REPLACED广播 // 这两个广播不同之处在于PACKAGE_REPLACE将携带一个extra信息 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras, null, null, updateUsers); sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null, null, packageName, null, updateUsers);
// 执行gc操作 Runtime.getRuntime().gc();
// 调用FileInstallArgs的doPostDeleteLI进行资源清理 res.removedInfo.args.doPostDeleteLI(true);
// 回调onPackageInstalled方法 installObserver.onPackageInstalled(res.name, res.returnCode, res.returnMsg, extras); }
以上为主要的方法摘要,具体可总结为:
1、第一步:这里主要是先将安装信息从安装列列表中移除,这个也是前面在processPendingInstall中添加的
2、第二步:安装成功后,获取运行时权限
3、第三步:获取权限后,发送ACTION_PACKAGE_ADDED广播,告诉Laucher之流,更新icon
4、第四步:如果是升级更新则在发送两条广播
ACTION_PACKAGE_REPLACED:一个新版本的应用安装到设备上,替换换之前已经存在的版本
ACTION_MY_PACKAGE_REPLACED:应用的新版本替换旧版本被安装,只发给被更新的应用自己
5、第五步:如果安装包中设置了PRIVATE_FLAG_FORWARD_LOCK或者被要求安装在SD卡上,则调用sendResourcesChangedBroadcast方法来发送一个资源更改的广播
6、第六步:如果该应用是一个浏览器,则要清除浏览器设置,重新检查浏览器设置
7、第七步:强制调用gc,出发JVM进行垃圾回收操作
8、第八步:删除旧的安装信息
9、回调回调 IPackageInstallObserver2 的 packageInstalled 方法。告诉 PackageInstaller 安装结果。从而实现了安装回调到UI层
5.安装总结
上述几部分大致说明 PMS 处理 APK 的主要步骤,可总结如下:
1、当 PackageInstaller 将 APK 的信息提交给 PMS 处理,PMS 会通过向 PackageHandler 发送消息来驱动 APK 的复制和安装工作
2、PMS 发送 INIT_COPY 和 MCS_BOUND 类型的消息,控制 PackageHandler 来绑定 DefaultContainerService 来完成 APK 的复制等工作
3、复制 APK 完成之后,则开始进行安装 APK 的流程,包括安装前的检查、安装 APK 和安装后的收尾工作。
WMS篇
WindowManagerService服务(WMS)的实现是相当复杂的,毕竟它要管理的整个系统所有窗口的UI,而在任何一个系统中,窗口管理子系统都是极其复杂的。而WMS就是管理整个系统的窗口的。
WMS功能
- 窗口管理:负责启动、添加、删除窗口,管理窗口大小、层级,核心成员有:WindowContainer、RootWindowContainer、* DisplayContent、TaskStack、Task、AppWindowToken、WindowState;
- 窗口动画:由其子系统 WindowAnimator 管理;
- 输入系统中转站:通过对窗口的触摸从而产生触摸事件,由 InputMethodService(IMS)对触摸事件进行处理,它会寻找一个最合适的窗口处理触摸反馈信息;
- Surface 管理:为每个窗口分配一块 Surface,用于绘制要显示的内容。
WMS创建过程中线程关系
WMS 创建过程中涉及到的类主要有 SystemServer、WindowManagerService(WMS)、WindowManagerPolicy(WMP),它们都在 system_server 进程中运行,但是会在不同线程中运行,如下所示。
WMS启动流程
(1)main
public static void main(String[] args) { new SystemServer().run(); }
(2)run
/frameworks/base/services/java/com/android/server/SystemServer.java
private void run() { try { ... // 创建Looper Looper.prepareMainLooper(); // 加载libandroid_servers.so System.loadLibrary("android_servers"); // 创建系统的 Context:ContextImpl.createSystemContext(new ActivityThread()) createSystemContext(); // 创建 SystemServiceManager mSystemServiceManager = new SystemServiceManager(mSystemContext); LocalServices.addService(SystemServiceManager.class, mSystemServiceManager); ... } ... try { //启动引导服务,ActivityManagerService、ActivityTaskManagerService、PackageManagerService、PowerManagerService、DisplayManagerService 等 startBootstrapServices(); //启动核心服务,BatteryService、UsageStatusService 等 startCoreServices(); //启动其他服务,InputManagerService、WindowManagerService、CameraService、AlarmManagerService 等 startOtherServices(); ... } ... // 开启消息循环 Looper.loop(); }
(3)startOtherServices
/frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() { ... WindowManagerService wm = null; ... InputManagerService inputManager = null; ... try { ... inputManager = new InputManagerService(context); ... //PhoneWindowManager 是 WMP 的实现类 wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore, new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager); ServiceManager.addService(Context.WINDOW_SERVICE, wm, false, DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO); ServiceManager.addService(Context.INPUT_SERVICE, inputManager, false, DUMP_FLAG_PRIORITY_CRITICAL); ... mActivityManagerService.setWindowManager(wm); ... wm.onInitReady(); //initPolicy ... //wm 的 mInputManagerCallback 属性在定义时就被初始化 inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback()); inputManager.start(); ... } ... try { wm.displayReady(); //初始化屏幕信息 } ... try { wm.systemReady(); //通知 WMS 系统的初始化完成 } ... final Configuration config = wm.computeNewConfiguration(DEFAULT_DISPLAY); ... }
注意:在 WindowManagerService.main() 中,传入了 InputManagerService、PhoneWindowManager(WindowManagerPolicy 的实现类)、ActivityTaskManagerService(简称 ATMS)
通过 ServiceManager.addService() 将 Context.WINDOW_SERVICE 与 WMS 绑定,因此在其他进程中可以通过如下方式获取 WMS。
IBinder b = ServiceManager.getService(Context.WINDOW_SERVICE); IWindowManager wm = IWindowManager.Stub.asInterface(b);
(3)main
public static WindowManagerService main(final Context context, final InputManagerService im, final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy, ActivityTaskManagerService atm) { return main(context, im, showBootMsgs, onlyCore, policy, atm, SurfaceControl.Transaction::new); }
public static WindowManagerService main(final Context context, final InputManagerService im, final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy, ActivityTaskManagerService atm, TransactionFactory transactionFactory) { //在 android.display 线程中创建 WMS(此时 system_server 线程阻塞) DisplayThread.getHandler().runWithScissors(() -> sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy, atm, transactionFactory), 0); return sInstance; }
WMS 初始化
本节主要研究 WMS 在初始化时做的工作。
(1)构造函数
/frameworks/base/services/java/com/android/server/wm/WindowManagerService.java
private WindowManagerService(Context context, InputManagerService inputManager, boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy, ActivityTaskManagerService atm, TransactionFactory transactionFactory) { ... mAtmService = atm; mContext = context; ... mInputManager = inputManager; mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); ... mPolicy = policy; //动画管理 mAnimator = new WindowAnimator(this); //根容器,其子容器是 DisplayContent mRoot = new RootWindowContainer(this); mWindowPlacerLocked = new WindowSurfacePlacer(this); ... //mPolicy 是 PhoneWindowManager 对象,WindowManagerPolicy 的实现类 LocalServices.addService(WindowManagerPolicy.class, mPolicy); ... //DM mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE); //PM mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); //AMS mActivityManager = ActivityManager.getService(); //ATMS mActivityTaskManager = ActivityTaskManager.getService(); //ActivityManagerInternal mAmInternal = LocalServices.getService(ActivityManagerInternal.class); //ActivityTaskManagerInternal mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class); ... //PackageManagerInternal mPmInternal = LocalServices.getService(PackageManagerInternal.class); //添加本地服务 LocalServices.addService(WindowManagerInternal.class, new LocalService()); } LocalService 是 WMS 的内部类,也是 WindowManagerInternal 的实现类。
(2)初始化 WMP
public void onInitReady() { //初始化 WMP initPolicy(); ... //打开 Surface 事务:SurfaceControl.openTransaction() openSurfaceTransaction(); ... } private void initPolicy() { //在 android.ui 线程中执行 UiThread.getHandler().runWithScissors(new Runnable() { @Override public void run() { WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper()); mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this); } }, 0); }
(3)初始化 Display
public void displayReady() { synchronized (mGlobalLock) { if (mMaxUiWidth > 0) { mRoot.forAllDisplays(displayContent -> displayContent.setMaxUiWidth(mMaxUiWidth)); } final boolean changed = applyForcedPropertiesForDefaultDisplay(); mAnimator.ready(); ... } ... updateCircularDisplayMaskIfNeeded(); }
(4)通知系统 WMS 初始化完成
public void systemReady() { mSystemReady = true; mPolicy.systemReady(); mRoot.forAllDisplayPolicies(DisplayPolicy::systemReady); mTaskSnapshotController.systemReady(); ... UiThread.getHandler().post(mSettingsObserver::updateSystemUiSettings); UiThread.getHandler().post(mSettingsObserver::updatePointerLocation); ... }
总结
服务端
- AMS 主要用于管理所有应用程序的Activity
- WMS 管理各个窗口,隐藏,显示等
- PMS 用来管理跟踪所有应用APK,安装,解析,控制权限等.
- 还有用来处理触摸消息的两个类KeyInputQueue和InputDispatchThread,一个用来读消息,一个用来分发消息.。
客户端
- 主要包括ActivityThread,Activity,DecodeView及父类View,PhoneWindow,ViewRootImpl及内部类等
- ActivityThread主要用来和AMS通讯的客户端,Activity是我们编写应用比较熟悉的类。
这里只是简单的认识和归纳总结一下,非常感谢以上博主的贡献。后期我会深入了解Android系统的源码,然后专开一个专栏来详细介绍PMS、AMS、WMS。
技术资料提供:Frame Work源码解析手册
最后
如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。
如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。
一、架构师筑基必备技能
1、深入理解Java泛型
2、注解深入浅出
3、并发编程
4、数据传输与序列化
5、Java虚拟机原理
6、高效IO
……
二、Android百大框架源码解析
1.Retrofit 2.0源码解析
2.Okhttp3源码解析
3.ButterKnife源码解析
4.MPAndroidChart 源码解析
5.Glide源码解析
6.Leakcanary 源码解析
7.Universal-lmage-Loader源码解析
8.EventBus 3.0源码解析
9.zxing源码分析
10.Picasso源码解析
11.LottieAndroid使用详解及源码解析
12.Fresco 源码分析——图片加载流程
三、Android性能优化实战解析
- 腾讯Bugly:对字符串匹配算法的一点理解
- 爱奇艺:安卓APP崩溃捕获方案——xCrash
- 字节跳动:深入理解Gradle框架之一:Plugin, Extension, buildSrc
- 百度APP技术:Android H5首屏优化实践
- 支付宝客户端架构解析:Android 客户端启动速度优化之「垃圾回收」
- 携程:从智行 Android 项目看组件化架构实践
- 网易新闻构建优化:如何让你的构建速度“势如闪电”?
- …
四、高级kotlin强化实战
1、Kotlin入门教程
2、Kotlin 实战避坑指南
3、项目实战《Kotlin Jetpack 实战》
- 从一个膜拜大神的 Demo 开始
- Kotlin 写 Gradle 脚本是一种什么体验?
- Kotlin 编程的三重境界
- Kotlin 高阶函数
- Kotlin 泛型
- Kotlin 扩展
- Kotlin 委托
- 协程“不为人知”的调试技巧
- 图解协程:suspend
五、Android高级UI开源框架进阶解密
1.SmartRefreshLayout的使用
2.Android之PullToRefresh控件源码解析
3.Android-PullToRefresh下拉刷新库基本用法
4.LoadSir-高效易用的加载反馈页管理框架
5.Android通用LoadingView加载框架详解
6.MPAndroidChart实现LineChart(折线图)
7.hellocharts-android使用指南
8.SmartTable使用指南
9.开源项目android-uitableview介绍
10.ExcelPanel 使用指南
11.Android开源项目SlidingMenu深切解析
12.MaterialDrawer使用指南
六、NDK模块开发
1、NDK 模块开发
2、JNI 模块
3、Native 开发工具
4、Linux 编程
5、底层图片处理
6、音视频开发
7、机器学习
七、Flutter技术进阶
1、Flutter跨平台开发概述
2、Windows中Flutter开发环境搭建
3、编写你的第一个Flutter APP
4、Flutter开发环境搭建和调试
5、Dart语法篇之基础语法(一)
6、Dart语法篇之集合的使用与源码解析(二)
7、Dart语法篇之集合操作符函数与源码分析(三)
…
八、微信小程序开发
1、小程序概述及入门
2、小程序UI开发
3、API操作
4、购物商场项目实战……
全套视频资料:
一、面试合集
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新