本文基于Android_9.0、kernel_3.18源码
PMS的作用
在讨论PMS作用之前,我们不妨考虑一个问题:如果我们想要打开一个app,要经历哪些过程?
1、遍历data/app目录找到apk
2、解析AndroidManifest.xml文件
3、找到要启动的Activity,加载class
4、实例化Activity对象,进行展示
显然如果每次启动一个app都进行这几步操作,是非常消耗资源的,因此google设计了PMS、AMS来完成这些工作:
前两步由PMS完成,在开机时解析xml,然后对解析的数据进行缓存,加快App启动速度;
后两步由AMS完成,在真正启动的时候进行操作。
PMS启动流程

frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
frameworks/base/services/core/java/com/android/server/pm/ParallelPackageParser.java
frameworks/base/core/java/android/content/pm/PackageParser.java
由Binder(五)服务注册流程-发送注册请求可知:
手机开机后会启动system_server进程,然后调用SystemServer的main方法,在main方法中通过startBootstrapServices启动PMS。
private void startBootstrapServices() {
...
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
...
}
1、PMS->main()
public static PackageManagerService main(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
// Self-check for initial settings.
PackageManagerServiceCompilerMapping.checkProperties();
// 创建对象
PackageManagerService m = new PackageManagerService(context, installer,
factoryTest, onlyCore);
m.enableSystemUserPackages();
// 向ServiceManager注册
ServiceManager.addService("package", m);
final PackageManagerNative pmn = m.new PackageManagerNative();
ServiceManager.addService("package_native", pmn);
return m;
}
在PMS的main方法中,创建了PMS对象,然后向servicemanager注册服务。
2、PMS构造方法
public class Environment {
...
private static final File DIR_ANDROID_DATA = getDirectory(ENV_ANDROID_DATA, "/data");
public static File getDataDirectory() {
return DIR_ANDROID_DATA;
}
...
}
public class PackageManagerService extends IPackageManager.Stub
implements PackageSender {
// app的安装目录
private static final File sAppInstallDir = new File(Environment.getDataDirectory(), "app");
public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
...
// 扫描App的安装目录
scanDirTracedLI(sAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
...
}
private void scanDirTracedLI(File scanDir, final int parseFlags, int scanFlags, long currentTime) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir [" + scanDir.getAbsolutePath() + "]");
try {
scanDirLI(scanDir, parseFlags, scanFlags, currentTime);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
...
}
PMS的构造方法代码比较多,这里只分析扫描app的操作,通过scanDirTracedLI()调用到scanDirLI()扫描安装目录。
3、scanDirLI()
private void scanDirLI(File scanDir, int parseFlags, int scanFlags, long currentTime) {
final File[] files = scanDir.listFiles();
...
// 新建ParallelPackageParser
try (ParallelPackageParser parallelPackageParser = new ParallelPackageParser(
mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir,
mParallelPackageParserCallback)) {
int fileCount = 0;
// 遍历找到app
for (File file : files) {
final boolean isPackage = (isApkFile(file) || file.isDirectory())
&& !PackageInstallerService.isStageName(file.getName());
if (!isPackage) {
// Ignore entries which are not packages
continue;
}
// 线程池操作
parallelPackageParser.submit(file, parseFlags);
fileCount++;
}
// 遍历处理结果
for (; fileCount > 0; fileCount--) {
ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take();
Throwable throwable = parseResult.throwable;
int errorCode = PackageManager.INSTALL_SUCCEEDED;
if (throwable == null) {
...
try {
if (errorCode == PackageManager.INSTALL_SUCCEEDED) {
scanPackageChildLI(parseResult.pkg, parseFlags, scanFlags,
currentTime, null);
}
} catch (PackageManagerException e) {...}
}
...
}
}
}
在scanDirLI方法中:
首先,新建ParallelPackageParser对象,用来解析;
然后,遍历安装目录,判断是否是app目录;
再然后,将得到的目录通过submit交由ParallelPackageParser处理;
最后,得到结果后,通过scanPackageChildLI再次处理。
4、ParallelPackageParser
class ParallelPackageParser implements AutoCloseable {
// 线程池
private final ExecutorService mService = ConcurrentUtils.newFixedThreadPool(MAX_THREADS,
"package-parsing-thread", Process.THREAD_PRIORITY_FOREGROUND);
// 存储解析结果
private final BlockingQueue<ParseResult> mQueue = new ArrayBlockingQueue<>(QUEUE_CAPACITY);
public void submit(File scanFile, int parseFlags) {
// 提交到线程池
mService.submit(() -> {
ParseResult pr = new ParseResult();
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parallel parsePackage [" + scanFile + "]");
try {
// 新建PackageParser
PackageParser pp = new PackageParser();
pp.setSeparateProcesses(mSeparateProcesses);
pp.setOnlyCoreApps(mOnlyCore);
pp.setDisplayMetrics(mMetrics);
pp.setCacheDir(mCacheDir);
pp.setCallback(mPackageParserCallback);
pr.scanFile = scanFile;
// 对package进行解析
pr.pkg = parsePackage(pp, scanFile, parseFlags);
} catch (Throwable e) {
pr.throwable = e;
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
try {
// 将处理结果添加到mQueue中
mQueue.put(pr);
} catch (InterruptedException e) {
...
}
});
}
@VisibleForTesting
protected PackageParser.Package parsePackage(PackageParser packageParser, File scanFile,
int parseFlags) throws PackageParser.PackageParserException {
return packageParser.parsePackage(scanFile, parseFlags, true /* useCaches */);
}
...
}
ParallelPackageParser定义了mService线程池对数据进行解析;定义了BlockingQueue类型的mQueue对结果进行存储。
submit方法将解析任务提交给线程池,在任务中:创建PackageParser对象,借用它的parsePackage对package解析;解析完毕后,将解析结果添加到mQueue中。
5、PackageParser.java->parsePackage()
public PackageParser.Package parsePackage(File packageFile, int flags, boolean useCaches)
throws PackageParser.PackageParserException {
// 如果有缓存,直接返回缓存
PackageParser.Package parsed = useCaches ? getCachedResult(packageFile, flags) : null
if (parsed != null) {
return parsed;
}
long parseTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
// 解析package
if (packageFile.isDirectory()) {
parsed = parseClusterPackage(packageFile, flags);
} else {
parsed = parseMonolithicPackage(packageFile, flags);
}
long cacheTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
// 缓存
cacheResult(packageFile, flags, parsed);
...
return parsed;
}
首先,通过getCachedResult查找本地缓存,如果有的话直接返回;
然后,对package解析;
最后,通过cacheResult对解析结果进行缓存。
6、包解析
private PackageParser.Package parseClusterPackage(File packageDir, int flags) throws PackageParser.PackageParserException {
// 轻量解析
final PackageParser.PackageLite lite = parseClusterPackageLite(packageDir, 0);
...
try {
final AssetManager assets = assetLoader.getBaseAssetManager();
final File baseApk = new File(lite.baseCodePath);
// 解析
final PackageParser.Package pkg = parseBaseApk(baseApk, assets, flags);
...
// 赋值
if (!ArrayUtils.isEmpty(lite.splitNames)) {
final int num = lite.splitNames.length;
pkg.splitNames = lite.splitNames;
pkg.splitCodePaths = lite.splitCodePaths;
pkg.splitRevisionCodes = lite.splitRevisionCodes;
pkg.splitFlags = new int[num];
pkg.splitPrivateFlags = new int[num];
pkg.applicationInfo.splitNames = pkg.splitNames;
pkg.applicationInfo.splitDependencies = splitDependencies;
pkg.applicationInfo.splitClassLoaderNames = new String[num];
for (int i = 0; i < num; i++) {
final AssetManager splitAssets = assetLoader.getSplitAssetManager(i);
parseSplitApk(pkg, i, splitAssets, flags);
}
}
pkg.setCodePath(packageDir.getCanonicalPath());
pkg.setUse32bitAbi(lite.use32bitAbi);
return pkg;
} catch (IOException e) {...} finally {
IoUtils.closeQuietly(assetLoader);
}
}
public PackageParser.Package parseMonolithicPackage(File apkFile, int flags) throws PackageParser.PackageParserException {
// 轻量解析
final PackageParser.PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
// 核心app的校验
if (mOnlyCoreApps) {
if (!lite.coreApp) {
throw new PackageParser.PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
"Not a coreApp: " + apkFile);
}
}
final SplitAssetLoader assetLoader = new DefaultSplitAssetLoader(lite, flags);
try {
// 解析
final PackageParser.Package pkg = parseBaseApk(apkFile, assetLoader.getBaseAssetManager(), flags);
pkg.setCodePath(apkFile.getCanonicalPath());
pkg.setUse32bitAbi(lite.use32bitAbi);
return pkg;
} catch (IOException e) {...} finally {
IoUtils.closeQuietly(assetLoader);
}
}
Google在Android 5.0引入了Split APK机制,用来解决65536上限,以及APK安装包越来越大等问题;这样,apk就分为两类:
1、Single APK:安装文件为一个完整的APK;
2、Mutiple APK:安装文件在一个文件目录中,其内部有多个被拆分的APK,这些APK由一个 base APK和N个split APK组成。
因此解析的方式也分为两种,parseMonolithicPackage用来解析single Apk、parseClusterPackage用来解析Mutiple Apk。
它们内部都调用轻量解析和parseBaseApk,解析的主要操作基本一致。
7、parseBaseApk()
public static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
private PackageParser.Package parseBaseApk(File apkFile, AssetManager assets, int flags)
throws PackageParser.PackageParserException {
final String apkPath = apkFile.getAbsolutePath();
...
XmlResourceParser parser = null;
try {
final int cookie = assets.findCookieForPath(apkPath);
if (cookie == 0) {
throw new PackageParser.PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
"Failed adding asset path: " + apkPath);
}
// 打开AndroidManifest.xml文件
parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
final Resources res = new Resources(assets, mMetrics, null);
final String[] outError = new String[1];
// 解析
final PackageParser.Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
...
return pkg;
} catch (PackageParser.PackageParserException e) {...} catch (Exception e) {...} finally {
IoUtils.closeQuietly(parser);
}
}
在parseBaseApk中,打开AndroidManifest.xml文件,然后调用parseBaseApk重载方法进行解析。
private PackageParser.Package parseBaseApk(String apkPath, Resources res, XmlResourceParser parser, int flags
String[] outError) throws XmlPullParserException, IOException {
final String splitName;
final String pkgName;
try {
// 解析包名
Pair<String, String> packageSplit = parsePackageSplitNames(parser, parser);
pkgName = packageSplit.first;
splitName = packageSplit.second;
...
} catch (PackageParser.PackageParserException e) {...}
...
final PackageParser.Package pkg = new PackageParser.Package(pkgName);
// 解析app相关参数
TypedArray sa = res.obtainAttributes(parser, com.android.internal.R.styleable.AndroidManifest);
pkg.mVersionCode = sa.getInteger(
com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
pkg.mVersionCodeMajor = sa.getInteger(
com.android.internal.R.styleable.AndroidManifest_versionCodeMajor, 0);
...
return parseBaseApkCommon(pkg, null, res, parser, flags, outError);
}
在重载方法中,解析包名,然后创建Package对象,并且解析一些app的基础参数:VersionCode、VersionName等;最后通过parseBaseApkCommon进一步解析。
8、parseBaseApkCommon()
private PackageParser.Package parseBaseApkCommon(PackageParser.Package pkg, Set<String> acceptedTags, Resources res,
XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException,
IOException {
int type;
boolean foundApp = false;
TypedArray sa = res.obtainAttributes(parser, com.android.internal.R.styleable.AndroidManifest);
...
// 解析标签
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}
String tagName = parser.getName();
...
// 解析application标签
if (tagName.equals(TAG_APPLICATION)) {
...
if (!parseBaseApplication(pkg, res, parser, flags, outError)) {
return null;
}
} else if (tagName.equals(TAG_OVERLAY)) {
...
} else if (tagName.equals(TAG_KEY_SETS)) {
...
} else if (tagName.equals(TAG_PERMISSION_GROUP)) {// 解析权限
...
} else if (tagName.equals(TAG_PERMISSION)) {// 解析权限
...
} else if (tagName.equals(TAG_PERMISSION_TREE)) {
...
} else if (tagName.equals(TAG_USES_PERMISSION)) {
...
} else if (tagName.equals(TAG_USES_PERMISSION_SDK_M)
|| tagName.equals(TAG_USES_PERMISSION_SDK_23)) {
...
} else if (tagName.equals(TAG_USES_CONFIGURATION)) {
...
} else if (tagName.equals(TAG_USES_FEATURE)) {
...
} else if (tagName.equals(TAG_FEATURE_GROUP)) {
...
} else if (tagName.equals(TAG_USES_SDK)) {
...
} else if (tagName.equals(TAG_SUPPORT_SCREENS)) {
...
} else if (tagName.equals(TAG_PROTECTED_BROADCAST)) {
...
} else if (tagName.equals(TAG_INSTRUMENTATION)) {
...
} else if (tagName.equals(TAG_ORIGINAL_PACKAGE)) {
...
} else if (tagName.equals(TAG_ADOPT_PERMISSIONS)) {
...
} else if (tagName.equals(TAG_USES_GL_TEXTURE)) {
...
} else if (tagName.equals(TAG_COMPATIBLE_SCREENS)) {
...
} else if (tagName.equals(TAG_SUPPORTS_INPUT)) {//
...
} else if (tagName.equals(TAG_EAT_COMMENT)) {
...
} else if (tagName.equals(TAG_PACKAGE)) {
...
} else if (tagName.equals(TAG_RESTRICT_UPDATE)) {
...
} else if (RIGID_PARSER) {
...
} else {
...
}
}
...
return pkg;
}
该方法会对AndroidManifest.xml中的标签进行解析,包括application、uses-permission等,我们主要关注对application的解析。
9、parseBaseApplication()
private boolean parseBaseApplication(PackageParser.Package owner, Resources res,
XmlResourceParser parser, int flags, String[] outError)
throws XmlPullParserException, IOException {
final ApplicationInfo ai = owner.applicationInfo;
final String pkgName = owner.applicationInfo.packageName;
TypedArray sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifestApplication);
// 解析application定义的内容,名称、icon等
if (!parsePackageItemInfo(owner, ai, outError,
"<application>", sa, false /*nameRequired*/,
com.android.internal.R.styleable.AndroidManifestApplication_name,
com.android.internal.R.styleable.AndroidManifestApplication_label,
com.android.internal.R.styleable.AndroidManifestApplication_icon,
com.android.internal.R.styleable.AndroidManifestApplication_roundIcon,
com.android.internal.R.styleable.AndroidManifestApplication_logo,
com.android.internal.R.styleable.AndroidManifestApplication_banner)) {
sa.recycle();
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
...
int type;
boolean hasActivityOrder = false;
boolean hasReceiverOrder = false;
boolean hasServiceOrder = false;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}
String tagName = parser.getName();
if (tagName.equals("activity")) {// 解析activity
PackageParser.Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
owner.baseHardwareAccelerated);
...
// 添加到package中
owner.activities.add(a);
} else if (tagName.equals("receiver")) {// 解析receiver
PackageParser.Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
true, false);
...
owner.receivers.add(a);
} else if (tagName.equals("service")) {// 解析service
PackageParser.Service s = parseService(owner, res, parser, flags, outError, cachedArgs);
...
owner.services.add(s);
} else if (tagName.equals("provider")) {// 解析provider
...
owner.providers.add(p);
} else if (tagName.equals("activity-alias")) {
...
} else if (parser.getName().equals("meta-data")) {
...
} else if (tagName.equals("static-library")) {
...
} else if (tagName.equals("library")) {
...
} else if (tagName.equals("uses-static-library")) {
...
} else if (tagName.equals("uses-library")) {
...
} else if (tagName.equals("uses-package")) {
...
} else {
...
}
}
// 排序
if (hasActivityOrder) {
Collections.sort(owner.activities, (a1, a2) -> Integer.compare(a2.order, a1.order));
}
if (hasReceiverOrder) {
Collections.sort(owner.receivers, (r1, r2) -> Integer.compare(r2.order, r1.order));
}
if (hasServiceOrder) {
Collections.sort(owner.services, (s1, s2) -> Integer.compare(s2.order, s1.order));
}
...
return true;
}
对四大组件进行解析,并加入到package中。具体的解析内容无非是对于xml各种标签的识别,不再详述。
10、scanPackageChildLI()
private PackageParser.Package scanPackageChildLI(PackageParser.Package pkg,
final @ParseFlags int parseFlags, @PackageManagerService.ScanFlags int scanFlags, long currentTime,
@Nullable UserHandle user)
throws PackageManagerException {
...
// Scan the parent
PackageParser.Package scannedPkg = addForInitLI(pkg, parseFlags,
scanFlags, currentTime, user);
// Scan the children
final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
for (int i = 0; i < childCount; i++) {
PackageParser.Package childPackage = pkg.childPackages.get(i);
addForInitLI(childPackage, parseFlags, scanFlags,
currentTime, user);
}
if ((scanFlags & SCAN_CHECK_ONLY) != 0) {
return scanPackageChildLI(pkg, parseFlags, scanFlags, currentTime, user);
}
return scannedPkg;
}
private PackageParser.Package addForInitLI(PackageParser.Package pkg,
@ParseFlags int parseFlags, @PackageManagerService.ScanFlags int scanFlags, long currentTime,
@Nullable UserHandle user)
throws PackageManagerException {
...
if (scanSystemPartition && isSystemPkgUpdated && !isSystemPkgBetter) {
...
synchronized (mPackages) {
if (!mPackages.containsKey(pkg.packageName)) {
mPackages.put(pkg.packageName, pkg);
}
}
...
}
...
final PackageParser.Package scannedPkg = scanPackageNewLI(pkg, parseFlags, scanFlags
| SCAN_UPDATE_SIGNATURE, currentTime, user);
...
return scannedPkg;
}
回到scanDirLI中,代码会从mQueue中取到解析的结果,进行扫描;然后通过addForInitLI将结果缓存到PMS的mPackages中。
11、commitPackageSettings
private void commitPackageSettings(PackageParser.Package pkg,
@Nullable PackageParser.Package oldPkg, PackageSetting pkgSetting, UserHandle user,
final @ScanFlags int scanFlags, boolean chatty) {
...
mProviders.addProvider(p);
...
mServices.addService(s);
...
mReceivers.addActivity(a, "receiver");
...
mActivities.addActivity(a, "activity");
}
在scanPackageNewLI中,会通过如下调用链scanPackageNewLI->commitScanResultsLocked->commitPackageSettings调用到commitPackageSettings,将四大组件的信息缓存在PMS中。
至此,整个package解析完毕,通过解析生成package实体,其中包括app的基础信息、权限配置、四大组件信息等;并通过PMS的mPackages进行缓存。
新应用安装的解析流程

packages/apps/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java
xref/frameworks/base/core/java/android/content/pm/PackageInstaller.java
![]() |
![]() |
---|
通过adb shell 命令,结合dumpsys window | grep mCurrentFocus 可以看到当前运行的界面,在安装apk的时候,我们可以看到,最终是通过com.android.packageinstaller.InstallInstalling 页面进行安装。

1、InstallInstalling
public class InstallInstalling extends Activity {
...
@Override
protected void onResume() {
...
if (mInstallingTask == null) {
PackageInstaller installer = getPackageManager().getPackageInstaller();
PackageInstaller.SessionInfo sessionInfo = installer.getSessionInfo(mSessionId);
if (sessionInfo != null && !sessionInfo.isActive()) {
// 创建InstallingAsyncTask
mInstallingTask = new InstallingAsyncTask();
mInstallingTask.execute();
} else {...}
}
}
private final class InstallingAsyncTask extends AsyncTask<Void, Void,
PackageInstaller.Session> {
volatile boolean isDone;
@Override
protected PackageInstaller.Session doInBackground(Void... params) {
PackageInstaller.Session session;
try {
session = getPackageManager().getPackageInstaller().openSession(mSessionId);
} catch (IOException e) {
return null;
}
...
}
@Override
protected void onPostExecute(PackageInstaller.Session session) {
if (session != null) {
...
// 通过session.commi通知PMS
session.commit(pendingIntent.getIntentSender());
mCancelButton.setEnabled(false);
setFinishOnTouchOutside(false);
} else {...}
}
}
...
}
在onResume中创建InstallingAsyncTask并启动,在InstallingAsyncTask中,执行完doInBackground后通过session.commit通知PMS。
2、PackageInstallerSession.commit
PackageInstaller.Session.commit会通过aidl 调用到PackageInstallerSession.commit,之后的事情发生在服务端。
@Override
public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
...
synchronized (mLock) {
...
mHandler.obtainMessage(MSG_COMMIT).sendToTarget();
}
...
}
private final Handler.Callback mHandlerCallback = new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MSG_EARLY_BIND:
...
break;
case MSG_COMMIT:
synchronized (mLock) {
try {
commitLocked();
} catch (PackageManagerException e) {...}
}
break;
...
}
return true;
}
};
在mHandlerCallback中通过commitLocked进行处理。
3、commitLocked
private void commitLocked()
throws PackageManagerException {
...
mPm.installStage(mPackageName, stageDir, localObserver, params,
mInstallerPackageName, mInstallerUid, user, mSigningDetails);
}
通过commitLocked会调用到PMS的installStage。
4、installStage
void installStage(String packageName, File stagedDir,
IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams,
String installerPackageName, int installerUid, UserHandle user,
PackageParser.SigningDetails signingDetails) {
...
final Message msg = mHandler.obtainMessage(INIT_COPY);
...
final InstallParams params = new InstallParams(origin, null, observer,
sessionParams.installFlags, installerPackageName, sessionParams.volumeUuid,
verificationInfo, user, sessionParams.abiOverride,
sessionParams.grantedRuntimePermissions, signingDetails, installReason);
params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
msg.obj = params;
...
mHandler.sendMessage(msg);
}
生成InstallParams,并发送INIT_COPY由handler处理。
5、消息处理
public void handleMessage(Message msg) {
try {
doHandleMessage(msg);
} finally {...}
}
void doHandleMessage(Message msg) {
switch (msg.what) {
...
case INIT_COPY: {
// 获取params,注意这里是InstallParams类型
HandlerParams params = (HandlerParams) msg.obj;
...
if (!mBound) {...} else {
// 添加到mPendingInstalls中
mPendingInstalls.add(idx, params);
// Already bound to the service. Just make
// sure we trigger off processing the first request.
if (idx == 0) {
// 如果是第一个,则发送启动消息
mHandler.sendEmptyMessage(MCS_BOUND);
}
}
break;
}
case MCS_BOUND: {
...
if (mContainerService == null) {
...
} else if (mPendingInstalls.size() > 0) {
// 获取params,注意这里是InstallParams类型
HandlerParams params = mPendingInstalls.get(0);
if (params != null) {
...
// 调用startCopy
if (params.startCopy()) {
...
if (mPendingInstalls.size() > 0) {
mPendingInstalls.remove(0);
}
if (mPendingInstalls.size() == 0) {
...
} else {
...
// 如果没处理完,继续处理
mHandler.sendEmptyMessage(MCS_BOUND);
}
}
}
} else {...}
break;
}
...
}
}
获取params,加入mPendingInstalls中,如果插入的位置使0,则发送消息MCS_BOUND开始处理。在MCS_BOUND分支中,会调用params的startCopy。
6、startCopy
final boolean startCopy() {
boolean res;
...
handleReturnCode();
return res;
}
class InstallParams extends HandlerParams {
void handleReturnCode() {
if (mArgs != null) {
processPendingInstall(mArgs, mRet);
}
}
}
在startCopy中,会调用到handleReturnCode,由于真实的params是InstallParams,所以会调用到processPendingInstall。
7、processPendingInstall
private void processPendingInstall(final InstallArgs args, final int currentStatus) {
// Queue up an async operation since the package installation may take a little while.
mHandler.post(new Runnable() {
public void run() {
...
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
args.doPreInstall(res.returnCode);
synchronized (mInstallLock) {
installPackageTracedLI(args, res);
}
args.doPostInstall(res.returnCode, res.uid);
}
...
}
});
}
private void installPackageTracedLI(InstallArgs args, PackageInstalledInfo res) {
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackage");
installPackageLI(args, res);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
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 {
pkg = pp.parsePackage(tmpPackageFile, parseFlags);
DexMetadataHelper.validatePackageDexMetadata(pkg);
} catch (PackageParserException e) {
res.setError("Failed parse during installPackageLI", e);
return;
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
...
}
processPendingInstall会通过handler调用installPackageTracedLI方法,进而调用到installPackageLI,在这里我们可以看到是通过PackageParser.parsePackage方法对package进行解析;与前半部分分析便对上了。
网友评论