当前位置:   article > 正文

Android Framework 分析---3PackageManager 分析_android/app/activitythread->spackagemanager:landro

android/app/activitythread->spackagemanager:landroid/content/pm/ipackagemana

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的启动机制就变了,具体后续的文章会讲解。

  1. Installer installer = null;
  2. Slog.i(TAG, "Waiting for installd to be ready.");
  3. installer = new Installer();
  4. installer.ping();
  5. pm = PackageManagerService.main(context, installer,
  6. factoryTest != SystemServer.FACTORY_TEST_OFF,
  7. onlyCore);
  8. boolean firstBoot = false;
  9. try {
  10. firstBoot = pm.isFirstBoot();
  11. } catch (RemoteException e) {
  12. }
  1.  public static final IPackageManager main(Context context, Installer installer,
  2.             boolean factoryTest, boolean onlyCore) {
  3.         PackageManagerService m = new PackageManagerService(context, installer,
  4.                 factoryTest, onlyCore);
  5.         ServiceManager.addService("package", m);
  6.         return m;
  7.     }
在systemServer中初始化了Installer,并将它传入PackageManagerService.main()中。在main函数中将pm添加到ServiceManager中,供开发者调用。

2.PackageManagerService启动安装分析

启动PackageManagerService后,主要完成以下几个步骤

2.1.初始化PackageSetting,设置sharedUserID

 

  1. mSettings = new Settings(context);
  2. mSettings.addSharedUserLPw("android.uid.system",
  3. Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
  4. mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID, ApplicationInfo.FLAG_SYSTEM);
2.2.获取屏幕参数:

  1. WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
  2. Display d = wm.getDefaultDisplay();
  3. d.getMetrics(mMetrics);
2.3.使用HandlerThread开启packagemanager工作线程和初始化app目录

  1. mHandlerThread.start();
  2. mHandler = new PackageHandler(mHandlerThread.getLooper());
  3. File dataDir = Environment.getDataDirectory();
  4. mAppDataDir = new File(dataDir, "data");
  5. mAppInstallDir = new File(dataDir, "app");
  6. mAppLibInstallDir = new File(dataDir, "app-lib");
  7. mAsecInternalPath = new File(dataDir, "app-asec").getPath();
  8. mUserAppDataDir = new File(dataDir, "user");
  9. mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
2.4.加载Framework的主要jar和BOOTCLASSPATH

  1. mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
  2. mDalvikCacheDir = new File(dataDir, "dalvik-cache");
  3. boolean didDexOpt = false;
  4. /**
  5. * Out of paranoia, ensure that everything in the boot class
  6. * path has been dexed.
  7. */
  8. String bootClassPath = System.getProperty("java.boot.class.path");
2.5.安装system/app,vendor/app和data/app目录下apk

  1. // Collect all system packages.
  2. mSystemAppDir = new File(Environment.getRootDirectory(), "app");
  3. mSystemInstallObserver = new AppDirObserver(
  4. mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
  5. mSystemInstallObserver.startWatching();
  6. scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM
  7. | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
  8. // Collect all vendor packages.
  9. mVendorAppDir = new File("/vendor/app");
  10. mVendorInstallObserver = new AppDirObserver(
  11. mVendorAppDir.getPath(), OBSERVER_EVENTS, true);
  12. mVendorInstallObserver.startWatching();
  13. scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM
  14. | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
  15. ......
  16. mAppInstallObserver = new AppDirObserver(
  17. mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
  18. mAppInstallObserver.startWatching();
  19. 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类里去寻找实现。

 

  1. /** Return PackageManager instance to find global package information. */
  2. public abstract PackageManager getPackageManager();
但是context是虚函数,因此要找到它的实现,由于context的实现采用 设计模式里面的 "桥接模式' 因此很容易想到从contextImpl.java 中寻找实现。

果然找到。

  1. public PackageManager getPackageManager() {
  2. if (mPackageManager != null) {
  3. return mPackageManager;
  4. }
  5. IPackageManager pm = ActivityThread.getPackageManager();
  6. if (pm != null) {
  7. // Doesn't matter if we make more than one instance.
  8. return (mPackageManager = new ApplicationPackageManager(this, pm));
  9. }
  10. return null;
  11. }

从代码上看获取IPackageManager,还是需要从ActivityThread中获取。我在Activity里面获取吗出现在ActivityThread 也不意外。

那我们就看看他是怎么实现的

  1. public static IPackageManager getPackageManager() {
  2. if (sPackageManager != null) {
  3. //Slog.v("PackageManager", "returning cur default = " + sPackageManager);
  4. return sPackageManager;
  5. }
  6. IBinder b = ServiceManager.getService("package");
  7. //Slog.v("PackageManager", "default service binder = " + b);
  8. sPackageManager = IPackageManager.Stub.asInterface(b);
  9. //Slog.v("PackageManager", "default service = " + sPackageManager);
  10. return sPackageManager;
  11. }
原来是通过ServiceManager.getService("package").从上你们的代码知道,这句其实就是获取PackageManagerService 并赋给IBinder ,成为一个binder对象。

通过asInterface()函数,通过binder对象获取接口类IPackageManager的实例。并返回回去。

  1. if (pm != null) {
  2. // Doesn't matter if we make more than one instance.
  3. return (mPackageManager = new ApplicationPackageManager(this, pm));
  4. }


在接着同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





 






 



声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/199073
推荐阅读
相关标签
  

闽ICP备14008679号