Binder java层实现原理

本文深入剖析了Android中AIDL(Android Interface Definition Language)的工作原理,详细解释了aidl文件如何生成Stub和Proxy类,以及它们在Binder机制中的作用。文章还介绍了HelloService的启动过程,展示了如何在Java层获取远程服务接口,并探讨了在C层实现Java层回调的方法。通过对AIDL的学习,读者能够理解Android系统中不同进程间的通信机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

https://www.bilibili.com/video/BV1zb4y187MW/
一、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、付费专栏及课程。

余额充值