Binder 자바 층 실현 원리

8145 단어
안 드 로 이 드 는 자바 로 이 루어 졌 기 때문에 binder 는 자바 에서 많이 사용 된다.이 블 로 그 는 나 선생님 쪽 블 로그 에서 한 단락 을 골 라 스스로 분석 했다.
다음은 자신 이 쓴 에 이 드 파일 입 니 다.
package android.os;

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

       이것 은 aidl 파일 입 니 다. 컴 파일 한 후에 IHello Service. java 가 생 성 됩 니 다.이 파일 의 내용 에 어떤 비밀 이 숨겨 져 있 는 지 살 펴 보 자. 프로 세 스 간 통신 을 이렇게 신기 하 게 지원 할 수 있다.
자바 에 adl 파일 이 있 습 니 다. 많은 작업 을 줄 였 습 니 다. 사실은 다음 단락 에서 adl 파일 을 펼 치 는 것 이 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;
}

   여기 서 우 리 는 IHello Service. aidl 이라는 파일 을 컴 파일 한 후의 정 체 를 볼 수 있 습 니 다. 원래 IHello Service 인터페이스의 정의 에 따라 해당 하 는 Stub 와 Proxy 류 를 생 성 하 는 것 입 니 다. 이것 이 바로 우리 가 익숙 한 Binder 체제 의 내용 입 니 다. 즉, 이 Hello Service 를 실현 하 는 서버 는 반드시 이곳 의 IHello Service. Stub 류 를 계속 해 야 합 니 다.이 Hello Service 의 원 격 인 터 페 이 스 는 바로 이곳 의 IHello Service. stub. Proxy 대상 이 얻 은 IHello Service 인터페이스 입 니 다.다음 내용 은 IHello Service. Stub 와 IHello Service. Stub. Proxy 가 어떻게 만 들 거나 사용 하 는 지 볼 수 있 습 니 다.
 셋. HelloService 시작 과정
        HelloService 의 시작 과정 을 논의 하기 전에 HelloService 인 터 페 이 스 를 실현 하 는 서버 가 어떻게 정의 되 는 지 살 펴 보 겠 습 니 다.
        Ubuntu 에서 Android 시스템 의 Application Frameworks 층 에 하드웨어 접근 서 비 스 를 추가 한 것 을 기억 합 니 다. 저 희 는 frameworks / base / services / java / com / android / server 디 렉 터 리 에 Hello Service. 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 는 IHello Service. Stub 류 를 계속 진행 하 였 으 며, 로 컬 방법 으로 getVal 과 setVal 두 함 수 를 호출 하 였 습 니 다.저 희 는 이 두 함수 의 구체 적 인 실현 에 관심 이 없습니다. 관심 이 있 는 독 자 는 Ubuntu 에서 안 드 로 이 드 시스템 의 Application Frameworks 층 에 하드웨어 액세스 서 비 스 를 추가 하 는 것 을 참고 할 수 있 습 니 다.
        Hello Service 라 는 서버 클래스 가 생 긴 후, 다음 단 계 는 어떻게 그것 을 시작 할 것 인 가 를 고려 하 는 것 이다.frameworks / base / services / java / com / android / server / System Server. 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();
	}
	......
}
4. Client 가 HelloService 의 자바 원 격 인 터 페 이 스 를 가 져 오 는 과정
        앞에서 우 리 는 안 드 로 이 드 시스템 하드웨어 추상 층 (HAL) 을 공부 할 때 우 분투 에서 안 드 로 이 드 시스템 에 자바 응용 프로그램 테스트 Application Frameworks 층 의 하드웨어 서 비 스 를 내장 하 는 글 에서 우 리 는 응용 프로그램 을 만 들 었 다. 이 응용 프로그램 은 클 라 이언 트 역할 로 Service Manager 라 는 자바 원 격 인 터 페 이 스 를 통 해 HelloService 의 원 격 인 터 페 이 스 를 얻 었 다.헬 로 서비스 가 제공 하 는 서 비 스 를 호출 합 니 다.
        Service Manager 라 는 자바 원 격 인 터 페 이 스 를 통 해 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       
	}

	......
}
자바 가 c + + 를 호출 하 는 JNI 는 분석 하지 않 습 니 다.


좋은 웹페이지 즐겨찾기