Android进程通信之Binder浅析

常听Android的IPC是Binder机制,之前也看不少别人的博客。但总是似懂非懂。最近自己结合别人的博客和Activity的启动流程分析了一下。大致如下。(只是自己简单的理解,有错误的话希望大神能帮忙指正一下,谢谢)

1:Binder,可以在进程中传递的对象

2:Parcelable类型数据可以通过Binder和Intent传递


Activity启动流程(到Service):

    我们从startActivity开始,一直到Instrumentation.execStartActivity都很明确。这个方法中调用到ActivityManagerNative.getDefault().startActivity。

 int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);

ActivityManagerNative.getDefault()

static public IActivityManager getDefault() {
        return gDefault.get();
    }
再看gDefault:
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");    //获取服务Binder
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);        //获取Proxy对象
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };

通过ServiceManager.getService获取了指定服务的Binder,然后通过asInterface的方法获取到一个Proxy对象

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

        return new ActivityManagerProxy(obj);
    }

那么我们前面的ActivityManagerNative.getDefault().startActivity其实就是调用的proxy的StartActivity方法。

public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
            String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeString(callingPackage);
        intent.writeToParcel(data, 0);
        data.writeString(resolvedType);
        data.writeStrongBinder(resultTo);
        data.writeString(resultWho);
        data.writeInt(requestCode);
        data.writeInt(startFlags);
        if (profilerInfo != null) {
            data.writeInt(1);
            profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
        } else {
            data.writeInt(0);
        }
        if (options != null) {
            data.writeInt(1);
            options.writeToParcel(data, 0);
        } else {
            data.writeInt(0);
        }
        mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);  //传递消息
        reply.readException();
        int result = reply.readInt();
        reply.recycle();
        data.recycle();
        return result;
    }

Proxy中先使用Parcel封装了数据,然后拿构造函数中的Binder对象,也就是相关服务的Binder对象执行了transact方法,这里我的理解是这个方法将标识(START_ACTIVITY_TRANSACTION)和封装的数据通过Binder驱动,发送给了相关的服务--ActivityManagerService。完成一次跨进程的消息传递

ActivityManagerService要在自己的onTransact方法中处理接收的消息。因为它是继承自ActivityManagerNative的,自己也没有重写这个方法,所以调用的是ActivityManagerNative的onTransact方法。这个方法调用了startActivity方法,也就是调用了ActivityManagerService的startActivity方法

public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
        switch (code) {
        case START_ACTIVITY_TRANSACTION:
        {
            data.enforceInterface(IActivityManager.descriptor);
            IBinder b = data.readStrongBinder();
            IApplicationThread app = ApplicationThreadNative.asInterface(b);
            String callingPackage = data.readString();
            Intent intent = Intent.CREATOR.createFromParcel(data);
            String resolvedType = data.readString();
            IBinder resultTo = data.readStrongBinder();
            String resultWho = data.readString();
            int requestCode = data.readInt();
            int startFlags = data.readInt();
            ProfilerInfo profilerInfo = data.readInt() != 0
                    ? ProfilerInfo.CREATOR.createFromParcel(data) : null;
            Bundle options = data.readInt() != 0
                    ? Bundle.CREATOR.createFromParcel(data) : null;
            int result = startActivity(app, callingPackage, intent, resolvedType,        //调用服务的startActivity
                    resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
            reply.writeNoException();
            reply.writeInt(result);
            return true;
        }

如上,调用到的startActivity其实就是ActivityManagerService的方法。

至此,服务开始执行startActivity方法


Binder机制提到的四个角色上面都找到了:Client,ServiceManager,Service,Binder驱动。

也就是Client通过ServiceManager拿到服务的Binder,创建Proxy对象,再使用proxy对象通过Binder机制传递消息到Service进程。服务进程根据标识,分辨调用自己的哪个方法



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值