一.基于源码分析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(),代码如下:
- public class SystemServer {
- ....
- public static void main(String[] args) {
- ....
- init1(args);
- }
- ....
- }
init1()是native函数,它的定义为native public static void init1(String[] args);它的内部会进行一些与Dalvik虚拟机相关的初始化工作,执行完初始化工作后,其内部会调用java端的SystemServer类的init2()函数。
而SystemServer类中的init2()函数的实现代码如下:
- public static final void init2() {
- Slog.i(TAG, "Entered the Android system server!");
- Thread thr = new ServerThread();
- thr.setName("android.server.ServerThread");
- thr.start();
- }
该函数实现创建和启动ServerThread线程。
我们再来看看ServerThread线程类的run()方法中的部分代码,如下:
- class ServerThread extends Thread {
- ....
- @Override
- public void run() {
- ....
-
- try {
- Slog.i(TAG, "Entropy Service");
- ServiceManager.addService("entropy", new EntropyService());
- Slog.i(TAG, "Power Manager");
- power = new PowerManagerService();
- ServiceManager.addService(Context.POWER_SERVICE, power);
- ....
- Slog.i(TAG, "Telephony Registry");
- ServiceManager.addService("telephony.registry", new TelephonyRegistry(context));
- ....
-
- }
- }
- }
在该线程类的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):
-
- public final class ServiceManager {
- private static final String TAG = "ServiceManager";
-
- private static IServiceManager sServiceManager;
- private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();
-
- private static IServiceManager getIServiceManager() {
- if (sServiceManager != null) {
- return sServiceManager;
- }
-
-
- sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
- return sServiceManager;
- }
-
-
-
-
-
-
-
- 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;
- }
-
-
-
-
-
-
-
-
- public static void addService(String name, IBinder service) {
- try {
- getIServiceManager().addService(name, service);
- } catch (RemoteException e) {
- Log.e(TAG, "error in addService", e);
- }
- }
-
-
-
-
-
- public static IBinder checkService(String name) {
- try {
- IBinder service = sCache.get(name);
- if (service != null) {
- return service;
- } else {
- return getIServiceManager().checkService(name);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "error in checkService", e);
- return null;
- }
- }
-
-
-
-
- public static String[] listServices() throws RemoteException {
- try {
- return getIServiceManager().listServices();
- } catch (RemoteException e) {
- Log.e(TAG, "error in listServices", e);
- return null;
- }
- }
-
-
-
-
-
-
-
-
-
- public static void initServiceCache(Map<String, IBinder> cache) {
- if (sCache.size() != 0) {
- throw new IllegalStateException("setServiceCache may only be called once");
- }
- sCache.putAll(cache);
- }
- }
该类中提供一个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文件代码:
-
-
-
-
-
-
-
- public interface IMyService extends android.os.IInterface {
-
-
- public static abstract class Stub extends android.os.Binder implements
- IMyService {
- private static final java.lang.String DESCRIPTOR = "IMyService";
-
-
- public Stub() {
- this.attachInterface(this, DESCRIPTOR);
- }
-
-
-
-
-
-
-
-
- public static IMyService asInterface(android.os.IBinder obj) {
- if ((obj == null)) {
- return null;
- }
- android.os.IInterface iin = (android.os.IInterface) obj
- .queryLocalInterface(DESCRIPTOR);
-
- if (((iin != null) && (iin instanceof IMyService))) {
- return ((IMyService) iin);
- }
-
-
-
- return new IMyService.Stub.Proxy(obj);
- }
-
- public android.os.IBinder asBinder() {
- return this;
- }
-
-
-
-
-
-
-
-
- @Override
- public boolean onTransact(int code, android.os.Parcel data,
- android.os.Parcel reply, int flags)
- throws android.os.RemoteException {
- switch (code) {
- case INTERFACE_TRANSACTION: {
- reply.writeString(DESCRIPTOR);
- return true;
- }
- case TRANSACTION_getName: {
-
- data.enforceInterface(DESCRIPTOR);
-
-
-
-
- java.lang.String _result = this.getName();
- reply.writeNoException();
-
- reply.writeString(_result);
- return true;
- }
- case TRANSACTION_setName: {
- data.enforceInterface(DESCRIPTOR);
- java.lang.String _arg0;
-
- _arg0 = data.readString();
-
- this.setName(_arg0);
- reply.writeNoException();
- return true;
- }
- }
- return super.onTransact(code, data, reply, flags);
- }
-
-
- private static class Proxy implements IMyService {
-
- private android.os.IBinder mRemote;
-
- Proxy(android.os.IBinder remote) {
-
- mRemote = remote;
- }
-
- public android.os.IBinder asBinder() {
- return mRemote;
- }
-
- public java.lang.String getInterfaceDescriptor() {
- return DESCRIPTOR;
- }
-
- public java.lang.String getName() throws android.os.RemoteException {
-
- android.os.Parcel _data = android.os.Parcel.obtain();
- android.os.Parcel _reply = android.os.Parcel.obtain();
- java.lang.String _result;
- try {
-
- _data.writeInterfaceToken(DESCRIPTOR);
-
- mRemote.transact(Stub.TRANSACTION_getName, _data, _reply, 0);
- _reply.readException();
-
- _result = _reply.readString();
- } finally {
- _reply.recycle();
- _data.recycle();
- }
- return _result;
- }
-
- public void setName(java.lang.String name)
- throws android.os.RemoteException {
- android.os.Parcel _data = android.os.Parcel.obtain();
- android.os.Parcel _reply = android.os.Parcel.obtain();
- try {
- _data.writeInterfaceToken(DESCRIPTOR);
-
- _data.writeString(name);
-
- mRemote.transact(Stub.TRANSACTION_setName, _data, _reply, 0);
- _reply.readException();
- } finally {
- _reply.recycle();
- _data.recycle();
- }
- }
- }
-
- static final int TRANSACTION_getName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
- static final int TRANSACTION_setName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
- }
-
- public java.lang.String getName() throws android.os.RemoteException;
-
- public void setName(java.lang.String name)
- throws android.os.RemoteException;
- }
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,该类的实现代码如下:
- import android.os.RemoteException;
-
- public class MyService extends IMyService.Stub
- {
- private String ServiceName;
-
-
- @Override
- public String getName() throws RemoteException
- {
-
- return ServiceName;
- }
-
-
- @Override
- public void setName(String name) throws RemoteException
- {
-
- ServiceName = name;
- }
-
- }
当然,自定义的系统服务类MyService中的函数,还可以通过调用一些native方法实现调用Android中间层的先关函数(JNI)。ok,系统服务类代码编写完后,接下来就是在ServerThread线程中注册该系统服务了,如下注册代码:
ServiceManager.addService("myservice", new MyService());
三.实现跨进程访问自定义的系统服务
系统服务类的创建和注册已经完成,那么,该如何进行IPC调用呢。很显然,通过前面对IMyService.java文件的介绍和解析,我们知道,重点在于IMyService.Stub的asInterfcace函数。比如,我们在另外一个进程中编写一个MyServiceManager类来实现获取远程MyService服务,并实现调用相关的函数。代码如下:
- import android.os.IBinder;
- import android.os.ServiceManager;
-
- public class MyServiceManager
- {
-
- private static IMyService mRemoteService;
-
- public static IMyService getService()
- {
- if(mRemoteService == null)
- {
-
- IBinder iBinder = ServiceManager.getService("myservice");
- mRemoteService = IMyService.Stub.asInterface(iBinder);
- }
- return mRemoteService;
- }
-
- public static String getName()
- {
- getService().getName();
- }
-
- public static String setName(String name)
- {
- getService().setName(name);
- }
- }
这样,不同进程的客户端就可以通过该类来实现与系统服务的连接和调用了。
注:上面的相关类实现都是基于源码环境开发的,而不是第三方开发。MyService.java,IMyService.java,MyServiceManager.java等文件是存放在源码路径frameworks\base\core\java\android\MyProject中,MyProject是自己创建的文件夹,编译也都是在Linux环境下基于源码编译的。
原文地址: http://blog.csdn.net/stevenhu_223/article/details/8541155