学习参考:http://blog.csdn.net/luoshengyang/article/details/6642463
本博文将基于Binder扩展android的系统服务,在编写实例的同时,将会对Binder机制在framework层的接口源码进行分析。
扩展的系统服务描述如下:霍金不会说话,希望Android手机帮助他说话,那么需要将说话的服务当作系统服务放到到Android系统中。实例会编写或分析如下内容:
- 获取Service Manager的Java远程接口的过程;
- 系统服务HawkingService接口的定义;
- HawkingService的启动过程;
- Client获取HawkingService的Java远程接口的过程;
1. 获取ServiceManager的Java远程接口的过程
因为系统服务全部被ServiceManager管理,所以这里将分析一下如何获取ServiceManager的Java远程接口。下面是ServiceManager相关的类图。
如图所示,ServiceManager中有个getIServiceManager方法可以返回ServiceManager的Java运程接口,利用返回的对象就可以获得ServiceManager对系统服务管理的服务了。
private static IServiceManager getIServiceManager() { if (sServiceManager != null) { return sServiceManager; } // Find the service manager sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject()); return sServiceManager; }跟踪代码可以看到最终要返回IServiceManager,需要往ServiceManagerProxy的构造函数中传入一个IBinder对象,这个对象是由BinderInternal.getContextObject()返回的。
public static final native IBinder getContextObject();
而getContextObject是个native方法,通过JNI返回了一个IBinder对象。具体的C++层的代码这里暂时不做分析。这样获取ServiceManager的Java远程接口就结束了。
2. 系统服务HawkingService接口的定义
HawkingService提供的服务就是say,如下:
interface IHawkingService{ void say(String sth); }
我利用AIDL生成了HawkingService相关的proxy,stub代码,如下:
public interface IHawkingService extends IInterface { //Hawking Server public static abstract class Stub extends Binder implements IHawkingService { private static final java.lang.String DESCRIPTOR = "com.test.IHawkingService"; public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * 如果是本地服务接口,将IBinder对象cast为IHawkingService并返回 * 如果不是本地服务(可能是远程服务)接口,返回IHawkingService的代理对象 */ public static IHawkingService asInterface(IBinder obj) { if ((obj == null)) { return null; } IInterface iin = (IInterface) obj.queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof IHawkingService))) { return ((IHawkingService) iin); } return new IHawkingService.Stub.Proxy(obj); } public IBinder asBinder() { return this; } @Override public boolean onTransact(int code, Parcel data,Parcel reply, int flags) throws RemoteException { switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(DESCRIPTOR); return true; } case TRANSACTION_say: { data.enforceInterface(DESCRIPTOR); String _arg0 = data.readString(); this.say(_arg0); reply.writeNoException(); return true; } } return super.onTransact(code, data, reply, flags); } //Hawking Proxy private static class Proxy implements IHawkingService { private IBinder mRemote; Proxy(IBinder remote) { mRemote = remote; } public IBinder asBinder() { return mRemote; } public void say(String sth) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeString(sth); mRemote.transact(Stub.TRANSACTION_say, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } } static final int TRANSACTION_say = (IBinder.FIRST_CALL_TRANSACTION + 0); } public void say(String sth) throws RemoteException; }
IHawkingService的服务端实现类时HawkingService,代码如下
public class HawkingService extends IHawkingService.Stub{ @Override public void say(String sth) throws RemoteException { System.out.println("hawking say: "+sth); } }
3. HawkingService服务的启动过程
开机时,系统服务的启动都是交给SystemServer进行处理的,SystemServer会启动一个ServerThread的线程用于启动系统服务并把启动的服务添加到ServiceManager中。
public class SystemServer { native public static void init1(String[] args); public static void main(String[] args) { ....... } public static final void init2() { Slog.i(TAG, "Entered the Android system server!"); Thread thr = new ServerThread(); thr.setName("android.server.ServerThread"); thr.start(); } }
class ServerThread extends Thread { ...... @Override public void run() { ..... Looper.prepare(); ...... try { Slog.i(TAG, "HawkingService"); ServiceManager.addService("hawking", new HawkingService()); } catch (Throwable e) { Slog.e(TAG, "Failure starting Hawking Service", e); } ...... Looper.loop(); ...... } }
如上述代码ServiceManager.addService("hawking", new HawkingService());,new HawkingService()是创建了一个Binder对象,下面我们就来看一下,如何创建一个Binder对象以及如何将这个进行add Service。
创建Binder对象过程:
public class Binder implements IBinder { ...... private int mObject; ...... public Binder() { init(); ...... } private native final void init(); ...... }
new HawkingService()会调用Binder的构造函数,如上述代码,Binder的构造函数会调用一个native方法init,这个方法定义在frameworks/base/core/jni/android_util_Binder.cpp中。
static void android_os_Binder_init(JNIEnv* env, jobject clazz) { JavaBBinderHolder* jbh = new JavaBBinderHolder(env, clazz); if (jbh == NULL) { jniThrowException(env, "java/lang/OutOfMemoryError", NULL); return; } LOGV("Java Binder %p: acquiring first ref on holder %p", clazz, jbh); jbh->incStrong(clazz); env->SetIntField(clazz, gBinderOffsets.mObject, (int)jbh); }
可以看出init做的事情就是创建一个JavaBBinderHolder对象,并将对象地址返回给mObject。
ServiceManager.addService过程
class ServiceManagerProxy implements IServiceManager { public ServiceManagerProxy(IBinder remote) { mRemote = remote; } ...... 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(); } ...... private IBinder mRemote; }
addService最终的实现在ServiceManagerProxy中。上述代码 data.writeStrongBinder(service) 是将Binder对象写入到Parcel包裹中,这个写入的对象service就是刚才生成的mObject地址转化过来的。具体的实现在writeStrongBinder的JNI实现中。
4.Client获取HawkingService的Java远程接口的过程
下面编写一个客户端通过ServiceManager的getService方法去获取系统服务HawkingService。
public class HawkingActivity extends Activity{ private IHawkingService hawkingService; @Override public void onCreate(Bundle savedInstanceState) { hawkingService= IHawkingService.Stub.asInterface( ServiceManager.getService("hawking")); hawkingService.say("Hello everyone"); } }
ServiceManager.getService实际上是调用了ServiceManagerProxy.getService函数。
class ServiceManagerProxy implements IServiceManager { public ServiceManagerProxy(IBinder remote) { mRemote = remote; } public IBinder getService(String name) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IServiceManager.descriptor); data.writeString(name); mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0); IBinder binder = reply.readStrongBinder(); reply.recycle(); data.recycle(); return binder; } ....... }
相关推荐
将android的binder框架移植到linux下面,同时写了一个点灯硬件服务进行测试,还包括android logger系统 测试半年未发现问题
android binder实例 android binder实例
android binder流程图
自己写的android binder通信的实例,实现了C/S架构,虽然简单,但基本功能还是实现了。
通过图解的方式,将Android Binder通信的根本原理呈现出来。
Android Binder机制 总共11篇博客。详细介绍BINDER的内部机制
此是android binder IPC机制了解有帮助
android binder 详解
binder是Android framework进程间通信机制。对android binder进行一部分的分析。
罗升阳在介绍和学习Binder的Blog中推荐:《Android Binder设计与实现》一文,详细地介绍了内核空间的Binder驱动程序的数据结构和设计原理
这是Android直接通过binder通信的列子
需要在系统源码下编译,或者提取出对应的头文件亦可。这里需要注意Android4.x以后系统SeLinux如果打开,系统级需要配置对应的sepolicy才能使用。测试阶段推荐直接setenforce 0关闭鉴权即可
Android 手把手教你实现Android Binder连接池。
3. sdkserver是binder服务(编译后生成sdkserver二进制),sdklib是binder的client(编译生成so),sdkclient(编译生成bin)是用来测试sdklib的。 4. 编译完成后把两个bin文件放到andoid系统的/system/bin目录下,...
android binder的学习实例,仅供大家学习参考,麻雀虽小,五脏俱全。
AndroidBinder机制总结[归纳].pdf
android系统深入浅出binder机制分析
此代码是Android Binder一个C/C++层的实现demo,简单的描述了client和server的实现过程。
android binder c++ 代码实现,添加内存共享、读写通知通过binder通行。代码再Android 9上测试无问题。
android binder架构说明.从应用到linux驱动来说明binder架构.