[Binder机制]众多Service启动流程-java层Service(一)

​ 上一篇文章中讲述了大管家servicemanager的启动流程,其中servicemanager多次与binder驱动交互,最终由于读取不到service们发送的命令而挂起进程。本篇文章将以一个service启动为例,分析service启动的流程,以便大家更好的理解binder机制中各个角色的交互关系。

​ 首先上一篇文章中提到:XXXManagerService: 服务提供者。可以理解解为“淘宝卖家”。作为“淘宝卖家”的service们首先要向servicemanager(淘宝网站)注册它们的信息,那么问题来了,怎么向servicemanager注册它们的信息呢?通过上一篇文章我们了解到servicemanager将自己注册成了“大管家”,并且这个大管家是独一无二的,这样的话service们只要进入binder驱动中告诉它:“我需要这个独一无二的‘大管家’”,那么binder驱动就会找到servicemanager交给service们,service们再将自己注册到servicemanager中即可。流程到此还不算完因为虽然service虽然已经向servicemanager注册了,但是它最本职的工作是面向应用程序的,它需要向应用程序或者其他任何需要服务的程序提供服务,类比“淘宝卖家”最本职的工作是给“淘宝买家”提供商品。分析到此,有可能有些读者可能会发现,servicemanager为service们提供注册功能,那么servicemanager算不算是一个特殊的service呢?答案是肯定的,不同的是service们服务的目标是普通进程,而servicemanager是专门为service们提供服务的服务。那么根据上一篇文章的分析,可以知道既然service想要为其他普通进程提供服务,必然要接收它们提供的命令,类似淘宝买家要向淘宝卖家发送“我要买某某某商品”命令。那么根据推断service里面肯定有一个循环来接收普通进程发送的命令,就像servicemanager这个特殊的service一样,它有一个binder_looper中的for循环来接收service们发出的命令。

​ 经过上一段的分析,应该还是不能对service的启动流程有清晰的认识,只要稍有印象即可。在接下来的篇幅中会一步一步分析service的启动过程,相信会对service的启动有更深刻的理解。

​ 要说明的是service众多,有的是以标准C语言程序存在,有的是以java语言程序存在,本篇文章先分析java语言程序的service,而C语言的service将在下一篇文章中介绍。取ActivityManagerService(AMS)的启动作为代表进行分析,其他service启动大同小异。

​ 关于AMS启动首先做一下说明:在Android系统启动时会创建SystemServer进程,源代码地址在frameworks/base/services/java/com/android/server/SystemServer.java,而该进程启动后会经过一系列操作调用两个方法,一个是init1方法,一个是init2方法,init1方法中讲主讲的C语言service启动,而init2方法则启动java语言实现的service,至于SystemServer进程如何启动,以及init1和init2方法如何调用会在文章后面讲解,此处暂时知道这两个方法会在SystemServer进程启动时依次调用即可。

step1

public static final void init2() {
        Slog.i(TAG, "Entered the Android system server!");
        Thread thr = new ServerThread();
        thr.setName("android.server.ServerThread");
        thr.start();
    }

位置:frameworks/base/services/java/com/android/server/SystemServer.java

​ 程序较短,首先创建ServerThread线程,然后启动该线程。

​ 接下里进入ServerThread线程中查看代码。

class ServerThread extends Thread {

    @Override
    public void run() {
        ...
        context = ActivityManagerService.main(factoryTest);
        ...
        ActivityManagerService.setSystemProcess();
        ...
    }
}

位置:frameworks/base/services/java/com/android/server/SystemServer.java

​ ServerThread的主要功能是启动java层的各个service,只分析与AMS启动相关内容。run方法中调用ActivityManagerService静态方法main和setSystemProcess,首先分析ActivityManagerService的main方法。

    public static final Context main(int factoryTest) {
        AThread thr = new AThread();
        thr.start();

        synchronized (thr) {
            while (thr.mService == null) {
                try {
                    thr.wait();
                } catch (InterruptedException e) {
                }
            }
        }

        ActivityManagerService m = thr.mService;
        mSelf = m;
        ....
    }

位置:frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

​ 忽略无关代码。main方法中首先启动了Athread线程,然后获取thr对象锁,进入临界区,若thr.mService的值为空,则阻塞当前线程,等待唤醒,可以猜测,在Athread线程中一定有关于thr.mService的赋值操作。下面进入到AThread中分析代码。

    static class AThread extends Thread {
        ActivityManagerService mService;
        ...

        public AThread() {
            super("ActivityManager");
        }

        public void run() {
            ...
            ActivityManagerService m = new ActivityManagerService();

            synchronized (this) {
                mService = m;
                notifyAll();
            }
          ...
        }
    }

位置:frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

​ 忽略无关代码。AThread的run方法中首先创建了一个ActivityManagerService对象,然后进入临界区,将ActivityManagerService对象赋值为mService,再唤醒所有在AThread上等待的线程,这样执行main方法的线程将被唤醒继续执行。而main方法剩余操作将创建的ActivityManagerService对象赋值给了静态成员变量mSelf。这样main方法中关于AMS启动的部分就分析完了,接下来分析ServerThread中执行的ActivityManagerService.setSystemProcess()。

 public static void setSystemProcess() {
            ...
            ActivityManagerService m = mSelf;
            ServiceManager.addService("activity", m);
            ....
 }

位置:frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

​ 忽略无关代码。setSystemProcess只是将main方法中赋值的mSelf取出然后传入到ServiceManager.addService中去。接下来分析ServiceManager.addService方法。

  public static void addService(String name, IBinder service) {
        try {
            getIServiceManager().addService(name, service);
        } catch (RemoteException e) {
            Log.e(TAG, "error in addService", e);
        }
    }

位置:frameworks/base/core/java/android/os/ServiceManager.java

​ 方法又将”activity”和mSelf转发给getIServiceManager().addService方法。注意这里的addService方法接收的是String类型和IBinder类型的参数,查看ActivityManagerService.java知道ActivityManagerService继承自ActivityManagerNative,而ActivityManagerNative又继承自Binder,Binder实现了IBinder接口。接下来先分析getIServiceManager()方法的执行。

    private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }

        // 获取sServiceManager
        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
        return sServiceManager;
    }

位置:fameworks/base/core/java/android/os/ServiceManager.java

​ 首先判断sServiceManager是否已经赋值,避免重复操作,sServiceManager声明为IServiceManager。下一句代码便是创建sServiceManager的地方,首先调用了静态方法BinderInternal.getContextObject(),先分析该方法。

public static final native IBinder getContextObject();

位置:frameworks/base/core/java/com/android/internal/os/BinderInternal.java

​ getContextObject方法是native方法,对应frameworks/base/core/jni/android_util_Binder.cpp中的android_os_BinderInternal_getContextObject函数,关于android系统如何映射native方法,后续文章会进行讲解,后面会多次遇到native方法,按照文章思路继续分析即可。接下来进入step2,分析getContextObject的执行结果。

step2

static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
    return javaObjectForIBinder(env, b);
}

位置:frameworks/base/core/jni/android_util_Binder.cpp

​ 首先解释一下sp,sp是smart pointer的缩写,意为智能指针,我们知道在C语言中内存的申请后必须手动释放,否则就会出现内存泄漏现象,在Android系统中,为了避免内存泄漏,定义了智能指针,实现内存的自动释放。其大概原理是,当智能指针的指向的对象引用被引用的次数为0时会自动释放内存。此处定义了一个指向IBinder类型的智能指针b,而ProcessState::self()->getContextObject(NULL)则返回一个IBinder类型的值。下面我们先进入静态函数ProcessState::self()中分析。

sp<ProcessState> ProcessState::self()
{
    if (gProcess != NULL) return gProcess;

    AutoMutex _l(gProcessMutex);
    if (gProcess == NULL) gProcess = new ProcessState;
    return gProcess;
}

位置:frameworks/base/libs/binder/ProcessState.cpp

​ 代码逻辑很简单,这是一个进程单例,整个进程中只有一个ProcessState对象,self方法返回该ProcessState对象。由于首次进入self函数,会调用构造函数创建该单例对象gProcess。下面进入ProcessState构造函数中分析。

ProcessState::ProcessState()
    : mDriverFD(open_driver())
    , mVMStart(MAP_FAILED)
    , mManagesContexts(false)
    , mBinderContextCheckFunc(NULL)
    , mBinderContextUserData(NULL)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1)
{
    if (mDriverFD >= 0) {
        // XXX Ideally, there should be a specific define for whether we
        // have mmap (or whether we could possibly have the kernel module
        // availabla).
#if !defined(HAVE_WIN32_IPC)
        // mmap the binder, providing a chunk of virtual address space to receive transactions.
        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
        if (mVMStart == MAP_FAILED) {
            // *sigh*
            LOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
            close(mDriverFD);
            mDriverFD = -1;
        }
#else
        mDriverFD = -1;
#endif
    }

    LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened.  Terminating.");
}

位置:frameworks/base/libs/binder/ProcessState.cpp

​ 首先调用了open_driver函数,并将返回值复制给mDriverFD变量,然后初始化了一堆其他的成员变量。可以猜测到open_driver函数应该就是打开binder驱动的函数,稍后我们再验证。然后该判断打开binder驱动打开是否成功,若成功打开,调用binder驱动提供的mmap函数映射内存。回顾上一篇文章servicemanager的启动,它在binder_open函数一样是进行了打开驱动和映射内存两项操作。下面分析open_driver函数。

static int open_driver()
{
    int fd = open("/dev/binder", O_RDWR);
    if (fd >= 0) {
        fcntl(fd, F_SETFD, FD_CLOEXEC);
        int vers;
        status_t result = ioctl(fd, BINDER_VERSION, &vers);
        if (result == -1) {
            LOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
            close(fd);
            fd = -1;
        }
        if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
            LOGE("Binder driver protocol does not match user space protocol!");
            close(fd);
            fd = -1;
        }
        size_t maxThreads = 15;
        result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
        if (result == -1) {
            LOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
        }
    } else {
        LOGW("Opening '/dev/binder' failed: %s\n", strerror(errno));
    }
    return fd;
}

位置:frameworks/base/libs/binder/ProcessState.cpp

同样是调用open函数打开binder驱动,然后进行错误判断,和servicemanager不同的是,该函数打开binder驱动后进行了两次ioctl函数的调用。这两次ioctl函数的调用发送的命令是BINDER_VERSION和BINDER_SET_MAX_THREADS,根据名字可以猜测到分别用来获取binder的版本,和设置最大线程数。下面先分析BINDER_VERSION的调用。

static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
  ...
    switch (cmd) {
        ...
        case BINDER_VERSION:
        if (size != sizeof(struct binder_version)) {
            ret = -EINVAL;
            goto err;
        }
        if (put_user(BINDER_CURRENT_PROTOCOL_VERSION, &((struct binder_version *)ubuf)->protocol_version)) {
            ret = -EINVAL;
            goto err;
        }
        ...
    }
  ...
}

位置:drivers/staging/android/binder.c

​ 只分析case BINDER_VERSION内容。首先验证命令大小,然后将BINDER_CURRENT_PROTOCOL_VERSION的值写入&((struct binder_version *)ubuf)->protocol_version)中,而ubuf是在当前情况下传入的是int指针,此时将其强制转换为struct binder_version指针,并且binder_version中只有一个protocol_version属性,因此当相当于将BINDER_CURRENT_PROTOCOL_VERSION的值直接存入到传入参数&vers指向的地址中去。接下来分析另一个ioctl函数调用。

static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
  ...
    switch (cmd) {
        ...
        case BINDER_SET_MAX_THREADS:
        if (copy_from_user(&proc->max_threads, ubuf, sizeof(proc->max_threads))) {
            ret = -EINVAL;
            goto err;
        }
        break;
        ...
    }
  ...
}

位置:drivers/staging/android/binder.c

​ 只分析case BINDER_SET_MAX_THREADS内容。此处将传入的maxThreads值复制到当前进程的binder_proc的max_threads变量中去。这样open_driver函数的调用就分析完成了。而ProcessState构造函数的剩余代码只是一些出错分析,这样ProcessState::self函数也执行完了,并返回到android_os_BinderInternal_getContextObject中执行getContextObject函数且传入参数为NULL。接下来进入ProcessState的getContextObject函数继续分析。

sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
{
    return getStrongProxyForHandle(0);
}

位置:frameworks/base/libs/binder/ProcessState.cpp

此处调用了getStrongProxyForHandle函数且传入值为0,继续分析getStrongProxyForHandle函数。

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    sp<IBinder> result;
    //加锁
    AutoMutex _l(mLock);
    //通过参数handler查找handle_entry结构体
    handle_entry* e = lookupHandleLocked(handle);

    if (e != NULL) {
        // We need to create a new BpBinder if there isn't currently one, OR we
        // are unable to acquire a weak reference on this current one.  See comment
        // in getWeakProxyForHandle() for more info about this.
        IBinder* b = e->binder;
        if (b == NULL || !e->refs->attemptIncWeak(this)) {
            b = new BpBinder(handle); 
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
        } else {
            // This little bit of nastyness is to allow us to add a primary
            // reference to the remote proxy when this team doesn't have one
            // but another team is sending the handle to us.
            result.force_set(b);
            e->refs->decWeak(this);
        }
    }

    return result;
}

位置:frameworks/base/libs/binder/ProcessState.cpp

​ 首先定义返回值result,然后加锁,再从本地列表中handle_entry,若查不到则会创建一个返回给e,lookupHandleLocked的执行可自行查看。此时假设第一次执行getStrongProxyForHandle(0),显然if语句为真,b的值为NULL,则下一个if语句为真,创建BpBinder对象,并传入handler即0,再将b的值赋值给e->binder以便下次使用不再创建。接下里来将b的引用计数器赋值给e->refs,最后赋值b给result。总的来说该函数就是通过handler值创建了一个BpBinder的代理对象,并且将这个代理类存储到列表中,以便下次使用相同的handler调用该函数时不需要重新创建BpBinder。关于代理对象的意思可以查找关于设计模式中代理模式的用法,不再赘述。这样代码返回到android_os_BinderInternal_getContextObject函数继续执行,android_os_BinderInternal_getContextObject最后将javaObjectForIBinder的返回值return。javaObjectForIBinder函数的作用根据名字可以猜测,它应该是通过IBinder参数创建一个java的对象。javaObjectForIBinder函数在以后的分析中会经常使用,此处稍做解释,我们知道getStrongProxyForHandle只是创建了一个C语言层面的BpBinder,其中BpBinder继承了IBinder,那么这个BpBinder最终要拿来返回给java语言使用,但是它偏偏是一个C语言的对象,那么就需要一个java类来代表BpBinder,这个java类就是BinderProxy,位于frameworks/base/core/java/android/os/Binder.java中,巧妙的是BinderProxy中有一个int类型的属性mObject,它用来存储C语言层面的BpBinder的地址,这样下次需要使用BpBinder时就从BinderProxy的mObject中取出BpBinder的地址来操作BpBinder即可。概括的来说就是在BpBinder这个类上再加一层代理类BinderProxy,这种跨两种语言的代理模式经常在Android系统中出现。这样应该就明白了javaObjectForIBinder就是根据getStrongProxyForHandle返回的BpBinder创建了一个BinderProxy。关于javaObjectForIBinder的代码内容不再解释,有兴趣的可以自行研读。这样代码就一层层的返回到了getIServiceManager的执行中去,getIServiceManager方法最后将调用ServiceManagerNative.asInterface且参数为返回的BinderProxy,下面进入ServiceManagerNative.asInterface中分析。

    static public IServiceManager asInterface(IBinder obj)
    {
        if (obj == null) {
            return null;
        }
        IServiceManager in =
            (IServiceManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }

        return new ServiceManagerProxy(obj);
    }

位置:frameworks/base/core/java/android/os/ServiceManagerNative.java

​ 首先检查参数合法性,然后调用queryLocalInterface方法,queryLocalInterface的作用是查看要申请的service是否是本进程中的service,很明显要申请的servicemanager不在本进程中,最后创建了一个ServiceManagerProxy并传入了IBinder,这里ServiceManaagerProxy是对BinderProxy的进一步代理。这样getIServiceManager方法就执行完毕了,返回到再上一层的addService中执行,接着addService调用了getIServiceManager返回的ServiceManagerProxy实例的addService方法且传入参数name和ServiceManagerProxy,这里name是字符串“activity”,如果忘记的话可以反回前面相关的部分查看,可以注意到addService方法中有一个try-catch用来捕捉RemoteException, 这是一个远程连接异常,这样我们就可以猜测到接下来要执行的addService方法应该会涉及到远程连接,远程连接是什么呢?这里当然通过binder驱动和servicemanager程发生数据交互了!接下来进入step3分析addService方法的执行。

step3

    public void addService(String name, IBinder service)
            throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeString(name);
        data.writeStrongBinder(service);
        mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
        reply.recycle();
        data.recycle();
    }

位置:frameworks/base/core/java/android/os/ServiceManagerNative.java

​ 首先从step2中我们知道调用addService函数的IBinder其实是一个ServiceManagerProxy实例。addService函数中首先创建了data和reply两个Parcel的实例,这个Parcel是什么呢?可以把它理解成一种“包裹”,“包裹”里放着要进行IPC的数据,其中IPC包括数据读取和数据写入,data对应要写入的数据,而reply对应读取的数据。理解完Parcel的作用,我们再来看看它是如何实现的,这里要注意的是,Parcel这个概念在java和C语言层面都存在,几乎伴随着整个Binder机制,因此我们先分析Parcel的创建过程,其他操作待用到再进行分析。

...
private static final Parcel[] sOwnedPool = new Parcel[POOL_SIZE];
...
public static Parcel obtain() {
        final Parcel[] pool = sOwnedPool;
        synchronized (pool) {
            Parcel p;
            for (int i=0; i<POOL_SIZE; i++) {
                p = pool[i];
                if (p != null) {
                    pool[i] = null;
                    if (DEBUG_RECYCLE) {
                        p.mStack = new RuntimeException();
                    }
                    return p;
                }
            }
        }
        return new Parcel(0);
    }

位置:frameworks/base/core/java/android/os/Parcel.java

​ 一般来说,java的名为obtain的工厂方法都是实现了实例缓冲池的,这里也不例外,首先类赋值默认的缓冲池给pool数组,然后进入临界区,从缓冲池中取实例,若缓冲池中有实例,则取出并返回,且将池中该位置实例置空。若无实例则以0为参数调用构造函数创建实例。这里由于sOwnedPool只是一个空数组,并没有填入实例,因此取不到实例,所以调用new Parcel(0)。

    private Parcel(int obj) {
        if (DEBUG_RECYCLE) {
            mStack = new RuntimeException();
        }
        //Log.i(TAG, "Initializing obj=0x" + Integer.toHexString(obj), mStack);
        init(obj);
    }

位置:frameworks/base/core/java/android/os/Parcel.java

​ 构造函数调用了init方法。

    private native void init(int obj);

位置:frameworks/base/core/java/android/os/Parcel.java

​ init函数是本地方法,接下来进入本地层代码分析。

static void android_os_Parcel_init(JNIEnv* env, jobject clazz, jint parcelInt)
{
    Parcel* parcel = (Parcel*)parcelInt;
    int own = 0;
    if (!parcel) {
        //LOGI("Initializing obj %p: creating new Parcel\n", clazz);
        own = 1;
        parcel = new Parcel;
    } else {
        //LOGI("Initializing obj %p: given existing Parcel %p\n", clazz, parcel);
    }
    if (parcel == NULL) {
        jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
        return;
    }
    //LOGI("Initializing obj %p from C++ Parcel %p, own=%d\n", clazz, parcel, own);
    env->SetIntField(clazz, gParcelOffsets.mOwnObject, own);
    env->SetIntField(clazz, gParcelOffsets.mObject, (int)parcel);
}

位置:frameworks/base/core/jni/android_util_Binder.cpp

​ 因为传入参数obj为0因此,指针parcel被赋值为NULL。然后判断parcel是否为NULL,此处为NULL,则赋值own为1,新建本地层的Parcel对象。然后做错误检查,最后将own的值赋值给clazz的mOwnObject变量,也就是java层的Parcel的mOwnObject变量,同理赋值给mObject变量。这里可以理解为java层的Parcel类只是作为本地层Parcel类的代理类而已,真正存储数据的还是本地层的Parcel实例。这样就回到了addService方法中继续执行了。接下来执行data.writeInterfaceToken(IServiceManager.descriptor);因此继续分析writeInterfaceToken函数。

public final native void writeInterfaceToken(String interfaceName);

位置:frameworks/base/core/java/android/os/Parcel.java

​ 首先IServiceManager.descriptor变量是字符串“android.os.IServiceManager”。writeInterfaceToken是本地方法。

static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jobject clazz, jstring name)
{
    Parcel* parcel = parcelForJavaObject(env, clazz);
    if (parcel != NULL) {
        // In the current implementation, the token is just the serialized interface name that
        // the caller expects to be invoking
        const jchar* str = env->GetStringCritical(name, 0);
        if (str != NULL) {
            parcel->writeInterfaceToken(String16(str, env->GetStringLength(name)));
            env->ReleaseStringCritical(name, str);
        }
    }
}

位置:frameworks/base/core/jni/android_util_Binder.cpp

​ 首先从java层取出对应的本地层Parcel对象。若不为NULL,则取出字符串“android.os.IServiceManager”,再判断取出字符串不为空,则调用parcel对象的writeInterfaceToken函数,最后释放字符串。下面分析本地层writeInterfaceToken函数的执行。

// Write RPC headers.  (previously just the interface token)
status_t Parcel::writeInterfaceToken(const String16& interface)
{
    writeInt32(IPCThreadState::self()->getStrictModePolicy() |
               STRICT_MODE_PENALTY_GATHER);
    // currently the interface identification token is just its name as a string
    return writeString16(interface);
}

位置:frameworks/base/libs/binder/Parcel.cpp

​ 该函数注释写道“Write RPC headers. (previously just the interface token)”,意思是“写入RCP头部信息。(最前面只是接口的token)”,另一个注释:“currently the interface identification token is just its name as a string”,意思是“当前的的接口身份标识符就是它的一个字符串名称”。大概可以猜测出,writeInt32函数用于写入一个标识符没有实用信息,而writeString16用于写入鉴别身份的标识,也就是写入字符串“android.os.IServiceManager”,这两个函数就不再深入分析了,只是往Parcel中写入对应数据而已。这样就回到了addService方法中了,接下来将执行data.writeString(name);。

public final native void writeString(String val);

位置:frameworks/base/core/java/android/os/Parcel.java

​ writeString依然是本地方法。

static void android_os_Parcel_writeString(JNIEnv* env, jobject clazz, jstring val)
{
    Parcel* parcel = parcelForJavaObject(env, clazz);
    if (parcel != NULL) {
        status_t err = NO_MEMORY;
        if (val) {
            const jchar* str = env->GetStringCritical(val, 0);
            if (str) {
                err = parcel->writeString16(str, env->GetStringLength(val));
                env->ReleaseStringCritical(val, str);
            }
        } else {
            err = parcel->writeString16(NULL, 0);
        }
        if (err != NO_ERROR) {
            signalExceptionForError(env, clazz, err);
        }
    }
}

位置:frameworks/base/core/jni/android_util_Binder.cpp

​ 同样是先取出java层Parcel实例对应本地层的Parcel对象,然后使用writeString16函数将字符串“activity”写入。然后执行data.writeStrongBinder(service);。

public final native void writeStrongBinder(IBinder val);

位置:frameworks/base/core/java/android/os/Parcel.java

依然是本地方法。

static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jobject clazz, jobject object)
{
    Parcel* parcel = parcelForJavaObject(env, clazz);
    if (parcel != NULL) {
        const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
        if (err != NO_ERROR) {
            signalExceptionForError(env, clazz, err);
        }
    }
}

位置:frameworks/base/core/jni/android_util_Binder.cpp

​ 同样先找到本地层Parcel,然后调用了writeStrongBinder函数。再将传入的ActivityManagerService,也就是jobject object,作为参数调用ibinderForJavaObject函数。接下来分析ibinderForJavaObject函数。

sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{
    if (obj == NULL) return NULL;

    if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
        JavaBBinderHolder* jbh = (JavaBBinderHolder*)
            env->GetIntField(obj, gBinderOffsets.mObject);
        return jbh != NULL ? jbh->get(env, obj) : NULL;
    }

    if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
        return (IBinder*)
            env->GetIntField(obj, gBinderProxyOffsets.mObject);
    }

    LOGW("ibinderForJavaObject: %p is not a Binder object", obj);
    return NULL;
}

位置:frameworks/base/core/jni/android_util_Binder.cpp

​ 从名字可以看出来这是一个从java层的IBinder对象转换为本地层IBinder的函数,是不是有点类似Parcel,没错IBinder实体,也就是AMS,或者说服务实体在java层和本地层也是一一对应的,可是这里是转换为本地层的IBinder,AMS并没有创建对应的本地层IBinder啊?其实这里它已经创建了,与Parcel在构造函数中创建一样,AMS也是在它的构造函数中茶创建了本地层对应的IBinder,之前我们并没有分析这部分代码,现在回头分析AMS的创建。还记得frameworks/base/services/java/com/android/server/am/ActivityManagerService.java中的AThread线程吗?在它的run方法中调用了new ActivityManagerService(),这里创建的AMS实例也就是ibinderForJavaObject传入的jobject obj,我们知道ActivityManagerService继承自ActivityManagerNative,而ActivityManagerNative又继承自Binder,所以在ActivityManagerService构造函数调用时Binder的构造函数也调用,在它的构造函数里就完成了本地层的IBinder创建。

    public Binder() {
        init();

        if (FIND_POTENTIAL_LEAKS) {
            final Class<? extends Binder> klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
                Log.w(TAG, "The following Binder class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }
    }

位置:frameworks/base/core/java/android/os/Binder.java

​ 这里只有init起到了作用。

private native final void init();

位置:frameworks/base/core/java/android/os/Binder.java

本地方法。

static void android_os_Binder_init(JNIEnv* env, jobject obj)
{
    JavaBBinderHolder* jbh = new JavaBBinderHolder();
    if (jbh == NULL) {
        jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
        return;
    }
    LOGV("Java Binder %p: acquiring first ref on holder %p", obj, jbh);
    jbh->incStrong((void*)android_os_Binder_init);
    env->SetIntField(obj, gBinderOffsets.mObject, (int)jbh);
}

位置:frameworks/base/core/jni/android_util_Binder.cpp

​ 这里首先创建了JavaBBinderHolder对象,然后增加它的强引用,最后再把它的地址存入java层IBinder也就是Binder(AMS)实例的mObject属性中,以便进入本地层使用。从JavaBBinderHolder名字可以猜测它一个Holder,那么它应该持有一个本地层IBinder,那么我们继续分析JavaBBinderHolder类。

class JavaBBinderHolder : public RefBase
{
public:
    sp<JavaBBinder> get(JNIEnv* env, jobject obj)
    {
        AutoMutex _l(mLock);
        sp<JavaBBinder> b = mBinder.promote();
        if (b == NULL) {
            b = new JavaBBinder(env, obj);
            mBinder = b;
            LOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%d\n",
                 b.get(), b->getWeakRefs(), obj, b->getWeakRefs()->getWeakCount());
        }

        return b;
    }

    sp<JavaBBinder> getExisting()
    {
        AutoMutex _l(mLock);
        return mBinder.promote();
    }

private:
    Mutex           mLock;
    wp<JavaBBinder> mBinder;
};

位置:frameworks/base/core/jni/android_util_Binder.cpp

​ 可以看到它持有一个JavaBBinder对象,可是它暂时是NULL值。这样我们再回到ibinderForJavaObject函数中,根据函数内容,首先判断AMS是否是一个Binder对象,当然是,则首先取出AMS中存储的JavaBBinderHolder,再执行return jbh != NULL ? jbh->get(env, obj) : NULL;,所以执行了 jbh->get(env, obj),我们分析它的get函数,代码逻辑较简单,首先从取出JavaBBinder,若JavaBBinder为空则创建一个JavaBBinder并赋值给mBinder,最后返回创建的JavaBBinder。那么我们接着分析下JavaBBinder的构造函数。

class JavaBBinder : public BBinder
{
public:
    JavaBBinder(JNIEnv* env, jobject object)
        : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object))
    {
        LOGV("Creating JavaBBinder %p\n", this);
        android_atomic_inc(&gNumLocalRefs);
        incRefsCreated(env);
    }
 ...
   private:
    ...
    jobject const   mObject;
};

位置:frameworks/base/core/jni/android_util_Binder.cpp

​ JavaBBinder调用构造函数时将AMS,也就是java层Binder实体存入了mObject变量,这样就清楚了,JavaBBinder其实是 一个代理类,他用来代理java层的AMS。这样get函数执行完了,接着ibinderForJavaObject函数也执行完了,返回到android_os_Parcel_writeStrongBinder函数执行writeStrongBinder。

status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
    return flatten_binder(ProcessState::self(), val, this);
}

位置:frameworks/base/libs/binder/Parcel.cpp

​ 本函数调用了flatten_binder函数。

status_t flatten_binder(const sp<ProcessState>& proc,
    const sp<IBinder>& binder, Parcel* out)
{
    flat_binder_object obj;

    obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
    if (binder != NULL) {
        IBinder *local = binder->localBinder();
        if (!local) {
            BpBinder *proxy = binder->remoteBinder();
            if (proxy == NULL) {
                LOGE("null proxy");
            }
            const int32_t handle = proxy ? proxy->handle() : 0;
            obj.type = BINDER_TYPE_HANDLE;
            obj.handle = handle;
            obj.cookie = NULL;
        } else {
            obj.type = BINDER_TYPE_BINDER;
            obj.binder = local->getWeakRefs();
            obj.cookie = local;
        }
    } else {
        obj.type = BINDER_TYPE_BINDER;
        obj.binder = NULL;
        obj.cookie = NULL;
    }

    return finish_flatten_binder(binder, obj, out);
}

位置:frameworks/base/libs/binder/Parcel.cpp

​ 这里首先创建了flat_binder_object结构体,然后赋值了它的flags属性,其中0x7f转换为二进制位1111111,而FLAT_BINDER_FLAG_ACCEPTS_FDS定义在内核工程中,位置是drivers/staging/android/binder.h,其值是0x100,二进制为100000000,做与运算结构是101111111。显然binder不为空,进入if语句后调用binder->localBinder(),我们知道传入进来的binder是ibinderForJavaObject函数返回的JavaBBinder,如果忘记的话可以查看前面的分析。而JavaBBinder继承自BBinder,那么我们接着分析BBinder的localBinder函数。

BBinder* BBinder::localBinder()
{
    return this;
}

位置:frameworks/base/libs/binder/Binder.cpp

​ 返回的就是当前BBinder。那么继续分析flatten_binder,进入else语句执行obj.type = BINDER_TYPE_BINDER; obj.binder = local->getWeakRefs(); obj.cookie = local;。最后调用finish_flatten_binder并返回。

inline static status_t finish_flatten_binder(
    const sp<IBinder>& binder, const flat_binder_object& flat, Parcel* out)
{
    return out->writeObject(flat, false);
}

位置:frameworks/base/libs/binder/Parcel.cpp

​ 这里把flat_binder_object对象写入了Parcel,这样整个writeStrongBinder函数的执行也就完成了,我们总结一下writeStrongBinder的作用。它主要是将创建好的JavaBBinder,也就是AMS的代理类,封装成了flat_binder_object结构体,再把这个结构体写入到Parcel中去。这样我们再返回到addService函数,执行mRemote.transact函数,由于mRemote.transact这段语句执行完毕以后,跨进程告诉SM注册AMS也就执行完了,所以transact中有相当复杂的逻辑,我们留到下一篇文章中再分析。

总结:

  • 首先创建ActivityManagerService对象,同时创建一个本地层的JavaBBinderHolder,JavaBBinderHolder中有一个JavaBBinder作为AMS对象的代理类。
  • 通过本地层创建servicemanager的代理对象BpBinder,并且将它封装成ServiceManagerProxy
  • 调用ServiceManagerProxy的addService注册ActivityManagerService,注册前创建Parcel data,用来发送写入信息,并将data中写入需要的相关数据。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值