关于android:Binder-java层实现原理

4次阅读

共计 5700 个字符,预计需要花费 15 分钟才能阅读完成。

https://www.bilibili.com/vide…

一、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 代码了。

正文完
 0