Android Framework 分析---PackageManager 分析

在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 分析

时间: 2024-12-23 19:59:48

Android Framework 分析---PackageManager 分析的相关文章

Android Framework 分析---消息机制Native层

在Android的消息机制中,不仅提供了供Application 开发使用的java的消息循环.其实java的机制最终还是靠native来实现的.在native不仅提供一套消息传递和处理的机制,还提供了自定义文件描述符的I/O时间的监听机制.下面我们从具体代码中分析一下. Native层的关键类: Looper.cpp.该类中提供了pollOnce 和wake的休眠和唤醒机制.同时在构造函数中也创建 管道 并加入epoll的机制中,来监听其状态变化. Looper::Looper(bool al

[Android]Fragment源码分析(三) 事务

Fragment管理中,不得不谈到的就是它的事务管理,它的事务管理写的非常的出彩.我们先引入一个简单常用的Fragment事务管理代码片段: FragmentTransaction ft = this.getSupportFragmentManager().beginTransaction(); ft.add(R.id.fragmentContainer, fragment, "tag"); ft.addToBackStack("<span style="fo

Android -- Wifi连接流程分析

Android -- Wifi连接流程分析 当我们在Android手机上连接一个AP时,间接调用WifiManager的connect()方法: /** * Connect to a network with the given configuration. The network also * gets added to the supplicant configuration. * * For a new network, this function is used instead of a

Android Zygote源码分析

目录 目录 概述 zygote分析 AppRuntime分析 创建虚拟机startVm 注册JNI函数startReg 进入JAVA世界 建立IPC通信服务端registerZygoteSocket 预加载类和资源preload 启动system_server 有求必应之等待请求runSelectLoop 概述 在Android系统中,所有的应用程序进程,以及用来运行系统关键服务的System进程都是由zygote进程负责创建的.因此,我们将它称为进程孵化器.zygote进程是通过复制自身的方式

Android recovery UI实现分析

Android recovery模式为何物? 关于这个问题, baidu上已经有无数的答案.不理解的朋友先补习一下. 从纯技术角度来讲, recovery和android本质上是两个独立的rootfs,  仅仅是recovery这个rootfs存在的意义就是为android这个rootfs服务,因此被解释为Android系统的一部分. recovery作为一个简单的rootfs, 提供了很有限的几个功能,仅仅包括了几个简单的库,UI的显示採用的是直接刷framebuffer的形式,作为andro

Android深入浅出之 AudioTrack分析

Android深入浅出之Audio 第一部分 AudioTrack分析 一 目的 本文的目的是通过从Audio系统来分析Android的代码,包括Android自定义的那套机制和一些常见类的使用,比如Thread,MemoryBase等. 分析的流程是: l         先从API层对应的某个类开始,用户层先要有一个简单的使用流程. l         根据这个流程,一步步进入到JNI,服务层.在此过程中,碰到不熟悉或者第一次见到的类或者方法,都会解释.也就是深度优先的方法. 1.1 分析工

Android 外部存储权限分析

不知道你有么有发现,来自菜鸟的成长史:http://blog.csdn.net/zjbpku/article/details/25161131, KitKat之后的版本不再支持用户对外置SDcard(Secondary Storage)的写入等操作.如果用户想要将文件等copy到手机中,则只能 存储到内部存储器中,而无法存储到外置sdcard中,而且无法创建新的文件夹,这样一来给用户和开发者都带来了一定的不便.之所 以在KitKat之后版本中无法操作外置Sdcard,是因为Google更改了此模

Android -- Vold机制简要分析

Android -- Vold机制简要分析 Vold是用于管理和控制Android外部存储介质的后台进程,这里说的管控,主要包括SDK的插拔.挂载/卸载和格式化等:它是Android平台外部存储系统的管控枢纽. Vold的整个控制模块主要由三个类模块构成:NetlinkManager.VolumeManager和CommandListener,它们的功能划分大概是: NetlinkManager:用于从kernel中获取SD卡插拔的Uevnet消息 VolumeManager:管理模块,对Net

Android Volley源码分析

今天来顺手分析一下谷歌的volley http通信框架.首先从github上 下载volley的源码, 然后新建你自己的工程以后 选择import module 然后选择volley. 最后还需要更改1个 配置文件 就是我选中的那句话.记得要加.不然会报错.把volley作为一个module 在你的项目中引用的原因是,因为我们要分析源码,需要测试我们心中所想.所以这么做是最方便的. 就相当于eclipse里面的工程依赖. 有关于volley 如何使用的教程 我就不在这写了,请自行谷歌,我们直接看