1. 什么是PMS、AMS
- PackageManageService简称PMS,它是用来管理所有包信息,包括应用安装、卸载、更新以及解析AndroidManifest,将解析出来的数据生成javabean,保存在ArrayList中。
- ActivityManagerService简称AMS,主要负责android系统中,四大组件的启动、切换、调度以及应用进程的管理 和调度。AMS在启动app做相关工作,都与PMS有关。
1.1. 系统启动流程
我们了解app安装启动流程前,我们先来简单的聊下android启动的流程,我们知道,当bootloader启动后在去启动kernel,kernel启动完后,在用户空间启动init进程,再通过init进程,来读取init.rc中的相关配置,init进程会启动ServerManager和Zygote进程,Zygote进程又会启动创建Java虚拟机并为Java虚拟机注册JNI方法,创建服务器端Socket,启动SystemServer进程。Systemserver会启动各种系统服务,这些服务包括AMS和PMS。
1.2. PMS解包流程
- PMS已经起来了,那它是怎么解析安装包的呢?
系统的apk一般安装system/app目录下,用户安装到一般在/data/app目录下,系统启动后,PMS会去扫描这些目录,PMS找到包中的Androidmainfest.xml文件,通过dom解析的方式,将相关信息保存在内存中,并且提供查询功能。我们一起来看看PackageServiceManager.java这个类,源码路径/framework/base/comandroid/server/pm
...
//读取data目录下的app
File dataDir = Environment.getDataDirectory();
mAppInstallDir = new File(dataDir, "app");
...
//读取system系统目录下的apk文件
final File systemAppDir = new File(Environment.getRootDirectory(), "app");
scanDirTracedLI(systemAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
...
private void scanDirLI(File dir, int parseFlags, int scanFlags, long currentTime) {
...
for (File file : files) {
//判断是否是以.apk结尾的文件
final boolean isPackage = (isApkFile(file) || file.isDirectory())
&& !PackageInstallerService.isStageName(file.getName());
if (!isPackage) {
// Ignore entries which are not packages
continue;
}
//添加到子线程交给ParallelPackageParser解析
parallelPackageParser.submit(file, parseFlags);
fileCount++;
}
...
public void submit(File scanFile, int parseFlags) {
...
PackageParser pp = new PackageParser();
pp.setSeparateProcesses(mSeparateProcesses);
pp.setOnlyCoreApps(mOnlyCore);
pp.setDisplayMetrics(mMetrics);
pp.setCacheDir(mCacheDir);
pp.setCallback(mPackageParserCallback);
pr.scanFile = scanFile;
//交给packageParse解析
pr.pkg = parsePackage(pp, scanFile, parseFlags);
}
...
protected PackageParser.Package parsePackage(PackageParser packageParser, File scanFile,
int parseFlags) throws PackageParser.PackageParserException {
return packageParser.parsePackage(scanFile, parseFlags, true /* useCaches */);
}
..
public Package parsePackage(File packageFile, int flags, boolean useCaches)
throws PackageParserException {
Package parsed = useCaches ? getCachedResult(packageFile, flags) : null;
//如果有缓存直接返回
if (parsed != null) {
return parsed;
}
//包文件是否是文件夹
if (packageFile.isDirectory()) {
parsed = parseClusterPackage(packageFile, flags);
} else {
parsed = parseMonolithicPackage(packageFile, flags);
}
cacheResult(packageFile, flags, parsed);
return parsed;
}
...
public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
//解析apk
final Package pkg = parseBaseApk(apkFile, assets, flags);
pkg.setCodePath(apkFile.getAbsolutePath());
pkg.setUse32bitAbi(lite.use32bitAbi);
return pkg;
}
...
private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
throws PackageParserException {
final String apkPath = apkFile.getAbsolutePath();
final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
Resources res = null;
//开启dom解析
XmlResourceParser parser = null;
res = new Resources(assets, mMetrics, null);
parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
final String[] outError = new String[1];
final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
return pkg;
}
用一个简单的图来总结下PMS流程
2. 我们在来看看AMS是怎么和PMS联系在一起的!
1.Activity启动
我们在启动一个应用时都会调用startAcitivty这个方法,这个方法总体会经历三个步骤
1.告知ams要启动一个指定的activity
2.AMS从PMS中查找要启动的Activty的信息
3.启动指定的Activity
我们通过代码来分析下这个过程:
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1);
}
}
@Override
public void startActivityForResult(
String who, Intent intent, int requestCode, @Nullable Bundle options) {
//委托给Instrumentation来启动
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, who,
intent, requestCode, options);
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, who,
intent, requestCode, options);
由代码我们可以看到,startActivity最终委托给Instrumentation来启动,我们一起来看下这个类
public ActivityResult execStartActivity(
// 核心代码,找到ams 通知它我要启动Activity
int result = ActivityManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target, requestCode, 0, null, options);
}
好了Instrumentation也只是告知Ams要启动一个Activity,那它又是怎么做的呢,
我们知道app和ams属于进程间通信,他们之间是通过binder来通信的,把上面的
代码拆分开来, ActivityManager.getService()这个部分是获取binder对象映射,后
面.startActivity(xxx)就是执行AMS进程中的方法,我们一起来看看代码,先跟进去
getService这个方法,
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
//通过ServiceManager获取AMS服务
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
//IActivity是binder的代码
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
好了,这个里面拿到了ams的代理binder,最终执行startActivity时会去执行ams里面的方法,我们跟进去瞧瞧
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
上面的代码最终会执行到ActivityStarter这个类中
final int startActivityMayWait(IApplicationThread caller, int callingUid,
String callingPackage, Intent intent, String resolvedType,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, WaitResult outResult,
Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
IActivityContainer iContainer, TaskRecord inTask, String reason) {
```ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
...
return res
}
...
}
我们去看看mSupervisor这个里面又是怎么调用的
ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId, int flags) {
synchronized (mService) {
//调用ams里面的方法
return mService.getPackageManagerInternalLocked().resolveIntent(intent, resolvedType,
PackageManager.MATCH_INSTANT | PackageManager.MATCH_DEFAULT_ONLY | flags
| ActivityManagerService.STOCK_PM_FLAGS, userId);
}
}
这个又走到ams里面去了,我们在进ams看看
PackageManagerInternal getPackageManagerInternalLocked() {
if (mPackageManagerInt == null) {
//这个就走到PackageManagerInternal里面去了
mPackageManagerInt = LocalServices.getService(PackageManagerInternal.class);
}
return mPackageManagerInt;
}
我们在来看看PackageManagerInternal
public abstract class PackageManagerInternal{}
原来是个抽象类,那它的实现在哪里呢,我们在PackManagerService中找到了它
private class PackageManagerInternalImpl extends PackageManagerInternal {
...
@Override
public ResolveInfo resolveIntent(Intent intent, String resolvedType,
int flags, int userId) {
//作为PackManagerService的内部类,转发am的请求,并把pms中存储的相关Activity信息转给ams
return resolveIntentInternal(
intent, resolvedType, flags, userId, true /*resolveForStart*/);
}
...
}
好了,AMS这就和PMS的联系建立起来了。