https://blog.csdn.net/alexwll/article/details/102777742
1.管理系统的jar包和系统的apk,负责系统的权限
2.负责apk的卸载,安装,更新,解析
3.对其他应用服务提供安装卸载服务;
和intsalld链接进行apk的安装卸载操作(实际安装卸载apk是有installd来进行的,PMS只是提供接口);
创建PackageHandle来处理外部apk的安装卸载请求;
处理系统权限相关文件
扫描安装
service-client结构
service:提供代理类proxy给client调用,所有动作的具体实现都是在Service中实现的。
PackageManagerService,( )
client:获得Service的proxy实现调用
PackageManager,ApplicationManager,其余都是Service
PackageManager实际是一个抽象类,主要是用来调用Service中的方法。以getPackageInfo为例,来讲述Client如何调用Service中的方法:
frameworks/base/core/java/android/content/pm/PackageManager.java
public abstract class PackageManager {
...//三个点代表省略部分代码
public abstract PackageInfo getPackageInfo(String packageName, @PackageInfoFlags int flags)
throws NameNotFoundException;
@RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
public abstract PackageInfo getPackageInfoAsUser(String packageName,
@PackageInfoFlags int flags, @UserIdInt int userId) throws NameNotFoundException;
...
}
对PackManager的调用上下文ContextImpl.java,即使用Context.getPackageManager();
/frameworks/base/core/java/android/app/ContextImpl.java
@Override
public PackageManager getPackageManager() {
if (mPackageManager != null) {
return mPackageManager;
}
IPackageManager pm = ActivityThread.getPackageManager();
if (pm != null) {
// Doesn't matter if we make more than one instance.
return (mPackageManager = new ApplicationPackageManager(this, pm));
}
return null;
}
分为:
(1)ActivityThread.getPackageManager()
frameworks/base/core/java/android/app/ActivityThread.java
@UnsupportedAppUsage
public static IPackageManager getPackageManager() {
if (sPackageManager != null) {
//Slog.v("PackageManager", "returning cur default = " + sPackageManager);
return sPackageManager;
}
IBinder b = ServiceManager.getService("package");
//Slog.v("PackageManager", "default service binder = " + b);
sPackageManager = IPackageManager.Stub.asInterface(b);
//Slog.v("PackageManager", "default service = " + sPackageManager);
return sPackageManager;
}
首先获取package服务,实际是PackageManagerService(PMS),然后IPackageManager.Stub.asInterface(b)得到内部类,即代理类IPackageManager.Stub.Proxy。即调用了proxy.getPackageInfo方法。
(2)return (mPackageManager = new ApplicationPackageManager(this, pm));
/frameworks/base/core/java/android/app/ApplicationPackageManager.java
@Override
public PackageInfo getPackageInfo(String packageName, int flags)
throws NameNotFoundException {
return getPackageInfoAsUser(packageName, flags, getUserId());
}
@Override
public PackageInfo getPackageInfo(VersionedPackage versionedPackage, int flags)
throws NameNotFoundException {
final int userId = getUserId();
try {
PackageInfo pi = mPM.getPackageInfoVersioned(versionedPackage,
updateFlagsForPackage(flags, userId), userId);
if (pi != null) {
return pi;
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
throw new NameNotFoundException(versionedPackage.toString());
}
/×××××××××××××××××××××××××××××××××××××××××××××/
@Override
public PackageInfo getPackageInfoAsUser(String packageName, int flags, int userId)
throws NameNotFoundException {
try {
PackageInfo pi = mPM.getPackageInfo(packageName,
updateFlagsForPackage(flags, userId), userId);
if (pi != null) {
return pi;
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
throw new NameNotFoundException(packageName);
}
/***********************************************/
private final IPackageManager mPM;
/***********************************************/
IPackageManager:即aidl接口
读取权限:
遍历、system/etc/permissions/目录下的xml文件并将解析结果添加到哈希对象中;
data/system permissions
更新system/framework/下的jar包
创建监控线程system/app
scanDirLi:扫描系统中的apk
解析AndroidManifest.xml的信息
将安装包apk的信息添加到本地配置,系统重新启动不需要再次安装。
public class PackageManagerService extends IPackageManager.Stub {
...
public static PackageManagerService main(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
// Self-check for initial settings.
PackageManagerServiceCompilerMapping.checkProperties();
//创建PackageManagerService
PackageManagerService m = new PackageManagerService(context, installer,
factoryTest, onlyCore);
m.enableSystemUserPackages();
// Disable any carrier apps. We do this very early in boot to prevent the apps from being
// disabled after already being started.
CarrierAppUtils.disableCarrierAppsUntilPrivileged(context.getOpPackageName(), m,
UserHandle.USER_SYSTEM);
//创建完成后把PMS加入到ServiceManager中
ServiceManager.addService("package", m);
return m;
}
...
@Override
public PackageInfo getPackageInfo(String packageName, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
flags = updateFlagsForPackage(flags, userId, packageName);
enforceCrossUserPermission(Binder.getCallingUid(), userId,
false /* requireFullPermission */, false /* checkShell */, "get package info");
// reader
synchronized (mPackages) {
final boolean matchFactoryOnly = (flags & MATCH_FACTORY_ONLY) != 0;
PackageParser.Package p = null;
if (matchFactoryOnly) {
final PackageSetting ps = mSettings.getDisabledSystemPkgLPr(packageName);
if (ps != null) {
return generatePackageInfo(ps, flags, userId);
}
}
if (p == null) {
p = mPackages.get(packageName);
if (matchFactoryOnly && p != null && !isSystemApp(p)) {
return null;
}
}
if (DEBUG_PACKAGE_INFO)
Log.v(TAG, "getPackageInfo " + packageName + ": " + p);
if (p != null) {
return generatePackageInfo((PackageSetting)p.mExtras, flags, userId);
}
if (!matchFactoryOnly && (flags & MATCH_UNINSTALLED_PACKAGES) != 0) {
final PackageSetting ps = mSettings.mPackages.get(packageName);
return generatePackageInfo(ps, flags, userId);
}
}
return null;
}
}
我们来分析这个代码片段:
1、第一点也是最关键的一点,PackageManagerService继承IPackageManager.Stub类,而IPackageManager.Stub类继承自Binder实现IpackageManager接口
2、这里请上翻看客户端中讲的最后个方法ActivityThread.getPackageManager(),这个方法中先是获得Binder实例:IBinder b = ServiceManager.getService("package")然后通过binder实例获得代理类Proxy
3、我们看服务端代码,在PMS创建完成后就添加到了ServiceManager中:ServiceManager.addService("package", m);所以2中实际得到的是PMS的Binder类型实例,然后得到PMS的代理类
4、接着上面的getPackageInfo方法,调用到Stub中的getPackageInfo接口方法,PackageManagerService则是接口方法getPackageInfo的实现,所以最终方法是调用到了PackageManagerService.getPackageInfo
Android程序包管理机制
包含内容:
根据Intent 匹配到对应的的Activity,provider,Service。即应用程序调用startAtivity(inent),能将参数中包含的特定intent转换成对应的一个包含此信息的activity。
进行权限检查。当需要特定权限时,系统可判断是否拥有权限。
提供安装,删除应用程序的接口。
包管理分为三层:
应用程序层,PMS服务层,数据文件层
1.应用程序层
应用程序使用包管理服务时,调用Contextlmpl类的getPackageManager()返回一个ApplicationPackageManager对象,继承于PackageManager抽象类。 参数传入Pms,Apm类调用各种pms的类方法。
2.数据文件层
使用xml文件管理相关信息。
第一个目录:"system/etc/permissions"该目录用于权限的管理,定义系统中包含了那些用户权限,应用可以在AndroidMananifest.xml,其中platform.xml为特别的uid和gid分配了默认的权限。
第二个目录:"data/system/packages.xml"保存安装程序的基本包信息,例如:
....
所有系统app保存在System/app或System/pri-app/下面。第二个中的service不可以被kill掉。
非系统app保存在data/app/目录下,/data/davik-cache目录下保存了程序执行代码,当程序运行前,Pms会从APK文件中提取出代码文件也就是dex文件,并将该文件存储在该目录下,以便以后能快速运行该程序。
framework库文件,这些文件保存在/system/framework目录下,系统开机时davik虚拟机会加载这些库文件,在pms启动时,将这些文件转换成dex文件,并保存到/data/dalvik-cache目录下。
应用程序使用的数据文件。分别为sharepreference存储、数据库存储和文件存储,前两种文件一般会保存在/data/data/xxx/目录下,xxx代表程序包名,文件存储可以保存在内置存储或者外置存储的任意位置。
未完待续。。。。。。
3.PMS服务层
1.启动入口
PMS属于系统服务,启动入口在SystemServer中的main方法
public static void main(String[] args) {
new SystemServer().run();
}
private void run() {
...
traceBeginAndSlog("StartServices");
//启动引导服务,PMS的启动包含在此
startBootstrapServices();
//启动核心服务
startCoreServices();
//启动其他服务
startOtherServices();
...
}
private void startBootstrapServices() {
...
//启动安装服务
traceBeginAndSlog("StartInstaller");
Installer installer = mSystemServiceManager.startService(Installer.class);
traceEnd();
...
//启动PMS
// Start the package manager.
if (!mRuntimeRestart) {
MetricsLogger.histogram(null, "boot_package_manager_init_start",
(int) SystemClock.elapsedRealtime());
}
traceBeginAndSlog("StartPackageManagerService");
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
mFirstBoot = mPackageManagerService.isFirstBoot();
mPackageManager = mSystemContext.getPackageManager();
traceEnd();
if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {
MetricsLogger.histogram(null, "boot_package_manager_init_ready",
(int) SystemClock.elapsedRealtime());
}
...
}
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
概括来讲,Android系统启动时,会创建SystemServer进程,进程运行会执行SystemServer类中的run方法,在run方法中会启动三类服务,包括引导服务、核心服务和其他服务,PMS包含在引导服务中,在启动引导服务时启动PMS。
主要作用概述:
1.创建mSettings对象,将PMS的mPackage传入,此集合保存所有apk的数据;
2.调用readLPw()读取data/system/packages.xml文件;
3.调用ScanDirTracedLI()扫描系统apk(system/app /pri-app);
4.调用ScanDirTracedLI ()扫描第三方apk(vendor/app);
5.调用writeLPw()将扫描的结果重新写入packages.xml;
public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
.....
synchronized (mInstallLock) {
synchronized (mPackages) {
// Expose private service for system components to use.
LocalServices.addService(
PackageManagerInternal.class, new PackageManagerInternalImpl());
sUserManager = new UserManagerService(context, this,
new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages);
mComponentResolver = new ComponentResolver(sUserManager,
LocalServices.getService(PackageManagerInternal.class),
mPackages);
mPermissionManager = PermissionManagerService.create(context,
mPackages /*externalLock*/);
mDefaultPermissionPolicy = mPermissionManager.getDefaultPermissionGrantPolicy();
mSettings = new Settings(Environment.getDataDirectory(),
mPermissionManager.getPermissionSettings(), mPackages);
}
}
.....
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "read user settings");
mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false));
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
...
mCacheDir = preparePackageParserCache();
// Set flag to monitor and not change apk file paths when
// scanning install directories.
int scanFlags = SCAN_BOOTING | SCAN_INITIAL;
if (mIsUpgrade || mFirstBoot) {
scanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE;
}
// Collect vendor/product/product_services overlay packages. (Do this before scanning
// any apps.)
// For security and version matching reason, only consider overlay packages if they
// reside in the right directory.
scanDirTracedLI(new File(VENDOR_OVERLAY_DIR),
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_VENDOR,
0);
scanDirTracedLI(new File(PRODUCT_OVERLAY_DIR),
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_PRODUCT,
0);
....
// can downgrade to reader
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "write settings");
mSettings.writeLPr();
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
SystemClock.uptimeMillis());
...
}