Android Framework 分析---3PackageManager 分析
来源:互联网 发布:功夫英语 知乎 编辑:程序博客网 时间:2024/05/01 14:21
Android开发交流群:484966421 OSHome。
微信公众号:oshome2015
在windowphone,ios和android中到目前为止,还是android的市场份额最大。个人认为除了google开源外,广大开发者早就了android的霸主地位。各位兄弟姐妹开发出各种各样的apk,才组成android的广阔天下。本篇主要分析一下android系统是针对处理这些apk的,主要涉及到pm这块的代码。分析这种底层服务,最好从android的开启启动流程中开始分析。因为这样才能更清楚的了解服务的启动流程。
1.在SystemServer.java 中启动PM
android 开机启动后加载的第一个java的程序就是SystemServer,在包含android系统的最主要的一些底层服务。在4.4kk之前都是建一个Thread线程来启动。4.4KK的启动机制就变了,具体后续的文章会讲解。
Installer installer = null; Slog.i(TAG, "Waiting for installd to be ready."); installer = new Installer(); installer.ping(); pm = PackageManagerService.main(context, installer, factoryTest != SystemServer.FACTORY_TEST_OFF, onlyCore); boolean firstBoot = false; try { firstBoot = pm.isFirstBoot(); } catch (RemoteException e) { }
public static final IPackageManager main(Context context, Installer installer, boolean factoryTest, boolean onlyCore) { PackageManagerService m = new PackageManagerService(context, installer, factoryTest, onlyCore); ServiceManager.addService("package", m); return m; }在systemServer中初始化了Installer,并将它传入PackageManagerService.main()中。在main函数中将pm添加到ServiceManager中,供开发者调用。
2.PackageManagerService启动安装分析
启动PackageManagerService后,主要完成以下几个步骤
2.1.初始化PackageSetting,设置sharedUserID
mSettings = new Settings(context); mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM); mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID, ApplicationInfo.FLAG_SYSTEM);2.2.获取屏幕参数:
WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); Display d = wm.getDefaultDisplay(); d.getMetrics(mMetrics);2.3.使用HandlerThread开启packagemanager工作线程和初始化app目录
mHandlerThread.start(); mHandler = new PackageHandler(mHandlerThread.getLooper()); File dataDir = Environment.getDataDirectory(); mAppDataDir = new File(dataDir, "data"); mAppInstallDir = new File(dataDir, "app"); mAppLibInstallDir = new File(dataDir, "app-lib"); mAsecInternalPath = new File(dataDir, "app-asec").getPath(); mUserAppDataDir = new File(dataDir, "user"); mDrmAppPrivateInstallDir = new File(dataDir, "app-private");2.4.加载Framework的主要jar和BOOTCLASSPATH
mFrameworkDir = new File(Environment.getRootDirectory(), "framework"); mDalvikCacheDir = new File(dataDir, "dalvik-cache"); boolean didDexOpt = false; /** * Out of paranoia, ensure that everything in the boot class * path has been dexed. */ String bootClassPath = System.getProperty("java.boot.class.path");2.5.安装system/app,vendor/app和data/app目录下apk
// Collect all system packages. mSystemAppDir = new File(Environment.getRootDirectory(), "app"); mSystemInstallObserver = new AppDirObserver( mSystemAppDir.getPath(), OBSERVER_EVENTS, true); mSystemInstallObserver.startWatching(); scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0); // Collect all vendor packages. mVendorAppDir = new File("/vendor/app"); mVendorInstallObserver = new AppDirObserver( mVendorAppDir.getPath(), OBSERVER_EVENTS, true); mVendorInstallObserver.startWatching(); scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);...... mAppInstallObserver = new AppDirObserver( mAppInstallDir.getPath(), OBSERVER_EVENTS, false); mAppInstallObserver.startWatching(); scanDirLI(mAppInstallDir, 0, scanMode, 0);
其中具体如果安装代码在scanDirLI()函数,最终调用scanPackageLI()进行安装。在安装过程中会搜集ApplicationInfo和ActivityInfo信息,比较签名,匹配本地so的目录。
具体细节参看PackageManagerService.java 中的
private PackageParser.Package scanPackageLI(PackageParser.Package pkg,int parseFlags, int scanMode, long currentTime, UserHandle user) {
函数。
3.在Activity使用PackageManger的分析
我们在应用经常通过
PackageManager pm = this.getPackageManager() 来获取pm。这部分主要从它的来源来深入分析。
由于我们在Activity中使用this来获取pm,很容易想到到context类里去寻找实现。
/** Return PackageManager instance to find global package information. */ public abstract PackageManager getPackageManager();但是context是虚函数,因此要找到它的实现,由于context的实现采用 设计模式里面的 "桥接模式' 因此很容易想到从contextImpl.java 中寻找实现。
果然找到。
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; }
从代码上看获取IPackageManager,还是需要从ActivityThread中获取。我在Activity里面获取吗出现在ActivityThread 也不意外。
那我们就看看他是怎么实现的
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; }原来是通过ServiceManager.getService("package").从上你们的代码知道,这句其实就是获取PackageManagerService 并赋给IBinder ,成为一个binder对象。
通过asInterface()函数,通过binder对象获取接口类IPackageManager的实例。并返回回去。
if (pm != null) { // Doesn't matter if we make more than one instance. return (mPackageManager = new ApplicationPackageManager(this, pm)); }
在接着同ApplicationPackageManager 创建PackageManager 对象。到此我们在Activity中就可以使用pm这个对象操作系统中的各种包。
4.Android 系统中PackageManager的关键类和UML的类图。
在pm中主要涉及的类和路径如下:
frameworks\base\services\java\com\android\server\pm\PackageManagerService.java 和 其他文件
frameworks\base\core\java\android\content\pm\IPackageManager.aidl
frameworks\base\core\java\android\app\ActivityThread.java ,context.java ,contextimpl.java
frameworks\base\core\java\android\content\pm\PackageManager.java
- Android Framework --- PackageManager 分析
- Android Framework 分析---3PackageManager 分析
- android中的packagemanager分析
- PackageManager分析(3)
- PackageManager分析(1)
- PackageManager分析(2)
- PackageManager分析(4)
- PackageManager分析(5)
- PackageManager 分析(1)
- Android Framework 分析
- Android Framework 分析
- Android Framework 分析
- Android Framework 分析
- Android Framework 分析
- android framework框架分析
- Android Framework 分析
- Android Framework 分析
- android framework Service分析
- DeCAF: A deep convolutional activation feature for generic visual recognition
- 程序猿必须知道的算法(第一弹)回溯法
- IOS系统架构
- Aspose.Word控件实现Word文档的操作(创建和合并单元格)
- 连接到 Flash 调试器
- Android Framework 分析---3PackageManager 分析
- Linux Posix Thread Programming
- andrpid优化之删除无用资源
- Qt对话框的生命周期及模态设置
- 当我们建站的时候,问问自己为什么要建设这个网站?有什么收益么?处于什么样子的目的?
- OCP-1Z0-051 第138题 not操作,IN、ANY、ALL的应用
- 棋牌社区最近更新源码
- 传吴佩慈产后被甩 纪晓波改贴大奶妹
- 图像库---Image Datasets---OpenSift源码---openSurf源码