android 系统核心机制binder(12)binder java层 TestClient  分析

112 篇文章 88 订阅

该系列文章总纲链接:专题分纲目录 android 系统核心机制 binder


本章关键点总结 & 说明:

这里关注 Binder Java 实现中TestClient分析,主要是 获取服务和使用服务流程,而事实上这些流程在TestServer端添加服务时均有相关的分析,因此该部分 相对来说较为简单。

TestClient源码如下:

import android.util.Slog;
import android.os.ServiceManager;
import android.os.IBinder;
/* test_client <hello> [name] */

public class TestClient {
    private static final String TAG = "TestClient";
    public static void main(String args[])
    {
        if (args.length == 0)
        {
            System.out.println("Usage: need parameter: <hello> [name]");
            return;
        }

        if (args[0].equals("hello"))
        {
            //关键点1:获取hello服务的句柄 IBinder
            IBinder binder = ServiceManager.getService("hello");//getService
            if (binder == null)
            {
                Slog.i(TAG, "can not get hello service");
                return;
            }
            //关键点2:通过binder句柄 获取hello服务客户端
            IHelloService svr = IHelloService.Stub.asInterface(binder);

            if (args.length == 1)
            {
            		try {
	                svr.sayhello();//关键点3:客户端发送请求流程
	                System.out.println("call sayhello");
	                Slog.i(TAG, "call sayhello");
              	} catch (Exception e) {}
            }
            else
            {
            		try {
	                int cnt = svr.sayhello_to(args[1]);
	                System.out.println("call sayhello_to "+args[1]+" : cnt = "+cnt);
	                Slog.i(TAG, "call sayhello_to "+args[1]+" : cnt = "+cnt);
              	} catch (Exception e) {
                        System.out.println("call sayhello_to , err :"+e);
                        Slog.i(TAG, "call sayhello_to , err : "+e);
              	}
            }
        }
    }
}

1 获取服务的binder引用

首先关注如何获取服务,代码实现如下:

public static IBinder getService(String name) {
        try {
            IBinder service = sCache.get(name);
            if (service != null) {
                return service;
            } else {
                return getIServiceManager().getService(name);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in getService", e);
        }
        return null;
    }

接下里 这个过程有没有很熟悉,实际上和添加服务类似,实际上与服务添加流程类似,getIServiceManager()分析完毕,即得到了一个ServiceManagerProxy(BinderProxy(0));接下来 分析ServiceManagerProxy的getService函数,其代码如下:

public IBinder getService(String name) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeString(name);
        //mRemote实际上就是BinderProxy对象,调用它的transact,将封装好的请求数据发送出去
        mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
        IBinder binder = reply.readStrongBinder();
        reply.recycle();
        data.recycle();
        return binder;
    }

这里也与 服务添加流程分析一致,获取服务和添加服务相比,仅仅是发送的数据不同罢了,原理是一致的。

2  IHelloService.Stub.asInterface(binder);

asinterface的实现是在上一篇文章 TestServer的分析中,如下所示:

public static IHelloService asInterface(android.os.IBinder obj)
        {
            if ((obj==null)) {
            return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin!=null)&&(iin instanceof IHelloService))) {
            return ((IHelloService)iin);
            }
            return new IHelloService.Stub.Proxy(obj);
        }

上面代码和Native层interface_cast非常类似,也和之前分析的ServiceManagerProxy类似,都是以一个BpProxy对象为参数构造和业务相关的IHelloService.Stub.Proxy。 它的各个业务函数会将相应请求打包后交给BpProxy对象,最终由BpProxy对象发送给Binder驱动以完成一次通信。

3 svr.sayhello();客户端发送请求流程,使用服务

这里客户端开始走代理流程,根据之前 在binder java层 实现的框架中有:

private static class Proxy implements IHelloService
        {
            private android.os.IBinder mRemote;
            //...
            @Override public void sayhello() throws android.os.RemoteException
            {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_sayhello, _data, _reply, 0);
                    _reply.readException();
                }
                finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
            @Override public int sayhello_to(java.lang.String name) throws android.os.RemoteException
            {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                int _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeString(name);
                    mRemote.transact(Stub.TRANSACTION_sayhello_to, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readInt();
                }
                finally {
                    _reply.recycle();
                    _data.recycle();
                }
                    return _result;
            }
        }

这里最关键的语句便是 mRemote.transact(Stub.TRANSACTION_sayhello, _data, _reply, 0);这也是如服务端分析,走native层,最后再调用binder C++层的 IPCThreadState的transact函数,与binder驱动层交互。

4 总结

对于binder java层 客户端的分析,多数分析关键点已经在服务端的分析中解决了,因此binder java层客户端分析相对较为简单。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图王大胜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值