(五)Binder使用·下篇
通过一个BinderDemo项目,学习binder在java层的使用。
文章目录
一、获取Service Manager远程接口
Service Manager的Java远程接口是一个ServiceManagerProxy对象的IServiceManager接口,ServiceManagerProxy类实现了IServiceManager接口,IServiceManager提供了getService和addService两个成员函数来管理系统中的Service。
//frameworks/base/core/java/android/os/ServiceManager.java
public final class ServiceManager {
......
private static IServiceManager sServiceManager;
......
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
// Find the service manager
//相当于 new ServiceManagerProxy(new BinderProxy);
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
......
}
1.1 BinderInternal.getContextObject()
//frameworks/base/core/java/com/android/internal/os/BinderInternal.java
// 88
public static final native IBinder getContextObject();
//frameworks/base/core/jni/android_util_Binder.cpp
// 899
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
/* 打开 binder驱动( ProcessState是单例的) , 创建 BpBinder(handle) 对象, 并返回 */
sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
return javaObjectForIBinder(env, b);
}
//frameworks/base/core/jni/android_util_Binder.cpp
// 547
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
// 563 从 BpBinder中查找 BinderProxy对象, 第一次为 null
jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
// 576 创建 BinderProxy对象
object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
// 580 BinderProxy.mObject成员变量记录 BpBinder对象
env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
// 587 将 BinderProxy对象信息添加到 BpBinder的成员变量 mObjects中
val->attachObject(&gBinderProxyOffsets, refObject,
jnienv_to_javavm(env), proxy_cleanup);
// 593 BinderProxy.mOrgue成员变量记录死亡通知对象
env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get()));
1.2 ServiceManagerNative.asInterface
//frameworks/base/core/java/android/os/ServiceManagerNative.java
// 这里的参数obj是一个BinderProxy对象,它的queryLocalInterface函数返回null。因此,最终以这个
//BinderProxy对象为参数创建一个ServiceManagerProxy对象。
static public IServiceManager asInterface(IBinder obj)
// 38 因为 obj为 BinderProxy, 默认返回 null
IServiceManager in =
(IServiceManager)obj.queryLocalInterface(descriptor);
// 44
return new ServiceManagerProxy(obj);
1.3 ServiceManagerProxy
class ServiceManagerProxy implements IServiceManager {
...
public IBinder getService(String name) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
IBinder binder = reply.readStrongBinder();
reply.recycle();
data.recycle();
return binder;
}
...
public void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
data.writeStrongBinder(service);
data.writeInt(allowIsolated ? 1 : 0);
data.writeInt(dumpPriority);
mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
reply.recycle();
data.recycle();
}
}
...
在Java层,就有拥有了一个Service Manager远程接口ServiceManagerProxy。
二、AIDL接口定义(一个例子)
服务接口定义在frameworks/base/core/java/android/os/IBinderDemo.aidl文件中:
package android.os;
interface IBinderDemoService
{
void setText(int val);
int getText();
}
aidl文件,编译后会生成一个IBinderDemo.java文件:
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: frameworks/base/core/java/android/os/IHelloService.aidl
*/
package android.os;
public interface IBinderDemoService extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements android.os.IBinderDemoService
{
private static final java.lang.String DESCRIPTOR = "android.os.IBinderDemoService ";
/** 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.IBinderDemoService 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 android.os.IBinderDemoService ))) {
return ((android.os.IBinderDemoService )iin);
}
return new android.os.IBinderDemoService.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_setText:
{
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
this.setText(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_getText:
{
data.enforceInterface(DESCRIPTOR);
int _result = this.getText();
reply.writeNoException();
reply.writeInt(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements android.os.IBinderDemoService
{
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 setText(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_setText, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
public int getText() 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_getText, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_setText = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_getText = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
public void setText(int val) throws android.os.RemoteException;
public int getText() throws android.os.RemoteException;
}
三、addService注册服务
定义一个Service,frameworks/base/services/java/com/android/server目录下新增了一个BinderDemoService.java文件:
package com.android.server;
import android.content.Context;
import android.os.IBinderDemoService;
import android.util.Slog;
public class BinderDemoService extends IBinderDemoService.Stub {
private static final String TAG = "BinderDemoService ";
BinderDemoService() {
init_native();
}
public void setText(int val) {
setText_native(val);
}
public int getText() {
return getText_native();
}
private static native boolean init_native();
private static native void setText_native(int val);
private static native int getText_native();
}
定义Service完成之后,将BinderDemoService 注册到ServiceManager。
//frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
public class ActivityManagerService extends ...{
public void setSystemProcess() {
...
try {
...
ServiceManager.addService("binderdemo", new BinderDemoService ());
...
}
...
}
public final class ServiceManager {
......
private static IServiceManager sServiceManager;
......
public static void addService(String name, IBinder service) {
try {
getIServiceManager().addService(name, service);
} catch (RemoteException e) {
Log.e(TAG, "error in addService", e);
}
}
......
}
getIServiceManager()在前面已经分析过了,下面继续分析addService函数调用流程:
class ServiceManagerProxy implements IServiceManager {
public ServiceManagerProxy(IBinder remote) {
mRemote = remote;
}
......
public void addService(String name, IBinder service)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
data.writeStrongBinder(service); //此处 service == AMS
mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
reply.recycle();
data.recycle();
}
......
private IBinder mRemote;
}
writeStrongBinder函数又是一个JNI方法,它定义在frameworks/base/core/jni/android_util_Binder.cpp文件中:
static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jobject clazz, jobject object)
{
Parcel* parcel = parcelForJavaObject(env, clazz);
if (parcel != NULL) {
const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
if (err != NO_ERROR) {
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
}
}
}
这里的object参数是一个Java语言实现的Binder对象,在调用C++语言实现的Parcel::writeStrongBinder把这个对象写入到parcel对象时,首先通过ibinderForJavaObject函数把这个Java语言实现的Binder对象转换为C++语言实现的JavaBBinderHolder对象:
frameworks/base/core/jni/android_util_Binder.cpp
sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{
if (obj == NULL) return NULL;
if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
JavaBBinderHolder* jbh = (JavaBBinderHolder*)
env->GetIntField(obj, gBinderOffsets.mObject);
return jbh != NULL ? jbh->get(env) : NULL; // 返回 JavaBBinder对象
}
if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
return (IBinder*)
env->GetIntField(obj, gBinderProxyOffsets.mObject);
}
LOGW("ibinderForJavaObject: %p is not a Binder object", obj);
return NULL;
}
ServiceManagerProxy.addService这个函数中,还有一个比较重要的函数transact。 mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0),mRemote成员变量实际上是一个BinderProxy对象,我们再来看看BinderProxy.transact函数的实现:
final class BinderProxy implements IBinder {
......
public native boolean transact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException;
......
}
//frameworks/base/core/jni/android_util_Binder.cpp
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
jint code, jobject dataObj,
jobject replyObj, jint flags)
{
......
Parcel* data = parcelForJavaObject(env, dataObj);
if (data == NULL) {
return JNI_FALSE;
}
Parcel* reply = parcelForJavaObject(env, replyObj);
if (reply == NULL && replyObj != NULL) {
return JNI_FALSE;
}
IBinder* target = (IBinder*)
env->GetIntField(obj, gBinderProxyOffsets.mObject); //得到这个BpBinder对象的IBinder接口
if (target == NULL) {
jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");
return JNI_FALSE;
}
......
//有了这个IBinder接口后,通过BpBinder::transact函数进入到Binder驱动程序,然后Binder驱动程序唤醒Service Manager响应这个ADD_SERVICE_TRANSACTION
status_t err = target->transact(code, *data, reply, flags);
......
if (err == NO_ERROR) {
return JNI_TRUE;
} else if (err == UNKNOWN_TRANSACTION) {
return JNI_FALSE;
}
signalExceptionForError(env, obj, err);
return JNI_FALSE;
}
Service Manager收到这个ADD_SERVICE_TRANSACTION请求时,就会把这个Binder实体纳入到自己内部进行管理。
这样,实现BinderDemoService 的Server的启动过程就完成了。
四、getService获取远程接口
在BinderDemo 这个Activity的onCreate函数,通过IServiceManager.getService函数来获得HelloService的远程接口:
public class BinderDemo extends Activity implements OnClickListener {
......
private BinderDemoService binderService = null;
......
@Override
public void onCreate(Bundle savedInstanceState) {
binderService = BinderDemoService .Stub.asInterface(
ServiceManager.getService("binderdemo"));
}
......
}
ServiceManager.getService实际上是调用了ServiceManagerProxy.getService函数:
class ServiceManagerProxy implements IServiceManager {
public ServiceManagerProxy(IBinder remote) {
mRemote = remote;
}
......
public IBinder getService(String name) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
IBinder binder = reply.readStrongBinder();
reply.recycle();
data.recycle();
return binder;
}
......
private IBinder mRemote;
}
reply它是一个Parcel对象,从下面语句返回:
mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
//引用reply
IBinder binder = reply.readStrongBinder();
//frameworks/base/core/jni/android_util_Binder.cpp
//把Java语言实现的Parcel对象class转换成C++语言实现的Parcel对象parcel,接着
static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jobject clazz)
{
Parcel* parcel = parcelForJavaObject(env, clazz);
if (parcel != NULL) {
//相当于return javaObjectForIBinder(env, new BpBinder(handle));
return javaObjectForIBinder(env, parcel->readStrongBinder());
}
return NULL;
}
javaObjectForIBinder这个函数,主要作用就是创建一个BinderProxy对象,并且把刚才获得的BpBinder对象的地址保存在这个BinderProxy对象的mObject成员变量中。
回到onCreate()函数:
helloService = IHelloService.Stub.asInterface(
ServiceManager.getService("hello"))
相当于:
helloService = IHelloService.Stub.asInterface(new BinderProxy()));
具体定义:
public interface IBinderDemoService extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements android.os.IBinderDemoService
{
......
public static android.os.IBinderDemoService 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 android.os.IHelloService))) {
return ((android.os.IBinderDemoService )iin);
}
//相当于return new android.os.IHelloService.Stub.Proxy(new BinderProxy());
return new android.os.IBinderDemoService .Stub.Proxy(obj);
}
......
}
}
这样,就获得了BinderDemoService 的远程接口了,其实就是一个实现了IBinderDemoService 接口的IBinderDemoService .Stub.Proxy对象。
五、Client通过远程接口使用BinderDemoService提供的服务
上面获得远程接口后,就可以使用接口了:
public class BinderDemoextends Activity implements OnClickListener {
......
@Override
public void onClick(View v) {
if(v.equals(readButton)) {
int val = binderService.getVal();
......
}
}
......
}
binderService接口实际上是一个IBinderDemoService.Stub.Proxy对象,因此,我们进入到IBinderDemoService.Stub.Proxy类的getText函数中:
public interface BinderDemoService extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements android.os.IBinderDemoService
{
......
private static class Proxy implements android.os.IBinderDemoService
{
private android.os.IBinder mRemote;
......
public int getText() 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_getText, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
......
static final int TRANSACTION_getText = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
......
}
最终,经过层层返回,就回到IBinderDemoService.Stub.Proxy.getVal函数中来了,从下面语句返回:
mRemote.transact(Stub.TRANSACTION_getText, _data, _reply, 0);
并将结果读出来:
_result = _reply.readInt();
总结
以上通过一个BinderDemo例子详细讲解了binder的使用,本文仅仅简单介绍了binder的使用,而binder具体详细调用流程还得去阅读Android源代码。