PackageManagerService源码分析之入门(一)

版权声明:本文为博主原创文章,欢迎转载但需注明出处谢谢! https://blog.csdn.net/dongxianfei/article/details/52717981

1、背景

今天要分析的内容相信大家肯定都不会陌生,也许你平时没有直接去调用其方法,但是Android系统却无时无刻不在使用它,它就是我们今天要重点分析的Android核心服务PackageManagerService。

平时也许你感觉不到它的存在,或许这就是所有服务的共性吧,但是它却在系统中举足轻重。比如平时我们在重启手机时,它都会在系统后台默默的将所有已安装的应用进行扫描操作,另外就是当我们在安装应用时它也会进行安装操作。

在这里我也不说那么多的题外话了,我们直接进入今天的主题,由于PackageManagerService的源码较多(其工作是很劳累的),所以我准备分几个阶段来进行解读。

2、整体架构

大家要知道,像这种系统级别的核心服务Android是不会允许我们直接调用其方法的,Android肯定会想方设法的将其封装并提供一个对外的接口供开发者使用,所以今天我们就从开发者的角度来一步步的深入了解。

好啦进入我们今天的正题,大家都知道Context是一个抽象类,其定义的所有方法的真正的实现者是ContextImpl类,如果大家不是很明白的可以参考一下我的另外一篇文章Android中的Context源码分析,我们进入该类的getPackageManager方法。

class ContextImpl extends Context {

    private PackageManager mPackageManager;

    //当不为null时直接返回
    public PackageManager getPackageManager() {
        if (mPackageManager != null) {
            return mPackageManager;
        }

        //这里先调用ActivityThread的getPackageManager获得IPackageManager对象
        IPackageManager pm = ActivityThread.getPackageManager();
        if (pm != null) {
            // Doesn't matter if we make more than one instance.

            //创建ApplicationPackageManager对象
            return (mPackageManager = new ApplicationPackageManager(this, pm));
        }

        return null;
    }
}

我们先来看一下ActivityThread.getPackageManager方法,该方法是获得IPackageManager对象。

public final class ActivityThread {

    static IPackageManager sPackageManager;

    public static IPackageManager getPackageManager() {
        if (sPackageManager != null) {
            return sPackageManager;
        }

        //获得PackageManagerService的Binder对象
        IBinder b = ServiceManager.getService("package");
        //传入IPackageManager.Stub.asInterface方法中获得IPackageManager对象
        sPackageManager = IPackageManager.Stub.asInterface(b);
        //最终返回一个IPackageManager对象
        return sPackageManager;
    }
}

这里我们可以看到是通过IPackageManager.Stub.asInterface方法来获得IPackageManager对象,我们在进去看一下该方法。

public static android.content.pm.IPackageManager asInterface(android.os.IBinder obj)
    {
        if ((obj==null)) {
            return null;
        }
    android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
    if (((iin!=null)&&(iin instanceof android.content.pm.IPackageManager))) {
        return ((android.content.pm.IPackageManager)iin);
    }
    //这里最终通过创建IPackageManager的内部Proxy对象并返回
    return new android.content.pm.IPackageManager.Stub.Proxy(obj);
    }

这里需要说明一下,这个IPackageManager文件并不在源码中,最终文件在out目录下。

我们在来看一下Proxy这个类。

public interface IPackageManager extends android.os.IInterface

    public static abstract class Stub extends android.os.Binder implements android.content.pm.IPackageManager{

        private static class Proxy implements android.content.pm.IPackageManager{

            //Proxy类有一个成员变量mRemote的Binder对象,该对象用于和PackageManagerService进行通信
            private android.os.IBinder mRemote;
            Proxy(android.os.IBinder remote)
            {
                mRemote = remote;
            }
            @Override public android.os.IBinder asBinder()
            {
                return mRemote;
            }
        }
    }
}

好啦,分析到这里之后我们就将getPackageManager()方法中的IPackageManager pm = ActivityThread.getPackageManager();分析完毕啦,这里最终获得一个IPackageManager对象(其真正的是IPackageManager的Proxy对象),接下来我们继续分析。

getPackageManager()方法中接下来开始创建ApplicationPackageManager对象,并将ContextImpl对象和之前创建的IPackageManager的代理对象传入作为参数,我们进入ApplicationPackageManager的构造函数看一下。

final class ApplicationPackageManager extends PackageManager {

    private final ContextImpl mContext;
    private final IPackageManager mPM;

    ApplicationPackageManager(ContextImpl context,
                              IPackageManager pm) {
        mContext = context;
        mPM = pm;
    }
}

在ApplicationPackageManager的构造器中将IPackageManager的代理对象Proxy赋值给mPM成员变量,这样mPM成员变量就指向了IPackageManager.Stub.Proxy类型的变量。

好啦,到此我们就将和PackageManagerService相关的类都大致理清楚啦,我们现在来总结一下这几个类之间的关系。

3、总结

首先我们先看一张类之间的关系图,然后在来分析。

PKMS相关类图

从这个关系图可知,mPM变量指向Proxy代理,客户端可通过Context.getPackageManager()获得ApplicationPackageManager对象,调用ApplicationPackageManager的方法后将直接被调用到IPackageManager的Proxy代理方法,此时通过Binder类型mRemote变量来继续调用PackageManagerService方法,从而开始执行PackageManagerService方法。

接下来我们对本篇文章总结如下:
(1)IPackageManager接口中定义了服务端和客户端交流的方法,其还定义了一个内部类Proxy,该类继承于Binder并实现IPackageManager接口。

(2)PackageManagerService继承于IPackageManager.Stub类,由于Stub继承于Binder,所以PackageManagerService可作为服务端使用Binder通信。

(3)Stub内部还定义了一个Proxy类,该类有一个Binder类型的成员变量mRemote,用于和服务端PakcageManagerService通信。

(4)IPackageManager接口定义了许多业务函数,Android为其提供一个子集供开发者访问,该子集就是PackageManager抽象类,可通过Context.getPackageManager()方法获得,前面我们也说分析,该方法最终会返回PackageManager的子类ApplicationPackageManager对象。

(5)ApplicationPackageManager继承于PackageManager并实现其抽象方法,在之前的代码中我们也做分析了,在Context.getPackageManager()中将IPackageManager的代理对象Proxy赋值给ApplicationPackageManager的mPM成员变量,这样mPM成员变量就指向了IPackageManager.Stub.Proxy的代理对象,然后可通过Binder间接的调用到PackageManagerService方法。

好啦,今天的PackageMangerService的入门我们就说到这里了,下篇文章我们将正式分析PackageMangerService的功能PackageManagerService源码分析之第一阶段(二)

猜你喜欢

转载自blog.csdn.net/dongxianfei/article/details/52717981