PackageManagerService服务框架详解 您所在的位置:网站首页 packagename是什么 PackageManagerService服务框架详解

PackageManagerService服务框架详解

2023-10-31 02:18| 来源: 网络整理| 查看: 265

PMS系列: 1、本文PackageManagerService服务框架详解 2、PackageManagerService启动分析 3、PackageManagerService之app数据类(Settings)分析 4、PackageManagerService扫描安装apk详解 5、PackageManagerService根据权限等级管理权限(默认赋予apk权限)

framework层给我们提供了很多服务例如ActivityManager、WnidowManager、PackageManager等等,这些服务的框架都比较类似,刚好最近在阅读PMS服务相关的代码,这里对PackageManger的框架进行一个总结。先来一张图。

结构

这张图清晰的描述了PackageManager的框架。是一种标准的Service(服务端)-client(客户端)结构 这里简单说一下service-client service:提代理类proxy给client调用,所有动作的具体实现都是在service中进行; client:获得service的proxy实现调用; 图中client主要是PackageManager,ApplicationManager,其余都是服务端 本文讲述主要涉猎代码如下 Service: frameworks/base/core/java/android/content/pm/IPackageManager.aidl out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/content/pm/IPackageManager.java frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java Client: frameworks/base/core/java/android/content/pm/PackageManager.java frameworks/base/core/java/android/app/ApplicationPackageManager.java 理解PackageManager的框架实际就是理解aidl这种进程间的通信方式。

客户端

PackageManager是一个抽象类,里边主要是一些抽象方法,以getPackageInfo为例子,讲述client如何调用

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; ... }

我们对PackageManager的调用是上下文ContextImpl.java中Context.getPackageManager():

@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; }

这里返回的是ApplicationPackageManager,因为PackageManager是一个抽象类,它需要一个具体的实现,所以这里ApplicationPackageManager继承自PackageManager,代码片段如下:

public class ApplicationPackageManager extends PackageManager { private final IPackageManager mPM; ApplicationPackageManager(ContextImpl context, IPackageManager pm) { mContext = context; mPM = pm; } ... @Override public PackageInfo getPackageInfo(String packageName, int flags) throws NameNotFoundException { return getPackageInfoAsUser(packageName, flags, mContext.getUserId()); } @Override public PackageInfo getPackageInfoAsUser(String packageName, int flags, int userId) throws NameNotFoundException { try { PackageInfo pi = mPM.getPackageInfo(packageName, flags, userId); if (pi != null) { return pi; } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } throw new NameNotFoundException(packageName); } ... }

1、从ApplicationPackageManager的实现代码可以明确的看出,我们调用getPackageInfo实际上最后调用的是mPM.getPackageInfo(packageName, flags, userId)这里的mPM就是getPackageManager方法中带入的IPackageManager。 2、这个方法比较关键,从前面什么是service代码和什么是clent代码的分类中,我们知道IPackageManager这个是服务端提供的类 我们来看下ActivityThread.getPackageManager()这个方法:

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; }

1、这里的调用依赖android的Binder机制,实现进程之间的调用 2、ServiceManager.getService("package")得到的其实是PackageManagerService 3、然后调用IPackageManager.Stub.asInterface(b),得到IPackageManager的内部类,即代理类Proxy:IPackageManager.Stub.Proxy,所以得到的就是PackageManagerService的代理类 4、那么最后实际上是调用到了proxy.getPackageInfo方法, 5、这里的代码对aidl通信方式不熟悉的人看着可能会有点儿费解,这个方法调用到服务端了,我会在后面服务端解析中详细说明这个方法; 客户端的流程就分析到此,我们知道client的主要作用就是获得service的proxy来实现调用,最终实现就是获得proxy,下面我们进行服务端的代码分析:

服务端

在接着分析上文proxy.getPackageInfo之前,我们先分析一下service端是如何构成的

IPackageManager

服务端的定义是从IpackageManager.aidl文件开始的,接口IpackageManager.aidl中只定义了相关方法,代码片段:

interface IPackageManager { ... PackageInfo getPackageInfo(String packageName, int flags, int userId); int getPackageUid(String packageName, int flags, int userId); int[] getPackageGids(String packageName, int flags, int userId); ... }

android的编译会识别aidl的文件,aidl方式其实就是一种进程间通过Binder通信的方式,在编译的时候跟对aidl自动生成一个对应的java文件,这里生成的是IpackageManager.java文件,这也是为啥IpackageManager.java的路径是在out目录下的原因,没有编译工程之前是没有IpackageManager.java这个文件的。生成的IpackageManager.java这个文件对应图中的IpackageManager,我们来看看IpackageManager的构成,把IpackageManager.java的构成记在心里,基本也能理解aidl是怎么实现进程之间的通信的,IpackageManager.java代码片段如下:

public interface IPackageManager extends android.os.IInterface{ //IPackageManager中定义的类Stub,Stub集成自Binder,并实现IPackageManager.aidl中定义的接口 public static abstract class Stub extends android.os.Binder implements android.content.pm.IPackageManager{ ... public static android.content.pm.IPackageManager asInterface(android.os.IBinder obj){ if ((obj==null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); //如果是当前进程,返回的是IPackageManager本身 if (((iin!=null)&&(iin instanceof android.content.pm.IPackageManager))) { return ((android.content.pm.IPackageManager)iin); } //不是当前进程,返回的是代理类 return new android.content.pm.IPackageManager.Stub.Proxy(obj); } @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException { ... switch (code) { case TRANSACTION_getPackageInfo:{ data.enforceInterface(DESCRIPTOR); java.lang.String _arg0; _arg0 = data.readString(); int _arg1; _arg1 = data.readInt(); int _arg2; _arg2 = data.readInt(); android.content.pm.PackageInfo _result = this.getPackageInfo(_arg0, _arg1, _arg2); reply.writeNoException(); if ((_result!=null)) { reply.writeInt(1); _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE); ...//类似的case方法很多,这里只举例case TRANSACTION_getPackageInfo,其他代码省略 } ... } ... //类Stub中定义的代理类Proxy,Proxy中代理方法很多,这里同样只贴出了getPackageInfo方法 private static class Proxy implements android.content.pm.IPackageManager { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } ... @Override public android.content.pm.PackageInfo getPackageInfo(java.lang.String packageName, int flags, int userId) throws android.os.RemoteException{ android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); android.content.pm.PackageInfo _result; try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeString(packageName); _data.writeInt(flags); _data.writeInt(userId); mRemote.transact(Stub.TRANSACTION_getPackageInfo, _data, _reply, 0); _reply.readException(); if ((0!=_reply.readInt())) { _result = android.content.pm.PackageInfo.CREATOR.createFromParcel(_reply); } else { _result = null; } } finally { _reply.recycle(); _data.recycle(); } return _result; } ... } ... //这里的函数就是Stub实现的接口implements android.content.pm.IPackageManager,只列出来三个,别的都省略,继承接口方法必须全部实现,否则会报错 public void checkPackageStartable(java.lang.String packageName, int userId) throws android.os.RemoteException; public boolean isPackageAvailable(java.lang.String packageName, int userId) throws android.os.RemoteException; public android.content.pm.PackageInfo getPackageInfo(java.lang.String packageName, int flags, int userId) throws android.os.RemoteException; ... }

IpackageManager.java的理解主要分为三点: 1、IpackageManager.java中定义一个Stub类,这个类实现了IPackageManager.aidl中定义的接口; 2、代理类Proxy:IpackageManager.Stub.Proxy,Proxy中的方法供client调用; 3、调用Proxy中的方法其实就是间接调用了Stub中的onTransact方法,在onTransact中最终调用了Stub实现的接口方法;

我们接着客户端的代码接着分析,以实例来说明调用: 1、客户端调用实际是Proxy.getPackageInfo; 2、Proxy.getPackageInfo方法中调用mRemote.transact(Stub.TRANSACTION_getPackageInfo, _data, _reply, 0); 3、Stub.transact中android.content.pm.PackageInfo _result = this.getPackageInfo(_arg0, _arg1, _arg2); 4、this.getPackageInfo其实就是Stub实现的IPackageManager接口中的getPackageInfo方法,即: public android.content.pm.PackageInfo getPackageInfo(java.lang.String packageName, int flags, int userId) throws android.os.RemoteException;

那么现在看来方法调用现在是调用到了IPackageManager.java中Stub类中实现的接口getPackageInfo那么,我们接下来讲具体的实现PackageManagerService.java

PackageManagerservice

PMS的代码很长,这里只列举小部分

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

总结

PackageManager的框架就是一个Service-client结构 Service: IPackageManager.aidl - IPackageManager.java - PackageManagerService.java client: PackageManager.java - ApplicationPackageManager 把服务端的一个流向记住,你就完全能掌握PMS的框架结构了。

Read the fucking sources code!



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有