Binder java层实现原理

android使用java实现的,因此binder很多是在java中使用。此篇博客是在罗老师那边博客上节选一段,然后自己分析了下。

一、aidl文件

下面是自己写的一个aidl文件

package android.os;

interface IHelloService
{
	void setVal(int val);
	int getVal();
}

       注意,这是一个aidl文件,编译后会生成一个IHelloService.java。我们来看一下这个文件的内容隐藏着什么奥秘,可以这么神奇地支持进程间通信。

在java中有一个aidl文件,让我们省去了很多工作,其实下了下面这段将aidl文件展开其实很c++很像。

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: frameworks/base/core/java/android/os/IHelloService.aidl
 */
package android.os;
public interface IHelloService extends android.os.IInterface
{
	/** Local-side IPC implementation stub class. */
	public static abstract class Stub extends android.os.Binder implements android.os.IHelloService//相当于是一个Server端,需要一个子类来继续继承它,完成接口的实现
	{
		private static final java.lang.String DESCRIPTOR = "android.os.IHelloService";
		/** Construct the stub at attach it to the interface. */
		public Stub()
		{
			this.attachInterface(this, DESCRIPTOR);
		}

		/**
		* Cast an IBinder object into an android.os.IHelloService interface,
		* generating a proxy if needed.
		*/
		public static android.os.IHelloService asInterface(android.os.IBinder obj)//和c++类似,如果在client端才去new一个proxy
		{
			if ((obj==null)) {
				return null;
			}
			android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
			if (((iin!=null)&&(iin instanceof android.os.IHelloService))) {
				return ((android.os.IHelloService)iin);
			}
			return new android.os.IHelloService.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_setVal:
				{
					data.enforceInterface(DESCRIPTOR);
					int _arg0;
					_arg0 = data.readInt();
					this.setVal(_arg0);
					reply.writeNoException();
					return true;
				}
				case TRANSACTION_getVal:
				{
					data.enforceInterface(DESCRIPTOR);
					int _result = this.getVal();
					reply.writeNoException();
					reply.writeInt(_result);
					return true;
				}
			}
			return super.onTransact(code, data, reply, flags);
		}

		private static class Proxy implements android.os.IHelloService//这个内部类,相当于一个client端和C++类似
		{
			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 void setVal(int val) 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.writeInt(val);
					mRemote.transact(Stub.TRANSACTION_setVal, _data, _reply, 0);
					_reply.readException();
				}
				finally {
					_reply.recycle();
					_data.recycle();
				}
			}

			public int getVal() 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);
					mRemote.transact(Stub.TRANSACTION_getVal, _data, _reply, 0);
					_reply.readException();
					_result = _reply.readInt();
				}
				finally {
					_reply.recycle();
					_data.recycle();
				}
				return _result;
			}
		}

		static final int TRANSACTION_setVal = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
		static final int TRANSACTION_getVal = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
	}

	public void setVal(int val) throws android.os.RemoteException;
	public int getVal() throws android.os.RemoteException;
}

   这里我们可以看到IHelloService.aidl这个文件编译后的真面目,原来就是根据IHelloService接口的定义生成相应的Stub和Proxy类,这个就是我们熟悉的Binder机制的内容了,即实现这个HelloService的Server必须继续于这里的IHelloService.Stub类,而这个HelloService的远程接口就是这里的IHelloService.Stub.Proxy对象获得的IHelloService接口。接下来的内容,我们就可以看到IHelloService.Stub和IHelloService.Stub.Proxy是怎么创建或者使用的。


 二. HelloService的启动过程

        在讨论HelloService的启动过程之前,我们先来看一下实现HelloService接口的Server是怎么定义的。

我们在frameworks/base/services/java/com/android/server目录下新增了一个HelloService.java文件:

package com.android.server;

import android.content.Context;
import android.os.IHelloService;
import android.util.Slog;

public class HelloService extends IHelloService.Stub {//实现aidl文件解析后,里面的内部类
	private static final String TAG = "HelloService";

	HelloService() {
		init_native();
	}

	public void setVal(int val) {
		setVal_native(val);
	}	

	public int getVal() {
		return getVal_native();
	}
	
	private static native boolean init_native();
    	private static native void setVal_native(int val);
	private static native int getVal_native();
}
  这里,我们可以看到,HelloService继续了IHelloService.Stub类,它通过本地方法调用实现了getVal和setVal两个函数。
        有了HelloService这个Server类后,下一步就是考虑怎么样把它启动起来了。在frameworks/base/services/java/com/android/server/SystemServer.java文件中,定义了SystemServer类。SystemServer对象是在系统启动的时候创建的,它被创建的时候会启动一个线程来创建HelloService,并且把它添加到Service Manager中去。

       我们来看一下这部份的代码:

class ServerThread extends Thread {
	......

	@Override
	public void run() {

		......

		Looper.prepare();

		......

		try {
			Slog.i(TAG, "Hello Service");
			ServiceManager.addService("hello", new HelloService());//加入serviceManager中
		} catch (Throwable e) {
			Slog.e(TAG, "Failure starting Hello Service", e);
		}

		......

		Looper.loop();

		......
	}
}

......

public class SystemServer
{
	......

	/**
	* This method is called from Zygote to initialize the system. This will cause the native
	* services (SurfaceFlinger, AudioFlinger, etc..) to be started. After that it will call back
	* up into init2() to start the Android services.
	*/
	native public static void init1(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();
	}
	......
}


三. Client获取HelloService的Java远程接口的过程


        我们看看它是如何借助Service Manager这个Java远程接口来获得HelloService的远程接口的。在Hello这个Activity的onCreate函数,通过IServiceManager.getService函数来获得HelloService的远程接口:

public class Hello extends Activity implements OnClickListener {  
	...... 

	private IHelloService helloService = null;  

	......

	@Override  
	public void onCreate(Bundle savedInstanceState) {  

		helloService = IHelloService.Stub.asInterface(  
							ServiceManager.getService("hello"));//调用自定义的helloservice,不过需要自己asInterface转成自己的接口
	}

	......
}

至于,java调用c++的那些JNI就不分析了。


四、在c层service中实现java层回调

还有有时候我们自己写了一个c层的binder service,然后通过java调用service中代码,然后其实又需要在c层中注册回调。这个时候可以在c层service的注册接口中增加binder参数,然后在java中实现aidl文件,再把binder参数通过service调用传入c层service,到时候就可以在c层service中回调java代码了。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值