PMS服务启动原理详解
从开机到app启动PMS服务处理机制与流程
- Apk安装是怎么进行的,PMS如何分析APK压缩文件
- 开机时PMS做了什么,data/app目录下的扫描与分析
- PakageParse类源码解读
- AndroidManifest为什么要按照Google设计的写,PMS告诉你真相
- AMS与PMS交互过程解析
PackageInstaller 原理简述
应用安装是智能机的主要特点,即用户可以把各种应用(如游戏等)安装到手机上,并可以对其进行卸载等管理操作。APK是Android Package的缩写,即Android安装包。APK是类似Symbian Sis或Sisx的文件格式。通过将APK文件直接传到Android模拟器或Android手机中执行即可安装。
Android应用安装有如下四种方式
-
系统应用安装――开机时完成,没有安装界面
-
网络下载应用安装――通过market应用完成,没有安装界面
-
ADB工具安装――没有安装界面。
-
第三方应用安装――通过SD卡里的APK文件安装,有安装界面,由packageinstaller.apk应用处理安装及卸载过程的界面。
应用安装的流程及路径
- 应用安装涉及到如下几个目录:
system/app系统自带的应用程序,无法删除data/app: 用户程序安装的目录,有删除权限。
安装时把apk文件复制到此目录data/app存放应用程序的数据data/dalvik-cache将apk中的dex文件安装到dalvik-cache目录下(dex文件是dalvik虚拟机的可执行文件,其大小约为原始apk文件大小的四分之一)
安装过程:复制APK安装包到data/app目录下,解压并扫描安装包,把dex文件(Dalvik字节码)保存到dalvik-cache目录,并data/data目录下创建对应的应用数据目录。
卸载过程:删除安装过程中在上述三个目录下创建的文件及目录。
一、系统应用安装:
PackageManagerService处理各种应用的安装,卸载,管理等工作,开机时由systemServer启动此服务
(源文件路径:android\frameworks\base\services\java\com\android\server\PackageManagerService.java)
PackageManagerService服务启动的流程:
-
首先扫描安装“system\framework”目录下的jar包
-
scanDirLI(mFrameworkDir,PackageParser.PARSE_IS_SYSTEM, scanMode | SCAN_NO_DEX);
-
第二步扫描安装“system\app”目录下的各个系统应用
-
scanDirLI(mSystemAppDir,PackageParser.PARSE_IS_SYSTEM,scanMode);
-
第三步扫描“data\app”目录,即用户安装的第三方应用
scanDirLI(mAppInstallDir, 0, scanMode); -
第四步扫描" data\app-private"目录,即安装DRM保护的APK文件(目前没有遇到过此类的应用)。
scanDirLI(mDrmAppPrivateInstallDir,0, scanMode | SCAN_FORWARD_LOCKED);
安装应用的过程
- scanDirLI(Filedir, int flags, int scanMode) 遍历安装指定目录下的文件
2.scanPackageLI(FilescanFile,File destCodeFile, FiledestResourceFile, int parseFlags,int scanMode) //安装package文件
3.scanPackageLI(File scanFile, File destCodeFile, FiledestResourceFile,PackageParser.Package pkg, intparseFlags, int scanMode)//通过解析安装包parsePackage获取到安装包的信息结构
4.mInstaller.install(pkgName,pkg.applicationInfo.uid,pkg.applicationInfo.uid);//实现文件复制的安装过程(源文件路径:frameworks\base\cmds\installd\installd.install)
PMS 作用
PMS 快速定位到 某个类 activity 的入口
- 时期: 开机时
- Android 5s 手机启动
- PMS 耗费70%
- 缓存 信息缓存到我的数据库
PackageParser.java
/**
* Representation of a full package parsed from APK files on disk. A package
* consists of a single base APK, and zero or more split APKs.
*
* Deprecated internally. Use AndroidPackage instead.
*/
public final static class Package implements Parcelable {
@UnsupportedAppUsage
public String packageName;
// The package name declared in the manifest as the package can be
// renamed, for example static shared libs use synthetic package names.
public String manifestPackageName;
/** Names of any split APKs, ordered by parsed splitName */
public String[] splitNames;
// TODO: work towards making these paths invariant
public String volumeUuid;
/**
* Path where this package was found on disk. For monolithic packages
* this is path to single base APK file; for cluster packages this is
* path to the cluster directory.
*/
public String codePath;
/** Path of base APK */
public String baseCodePath;
/** Paths of any split APKs, ordered by parsed splitName */
public String[] splitCodePaths;
/** Revision code of base APK */
public int baseRevisionCode;
/** Revision codes of any split APKs, ordered by parsed splitName */
public int[] splitRevisionCodes;
/** Flags of any split APKs; ordered by parsed splitName */
public int[] splitFlags;
/**
* Private flags of any split APKs; ordered by parsed splitName.
*
* {@hide}
*/
public int[] splitPrivateFlags;
public boolean baseHardwareAccelerated;
// For now we only support one application per package.
@UnsupportedAppUsage
public ApplicationInfo applicationInfo = new ApplicationInfo();
@UnsupportedAppUsage
public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
@UnsupportedAppUsage
public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
@UnsupportedAppUsage
public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
@UnsupportedAppUsage
public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
@UnsupportedAppUsage
public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
@UnsupportedAppUsage
public final ArrayList<Service> services = new ArrayList<Service>(0);
@UnsupportedAppUsage
public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
SystemServer
// Start services.
try {
t.traceBegin("StartServices");
//启动引导服务 引导服务中启动 AMS, WMS, PMS
startBootstrapServices(t);
//启动核心服务
startCoreServices(t);
//启动其他服务
startOtherServices(t);
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
t.traceEnd(); // StartServices
}
PackageParser.java
//解析AndroidManifest.xml
private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
throws PackageParserException {
final String apkPath = apkFile.getAbsolutePath();
String volumeUuid = null;
if (apkPath.startsWith(MNT_EXPAND)) {
final int end = apkPath.indexOf('/', MNT_EXPAND.length());
volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
}
mParseError = PackageManager.INSTALL_SUCCEEDED;
mArchiveSourcePath = apkFile.getAbsolutePath();
if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
XmlResourceParser parser = null;
try {
final int cookie = assets.findCookieForPath(apkPath);
if (cookie == 0) {
throw new 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 Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
if (pkg == null) {
throw new PackageParserException(mParseError,
apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
}
pkg.setVolumeUuid(volumeUuid);
pkg.setApplicationVolumeUuid(volumeUuid);
pkg.setBaseCodePath(apkPath);
pkg.setSigningDetails(SigningDetails.UNKNOWN);
return pkg;
} catch (PackageParserException e) {
throw e;
} catch (Exception e) {
throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
"Failed to read manifest from " + apkPath, e);
} finally {
IoUtils.closeQuietly(parser);
}
}
- PMS 用来管理所有的package信息,包括安装、卸载、更新以及解析AndroidManifest.xml以组织相应的数据结构这些数据结构将会被PMS、
- data/app/pakage/base.apk
- system/app/pakage/base.apk
- systemService 启动 让后 在run 方法中启动 引导服务, 引导服务中启动 packageManageService, 然后 packageManageService 扫描 data/app/pakage/base.apk, system/app/pakage/base.apk 包下的文件,加载base.apk 储存到Package 对象里面,方便与查找 四大组件
- pms 解析手机里面所有apk的manifest.xml 文件
- ams pms交互,快速找到Activity(javabean) 再来反射 启动Activity 对象