PackageManagerService在Android中的非常重要,主要负责的功能如下:
1.解析AndroidManifest.xml,主要包括AndroidManifest中节点信息的解析和target-name的分析和提炼,这部分和ActivityManagerService和WindowManagerService都有紧急的联系。关于AndroidManifest.xml中的属性设置,会单独拎出来讲解,本文不扩展讲解。
2.扫描本地文件,主要针对apk,主要是系统应用、本地安装应用等等。这部分会在下面仔细讲解。
3.管理本地apk,主要包括安装、删除等等。
下面称PackageManagerService为PMS
一、PMS启动
PMS是系统的关键服务,也是在system_server进程中启动的,同AMS与其他的系统服务,下面是PMS的启动流程:
PackageManagerService启动流程.jpg
上面是PMS启动流程,PMS还是从systemServer中启动的系统服务,主要关注一下PMS在构造函数中做了什么,构造函数中一般是初始化PMS中需要使用的线程和读取基本的配置。
1.1 PMS系统服务注册的地方
PMS中的main函数中有PMS服务的注册,还是将PMS注册到ServiceManager中,然后service写入/dev/binder中,可以实现用户空间和内核空间的通信,这是binder通信机制相关的知识。
PackageManagerService.java
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.addService("package", m);
final PackageManagerNative pmn = m.new PackageManagerNative();
ServiceManager.addService("package_native", pmn);
return m;
}
除了PMS,这儿还注册了“package_native”的服务,这个服务主要是给native代码调用的,包含3个函数,获取package的相关信息(versionCode、uid、Installer相关信息)。
PackageManagerService m = new PackageManagerService(context, installer,
factoryTest, onlyCore);
这里传入PMS构造中的几个参数需要了解一下。
1.context,上下文。
2.installer,类是Installer.java
frameworks/base/services/core/java/com/android/server/pm/Installer.java
public class Installer extends SystemService {
//......
}
这是一个负责package安装、删除、迁移、更新的系统服务。因为PMS中需要管理package,那么就需要installer实例的协助。
3.factoryTest,当前是否是测试模式。
4.onlyCore,onlyCore为true表明当前的设置正在加密或者已经是加密的,说明此时只能运行核心app,刚开始不会扫描非系统app,这个会在扫描流程中详细说明下。
1.2 PMS构造函数剖析
PMS的构造函数代码非常多,有800多行,这么多代码,需要仔细剖析一下。这儿按照执行顺序将PMS构造函数分为下面几块:
1.2.1 设置uid属性
这里主要设置的是shareUsers属性,放在Settings中的ArrayMap中,先存起来。
1.2.2 初始化package解析和管理的对象
主要初始化的类是:
1.PackageDexOptimizer
2.DexManager
3.ArtManagerService
4.ProtectedPackages
1.2.3 创建PackageHandler处理package管理中消息
1.2.4 扫描系统app和系统目录下的jar
1.2.5 扫描应用app和应用目录下的lib
这个步骤的执行是有条件的,具体条件是 1.1小节中提到的onlyCore变量,如果onlyCore为false,才会执行扫描操作。
PackageManagerService.java
// Find base frameworks (resource packages without code).
scanDirTracedLI(frameworkDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED,
scanFlags | SCAN_NO_DEX, 0);
// Collected privileged system packages.
final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
scanDirTracedLI(privilegedAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);
// Collect ordinary system packages.
final File systemAppDir = new File(Environment.getRootDirectory(), "app");
scanDirTracedLI(systemAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
它们都是调用scanDirTracedLI,除了检索的目录不同,这个函数值得进一步探讨。
下面挑出final File systemAppDir = new File(Environment.getRootDirectory(), "app");
这个Environment.getRootDirectory()是什么?
private static final File DIR_ANDROID_ROOT = getDirectory(ENV_ANDROID_ROOT, "/system");
private static final File DIR_ANDROID_DATA = getDirectory(ENV_ANDROID_DATA, "/data");
public static File getRootDirectory() {
return DIR_ANDROID_ROOT;
}
说明这个systemAppDir目录就是/system/app/,存放系统应用的地方。
接下里讨论一下scanDirTracedLI(...)做什么。
先阐述一下scanDirTracedLI(...)的调用流程:
scanDirTraceLI流程.jpg
这儿做的事情很简单,总结起来就是解析/system/app 目录下面的所有apk,然后解析其中的文件,例如解析AndroidManifest.xml,解析assets,解析res等等,分别使用存储结构存储起来,这些数据在后面都会用到,本文只谈大纲,代码的详细分析流程我后面会重新开章节讲解,请见谅。
二、PMS结构分析
分析PMS的代码结构,有助于我们从整体架构的角度来分析PMS。
PackageManagerService.java
public class PackageManagerService extends IPackageManager.Stub
implements PackageSender {
}
IPackageManager.Stub是IPackageManager.aidl自动生成的,正好也说明了PMS是service端的,通过binder交互,这里主要看看IPackageManager.aidl有什么主要的方法。
我简单的分为下面几类:
2.1 权限管理方法
PermissionInfo getPermissionInfo(String name, String packageName, int flags);
ParceledListSlice queryPermissionsByGroup(String group, int flags);
PermissionGroupInfo getPermissionGroupInfo(String name, int flags);
ParceledListSlice getAllPermissionGroups(int flags);
int checkPermission(String permName, String pkgName, int userId);
int checkUidPermission(String permName, int uid);
boolean addPermission(in PermissionInfo info);
void removePermission(String name);
void grantRuntimePermission(String packageName, String permissionName, int userId);
void revokeRuntimePermission(String packageName, String permissionName, int userId);
void resetRuntimePermissions();
int getPermissionFlags(String permissionName, String packageName, int userId);
void updatePermissionFlags(String permissionName, String packageName, int flagMask,
int flagValues, int userId);
void updatePermissionFlagsForAllApps(int flagMask, int flagValues, int userId);
boolean shouldShowRequestPermissionRationale(String permissionName,
String packageName, int userId);
2.2 通用属性方法
PackageInfo getPackageInfo(String packageName, int flags, int userId);
PackageInfo getPackageInfoVersioned(in VersionedPackage versionedPackage,
int flags, int userId);
int getPackageUid(String packageName, int flags, int userId);
int[] getPackageGids(String packageName, int flags, int userId);
ApplicationInfo getApplicationInfo(String packageName, int flags ,int userId);
ActivityInfo getActivityInfo(in ComponentName className, int flags, int userId);
boolean activitySupportsIntent(in ComponentName className, in Intent intent,
String resolvedType);
ActivityInfo getReceiverInfo(in ComponentName className, int flags, int userId);
ServiceInfo getServiceInfo(in ComponentName className, int flags, int userId);
ProviderInfo getProviderInfo(in ComponentName className, int flags, int userId);
2.3 组件处理方法
ParceledListSlice queryIntentActivities(in Intent intent,
String resolvedType, int flags, int userId);
ParceledListSlice queryIntentActivityOptions(
in ComponentName caller, in Intent[] specifics,
in String[] specificTypes, in Intent intent,
String resolvedType, int flags, int userId);
ParceledListSlice queryIntentReceivers(in Intent intent,
String resolvedType, int flags, int userId);
ResolveInfo resolveService(in Intent intent,
String resolvedType, int flags, int userId);
ParceledListSlice queryIntentServices(in Intent intent,
String resolvedType, int flags, int userId);
ParceledListSlice queryIntentContentProviders(in Intent intent,
String resolvedType, int flags, int userId);
ProviderInfo resolveContentProvider(String name, int flags, int userId);
void querySyncProviders(inout List<String> outNames,
inout List<ProviderInfo> outInfo);
ParceledListSlice queryContentProviders(
String processName, int uid, int flags, String metaDataKey);
ComponentName getInstantAppResolverComponent();
ComponentName getInstantAppResolverSettingsComponent();
ComponentName getInstantAppInstallerComponent();
2.4 其他方法
//......
boolean isFirstBoot();
boolean isOnlyCoreApps();
boolean isUpgrade();
boolean isStorageLow();
//......
这儿并没有列出所有的方法,这些方法大家了解即可,不需要一个一个方法去抠,只需要抓住核心调用方法,最好和app开发结合起来理解即可。
PackageSender接口是主要处理receiver的,这些个receiver都是解析AndroidManifest的时候得到的receiver,了解即可。
interface PackageSender {
void sendPackageBroadcast(final String action, final String pkg,
final Bundle extras, final int flags, final String targetPkg,
final IIntentReceiver finishedReceiver, final int[] userIds);
void sendPackageAddedForNewUsers(String packageName, boolean isSystem,
int appId, int... userIds);
}
三、小结
本文简单分析了PMS的启动和构造函数,只阐述了大纲,我的思路是接下来会用一个章节讨论一下PMS是如何解析apk的。谢谢大家。
网友评论