Android BInder机制

最近研究了下binder 机制 发下你好难理解 然后写下 我的理解吧 。可能有些地方不是很准确。但是总体还是没问题的

binder 机制是我们android 中一个跨进程通信的好关于解释我引用了之前看到的一片文章 觉得总的还行 所以羞耻的 拿过来了 希望原作者看到不要见怪大笑。。。

Binder是一种基于C/S的架构,主要包括四个部分:服务端(Server),客户端(Client),Binder驱动,ServiceManager。Binder是Android系统中非常重要的一种IPC机制,如果你想研究Frameworks,必须先对Binder机制诱有一定的认识,否则是无法看懂Frameworks源码的。上述四个部分分别在不同的进程中,他们之间的交互都是通过Binder实现,现在站在宏观的角度来分析Server,Client,ServiceManager之间的关系,如下图:



(1)    当一个服务进程启动后,需要将其中的Service注册到ServiceManager中,此时底层会有两个变化:①后台启动一个监听线程,监听Binder驱动发过来的消息 ② 在Binder驱动中生存一个Service的Binder引用

(2)    Client想和某一个Service交互,需要向ServiceManager申请获得该Service在Binder中的引用,并存放在自身的mRemote变量中,之后通过mRemote调用 transact 进而调用 ontransact 就是server 重写的ontransact 然后来实现交互

下面我要写的是我 研究源码对这一过程的 研究 大家可以 跟着我看看源码  。 我们经常 在 程序中 调用系统服务的某些方法 那 其实这一过程就是 binder 机制 所以我记录了查看源码的研究过程。我们以   ActivityManager 为例 依次进入源码观看请大家系好安全带不然会飞起来的

<span style="font-size:18px;">    ActivityManager ma= (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    ma.getRunningAppProcesses();


    public List<RunningAppProcessInfo> getRunningAppProcesses() {
        try {
            return ActivityManagerNative.getDefault().getRunningAppProcesses();
        } catch (RemoteException e) {
            return null;
        }
    }


    /// ActivityManagerNative.getDefault()-- >
    static public IActivityManager getDefault() {
        return gDefault.get();
    }</span>




    gDefault  是个什么玩意  他就是 Singleton 一个获取泛型的单例对象的玩意  gDefault.get(); 获取了一个 IActivityManager 对象 -->
   
<span style="font-size:18px;">private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");




            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };</span>


    看源码我们发现 这里面 又 在获取IActivityManager 对象时 同时获取了actvity service 的ibinder.
对象IBinder b = ServiceManager.getService("activity");  --》

<span style="font-size:18px;">    public static IBinder getService(String name) {
        try {
            IBinder service = sCache.get(name);  // 拿到 service的iBinder 对象 所以 service 的ibinder
            // 一定是实现了ibinder接口
                        if (service != null) {
                                return service;
                            } else {
                               return getIServiceManager().getService(name);
                            }
                    } catch (RemoteException e) {
                        Log.e(TAG, "error in getService", e);
                   }
                return null;
    }</span>




    IActivityManager am = asInterface(b);  --->这里 传给代理proxy 一个service 的ibinder 对象 然后返回一个am 对象
    IActivityManager 这是 ActivityManger 与service 的 交互协议的指定类 就是 service 提供给外界的调用的抽象接口
   下面的代码都是在ActivityManagerNative 类中 他实现了 IActivityManager
<span style="font-size:18px;">  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);//传给代理proxy 一个service 的ibinder 对象
    }</span>


    // return new ActivityManagerProxy(obj);-->  讲service 的ibinder 对象存起来  mRemote
   
<span style="font-size:18px;">public ActivityManagerProxy(IBinder remote)
    {
        mRemote = remote;
    }
</span>



    接下来 可以通过 ActivityManagerProxy 类(写在了 ActivityManagerNative 文件里)。 与 service 进行通信 了终于到了  ma.getRunningAppProcesses(); 其实 上面这一对除了我 附上的说明外 还 证明了实际就是 ActivityManagerProxy  里面的 getRunningAppProcesses,我再给你们捋一捋
ma.getRunningAppProcesses();--》 ActivityManagerNative.getDefault().getRunningAppProcesses();
ActivityManagerNative.getDefault() 是什么  ? 他是  IActivityManager 那么在getdefault 的过程中我们其实是创建了
IActivityManager 的实现类 ActivityManagerProxy对象 所以
ma.getRunningAppProcesses(); 就是 ActivityManagerProxy.getRunningAppProcesses
那么看看源码
   
<span style="font-size:18px;"> public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses()
            throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        mRemote.transact(GET_RUNNING_APP_PROCESSES_TRANSACTION, data, reply, 0);
        reply.readException();
        ArrayList<ActivityManager.RunningAppProcessInfo> list
                = reply.createTypedArrayList(ActivityManager.RunningAppProcessInfo.CREATOR);
        data.recycle();
        reply.recycle();
        return list;
    }</span>


    // 这里调用了 ibinde 的transact 方法   transact 方法是什么看下ibinder 类


    public boolean transact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException;
    这都是啥 code 标识 方便 service 识别具体需要进行那个操作
    data parcel 类型 parcel 是一个进程间的交换数据的容器 那 data
    是client 发送给 service 的数据
    reply 其实是 service 返回给client 的数据
    那么问题来了 这也没有交互 啊。。 那么我们看看那Ibinder 的子类 binder 发现了 transact 方法
   
<span style="font-size:18px;">public final boolean transact(int code, Parcel data, Parcel reply,
                                  int flags) throws RemoteException {
        if (false) Log.v("Binder", "Transact: " + code + " to " + this);
        if (data != null) {
            data.setDataPosition(0);
        }
        boolean r = onTransact(code, data, reply, flags);
        if (reply != null) {
            reply.setDataPosition(0);
        }
        return r;
    }</span>


    这里调用了 ontranct 那么ontransact 是什么 ,所以我们之前能到的service 的ibinder 对象 其实是应该是binder对象
    实现了binder对象就复写了ontransact 方法 这样 client 调用binder对象的transact 的时候就同时调用了 ontransact 这样就
    实现了客户端与服务端的跨进程通信   我们来看看
    回到 ActivityManagerNative
    他继承了binder   有实现了 IActivityManager  但是他是一个抽象类  所以我们猜测 我们获取的activityservice的binder 对象可能是  继承了    IActivityManager 的子类的对象 。。下面看他里面的源码
   
<span style="font-size:18px;">  @Override
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
        case GET_RUNNING_APP_PROCESSES_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            List<ActivityManager.RunningAppProcessInfo> list = getRunningAppProcesses();
            reply.writeNoException();
            reply.writeTypedList(list);
            return true;
        }


    }
    }</span>

   我们看 这里 根据code 判断出要 执行service 的  getRunningAppProcesses 方法
这里 其实我还是没有弄得十分的明白但是肯定是 ActivityManagerProxy 调用 mRemote.transact()后 binder对象 同时调用了 ontranact 然后
  但是发现getRunningAppProcesses 没有在这个类中实现  所以我猜测 。我们在获取activityservice 服务的binder对时 其实获取的是一个 继承了activityMangerNative 的子类 的对象,他实现了getRunningAppProcesses 方法。也就是service端的具体实现方法。这样我们整个流程就通了 。

        1.ActivityManger getrunningAppProgress 时。先是拿到ActivityManagerProxy 对象同时获取 实现了activityMangerNative  子类的对象 也就是binder对象也是IActivityManger的实现类。 

2.通过 真个binder 对象 transact 方法 我们同时有调用了ontransact 方法 真个方法调用了getRunningAppProcesses 

3.拿到具体数据 写入到 rely 里。 返给ActivityManagerProxy    ActivityManagerProxy    方法返给ActivityManger
   
    这样我们就拿到了服务的数据。跨进程通信完成。

<span style="font-size:18px;"><span style="white-space:pre">	</span><pre name="code" class="html">	public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses()
        throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        mRemote.transact(GET_RUNNING_APP_PROCESSES_TRANSACTION, data, reply, 0);
        reply.readException();
        ArrayList<ActivityManager.RunningAppProcessInfo> list
        = reply.createTypedArrayList(ActivityManager.RunningAppProcessInfo.CREATOR);
        data.recycle();
        reply.recycle();
        return list;
        }</span>

 


    ArrayList<ActivityManager.RunningAppProcessInfo> list
            = reply.createTypedArrayList(ActivityManager.RunningAppProcessInfo.CREATOR);
    就是通过reply 包拿到了刚才 service 写进去的list 集合 到这里交互完成 了。 所以 我其实在 binder 与service 之前如何进行的 通 信还不是很清晰如果有哪位大神 看到了这篇文章可以 帮我指正下 不足 还有帮我 解下疑惑 、多谢!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值