一.基于源码分析Binder机制:

Binder机制是Android系统中实现跨进程通信(IPC)的一种重要机制。可以说,Binder机制在android系统中无处不在,所以,要研究android源码,学好Binder机制极其重要。

在学习Binder机制之前,我们先试着摸索一下系统中一些相关的涉及到Binder机制的代码。

首先,先看看SystemServer.java这个文件(基于android4.0源代码),该文件位于源码路径frameworks\base\services\java\com\android\server\SystemServer.java中,这个文件中有两个类,一个是SystemServer类(public),一个是线程类ServerThread。

SystemServer类的main函数中会先调用函数init1(),代码如下:

[java] view plaincopy
  1. public class SystemServer {
  2. ....
  3. public static void main(String[] args) {
  4. ....
  5. init1(args);
  6. }
  7. ....
  8. }

init1()是native函数,它的定义为native public static void init1(String[] args);它的内部会进行一些与Dalvik虚拟机相关的初始化工作,执行完初始化工作后,其内部会调用java端的SystemServer类的init2()函数。

而SystemServer类中的init2()函数的实现代码如下:

[java] view plaincopy
  1. public static final void init2() {
  2. Slog.i(TAG, "Entered the Android system server!");
  3. Thread thr = new ServerThread();
  4. thr.setName("android.server.ServerThread");
  5. thr.start();
  6. }

该函数实现创建和启动ServerThread线程。

我们再来看看ServerThread线程类的run()方法中的部分代码,如下:

[java] view plaincopy
  1. class ServerThread extends Thread {
  2. ....
  3. @Override
  4. public void run() {
  5. ....
  6. // Critical services...
  7. try {
  8. Slog.i(TAG, "Entropy Service");
  9. ServiceManager.addService("entropy", new EntropyService());
  10. Slog.i(TAG, "Power Manager");
  11. power = new PowerManagerService();
  12. ServiceManager.addService(Context.POWER_SERVICE, power);
  13. ....
  14. Slog.i(TAG, "Telephony Registry");
  15. ServiceManager.addService("telephony.registry", new TelephonyRegistry(context));
  16. ....
  17. }
  18. }
  19. }

在该线程类的run()函数中,很多的try{}代码块里,有如上类似的代码,它创建一个服务类,然后将初始化的服务类作为参数传进ServiceManager的addService函数中。也就是说,在frameworks\base\services\java\com\android\server源码路径里的服务类基本上都是在这里启动的。

而且这些服务类,一般都是继承于“I服务类名.Stub”(如IVibratorService.Stub,但有些继承Binder),I服务类名(如IVibratorService)是由aidl文件自动生成的。要想看系统中这些aidl文件生成的类(编译生成),可以在编译后的源码中,out文件目录下查找。比如,我要找IVibratorService.aidl生成的java文件:进入out目录,在Linux终端输入命令:find -name “IVibratorService.java”。这样就可以找到该类了。

我们再来看看ServiceManager这个类(源码所在路径\frameworks\base\core\java\android\os\ServiceManager.java):

[java] view plaincopy
  1. /** @hide */
  2. public final class ServiceManager {
  3. private static final String TAG = "ServiceManager";
  4. private static IServiceManager sServiceManager;
  5. private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();
  6. private static IServiceManager getIServiceManager() {
  7. if (sServiceManager != null) {
  8. return sServiceManager;
  9. }
  10. // Find the service manager
  11. sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
  12. return sServiceManager;
  13. }
  14. /**
  15. * Returns a reference to a service with the given name.
  16. *
  17. * @param name the name of the service to get
  18. * @return a reference to the service, or <code>null</code> if the service doesn't exist
  19. */
  20. public static IBinder getService(String name) {
  21. try {
  22. IBinder service = sCache.get(name);
  23. if (service != null) {
  24. return service;
  25. } else {
  26. return getIServiceManager().getService(name);
  27. }
  28. } catch (RemoteException e) {
  29. Log.e(TAG, "error in getService", e);
  30. }
  31. return null;
  32. }
  33. /**
  34. * Place a new @a service called @a name into the service
  35. * manager.
  36. *
  37. * @param name the name of the new service
  38. * @param service the service object
  39. */
  40. public static void addService(String name, IBinder service) {
  41. try {
  42. getIServiceManager().addService(name, service);
  43. } catch (RemoteException e) {
  44. Log.e(TAG, "error in addService", e);
  45. }
  46. }
  47. /**
  48. * Retrieve an existing service called @a name from the
  49. * service manager.  Non-blocking.
  50. */
  51. public static IBinder checkService(String name) {
  52. try {
  53. IBinder service = sCache.get(name);
  54. if (service != null) {
  55. return service;
  56. } else {
  57. return getIServiceManager().checkService(name);
  58. }
  59. } catch (RemoteException e) {
  60. Log.e(TAG, "error in checkService", e);
  61. return null;
  62. }
  63. }
  64. /**
  65. * Return a list of all currently running services.
  66. */
  67. public static String[] listServices() throws RemoteException {
  68. try {
  69. return getIServiceManager().listServices();
  70. } catch (RemoteException e) {
  71. Log.e(TAG, "error in listServices", e);
  72. return null;
  73. }
  74. }
  75. /**
  76. * This is only intended to be called when the process is first being brought
  77. * up and bound by the activity manager. There is only one thread in the process
  78. * at that time, so no locking is done.
  79. *
  80. * @param cache the cache of service references
  81. * @hide
  82. */
  83. public static void initServiceCache(Map<String, IBinder> cache) {
  84. if (sCache.size() != 0) {
  85. throw new IllegalStateException("setServiceCache may only be called once");
  86. }
  87. sCache.putAll(cache);
  88. }
  89. }

该类中提供一个getService(String name)的静态函数,参数name对应addService(String name, IBinder service)函数的name。name参数在SystemServer启动一个初始化的服务类,然后调用addService函数添加的时候指定(如ServiceManager.addService("entropy", new EntropyService()),name为“entropy”),那么当我们要在另外一个进程里(客户端)获取在SystemServer中启动运行的服务*(服务端),就需要调用ServiceManager类的getService(String name)函数了(如,我们要在客户端获取EntropyService服务对象,那么就需要调用ServiceManager.getService(“entropy”)),而通过getService获取的是一个IBinder,接着再通过调用对应服务类的aidl文件生成的接口的内部类Stub的asInterface(iBinder)方法,(比如,IAccountManager mRemoteService = IAccountManager.Stub.asasInterface(iBinder)),参数iBinder就是通过getService(String name)获取得到的对应的IBinder。这样,客户端就获取得到远程服务对象的代理,并不是服务类对象本身(具体后面会介绍)。

但是,我们发现,ServiceManager这个类是隐藏的(/** @hide */),也就是说在android SDK中不提供该类的接口。如果在开发的第三方应用中需要调用该类,只能通过反射来调用。

二.注册自定义的系统服务(Service类为客户端服务):

所谓的系统服务指可以使用getSystemService()方法获取的服务,即Binder服务,由继承Binder的类来实现。而我们开发第三方应用所常用的Service类服务为客户端服务。

当然,如果我们有需求,需要系统中注册运行一个自定义的系统服务,该服务在手机开机后执行一直运行着的工作(如,保存一些资源在该服务端,需要时,可以时刻获取)。那么,通过上面的介绍,我们可以在SystemServer中注册我们自己编写的系统服务。比如:假如MyService是自己定义的需要注册在SystemServer中的服务类,那么,我们可以在ServerThread类run函数中,try{}代码块添加如下代码: ServiceManager.addService("myservice", new MyService());

而这个我们自定义的MyService,我们该如何去实现它,已到达类似其他系统服务类的效果呢。通过上面的介绍,我们知道,系统服务类一般都继承由aidl文件生成的一个类的内部类(Stub)。抱着好奇的心态,我们不妨也类试试写一个IMyService的aidl文件,看看它生成的对应的java文件中的代码实现。关于aidl文件的相关知识,可以去参考这篇博客:http://www.cnblogs.com/over140/archive/2011/03/08/1976890.html;

下面的代码是在eclipse下的一个android工程项目中,建一个名为IMyService的后缀名aidl文件,然后eclipse会自动在工程的gen目录中生成的java代码;

IMyService.aidl文件中的定义:

interface IMyService
          {
             String getName();

void setName(String name);
          }

android工程gen目录中生成的IMyService.java文件代码:

[java] view plaincopy
  1. /*
  2. * This file is auto-generated.  DO NOT MODIFY.
  3. * Original file: D:\\WorkSpace\\RemoteServiceTest\\src\\com\\feixun\\hu\\IMyService.aidl
  4. */
  5. //IInterface是一个接口,提供一个asBinder()的方法声明,返回值为IBinder
  6. public interface IMyService extends android.os.IInterface {
  7. /** Local-side IPC implementation stub class. */
  8. //该内部类(一般称为桩)继承Biner,同时实现IMyService接口,也就说覆盖asBinder()方法
  9. public static abstract class Stub extends android.os.Binder implements
  10. IMyService {
  11. private static final java.lang.String DESCRIPTOR = "IMyService";
  12. /** Construct the stub at attach it to the interface. */
  13. public Stub() {
  14. this.attachInterface(this, DESCRIPTOR);
  15. }
  16. /**
  17. * Cast an IBinder object into an IMyService interface, generating a
  18. * proxy if needed.
  19. */
  20. /*客户端通过调用该方法实现跨进程访问,参数为对应获取得到的远程服务IBinder,
  21. * 一般是通过ServiceManager.getService获取
  22. */
  23. public static IMyService asInterface(android.os.IBinder obj) {
  24. if ((obj == null)) {
  25. return null;
  26. }
  27. android.os.IInterface iin = (android.os.IInterface) obj
  28. .queryLocalInterface(DESCRIPTOR);
  29. //若需要获取的服务为本地服务,则直接返回。
  30. if (((iin != null) && (iin instanceof IMyService))) {
  31. return ((IMyService) iin);
  32. }
  33. /*若不是本地进程所属服务(即跨进程服务),则返回创建的Proxy对象
  34. * 传递的参数obj,赋值给Binder驱动中的mRemote引用
  35. */
  36. return new IMyService.Stub.Proxy(obj);
  37. }
  38. public android.os.IBinder asBinder() {
  39. return this;
  40. }
  41. /*服务端重载的OnTransact,参数code用于标识客户端期望调用服务端的哪个函数
  42. * 参数data和reply均为包裹,都由客户端提供
  43. * data负责打包由客户端调用服务端函数时传进的参数
  44. * reply负责打包执行服务端函数后返回的结果数据,供客户端读取
  45. * flags定义执行IPC调用的模式,flags=等于0时为双向,即服务端执行完后返回一定的数据,
  46. * 为1时单向,即服务端执行完后不返回任何数据。
  47. */
  48. @Override
  49. public boolean onTransact(int code, android.os.Parcel data,
  50. android.os.Parcel reply, int flags)
  51. throws android.os.RemoteException {
  52. switch (code) {
  53. case INTERFACE_TRANSACTION: {
  54. reply.writeString(DESCRIPTOR);
  55. return true;
  56. }
  57. case TRANSACTION_getName: {
  58. //某种校验,与客户端的writeInterfaceToken()对应
  59. data.enforceInterface(DESCRIPTOR);
  60. /*调用MyService类的getName,该类实现IMyService.Stub
  61. * 即为真正实现功能的远程服务类,getName方法的具体实现
  62. * 在MyService中
  63. */
  64. java.lang.String _result = this.getName();
  65. reply.writeNoException();
  66. //将getName返回值_result写入reply
  67. reply.writeString(_result);
  68. return true;
  69. }
  70. case TRANSACTION_setName: {
  71. data.enforceInterface(DESCRIPTOR);
  72. java.lang.String _arg0;
  73. //读取客户端发来的data包裹,进行拆解得到客户端传进的相关参数
  74. _arg0 = data.readString();
  75. //setName方法没有返回值,所以不需要reply向客户端返回数据
  76. this.setName(_arg0);
  77. reply.writeNoException();
  78. return true;
  79. }
  80. }
  81. return super.onTransact(code, data, reply, flags);
  82. }
  83. //Binder驱动实现的代理机制,供远程客户端使用
  84. private static class Proxy implements IMyService {
  85. //远程服务端在Binder驱动中对应的Binder引用
  86. private android.os.IBinder mRemote;
  87. Proxy(android.os.IBinder remote) {
  88. //remote来自远程服务端对应的obj
  89. mRemote = remote;
  90. }
  91. public android.os.IBinder asBinder() {
  92. return mRemote;
  93. }
  94. public java.lang.String getInterfaceDescriptor() {
  95. return DESCRIPTOR;
  96. }
  97. public java.lang.String getName() throws android.os.RemoteException {
  98. //申请得到_data,_reply包裹对象(相当于创建对象)
  99. android.os.Parcel _data = android.os.Parcel.obtain();
  100. android.os.Parcel _reply = android.os.Parcel.obtain();
  101. java.lang.String _result;
  102. try {
  103. //与服务端的enforceInterface对应
  104. _data.writeInterfaceToken(DESCRIPTOR);
  105. //通过mRemote重载远程服务的onTransact方法,调用服务端的getName()函数
  106. mRemote.transact(Stub.TRANSACTION_getName, _data, _reply, 0);
  107. _reply.readException();
  108. //读取远程服务端getName函数返回的_result
  109. _result = _reply.readString();
  110. } finally {
  111. _reply.recycle();
  112. _data.recycle();
  113. }
  114. return _result;
  115. }
  116. public void setName(java.lang.String name)
  117. throws android.os.RemoteException {
  118. android.os.Parcel _data = android.os.Parcel.obtain();
  119. android.os.Parcel _reply = android.os.Parcel.obtain();
  120. try {
  121. _data.writeInterfaceToken(DESCRIPTOR);
  122. //往data包裹写入客户端传进的参数name,并发送到服务端
  123. _data.writeString(name);
  124. //通过mRemote重载远程服务的onTransact方法,调用服务端的setName()函数
  125. mRemote.transact(Stub.TRANSACTION_setName, _data, _reply, 0);
  126. _reply.readException();
  127. } finally {
  128. _reply.recycle();
  129. _data.recycle();
  130. }
  131. }
  132. }
  133. static final int TRANSACTION_getName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
  134. static final int TRANSACTION_setName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
  135. }
  136. public java.lang.String getName() throws android.os.RemoteException;
  137. public void setName(java.lang.String name)
  138. throws android.os.RemoteException;
  139. }

IMyService.java文件解析:
   1.该接口是由自定义的IMyService.aidl文件自动生成的,IMyService实现IInterface接口,IInterface提供一个asBinder()的方法声明,返回值为IBinder。

2.Stub类为IMyService接口的内部类,该内部类(一般称为桩)继承Biner,同时实现IMyService接口,也就说覆盖asBinder()方法。该类主要由服务端来使用。

3.Stub类中又有一个内部类Proxy(代理),该类就是实现跨进程访问的重要类。客户端跨进程获取的代理对象就是Proxy。

4.Proxy类中有一个mRemote,该mRemote为远程服务在Binder对象中对应的引用,通过该引用实现与远程服务的连接。

aidl文件编写完后,接下来就是实现功能代码块的系统服务类的编写了,这里我们将该系统服务实现类命名为MyService,该类的实现代码如下:

[java] view plaincopy
  1. import android.os.RemoteException;
  2. public class MyService extends IMyService.Stub
  3. {
  4. private String ServiceName;
  5. //重载IMyService接口的getName方法
  6. @Override
  7. public String getName() throws RemoteException
  8. {
  9. // TODO Auto-generated method stub
  10. return ServiceName;
  11. }
  12. //重载IMyService接口的setName方法
  13. @Override
  14. public void setName(String name) throws RemoteException
  15. {
  16. // TODO Auto-generated method stub
  17. ServiceName = name;
  18. }
  19. }

当然,自定义的系统服务类MyService中的函数,还可以通过调用一些native方法实现调用Android中间层的先关函数(JNI)。ok,系统服务类代码编写完后,接下来就是在ServerThread线程中注册该系统服务了,如下注册代码:

ServiceManager.addService("myservice", new MyService());

三.实现跨进程访问自定义的系统服务

系统服务类的创建和注册已经完成,那么,该如何进行IPC调用呢。很显然,通过前面对IMyService.java文件的介绍和解析,我们知道,重点在于IMyService.Stub的asInterfcace函数。比如,我们在另外一个进程中编写一个MyServiceManager类来实现获取远程MyService服务,并实现调用相关的函数。代码如下:

[java] view plaincopy
  1. import android.os.IBinder;
  2. import android.os.ServiceManager;
  3. public class MyServiceManager
  4. {
  5. private static IMyService mRemoteService;
  6. public static IMyService getService()
  7. {
  8. if(mRemoteService == null)
  9. {
  10. //参数对应在ServerThread中注册系统服务时指定的参数,即"myservice"
  11. IBinder iBinder = ServiceManager.getService("myservice");
  12. mRemoteService = IMyService.Stub.asInterface(iBinder);
  13. }
  14. return mRemoteService;
  15. }
  16. public static String getName()
  17. {
  18. getService().getName();
  19. }
  20. public static String setName(String name)
  21. {
  22. getService().setName(name);
  23. }
  24. }

这样,不同进程的客户端就可以通过该类来实现与系统服务的连接和调用了。

注:上面的相关类实现都是基于源码环境开发的,而不是第三方开发。MyService.java,IMyService.java,MyServiceManager.java等文件是存放在源码路径frameworks\base\core\java\android\MyProject中,MyProject是自己创建的文件夹,编译也都是在Linux环境下基于源码编译的。

原文地址: http://blog.csdn.net/stevenhu_223/article/details/8541155

Android Binder机制----实现自定义的系统服务相关推荐

  1. 理解Android Binder机制(1/3):驱动篇

    Binder的实现是比较复杂的,想要完全弄明白是怎么一回事,并不是一件容易的事情. 这里面牵涉到好几个层次,每一层都有一些模块和机制需要理解.这部分内容预计会分为三篇文章来讲解.本文是第一篇,首先会对 ...

  2. aidl使用_借助 AIDL 理解 Android Binder 机制——Binder 来龙去脉

    AIDL 是 Android Interface Definition Language(Android 接口定义语言)的缩写,它是 Android 进程间通信的接口语言.由于 Android 系统的 ...

  3. 理解Android Binder机制(3/3):Java层

    本文是Android Binder机制解析的第三篇,也是最后一篇文章.本文会讲解Binder Framework Java部分的逻辑. Binder机制分析的前面两篇文章,请移步这里: 理解Andro ...

  4. Android Binder机制学习笔记

    声明,学习材料:http://my.unix-center.net/~Simon_fu/?p=875,不是简单的copy 1    Android的进程间通讯机制(IPC)用的是自己的binder机制 ...

  5. Android - Binder机制 - Binder框架总结

    以下几篇文章是较深入分析binder机制. 目录 1. Android - Binder机制 - ServiceManager 2. Android - Binder机制 - 普通service注册 ...

  6. Android Binder机制情景源码分析之Binder回调注册和反注册

    我们在日常开发中,经常用到Binder来进行跨进程通信,有个比较常见的场景是向服务端注册Binder回调,比如: IActivityManager中有两个成对的方法,Client端向AMS所在的服务端 ...

  7. 不得不说的Android Binder机制与AIDL

    说起Android的进程间通信,想必大家都会不约而同的想起Android中的Binder机制.而提起Binder,想必也有不少同学会想起初学Android时被Binder和AIDL支配的恐惧感.但是作 ...

  8. 从AIDL一窥Android Binder机制

    Binder机制在Android系统中地位毋庸置疑,system_server就通过Binder来实现进程间的通信,从而达到管理.调用一系列系统服务的能力.本文就AIDL来解读一下Binder机制的. ...

  9. android Binder机制(一)架构设计

    Binder 架构设计 Binder 被设计出来是解决 Android IPC(进程间通信) 问题的.Binder 将两个进程间交互的理解为 Client 向 Server 进行通信. 如下:bind ...

最新文章

  1. 【实验】广域网点到点协议PPP PAP CHAP的双向验证、单项认证
  2. 极狐(GitLab)宣布获数亿元A轮融资,将加速推动中国开源DevOps生态
  3. android 获取相机方向,android – 从相机捕捉图像,导致炸毁方向
  4. springmvc与ajax交互常见问题
  5. linux中demo当前目录,Linux pwd命令:显示当前路径
  6. 解决ubuntu下arduino IDE的Serial Port无法选择问题
  7. 表格数据的识别与提取
  8. anaconda新建环境_机器学习实战-开发环境安装
  9. PHP错误处理注册机制
  10. html----选项卡自动切换以及鼠标悬停时停止(js)
  11. JavaScript强化教程——Bootstrap
  12. Atitit 知识管理的艺术 艾提拉著作 这个实际上涉及到知识的管理(获取 ,存储,索引,查找等方法 目录 1. 记不住的本质 2 1.1. 真的没有记住 2 1.2. 暂时没有搜索到,可能是
  13. aspupload 上传组件下载
  14. 【计蒜客 A1594 --- 封印之门】floyd
  15. php调用API支付接口 转至http://www.cnblogs.com/chaochao00o/p/6490463.html
  16. xor指令加解密(笔记)
  17. 快速批量创建文件夹、文件的快捷键
  18. android4.0.3 编译lichee 报错dhd-cdc-sdmmc-gpl-3.0.8问题
  19. gbase xdm管理控制台说明
  20. 印象笔记在Windows上创建手写笔记

热门文章

  1. Daily Scrum02 12.09
  2. .net中不同的方法相同的结果
  3. 《About Multi-Touch(多点触摸是个什么东西?)》:基于光学原理的多点触摸技术全解析...
  4. matlab中基本函数的用法
  5. 请解释和、|和||的区别?
  6. C++ 中const的用法,特别是用在函数前面与后面的区别!
  7. caffe使用过程中遇到的一些问题错误
  8. 【算法】ROI Align 原理
  9. [云炬创业基础笔记] 第四章测试14
  10. [MATLAB调试笔记]phase space plot