GVKun编程网logo

源码解析----aidl Binder框架(binder源码分析)

7

本篇文章给大家谈谈源码解析----aidlBinder框架,以及binder源码分析的知识点,同时本文还将给你拓展Android:跟我学Binder---(2)AIDL分析及手动实现、Androida

本篇文章给大家谈谈源码解析----aidl Binder框架,以及binder源码分析的知识点,同时本文还将给你拓展Android : 跟我学Binder --- (2) AIDL分析及手动实现、Android aidl Binder 框架浅析、Android aidl Binder框架浅析、Android Binder 框架实现之 Binder 相关的接口和类等相关知识,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

源码解析----aidl Binder框架(binder源码分析)

源码解析----aidl Binder框架(binder源码分析)

                                    Binder框架 

1.概述

Binder能干什么?Binder可以提供系统中任何程序都可以访问的全局服务。这个功能当然是任何系统都应该提供的,下面我们简单看一下Binder的框架

Android Binder框架分为服务器接口、Binder驱动、以及客户端接口;简单想一下,需要提供一个全局服务,那么全局服务那端即是服务器接口,任何程序即客户端接口,它们之间通过一个Binder驱动访问。

服务器端接口:实际上是Binder类的对象,该对象一旦创建,内部则会启动一个隐藏线程,会接收Binder驱动发送的消息,收到消息后,会执行Binder对象中的onTransact()函数,并按照该函数的参数执行不同的服务器端代码。

Binder驱动:该对象也为Binder类的实例,客户端通过该对象访问远程服务。

客户端接口:获得Binder驱动,调用其transact()发送消息至服务器

2、AIDL的使用

如果对Android比较熟悉,那么一定使用过AIDL,如果你还不了解,那么也没关系,下面会使用一个例子展示AIDL的用法。

我们使用AIDL实现一个跨进程的加减法调用  (本例子在androidstudio上运行的)

1、服务端

1.1新建一个项目,在module目录下创建Aidl文件,接口名为ICalcAIDL:

// ICalcAIDL.aidl
package qu.com.intentservice;

// Declare any non-default types here with import statements

interface ICalcAIDL {
   int add(int x,int y);
   int minus(int x,int y);
}

1.2在androidstudio-->Build-->MakeProjrct(从新编译项目)

之后会生成一个ICalcAIDL.java文件,路径:app/build/generated/source/aidl/debug/ICalcAIDL.java

这个文件我们之后会详细讲解。

1.3然后我们在项目中新建一个Service,代码如下:

package qu.com.intentservice;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

/**
 * Created by quguangle on 2016/11/22.
 */

public class CalcService extends Service
{
    private static final String TAG = "server";

    public void onCreate()
    {
        Log.e(TAG, "onCreate");
    }

    public IBinder onBind(Intent t)
    {
        Log.e(TAG, "onBind");
        return mBinder;
    }

    public void onDestroy()
    {
        Log.e(TAG, "onDestroy");
        super.onDestroy();
    }

    public boolean onUnbind(Intent intent)
    {
        Log.e(TAG, "onUnbind");
        return super.onUnbind(intent);
    }

    public void onRebind(Intent intent)
    {
        Log.e(TAG, "onRebind");
        super.onRebind(intent);
    }

    private final ICalcAIDL.Stub mBinder = new ICalcAIDL.Stub()
    {

        @Override
        public int add(int x, int y) throws RemoteException
        {
            return x + y;
        }

        @Override
        public int minus(int x, int y) throws RemoteException
        {
            return x - y;
        }

    };

}

在此Service中,使用生成的ICalcAIDL创建了一个mBinder的对象,并在Service的onBind方法中返回

最后记得在AndroidManifest中注册

 <service android:name=".CalcService">
            <intent-filter>
                <action android:name="com.qu.aidl.calc" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </service>

这里我们指定了一个name,因为我们一会会在别的应用程序中通过Intent来查找此Service。

到此,服务端编写完毕。下面开始编写客户端

2.客户端:

2.1同样的在module目录下创建Aidl,与服务端的包名相同,然后在把客户端的Aidl文件复制过来。

注意两个Aidl文件下文件包括包名应该是一模一样。

客户端的代码比较简单,创建一个布局,里面包含4个按钮,分别为绑定服务,解除绑定,调用加法,调用减法

布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:onClick="bindService"
        android:text="BindService" />

    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:onClick="unbindService"
        android:text="UnbindService" />

    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:onClick="addInvoked"
        android:text="13+13" />

    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:onClick="minInvoked"
        android:text="60-28" />

</LinearLayout>

主Activity:

package qu.com.handlerthread;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
/**
 * quagungle 2016/11/22
 */
import qu.com.intentservice.ICalcAIDL;

public class MainActivity extends AppCompatActivity {
    private ICalcAIDL mCalcAidl;

    private ServiceConnection mServiceConn = new ServiceConnection()
    {
        @Override
        public void onServiceDisconnected(ComponentName name)
        {
            Log.e("client", "onServiceDisconnected");
            mCalcAidl = null;
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service)
        {
            Log.e("client", "onServiceConnected");
            mCalcAidl = ICalcAIDL.Stub.asInterface(service);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }

    /**
     * 点击BindService按钮时调用
     * @param view
     */
    public void bindService(View view)
    {
        Intent intent = new Intent();
        intent.setAction("com.qu.aidl.calc");
        bindService(intent, mServiceConn, Context.BIND_AUTO_CREATE);
    }
    /**
     * 点击unBindService按钮时调用
     * @param view
     */
    public void unbindService(View view)
    {
        unbindService(mServiceConn);
    }
    /**
     * 点击13+13按钮时调用
     * @param view
     */
    public void addInvoked(View view) throws Exception
    {

        if (mCalcAidl != null)
        {
            int addRes = mCalcAidl.add(13, 13);
            Toast.makeText(this, addRes + "", Toast.LENGTH_SHORT).show();
        } else
        {
            Toast.makeText(this, "服务器被异常杀死,请重新绑定服务端", Toast.LENGTH_SHORT)
                    .show();

        }

    }
    /**
     * 点击60-28按钮时调用
     * @param view
     */
    public void minInvoked(View view) throws Exception
    {

        if (mCalcAidl != null)
        {
            int addRes = mCalcAidl.minus(60, 28);
            Toast.makeText(this, addRes + "", Toast.LENGTH_SHORT).show();
        } else
        {
            Toast.makeText(this, "服务端未绑定或被异常杀死,请重新绑定服务端", Toast.LENGTH_SHORT)
                    .show();

        }

    }

}

直接看运行结果:

我们首先点击BindService按钮,查看log如下:

11-22 13:07:13.744 1267-1267/qu.com.intentservice E/server: onCreate
11-22 13:07:13.744 1267-1267/qu.com.intentservice E/server: onBind
11-22 13:07:13.792 2017-2017/qu.com.handlerthread E/client: onServiceConnected

可以看到,点击BindService之后,服务端执行了onCreate和onBind的方法,并且客户端执行了onServiceConnected方法,标明服务器与客户端已经联通

然后点击13+13,60-28,可以成功的调用服务端的代码并返回正确的结果26,32

下面我们再点击unBindService

11-22 13:08:54.704 1267-1267/qu.com.intentservice E/server: onUnbind
11-22 13:08:54.708 1267-1267/qu.com.intentservice E/server: onDestroy

由于我们当前只有一个客户端绑定了此Service,所以Service调用了onUnbind和onDestory,并没有调用

onServiceDisconnected方法

然后我们继续点击13+13,60-28,运行后依然可以正确执行,也就是说即使onUnbind被调用,连接也是不会断开的,那么什么时候会断开呢?

即当服务端被异常终止的时候,比如我们现在在手机的正在执行的程序中找到该服务:

08-09 23:04:21.433: E/client(30146): onServiceDisconnected

可以看到调用了onServiceDisconnected方法,此时连接被断开,现在点击13+13,60-28的按钮,则会弹出Toast服务端断开的提示。

说了这么多,似乎和Binder框架没什么关系,下面我们来具体看一看AIDL为什么做了些什么。

3、分析AIDL生成的代码

1、服务端

先看服务端的代码,可以看到我们服务端提供的服务是由

private final ICalcAIDL.Stub mBinder = new ICalcAIDL.Stub()
	{

		@Override
		public int add(int x, int y) throws RemoteException
		{
			return x + y;
		}

		@Override
		public int minus(int x, int y) throws RemoteException
		{
			return x - y;
		}

	};

ICalcAILD.Stub来执行的,让我们来看看Stub这个类的声明:

public static abstract class Stub extends android.os.Binder implements qu.com.intentservice.ICalcAIDL

清楚的看到这个类是Binder的子类,是不是符合我们文章开通所说的服务端其实是一个Binder类的实例

接下来看它的onTransact()方法:

@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_add:
{
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
int _arg1;
_arg1 = data.readInt();
int _result = this.add(_arg0, _arg1);
reply.writeNoException();
reply.writeInt(_result);
return true;
}
case TRANSACTION_min:
{
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
int _arg1;
_arg1 = data.readInt();
int _result = this.min(_arg0, _arg1);
reply.writeNoException();
reply.writeInt(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}

文章开头也说到服务端的Binder实例会根据客户端依靠Binder驱动发来的消息,执行onTransact方法,然后由其参数决定执行服务端的代码。

可以看到onTransact有四个参数

code , data ,replay , flags

code 是一个整形的唯一标识,用于区分执行哪个方法,客户端会传递此参数,告诉服务端执行哪个方法

data客户端传递过来的参数

replay服务器返回回去的值

flags标明是否有返回值,0为有(双向),1为没有(单向)

我们仔细看case TRANSACTION_min中的代码

data.enforceInterface(DESCRIPTOR);与客户端的writeInterfaceToken对用,标识远程服务的名称

int _arg0;
_arg0 = data.readInt();
int _arg1;
_arg1 = data.readInt();

接下来分别读取了客户端传入的两个参数

int _result = this.min(_arg0, _arg1);
reply.writeNoException();
reply.writeInt(_result);

然后执行this.min,即我们实现的min方法;返回result由reply写回。

add同理,可以看到服务端通过AIDL生成Stub的类,封装了服务端本来需要写的代码。

2、客户端

客户端主要通过ServiceConnected与服务端连接

private ServiceConnection mServiceConn = new ServiceConnection()
	{
		@Override
		public void onServiceDisconnected(ComponentName name)
		{
			Log.e("client", "onServiceDisconnected");
			mCalcAidl = null;
		}

		@Override
		public void onServiceConnected(ComponentName name, IBinder service)
		{
			Log.e("client", "onServiceConnected");
			mCalcAidl = ICalcAIDL.Stub.asInterface(service);
		}
	};

如果你比较敏锐,应该会猜到这个onServiceConnected中的IBinder实例,其实就是我们文章开通所说的Binder驱动,也是一个Binder实例

在ICalcAIDL.Stub.asInterface中最终调用了:

public static qu.com.intentservice.ICalcAIDL asInterface(android.os.IBinder obj)
{
return new qu.com.intentservice.ICalcAIDL.Stub.Proxy(obj);
}

这个Proxy实例传入了我们的Binder驱动,并且封装了我们调用服务端的代码,文章开头说,客户端会通过Binder驱动的transact()方法调用服务端代码

直接看Proxy中的add方法

@Override public int add(int x, int y) 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);
_data.writeInt(x);
_data.writeInt(y);
mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}

首先声明两个Parcel对象,一个用于传递数据,一个用户接收返回的数据

_data.writeInterfaceToken(DESCRIPTOR);与服务器端的enforceInterfac对应

_data.writeInt(x);
_data.writeInt(y);写入需要传递的参数

mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);

终于看到了我们的transact方法,第一个对应服务端的code,_data,_repay分别对应服务端的data,reply,0表示是双向的

_reply.readException();
_result = _reply.readInt();

最后读出我们服务端返回的数据,然后return。可以看到和服务端的onTransact基本是一行一行对应的。

到此,我们已经通过AIDL生成的代码解释了Android Binder框架的工作原理。Service的作用其实就是为我们创建Binder驱动,即服务端与客户端连接的桥梁。

最后把我生成的ICalcAIDL.java文件贴出来:

package qu.com.intentservice;
// Declare any non-default types here with import statements

public interface ICalcAIDL extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements qu.com.intentservice.ICalcAIDL
{
private static final java.lang.String DESCRIPTOR = "qu.com.intentservice.ICalcAIDL";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
 * Cast an IBinder object into an qu.com.intentservice.ICalcAIDL interface,
 * generating a proxy if needed.
 */
public static qu.com.intentservice.ICalcAIDL asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof qu.com.intentservice.ICalcAIDL))) {
return ((qu.com.intentservice.ICalcAIDL)iin);
}
return new qu.com.intentservice.ICalcAIDL.Stub.Proxy(obj);
}
@Override 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_add:
{
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
int _arg1;
_arg1 = data.readInt();
int _result = this.add(_arg0, _arg1);
reply.writeNoException();
reply.writeInt(_result);
return true;
}
case TRANSACTION_minus:
{
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
int _arg1;
_arg1 = data.readInt();
int _result = this.min(_arg0, _arg1);
reply.writeNoException();
reply.writeInt(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements qu.com.intentservice.ICalcAIDL
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
@Override public int add(int x, int y) 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);
_data.writeInt(x);
_data.writeInt(y);
mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public int minus(int x, int y) 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);
_data.writeInt(x);
_data.writeInt(y);
mRemote.transact(Stub.TRANSACTION_min, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_minus = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
public int add(int x, int y) throws android.os.RemoteException;
public int min(int x, int y) throws android.os.RemoteException;
}

总结:从生成的ICalcAIDL.java文件我们可看出,客户端能够与服务端通信总体来说就是3个类+一个方法:

我们定义的接口ICalcAIDL类,抽象Stub内部类,动态代理的内部类Proxy,和asInterface()方法。

服务端通过Stub类创建一个mBinder对象,然后将这个mBinder对象传给客户端,而客户端拿到对象后在调用Stub类中静态asInterface()方法,它返回Proxy的对象,从而来调用服务端的方法。

到此所有的源码都看完了,希望能够帮到您!

 

 

 

 

Android : 跟我学Binder --- (2) AIDL分析及手动实现

Android : 跟我学Binder --- (2) AIDL分析及手动实现


目录:

  • Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制?

  • Android : 跟我学Binder --- (2) AIDL分析及手动实现

  • Android : 跟我学Binder --- (3) C程序示例

  • Android : 跟我学Binder --- (4) 驱动情景分析

  • Android : 跟我学Binder --- (5) C++实现

  • Android : 跟我学Binder --- (6)  JAVA实现

 

 

一、关于Android日常开发中进程间通信-AIDL

  通常Android应用开发中实现进程间通信用的最多的就是 AIDL,借助 AIDL 编译以后的代码能帮助我们进一步理解 Binder IPC 的通信原理。但是无论是从可读性还是可理解性上来看,编译器生成的代码对开发者并不友好。比如一个 INanoMethod.aidl 文件对应会生成一个 INanoMethod.java 文件,这个 java 文件包含了一个 INanoMethod接口、一个 Stub 静态的抽象类和一个 Proxy 静态类。Proxy 是 Stub 的静态内部类,Stub 又是 INanoMethod的静态内部类,这就造成了可读性和可理解性的问题。

  INanoMethod.aidl 内容:

package com.android.NanoServer;
import com.android.NanoServer.INanoMethodCallback;
// Declare any non-default types here with import statements

interface INanoMethod {
    /**
     * 注册INanoVoiceCallback相关回调接口.
     *
     * @param INanoVoiceCallback 回调接口
     */
    void registerCallBack( INanoMethodCallback callback);
    /**
     * 解除INanoVoiceCallback相关回调接口.
     *
     * @param INanoVoiceCallback 回调接口
     */
    void unregisterCallBack(INanoMethodCallback callback);
    /**
     * 保存Activity对象.
     */
    void registerActivity();

}

  通过编译器生产的 INanoMethod.java:

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: D:\\work\\Android\\project\\androidStudio\\BLE-GATT-\\aidl\\src\\main\\aidl\\com\\android\\NanoServer\\INanoMethod.aidl
 */
package com.android.NanoServer;
// Declare any non-default types here with import statements

public interface INanoMethod extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.android.NanoServer.INanoMethod
{
private static final java.lang.String DESCRIPTOR = "com.android.NanoServer.INanoMethod";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
 * Cast an IBinder object into an com.android.NanoServer.INanoMethod interface,
 * generating a proxy if needed.
 */
public static com.android.NanoServer.INanoMethod asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.android.NanoServer.INanoMethod))) {
return ((com.android.NanoServer.INanoMethod)iin);
}
return new com.android.NanoServer.INanoMethod.Stub.Proxy(obj);
}
@Override 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
{
java.lang.String descriptor = DESCRIPTOR;
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(descriptor);
return true;
}
case TRANSACTION_registerCallBack:
{
data.enforceInterface(descriptor);
com.android.NanoServer.INanoMethodCallback _arg0;
_arg0 = com.android.NanoServer.INanoMethodCallback.Stub.asInterface(data.readStrongBinder());
this.registerCallBack(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_unregisterCallBack:
{
data.enforceInterface(descriptor);
com.android.NanoServer.INanoMethodCallback _arg0;
_arg0 = com.android.NanoServer.INanoMethodCallback.Stub.asInterface(data.readStrongBinder());
this.unregisterCallBack(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_registerActivity:
{
data.enforceInterface(descriptor);
this.registerActivity();
reply.writeNoException();
return true;
}
default:
{
return super.onTransact(code, data, reply, flags);
}
}
}
private static class Proxy implements com.android.NanoServer.INanoMethod
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
/**
     * 注册INanoVoiceCallback相关回调接口.
     *
     * @param INanoVoiceCallback 回调接口
     */
@Override public void registerCallBack(com.android.NanoServer.INanoMethodCallback callback) 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.writeStrongBinder((((callback!=null))?(callback.asBinder()):(null)));
mRemote.transact(Stub.TRANSACTION_registerCallBack, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
/**
     * 解除INanoVoiceCallback相关回调接口.
     *
     * @param INanoVoiceCallback 回调接口
     */
@Override public void unregisterCallBack(com.android.NanoServer.INanoMethodCallback callback) 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.writeStrongBinder((((callback!=null))?(callback.asBinder()):(null)));
mRemote.transact(Stub.TRANSACTION_unregisterCallBack, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
/**
     * 保存Activity对象.
     */
@Override public void registerActivity() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_registerActivity, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_registerCallBack = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_unregisterCallBack = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_registerActivity = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
}
/**
     * 注册INanoVoiceCallback相关回调接口.
     *
     * @param INanoVoiceCallback 回调接口
     */
public void registerCallBack(com.android.NanoServer.INanoMethodCallback callback) throws android.os.RemoteException;
/**
     * 解除INanoVoiceCallback相关回调接口.
     *
     * @param INanoVoiceCallback 回调接口
     */
public void unregisterCallBack(com.android.NanoServer.INanoMethodCallback callback) throws android.os.RemoteException;
/**
     * 保存Activity对象.
     */
public void registerActivity() throws android.os.RemoteException;
}
  • IBinder : IBinder 是一个接口,代表了一种跨进程通信的能力,只要实现了这个接口,这个对象就能跨进程传输;

  • IInterface : IInterface 代表的就是 Server 进程对象具备什么样的能力,即能提供哪些方法,对应的就是 AIDL 文件中定义的接口;

  • Binder : Java 层的 Binder 类,代表的其实就是 Binder 本地对象。BinderProxy 类是 Binder 类的一个内部类,它代表远程进程的 Binder 对象的本地代理。这两个类都继承自 IBinder, 因而都具有跨进程传输的能力,实际在跨越进程时 Binder 驱动会自动完成这两个对象的转换。

  • Stub : 编写AIDL的时候,编译工具会生成一个名为 Stub 的静态内部类,这个类继承了 Binder, 说明它是一个 Binder 本地对象,它实现了 IInterface 接口,表明它具有 Server 承诺给 Client 的能力,Stub 是一个抽象类,具体的 IInterface 的相关实现需要开发者自己实现。

编译工具根据定义的.aidl文件生成的.java代码虽然难于阅读,但是Android之所以这样设计并不无道理,因为当有多个 AIDL 文件的时候把 INanoMethod、Stub、Proxy 放在同一个文件里能有效避免 Stub 和 Proxy 重名的问题。

 

二、手动编写代码来实现跨进程调用

   一次跨进程通信必然会涉及到两个进程,在这个例子中 BookManagerService 作为服务端进程,提供服务;ClientActivity 作为客户端进程,使用 BookManagerService提供的服务。那么服务端进程具备什么样的能力?能为客户端提供什么样的服务呢?前面介绍过的 IInterface 代表的就是服务端进程具体什么样的能力,即提供了什么功能的接口。因此需要定义一个 BookManager 接口,BookManager 继承自 IInterface ,表明服务端具备什么样的能力:

/**
 * 这个类用来定义服务端 BookManagerService 具备什么样的能力
 */
public interface BookManager extends IInterface {
  //提供添加书籍接口
void addBook(Book book) throws RemoteException; }

  只定义服务端具备什么样的能力是不够的,既然是跨进程调用,那需要实现一个跨进程调用对象 Stub。Stub 继承自 Binder, 说明它是一个 Binder 本地对象;实现 IInterface 接口,表明具有 Server 承诺给 Client 的能力;Stub 是一个抽象类,具体的 IInterface 的相关实现需要调用方自己实现:

public abstract class Stub extends Binder implements BookManager {

    ...
    
    public static BookManager asInterface(IBinder binder) {
        if (binder == null)
            return null;
        IInterface iin = binder.queryLocalInterface(DESCRIPTOR);
        if (iin != null && iin instanceof BookManager)
            return (BookManager) iin; //如果client和server在同一进程,则返回本地对象
        return new Proxy(binder);  //如果client和server不在同一进程,则创建并返回代理对象
    }

    ...

    @Override
  /**
   *  code:每个方法都有一个 int类型的数字(编号)用来区分
   *   data: 传过来的数据,其中包含参数,以及类的描述。
   *   reply:传回的数据,要写入是否发生了 Exception,以及返回值。
   *   flags:该方法是否有返回值 , 0表示有返回值。
   */
protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        switch (code) {

            case INTERFACE_TRANSACTION:
                reply.writeString(DESCRIPTOR);
                return true;

            case TRANSAVTION_addBook:
                data.enforceInterface(DESCRIPTOR);
                Book arg0 = null;
                if (data.readInt() != 0) {
                    arg0 = Book.CREATOR.createFromParcel(data); 
                }
                this.addBook(arg0); //调用本地.java中实现的方法
                reply.writeNoException();
                return true;

        }
        return super.onTransact(code, data, reply, flags);
    }
...
  static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); //转换成对应编号
}

  接下来就要实现这个代理类 Proxy 了,既然是代理类自然需要实现 BookManager 接口:

public class Proxy implements BookManager {
    
    ...

    public Proxy(IBinder remote) {
        this.remote = remote;
    }

    @Override
    public void addBook(Book book) throws RemoteException {

        Parcel data = Parcel.obtain();
        Parcel replay = Parcel.obtain();
        try {
            data.writeInterfaceToken(DESCRIPTOR);
            if (book != null) {
                data.writeInt(1);
                book.writeToParcel(data, 0);
            } else {
                data.writeInt(0);
            }
            remote.transact(Stub.TRANSAVTION_addBook, data, replay, 0); //调用Stub的onTransact方法中对应函数
            replay.readException();
        } finally {
            replay.recycle();
            data.recycle();
        }
    }

    ...
}

 

  以上关于 Stub 类中重点介绍下 asInterface 和 onTransact

  • asInterface : 当 Client 端在创建和服务端的连接,调用 bindService 时需要创建一个 ServiceConnection 对象作为入参。在 ServiceConnection 的回调方法 onServiceConnected 中 会通过这个 asInterface(IBinder binder) 拿到 BookManager 对象,这个 IBinder 类型的入参 binder 是驱动传上来的,正如上代码中看到的一样,方法中会去调用 binder.queryLocalInterface() 去查找 Binder 本地对象,如果找到了就说明 Client 和 Server 在同一进程,那么这个 binder 本身就是 Binder 本地对象,可以直接使用。否则说明是 binder 是个远程对象,也就是 BinderProxy,因此需要创建一个代理对象 Proxy,通过这个代理对象来是实现远程访问。
  • onTransact : 在 Proxy 中的 addBook() 方法中首先通过 Parcel 将数据序列化,然后调用 remote.transact()。正如前文所述 Proxy 是在 Stub 的 asInterface 中创建,能走到创建 Proxy 这一步就说明 Proxy 构造函数的入参是 BinderProxy,即这里的 remote 是个 BinderProxy 对象。最终通过一系列的函数调用,Client 进程通过系统调用陷入内核态,Client 进程中执行 addBook() 的线程挂起等待返回,驱动完成一系列的操作之后唤醒 Server 进程,调用 Server 进程本地对象的 onTransact(),最终又走到了 Stub 中的 onTransact() 中,onTransact() 根据函数编号调用相关函数,这里要提及一下,在跨进程调用的时候不会传递函数名而是传递编号来指明要调用哪个函数,如果提供给client端的aidl文件接口数量或者顺序和server端的声明不一样,则会导致函数调用错位的问题。

 

    在client端绑定服务及使用接口:

  ......
  /**
* 尝试与服务端建立连接 */ private void attemptToBindService() { Intent intent = new Intent(); intent.setAction("com.android.aidl.server"); intent.setPackage("com.android.NanoServer"); bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE); } private ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mBookManagerService = BookManager.Stub.asInterface(service); //获得代理对象 if (BookManagerService != null) { mBound = true; } } @Override public void onServiceDisconnected(ComponentName name) { mBound = false; } }; ...... //成功绑定服务后便可调用服务端提供的接口 try { if (mBookManagerService != null) {     mBookManagerService.addBook(book); } } catch (RemoteException e) { e.printStackTrace(); }

注:

  • 如果 Client 和 Server 在同一个进程,那么直接就是调用这个方法。
  • 如果是远程调用,Client 想要调用 Server 的方法就需要通过 Binder 代理来完成,也就是上面的 Proxy。

 

 

-end-

 

Android aidl Binder 框架浅析

Android aidl Binder 框架浅析

转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/38461079 ,本文出自 【张鸿洋的博客】

1、概述

Binder 能干什么?Binder 可以提供系统中任何程序都可以访问的全局服务。这个功能当然是任何系统都应该提供的,下面我们简单看一下 Android 的 Binder 的框架

Android Binder 框架分为服务器接口、Binder 驱动、以及客户端接口;简单想一下,需要提供一个全局服务,那么全局服务那端即是服务器接口,任何程序即客户端接口,它们之间通过一个 Binder 驱动访问。

服务器端接口:实际上是 Binder 类的对象,该对象一旦创建,内部则会启动一个隐藏线程,会接收 Binder 驱动发送的消息,收到消息后,会执行 Binder 对象中的 onTransact () 函数,并按照该函数的参数执行不同的服务器端代码。

Binder 驱动:该对象也为 Binder 类的实例,客户端通过该对象访问远程服务。

客户端接口:获得 Binder 驱动,调用其 transact () 发送消息至服务器

如果大家对上述不了解,没关系,下面会通过例子来更好的说明,实践是检验真理的唯一标准嘛

2、AIDL 的使用

如果对 Android 比较熟悉,那么一定使用过 AIDL,如果你还不了解,那么也没关系,下面会使用一个例子展示 AIDL 的用法。

我们使用 AIDL 实现一个跨进程的加减法调用

1、服务端

新建一个项目,创建一个包名:com.zhy.calc.aidl,在包内创建一个 ICalcAIDL 文件:

package com.zhy.calc.aidl;
interface ICalcAIDL
{
	int add(int x , int y);
	int min(int x , int y );
}

注意,文件名为 ICalcAIDL.aidl

然后在项目的 gen 目录下会生成一个 ICalcAIDL.java 文件,暂时不贴这个文件的代码了,后面会详细说明

然后我们在项目中新建一个 Service,代码如下:

package com.example.zhy_binder;

import com.zhy.calc.aidl.ICalcAIDL;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

public class CalcService extends Service
{
	private static final String TAG = "server";

	public void onCreate()
	{
		Log.e(TAG, "onCreate");
	}

	public IBinder onBind(Intent t)
	{
		Log.e(TAG, "onBind");
		return mBinder;
	}

	public void onDestroy()
	{
		Log.e(TAG, "onDestroy");
		super.onDestroy();
	}

	public boolean onUnbind(Intent intent)
	{
		Log.e(TAG, "onUnbind");
		return super.onUnbind(intent);
	}

	public void onRebind(Intent intent)
	{
		Log.e(TAG, "onRebind");
		super.onRebind(intent);
	}

	private final ICalcAIDL.Stub mBinder = new ICalcAIDL.Stub()
	{

		@Override
		public int add(int x, int y) throws RemoteException
		{
			return x + y;
		}

		@Override
		public int min(int x, int y) throws RemoteException
		{
			return x - y;
		}

	};

}
在此 Service 中,使用生成的 ICalcAIDL 创建了一个 mBinder 的对象,并在 Service 的 onBind 方法中返回

最后记得在 AndroidManifest 中注册

<service android:name="com.example.zhy_binder.CalcService" >
            <intent-filter>
                <action android:name="com.zhy.aidl.calc" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </service>

这里我们指定了一个 name,因为我们一会会在别的应用程序中通过 Intent 来查找此 Service;这个不需要 Activity,所以我也就没写 Activity,安装完成也看不到安装图标,悄悄在后台运行着。

到此,服务端编写完毕。下面开始编写客户端

2、客户端

客户端的代码比较简单,创建一个布局,里面包含 4 个按钮,分别为绑定服务,解除绑定,调用加法,调用减法

布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:onClick="bindService"
        android:text="BindService" />

    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:onClick="unbindService"
        android:text="UnbindService" />

    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:onClick="addInvoked"
        android:text="12+12" />

    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:onClick="minInvoked"
        android:text="50-12" />

</LinearLayout>

主 Activity

package com.example.zhy_binder_client;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.zhy.calc.aidl.ICalcAIDL;

public class MainActivity extends Activity
{
	private ICalcAIDL mCalcAidl;

	private ServiceConnection mServiceConn = new ServiceConnection()
	{
		@Override
		public void onServiceDisconnected(ComponentName name)
		{
			Log.e("client", "onServiceDisconnected");
			mCalcAidl = null;
		}

		@Override
		public void onServiceConnected(ComponentName name, IBinder service)
		{
			Log.e("client", "onServiceConnected");
			mCalcAidl = ICalcAIDL.Stub.asInterface(service);
		}
	};

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

	}
	
	/**
	 * 点击BindService按钮时调用
	 * @param view
	 */
	public void bindService(View view)
	{
		Intent intent = new Intent();
		intent.setAction("com.zhy.aidl.calc");
		bindService(intent, mServiceConn, Context.BIND_AUTO_CREATE);
	}
	/**
	 * 点击unBindService按钮时调用
	 * @param view
	 */
	public void unbindService(View view)
	{
		unbindService(mServiceConn);
	}
	/**
	 * 点击12+12按钮时调用
	 * @param view
	 */
	public void addInvoked(View view) throws Exception
	{

		if (mCalcAidl != null)
		{
			int addRes = mCalcAidl.add(12, 12);
			Toast.makeText(this, addRes + "", Toast.LENGTH_SHORT).show();
		} else
		{
			Toast.makeText(this, "服务器被异常杀死,请重新绑定服务端", Toast.LENGTH_SHORT)
					.show();

		}

	}
	/**
	 * 点击50-12按钮时调用
	 * @param view
	 */
	public void minInvoked(View view) throws Exception
	{

		if (mCalcAidl != null)
		{
			int addRes = mCalcAidl.min(58, 12);
			Toast.makeText(this, addRes + "", Toast.LENGTH_SHORT).show();
		} else
		{
			Toast.makeText(this, "服务端未绑定或被异常杀死,请重新绑定服务端", Toast.LENGTH_SHORT)
					.show();

		}

	}

}

很标准的绑定服务的代码。

直接看运行结果:

我们首先点击 BindService 按钮,查看 log

08-09 22:56:38.959: E/server(29692): onCreate
08-09 22:56:38.959: E/server(29692): onBind
08-09 22:56:38.959: E/client(29477): onServiceConnected
可以看到,点击 BindService 之后,服务端执行了 onCreate 和 onBind 的方法,并且客户端执行了 onServiceConnected 方法,标明服务器与客户端已经联通

然后点击 12+12,50-12 可以成功的调用服务端的代码并返回正确的结果

下面我们再点击 unBindService

08-09 22:59:25.567: E/server(29692): onUnbind
08-09 22:59:25.567: E/server(29692): onDestroy
由于我们当前只有一个客户端绑定了此 Service,所以 Service 调用了 onUnbind 和 onDestory

然后我们继续点击 12+12,50-12,通过上图可以看到,依然可以正确执行,也就是说即使 onUnbind 被调用,连接也是不会断开的,那么什么时候会端口呢?

即当服务端被异常终止的时候,比如我们现在在手机的正在执行的程序中找到该服务:

点击停止,此时查看 log

08-09 23:04:21.433: E/client(30146): onServiceDisconnected
可以看到调用了 onServiceDisconnected 方法,此时连接被断开,现在点击 12+12,50-12 的按钮,则会弹出 Toast 服务端断开的提示。

说了这么多,似乎和 Binder 框架没什么关系,下面我们来具体看一看 AIDL 为什么做了些什么。

3、分析 AIDL 生成的代码


1、服务端

先看服务端的代码,可以看到我们服务端提供的服务是由

private final ICalcAIDL.Stub mBinder = new ICalcAIDL.Stub()
	{

		@Override
		public int add(int x, int y) throws RemoteException
		{
			return x + y;
		}

		@Override
		public int min(int x, int y) throws RemoteException
		{
			return x - y;
		}

	};

ICalcAILD.Stub 来执行的,让我们来看看 Stub 这个类的声明:

public static abstract class Stub extends android.os.Binder implements com.zhy.calc.aidl.ICalcAIDL

清楚的看到这个类是 Binder 的子类,是不是符合我们文章开通所说的服务端其实是一个 Binder 类的实例

接下来看它的 onTransact () 方法:

@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_add:
{
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
int _arg1;
_arg1 = data.readInt();
int _result = this.add(_arg0, _arg1);
reply.writeNoException();
reply.writeInt(_result);
return true;
}
case TRANSACTION_min:
{
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
int _arg1;
_arg1 = data.readInt();
int _result = this.min(_arg0, _arg1);
reply.writeNoException();
reply.writeInt(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}

文章开头也说到服务端的 Binder 实例会根据客户端依靠 Binder 驱动发来的消息,执行 onTransact 方法,然后由其参数决定执行服务端的代码。

可以看到 onTransact 有四个参数

code , data ,replay , flags

code 是一个整形的唯一标识,用于区分执行哪个方法,客户端会传递此参数,告诉服务端执行哪个方法

data 客户端传递过来的参数

replay 服务器返回回去的值

flags 标明是否有返回值,0 为有(双向),1 为没有(单向)

我们仔细看 case TRANSACTION_min 中的代码

data.enforceInterface (DESCRIPTOR); 与客户端的 writeInterfaceToken 对用,标识远程服务的名称

int _arg0;
_arg0 = data.readInt();
int _arg1;
_arg1 = data.readInt();

接下来分别读取了客户端传入的两个参数

int _result = this.min(_arg0, _arg1);
reply.writeNoException();
reply.writeInt(_result);

然后执行 this.min,即我们实现的 min 方法;返回 result 由 reply 写回。

add 同理,可以看到服务端通过 AIDL 生成 Stub 的类,封装了服务端本来需要写的代码。

2、客户端

客户端主要通过 ServiceConnected 与服务端连接

private ServiceConnection mServiceConn = new ServiceConnection()
	{
		@Override
		public void onServiceDisconnected(ComponentName name)
		{
			Log.e("client", "onServiceDisconnected");
			mCalcAidl = null;
		}

		@Override
		public void onServiceConnected(ComponentName name, IBinder service)
		{
			Log.e("client", "onServiceConnected");
			mCalcAidl = ICalcAIDL.Stub.asInterface(service);
		}
	};

如果你比较敏锐,应该会猜到这个 onServiceConnected 中的 IBinder 实例,其实就是我们文章开通所说的 Binder 驱动,也是一个 Binder 实例

在 ICalcAIDL.Stub.asInterface 中最终调用了:

return new com.zhy.calc.aidl.ICalcAIDL.Stub.Proxy(obj);

这个 Proxy 实例传入了我们的 Binder 驱动,并且封装了我们调用服务端的代码,文章开头说,客户端会通过 Binder 驱动的 transact () 方法调用服务端代码

直接看 Proxy 中的 add 方法

@Override public int add(int x, int y) 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);
_data.writeInt(x);
_data.writeInt(y);
mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}

首先声明两个 Parcel 对象,一个用于传递数据,一个用户接收返回的数据

_data.writeInterfaceToken (DESCRIPTOR); 与服务器端的 enforceInterfac 对应

_data.writeInt(x);
_data.writeInt (y); 写入需要传递的参数

mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);

终于看到了我们的 transact 方法,第一个对应服务端的 code,_data,_repay 分别对应服务端的 data,reply,0 表示是双向的

_reply.readException();
_result = _reply.readInt();

最后读出我们服务端返回的数据,然后 return。可以看到和服务端的 onTransact 基本是一行一行对应的。

到此,我们已经通过 AIDL 生成的代码解释了 Android Binder 框架的工作原理。Service 的作用其实就是为我们创建 Binder 驱动,即服务端与客户端连接的桥梁。

AIDL 其实通过我们写的 aidl 文件,帮助我们生成了一个接口,一个 Stub 类用于服务端,一个 Proxy 类用于客户端调用。那么我们是否可以不通过写 AIDL 来实现远程的通信呢?下面向大家展示如何完全不依赖 AIDL 来实现客户端与服务端的通信。

4、不依赖 AIDL 实现程序间通讯


1、服务端代码

我们新建一个 CalcPlusService.java 用于实现两个数的乘和除

package com.example.zhy_binder;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;

public class CalcPlusService extends Service
{
	private static final String DESCRIPTOR = "CalcPlusService";
	private static final String TAG = "CalcPlusService";

	public void onCreate()
	{
		Log.e(TAG, "onCreate");
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId)
	{
		Log.e(TAG, "onStartCommand");
		return super.onStartCommand(intent, flags, startId);
	}

	public IBinder onBind(Intent t)
	{
		Log.e(TAG, "onBind");
		return mBinder;
	}

	public void onDestroy()
	{
		Log.e(TAG, "onDestroy");
		super.onDestroy();
	}

	public boolean onUnbind(Intent intent)
	{
		Log.e(TAG, "onUnbind");
		return super.onUnbind(intent);
	}

	public void onRebind(Intent intent)
	{
		Log.e(TAG, "onRebind");
		super.onRebind(intent);
	}

	private MyBinder mBinder = new MyBinder();

	private class MyBinder extends Binder
	{
		@Override
		protected boolean onTransact(int code, Parcel data, Parcel reply,
				int flags) throws RemoteException
		{
			switch (code)
			{
			case 0x110:
			{
				data.enforceInterface(DESCRIPTOR);
				int _arg0;
				_arg0 = data.readInt();
				int _arg1;
				_arg1 = data.readInt();
				int _result = _arg0 * _arg1;
				reply.writeNoException();
				reply.writeInt(_result);
				return true;
			}
			case 0x111:
			{
				data.enforceInterface(DESCRIPTOR);
				int _arg0;
				_arg0 = data.readInt();
				int _arg1;
				_arg1 = data.readInt();
				int _result = _arg0 / _arg1;
				reply.writeNoException();
				reply.writeInt(_result);
				return true;
			}
			}
			return super.onTransact(code, data, reply, flags);
		}

	};

}

我们自己实现服务端,所以我们自定义了一个 Binder 子类,然后复写了其 onTransact 方法,我们指定服务的标识为 CalcPlusService,然后 0x110 为乘,0x111 为除;

记得在 AndroidMenifest 中注册

<service android:name="com.example.zhy_binder.CalcPlusService" >
            <intent-filter>
                <action android:name="com.zhy.aidl.calcplus" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </service>

服务端代码结束。

2、客户端代码

单独新建了一个项目,代码和上例很类似

首先布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:onClick="bindService"
        android:text="BindService" />

    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:onClick="unbindService"
        android:text="UnbindService" />

    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:onClick="mulInvoked"
        android:text="50*12" />
    
    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:onClick="divInvoked"
        android:text="36/12" />

</LinearLayout>

可以看到加入了乘和除

然后是 Activity 的代码

package com.example.zhy_binder_client03;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends Activity
{

	private IBinder mPlusBinder;
	private ServiceConnection mServiceConnPlus = new ServiceConnection()
	{
		@Override
		public void onServiceDisconnected(ComponentName name)
		{
			Log.e("client", "mServiceConnPlus onServiceDisconnected");
		}

		@Override
		public void onServiceConnected(ComponentName name, IBinder service)
		{

			Log.e("client", " mServiceConnPlus onServiceConnected");
			mPlusBinder = service;
		}
	};

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

	}

	public void bindService(View view)
	{
		Intent intentPlus = new Intent();
		intentPlus.setAction("com.zhy.aidl.calcplus");
		boolean plus = bindService(intentPlus, mServiceConnPlus,
				Context.BIND_AUTO_CREATE);
		Log.e("plus", plus + "");
	}

	public void unbindService(View view)
	{
		unbindService(mServiceConnPlus);
	}

	public void mulInvoked(View view)
	{

		if (mPlusBinder == null)
		{
			Toast.makeText(this, "未连接服务端或服务端被异常杀死", Toast.LENGTH_SHORT).show();
		} else
		{
			android.os.Parcel _data = android.os.Parcel.obtain();
			android.os.Parcel _reply = android.os.Parcel.obtain();
			int _result;
			try
			{
				_data.writeInterfaceToken("CalcPlusService");
				_data.writeInt(50);
				_data.writeInt(12);
				mPlusBinder.transact(0x110, _data, _reply, 0);
				_reply.readException();
				_result = _reply.readInt();
				Toast.makeText(this, _result + "", Toast.LENGTH_SHORT).show();

			} catch (RemoteException e)
			{
				e.printStackTrace();
			} finally
			{
				_reply.recycle();
				_data.recycle();
			}
		}

	}
	
	public void divInvoked(View view)
	{

		if (mPlusBinder == null)
		{
			Toast.makeText(this, "未连接服务端或服务端被异常杀死", Toast.LENGTH_SHORT).show();
		} else
		{
			android.os.Parcel _data = android.os.Parcel.obtain();
			android.os.Parcel _reply = android.os.Parcel.obtain();
			int _result;
			try
			{
				_data.writeInterfaceToken("CalcPlusService");
				_data.writeInt(36);
				_data.writeInt(12);
				mPlusBinder.transact(0x111, _data, _reply, 0);
				_reply.readException();
				_result = _reply.readInt();
				Toast.makeText(this, _result + "", Toast.LENGTH_SHORT).show();

			} catch (RemoteException e)
			{
				e.printStackTrace();
			} finally
			{
				_reply.recycle();
				_data.recycle();
			}
		}

	}
}

为了明了,我直接在 mulInvoked 里面写了代码,和服务端都没有抽象出一个接口。首先绑定服务时,通过 onServiceConnected 得到 Binder 驱动即 mPlusBinder;

然后准备数据,调用 transact 方法,通过 code 指定执行服务端哪个方法,代码和上面的分析一致。

下面看运行结果:


是不是很好的实现了我们两个应用程序间的通讯,并没有使用 aidl 文件,也从侧面分析了我们上述分析是正确的。


好了,就到这里,相信大家看完这篇博文,对 aidl 和 Binder 的理解也会更加深刻。


测试代码点击下载

代码先安装 server 端的代码,然后再安装 client 端的。。。










Android aidl Binder框架浅析

Android aidl Binder框架浅析

1、概述

Binder能干什么?Binder可以提供系统中任何程序都可以访问的全局服务。这个功能当然是任何系统都应该提供的,下面我们简单看一下Android的Binder的框架

Android Binder框架分为服务器接口、Binder驱动、以及客户端接口;简单想一下,需要提供一个全局服务,那么全局服务那端即是服务器接口,任何程序即客户端接口,它们之间通过一个Binder驱动访问。

服务器端接口:实际上是Binder类的对象,该对象一旦创建,内部则会启动一个隐藏线程,会接收Binder驱动发送的消息,收到消息后,会执行Binder对象中的onTransact()函数,并按照该函数的参数执行不同的服务器端代码。

Binder驱动:该对象也为Binder类的实例,客户端通过该对象访问远程服务。

客户端接口:获得Binder驱动,调用其transact()发送消息至服务器

如果大家对上述不了解,没关系,下面会通过例子来更好的说明,实践是检验真理的唯一标准嘛

2、AIDL的使用

如果对Android比较熟悉,那么一定使用过AIDL,如果你还不了解,那么也没关系,下面会使用一个例子展示AIDL的用法。

我们使用AIDL实现一个跨进程的加减法调用

1、服务端

新建一个项目,创建一个包名:com.zhy.calc.aidl,在包内创建一个ICalcAIDL文件:

 

 
  1. package com.zhy.calc.aidl;

  2. interface ICalcAIDL

  3. {

  4. int add(int x , int y);

  5. int min(int x , int y );

  6. }


注意,文件名为ICalcAIDL.aidl

 

然后在项目的gen目录下会生成一个ICalcAIDL.java文件,暂时不贴这个文件的代码了,后面会详细说明

然后我们在项目中新建一个Service,代码如下:

 

 
  1. package com.example.zhy_binder;

  2.  
  3. import com.zhy.calc.aidl.ICalcAIDL;

  4.  
  5. import android.app.Service;

  6. import android.content.Intent;

  7. import android.os.IBinder;

  8. import android.os.RemoteException;

  9. import android.util.Log;

  10.  
  11. public class CalcService extends Service

  12. {

  13. private static final String TAG = "server";

  14.  
  15. public void onCreate()

  16. {

  17. Log.e(TAG, "onCreate");

  18. }

  19.  
  20. public IBinder onBind(Intent t)

  21. {

  22. Log.e(TAG, "onBind");

  23. return mBinder;

  24. }

  25.  
  26. public void onDestroy()

  27. {

  28. Log.e(TAG, "onDestroy");

  29. super.onDestroy();

  30. }

  31.  
  32. public boolean onUnbind(Intent intent)

  33. {

  34. Log.e(TAG, "onUnbind");

  35. return super.onUnbind(intent);

  36. }

  37.  
  38. public void onRebind(Intent intent)

  39. {

  40. Log.e(TAG, "onRebind");

  41. super.onRebind(intent);

  42. }

  43.  
  44. private final ICalcAIDL.Stub mBinder = new ICalcAIDL.Stub()

  45. {

  46.  
  47. @Override

  48. public int add(int x, int y) throws RemoteException

  49. {

  50. return x + y;

  51. }

  52.  
  53. @Override

  54. public int min(int x, int y) throws RemoteException

  55. {

  56. return x - y;

  57. }

  58.  
  59. };

  60.  
  61. }

在此Service中,使用生成的ICalcAIDL创建了一个mBinder的对象,并在Service的onBind方法中返回

 

最后记得在AndroidManifest中注册

 

 
  1. <service android:name="com.example.zhy_binder.CalcService" >

  2. <intent-filter>

  3. <action android:name="com.zhy.aidl.calc" />

  4.  
  5. <category android:name="android.intent.category.DEFAULT" />

  6. </intent-filter>

  7. </service>


这里我们指定了一个name,因为我们一会会在别的应用程序中通过Intent来查找此Service;这个不需要Activity,所以我也就没写Activity,安装完成也看不到安装图标,悄悄在后台运行着。

 

到此,服务端编写完毕。下面开始编写客户端

2、客户端

客户端的代码比较简单,创建一个布局,里面包含4个按钮,分别为绑定服务,解除绑定,调用加法,调用减法

布局文件:

 

 
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

  2. xmlns:tools="http://schemas.android.com/tools"

  3. android:layout_width="match_parent"

  4. android:layout_height="match_parent"

  5. android:orientation="vertical" >

  6.  
  7. <Button

  8. android:layout_width="fill_parent"

  9. android:layout_height="wrap_content"

  10. android:onClick="bindService"

  11. android:text="BindService" />

  12.  
  13. <Button

  14. android:layout_width="fill_parent"

  15. android:layout_height="wrap_content"

  16. android:onClick="unbindService"

  17. android:text="UnbindService" />

  18.  
  19. <Button

  20. android:layout_width="fill_parent"

  21. android:layout_height="wrap_content"

  22. android:onClick="addInvoked"

  23. android:text="12+12" />

  24.  
  25. <Button

  26. android:layout_width="fill_parent"

  27. android:layout_height="wrap_content"

  28. android:onClick="minInvoked"

  29. android:text="50-12" />

  30.  
  31. </LinearLayout>


主Activity

 

 

 
  1. package com.example.zhy_binder_client;

  2.  
  3. import android.app.Activity;

  4. import android.content.ComponentName;

  5. import android.content.Context;

  6. import android.content.Intent;

  7. import android.content.ServiceConnection;

  8. import android.os.Bundle;

  9. import android.os.IBinder;

  10. import android.util.Log;

  11. import android.view.View;

  12. import android.widget.Toast;

  13.  
  14. import com.zhy.calc.aidl.ICalcAIDL;

  15.  
  16. public class MainActivity extends Activity

  17. {

  18. private ICalcAIDL mCalcAidl;

  19.  
  20. private ServiceConnection mServiceConn = new ServiceConnection()

  21. {

  22. @Override

  23. public void onServiceDisconnected(ComponentName name)

  24. {

  25. Log.e("client", "onServiceDisconnected");

  26. mCalcAidl = null;

  27. }

  28.  
  29. @Override

  30. public void onServiceConnected(ComponentName name, IBinder service)

  31. {

  32. Log.e("client", "onServiceConnected");

  33. mCalcAidl = ICalcAIDL.Stub.asInterface(service);

  34. }

  35. };

  36.  
  37. @Override

  38. protected void onCreate(Bundle savedInstanceState)

  39. {

  40. super.onCreate(savedInstanceState);

  41. setContentView(R.layout.activity_main);

  42.  
  43. }

  44.  
  45. /**

  46. * 点击BindService按钮时调用

  47. * @param view

  48. */

  49. public void bindService(View view)

  50. {

  51. Intent intent = new Intent();

  52. intent.setAction("com.zhy.aidl.calc");

  53. bindService(intent, mServiceConn, Context.BIND_AUTO_CREATE);

  54. }

  55. /**

  56. * 点击unBindService按钮时调用

  57. * @param view

  58. */

  59. public void unbindService(View view)

  60. {

  61. unbindService(mServiceConn);

  62. }

  63. /**

  64. * 点击12+12按钮时调用

  65. * @param view

  66. */

  67. public void addInvoked(View view) throws Exception

  68. {

  69.  
  70. if (mCalcAidl != null)

  71. {

  72. int addRes = mCalcAidl.add(12, 12);

  73. Toast.makeText(this, addRes + "", Toast.LENGTH_SHORT).show();

  74. } else

  75. {

  76. Toast.makeText(this, "服务器被异常杀死,请重新绑定服务端", Toast.LENGTH_SHORT)

  77. .show();

  78.  
  79. }

  80.  
  81. }

  82. /**

  83. * 点击50-12按钮时调用

  84. * @param view

  85. */

  86. public void minInvoked(View view) throws Exception

  87. {

  88.  
  89. if (mCalcAidl != null)

  90. {

  91. int addRes = mCalcAidl.min(58, 12);

  92. Toast.makeText(this, addRes + "", Toast.LENGTH_SHORT).show();

  93. } else

  94. {

  95. Toast.makeText(this, "服务端未绑定或被异常杀死,请重新绑定服务端", Toast.LENGTH_SHORT)

  96. .show();

  97.  
  98. }

  99.  
  100. }

  101.  
  102. }

 

很标准的绑定服务的代码。

直接看运行结果:

我们首先点击BindService按钮,查看log

 

 
  1. 08-09 22:56:38.959: E/server(29692): onCreate

  2. 08-09 22:56:38.959: E/server(29692): onBind

  3. 08-09 22:56:38.959: E/client(29477): onServiceConnected

可以看到,点击BindService之后,服务端执行了onCreate和onBind的方法,并且客户端执行了onServiceConnected方法,标明服务器与客户端已经联通

 

然后点击12+12,50-12可以成功的调用服务端的代码并返回正确的结果

下面我们再点击unBindService

 

 
  1. 08-09 22:59:25.567: E/server(29692): onUnbind

  2. 08-09 22:59:25.567: E/server(29692): onDestroy

由于我们当前只有一个客户端绑定了此Service,所以Service调用了onUnbind和onDestory

 

然后我们继续点击12+12,50-12,通过上图可以看到,依然可以正确执行,也就是说即使onUnbind被调用,连接也是不会断开的,那么什么时候会端口呢?

即当服务端被异常终止的时候,比如我们现在在手机的正在执行的程序中找到该服务:

点击停止,此时查看log

 

08-09 23:04:21.433: E/client(30146): onServiceDisconnected

可以看到调用了onServiceDisconnected方法,此时连接被断开,现在点击12+12,50-12的按钮,则会弹出Toast服务端断开的提示。

 

说了这么多,似乎和Binder框架没什么关系,下面我们来具体看一看AIDL为什么做了些什么。

3、分析AIDL生成的代码

 

1、服务端

先看服务端的代码,可以看到我们服务端提供的服务是由

 

 
  1. private final ICalcAIDL.Stub mBinder = new ICalcAIDL.Stub()

  2. {

  3.  
  4. @Override

  5. public int add(int x, int y) throws RemoteException

  6. {

  7. return x + y;

  8. }

  9.  
  10. @Override

  11. public int min(int x, int y) throws RemoteException

  12. {

  13. return x - y;

  14. }

  15.  
  16. };


ICalcAILD.Stub来执行的,让我们来看看Stub这个类的声明:

 

 

 
  1. public static abstract class Stub extends android.os.Binder implements com.zhy.calc.aidl.ICalcAIDL

  2.  


清楚的看到这个类是Binder的子类,是不是符合我们文章开通所说的服务端其实是一个Binder类的实例

 

接下来看它的onTransact()方法:

 

 
  1. @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException

  2. {

  3. switch (code)

  4. {

  5. case INTERFACE_TRANSACTION:

  6. {

  7. reply.writeString(DESCRIPTOR);

  8. return true;

  9. }

  10. case TRANSACTION_add:

  11. {

  12. data.enforceInterface(DESCRIPTOR);

  13. int _arg0;

  14. _arg0 = data.readInt();

  15. int _arg1;

  16. _arg1 = data.readInt();

  17. int _result = this.add(_arg0, _arg1);

  18. reply.writeNoException();

  19. reply.writeInt(_result);

  20. return true;

  21. }

  22. case TRANSACTION_min:

  23. {

  24. data.enforceInterface(DESCRIPTOR);

  25. int _arg0;

  26. _arg0 = data.readInt();

  27. int _arg1;

  28. _arg1 = data.readInt();

  29. int _result = this.min(_arg0, _arg1);

  30. reply.writeNoException();

  31. reply.writeInt(_result);

  32. return true;

  33. }

  34. }

  35. return super.onTransact(code, data, reply, flags);

  36. }


文章开头也说到服务端的Binder实例会根据客户端依靠Binder驱动发来的消息,执行onTransact方法,然后由其参数决定执行服务端的代码。

 

可以看到onTransact有四个参数

code , data ,replay , flags

code 是一个整形的唯一标识,用于区分执行哪个方法,客户端会传递此参数,告诉服务端执行哪个方法

data客户端传递过来的参数

replay服务器返回回去的值

flags标明是否有返回值,0为有(双向),1为没有(单向)

我们仔细看case TRANSACTION_min中的代码

data.enforceInterface(DESCRIPTOR);与客户端的writeInterfaceToken对用,标识远程服务的名称

int _arg0;
_arg0 = data.readInt();
int _arg1;
_arg1 = data.readInt();

接下来分别读取了客户端传入的两个参数

int _result = this.min(_arg0, _arg1);
reply.writeNoException();
reply.writeInt(_result);

然后执行this.min,即我们实现的min方法;返回result由reply写回。

add同理,可以看到服务端通过AIDL生成Stub的类,封装了服务端本来需要写的代码。

2、客户端

客户端主要通过ServiceConnected与服务端连接

 

 
  1. private ServiceConnection mServiceConn = new ServiceConnection()

  2. {

  3. @Override

  4. public void onServiceDisconnected(ComponentName name)

  5. {

  6. Log.e("client", "onServiceDisconnected");

  7. mCalcAidl = null;

  8. }

  9.  
  10. @Override

  11. public void onServiceConnected(ComponentName name, IBinder service)

  12. {

  13. Log.e("client", "onServiceConnected");

  14. mCalcAidl = ICalcAIDL.Stub.asInterface(service);

  15. }

  16. };


如果你比较敏锐,应该会猜到这个onServiceConnected中的IBinder实例,其实就是我们文章开通所说的Binder驱动,也是一个Binder实例

 

在ICalcAIDL.Stub.asInterface中最终调用了:

 

return new com.zhy.calc.aidl.ICalcAIDL.Stub.Proxy(obj);


这个Proxy实例传入了我们的Binder驱动,并且封装了我们调用服务端的代码,文章开头说,客户端会通过Binder驱动的transact()方法调用服务端代码

 

直接看Proxy中的add方法

 

 
  1. @Override public int add(int x, int y) throws android.os.RemoteException

  2. {

  3. android.os.Parcel _data = android.os.Parcel.obtain();

  4. android.os.Parcel _reply = android.os.Parcel.obtain();

  5. int _result;

  6. try {

  7. _data.writeInterfaceToken(DESCRIPTOR);

  8. _data.writeInt(x);

  9. _data.writeInt(y);

  10. mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);

  11. _reply.readException();

  12. _result = _reply.readInt();

  13. }

  14. finally {

  15. _reply.recycle();

  16. _data.recycle();

  17. }

  18. return _result;

  19. }


首先声明两个Parcel对象,一个用于传递数据,一个用户接收返回的数据

 

_data.writeInterfaceToken(DESCRIPTOR);与服务器端的enforceInterfac对应

_data.writeInt(x);
_data.writeInt(y);写入需要传递的参数

mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);

终于看到了我们的transact方法,第一个对应服务端的code,_data,_repay分别对应服务端的data,reply,0表示是双向的

_reply.readException();
_result = _reply.readInt();

最后读出我们服务端返回的数据,然后return。可以看到和服务端的onTransact基本是一行一行对应的。

到此,我们已经通过AIDL生成的代码解释了Android Binder框架的工作原理。Service的作用其实就是为我们创建Binder驱动,即服务端与客户端连接的桥梁。

AIDL其实通过我们写的aidl文件,帮助我们生成了一个接口,一个Stub类用于服务端,一个Proxy类用于客户端调用。那么我们是否可以不通过写AIDL来实现远程的通信呢?下面向大家展示如何完全不依赖AIDL来实现客户端与服务端的通信。

4、不依赖AIDL实现程序间通讯

 

1、服务端代码

我们新建一个CalcPlusService.java用于实现两个数的乘和除

 

 
  1. package com.example.zhy_binder;

  2.  
  3. import android.app.Service;

  4. import android.content.Intent;

  5. import android.os.Binder;

  6. import android.os.IBinder;

  7. import android.os.Parcel;

  8. import android.os.RemoteException;

  9. import android.util.Log;

  10.  
  11. public class CalcPlusService extends Service

  12. {

  13. private static final String DESCRIPTOR = "CalcPlusService";

  14. private static final String TAG = "CalcPlusService";

  15.  
  16. public void onCreate()

  17. {

  18. Log.e(TAG, "onCreate");

  19. }

  20.  
  21. @Override

  22. public int onStartCommand(Intent intent, int flags, int startId)

  23. {

  24. Log.e(TAG, "onStartCommand");

  25. return super.onStartCommand(intent, flags, startId);

  26. }

  27.  
  28. public IBinder onBind(Intent t)

  29. {

  30. Log.e(TAG, "onBind");

  31. return mBinder;

  32. }

  33.  
  34. public void onDestroy()

  35. {

  36. Log.e(TAG, "onDestroy");

  37. super.onDestroy();

  38. }

  39.  
  40. public boolean onUnbind(Intent intent)

  41. {

  42. Log.e(TAG, "onUnbind");

  43. return super.onUnbind(intent);

  44. }

  45.  
  46. public void onRebind(Intent intent)

  47. {

  48. Log.e(TAG, "onRebind");

  49. super.onRebind(intent);

  50. }

  51.  
  52. private MyBinder mBinder = new MyBinder();

  53.  
  54. private class MyBinder extends Binder

  55. {

  56. @Override

  57. protected boolean onTransact(int code, Parcel data, Parcel reply,

  58. int flags) throws RemoteException

  59. {

  60. switch (code)

  61. {

  62. case 0x110:

  63. {

  64. data.enforceInterface(DESCRIPTOR);

  65. int _arg0;

  66. _arg0 = data.readInt();

  67. int _arg1;

  68. _arg1 = data.readInt();

  69. int _result = _arg0 * _arg1;

  70. reply.writeNoException();

  71. reply.writeInt(_result);

  72. return true;

  73. }

  74. case 0x111:

  75. {

  76. data.enforceInterface(DESCRIPTOR);

  77. int _arg0;

  78. _arg0 = data.readInt();

  79. int _arg1;

  80. _arg1 = data.readInt();

  81. int _result = _arg0 / _arg1;

  82. reply.writeNoException();

  83. reply.writeInt(_result);

  84. return true;

  85. }

  86. }

  87. return super.onTransact(code, data, reply, flags);

  88. }

  89.  
  90. };

  91.  
  92. }


我们自己实现服务端,所以我们自定义了一个Binder子类,然后复写了其onTransact方法,我们指定服务的标识为CalcPlusService,然后0x110为乘,0x111为除;

 

记得在AndroidMenifest中注册

 

 
  1. <service android:name="com.example.zhy_binder.CalcPlusService" >

  2. <intent-filter>

  3. <action android:name="com.zhy.aidl.calcplus" />

  4. <category android:name="android.intent.category.DEFAULT" />

  5. </intent-filter>

  6. </service>


服务端代码结束。

 

2、客户端代码

单独新建了一个项目,代码和上例很类似

首先布局文件:

 

 
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

  2. xmlns:tools="http://schemas.android.com/tools"

  3. android:layout_width="match_parent"

  4. android:layout_height="match_parent"

  5. android:orientation="vertical" >

  6.  
  7. <Button

  8. android:layout_width="fill_parent"

  9. android:layout_height="wrap_content"

  10. android:onClick="bindService"

  11. android:text="BindService" />

  12.  
  13. <Button

  14. android:layout_width="fill_parent"

  15. android:layout_height="wrap_content"

  16. android:onClick="unbindService"

  17. android:text="UnbindService" />

  18.  
  19. <Button

  20. android:layout_width="fill_parent"

  21. android:layout_height="wrap_content"

  22. android:onClick="mulInvoked"

  23. android:text="50*12" />

  24.  
  25. <Button

  26. android:layout_width="fill_parent"

  27. android:layout_height="wrap_content"

  28. android:onClick="divInvoked"

  29. android:text="36/12" />

  30.  
  31. </LinearLayout>


可以看到加入了乘和除

 

然后是Activity的代码

 

 
  1. package com.example.zhy_binder_client03;

  2.  
  3. import android.app.Activity;

  4. import android.content.ComponentName;

  5. import android.content.Context;

  6. import android.content.Intent;

  7. import android.content.ServiceConnection;

  8. import android.os.Bundle;

  9. import android.os.IBinder;

  10. import android.os.RemoteException;

  11. import android.util.Log;

  12. import android.view.View;

  13. import android.widget.Toast;

  14.  
  15. public class MainActivity extends Activity

  16. {

  17.  
  18. private IBinder mPlusBinder;

  19. private ServiceConnection mServiceConnPlus = new ServiceConnection()

  20. {

  21. @Override

  22. public void onServiceDisconnected(ComponentName name)

  23. {

  24. Log.e("client", "mServiceConnPlus onServiceDisconnected");

  25. }

  26.  
  27. @Override

  28. public void onServiceConnected(ComponentName name, IBinder service)

  29. {

  30.  
  31. Log.e("client", " mServiceConnPlus onServiceConnected");

  32. mPlusBinder = service;

  33. }

  34. };

  35.  
  36. @Override

  37. protected void onCreate(Bundle savedInstanceState)

  38. {

  39. super.onCreate(savedInstanceState);

  40. setContentView(R.layout.activity_main);

  41.  
  42. }

  43.  
  44. public void bindService(View view)

  45. {

  46. Intent intentPlus = new Intent();

  47. intentPlus.setAction("com.zhy.aidl.calcplus");

  48. boolean plus = bindService(intentPlus, mServiceConnPlus,

  49. Context.BIND_AUTO_CREATE);

  50. Log.e("plus", plus + "");

  51. }

  52.  
  53. public void unbindService(View view)

  54. {

  55. unbindService(mServiceConnPlus);

  56. }

  57.  
  58. public void mulInvoked(View view)

  59. {

  60.  
  61. if (mPlusBinder == null)

  62. {

  63. Toast.makeText(this, "未连接服务端或服务端被异常杀死", Toast.LENGTH_SHORT).show();

  64. } else

  65. {

  66. android.os.Parcel _data = android.os.Parcel.obtain();

  67. android.os.Parcel _reply = android.os.Parcel.obtain();

  68. int _result;

  69. try

  70. {

  71. _data.writeInterfaceToken("CalcPlusService");

  72. _data.writeInt(50);

  73. _data.writeInt(12);

  74. mPlusBinder.transact(0x110, _data, _reply, 0);

  75. _reply.readException();

  76. _result = _reply.readInt();

  77. Toast.makeText(this, _result + "", Toast.LENGTH_SHORT).show();

  78.  
  79. } catch (RemoteException e)

  80. {

  81. e.printStackTrace();

  82. } finally

  83. {

  84. _reply.recycle();

  85. _data.recycle();

  86. }

  87. }

  88.  
  89. }

  90.  
  91. public void divInvoked(View view)

  92. {

  93.  
  94. if (mPlusBinder == null)

  95. {

  96. Toast.makeText(this, "未连接服务端或服务端被异常杀死", Toast.LENGTH_SHORT).show();

  97. } else

  98. {

  99. android.os.Parcel _data = android.os.Parcel.obtain();

  100. android.os.Parcel _reply = android.os.Parcel.obtain();

  101. int _result;

  102. try

  103. {

  104. _data.writeInterfaceToken("CalcPlusService");

  105. _data.writeInt(36);

  106. _data.writeInt(12);

  107. mPlusBinder.transact(0x111, _data, _reply, 0);

  108. _reply.readException();

  109. _result = _reply.readInt();

  110. Toast.makeText(this, _result + "", Toast.LENGTH_SHORT).show();

  111.  
  112. } catch (RemoteException e)

  113. {

  114. e.printStackTrace();

  115. } finally

  116. {

  117. _reply.recycle();

  118. _data.recycle();

  119. }

  120. }

  121.  
  122. }

  123. }


为了明了,我直接在mulInvoked里面写了代码,和服务端都没有抽象出一个接口。首先绑定服务时,通过onServiceConnected得到Binder驱动即mPlusBinder;

 

然后准备数据,调用transact方法,通过code指定执行服务端哪个方法,代码和上面的分析一致。

下面看运行结果:

是不是很好的实现了我们两个应用程序间的通讯,并没有使用aidl文件,也从侧面分析了我们上述分析是正确的。

 

好了,就到这里,相信大家看完这篇博文,对aidl和Binder的理解也会更加深刻。

测试代码点击下载

代码先安装server端的代码,然后再安装client端的。。。

 

Android Binder 框架实现之 Binder 相关的接口和类

Android Binder 框架实现之 Binder 相关的接口和类

    Android Binder 框架实现之 Binder 相关的接口和类


Android Binder 框架实现目录:

Android Binder 框架实现之 Binder 的设计思想
Android Binder 框架实现之何为匿名 / 实名 Binder
Android Binder 框架实现之 Binder 中的数据结构
Android Binder 框架实现之 Binder 相关的接口和类
Android Binder 框架实现之 Parcel 详解之基本数据的读写
Android Binder 框架实现之 Parcel read/writeStrongBinder 实现
Android Binder 框架实现之 servicemanager 守护进程
Android Binder 框架实现之 defaultServiceManager () 的实现
Android Binder 框架实现之 Native 层 addService 详解之请求的发送
Android Binder 框架实现之 Native 层 addService 详解之请求的处理
Android Binder 框架实现之 Native 层 addService 详解之请求的反馈
Android Binder 框架实现之 Binder 服务的消息循环
Android Binder 框架实现之 Native 层 getService 详解之请求的发送
Android Binder 框架实现之 Native 层 getService 详解之请求的处理
Android Binder 框架实现之 Native 层 getService 详解之请求的反馈
Android Binder 框架实现之 Binder Native Service 的 Java 调用流程
Android Binder 框架实现之 Java 层 Binder 整体框架设计
Android Binder 框架实现之 Framework 层 Binder 服务注册过程源码分析
Android Binder 框架实现之 Java 层 Binder 服务跨进程调用源码分析
Android Binder 框架实现之 Java 层获取 Binder 服务源码分析


前言

   前面的篇章 AndroidBinder 框架实现之 Binder 中的数据结构对我们要攀登的 Binder 机制中将要牵涉到的数据结构 (包括应用层的和内核层的)做了非常详细的讲解和阐述。本篇幅重点要突破的是 Binder 机制中相关的接口和类,我们知道 Android 的绝大部分跨进程通信机制都是基于 Binder 的,正所谓做戏得全套,Binder 也不列外,这种机制不但会在底层 C++ 的世界使用,也会在上层 Java 的世界使用,所以必须提供 Java 和 C++ 两个层次的支持。当然这些 Android 的妈咪谷歌都为我们考虑到了。
   在正式开始正文介绍前附上本篇相关代码的所在文件的路径。

frameworks/base/core/java/android/os/IBinder.java
frameworks/base/core/java/android/os/Binder.java
frameworks/base/core/java/android/os/IInterface.java
frameworks/native/include/binder/IBinder.h
frameworks/native/libs/binder/Binder.cpp
frameworks/native/include/binder/Binder.h
frameworks/native/include/binder/BpBinder.h
frameworks/native/libs/binder/BpBinder.cpp
system/core/include/utils/RefBase.h
frameworks/native/include/binder/IInterface.h
frameworks/native/include/binder/ProcessState.h
frameworks/native/libs/binder/ProcessState.cpp
frameworks/native/include/binder/IPCThreadState.h
frameworks/native/libs/binder/IPCThreadState.cpp

注意:本文是基于 Android 7.1 版本进行介绍的!

1. Java 层次的 Binder 接口和类

   Java 层级 Binder 相关的接口和类并不是很多,因为 Binder 其实大部分的重头戏都是在 C++ 层和内核层,常见的接口和类有 IBinder 接口、IInterface 接口,Binder 类,BinderProxy 类等。

1.1 IBinder

   Android 要求所有的 Binder 实体都必须实现 IBinder 接口,其文件在 Android 源码的路径是 frameworks/base/core/java/android/os/IBinder.java,该接口的定义截选如下:

public interface IBinder {
   
   
   
	...
    public String getInterfaceDescriptor() throws RemoteException;
    public boolean pingBinder();
    public boolean isBinderAlive();
    public IInterface queryLocalInterface(String descriptor);
    public void dump(FileDescriptor fd, String[] args) throws RemoteException;
    public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException;
    public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
            String[] args, ResultReceiver resultReceiver) throws RemoteException;
    public boolean transact(int code, Parcel data, Parcel reply, int flags)
        throws RemoteException;
    public interface DeathRecipient {
   
   
   
        public void binderDied();
    }
    public void linkToDeath(DeathRecipient recipient, int flags)
            throws RemoteException;
    public boolean unlinkToDeath(DeathRecipient recipient, int flags);
}

1.2 IInterface

   IInterface 接口比较简单,其源码路径为仅仅单单定义了一个方法,不管是服务端还是客户端都需要实现该接口

public interface IInterface {
   
   
   
	IBinder asBinder();
}

1.3 BinderProxy

   BinderProxy 是 IBinder 的子类,客户端进程持有关联的服务的的 BinderProxy 对象从而完成相关的远程服务调用,其底层相对应的 C++ 层的 BpBinder 后续会介绍。

final class BinderProxy implements IBinder {
   
   
   
    public native boolean pingBinder();
    public native boolean isBinderAlive();

    public IInterface queryLocalInterface(String descriptor) {
   
   
   
        return null;
    }

    public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
   
   
   
        Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
        if (Binder.isTracingEnabled()) {
   
   
    Binder.getTransactionTracker().addTrace(); }
        return transactNative(code, data, reply, flags);
    }

    public native String getInterfaceDescriptor() throws RemoteException;
    public native boolean transactNative(int code, Parcel data, Parcel reply,
            int flags) throws RemoteException;
	...
}

1.4 Binder

   Binder 也是 IBinder 的子类,Java 层提供服务的 Server 进程持有一个 Binder 对象从而完成跨进程间通信。

public class Binder implements IBinder {
   
   
   

    public String getInterfaceDescriptor() {
   
   
   
        return mDescriptor;
    }
    
    public IInterface queryLocalInterface(String descriptor) {
   
   
   
        if (mDescriptor.equals(descriptor)) {
   
   
   
            return mOwner;
        }
        return null;
    }
	protected boolean onTransact(int code, Parcel data, Parcel reply,
            int flags) throws RemoteException {
   
   
   
    	...
    }
     public final boolean transact(int code, Parcel data, Parcel reply,
            int flags) throws RemoteException {
   
   
   
        if (false) Log.v("Binder", "Transact: " + code + " to " + this);

        if (data != null) {
   
   
   
            data.setDataPosition(0);
        }
        boolean r = onTransact(code, data, reply, flags);
        if (reply != null) {
   
   
   
            reply.setDataPosition(0);
        }
        return r;
    }
}

   Java 层次中,与 Binder 相关的接口或类的继承关系如下:
在这里插入图片描述
   在实际开发使用中,我们并不需要编写上图的 XXXXNative、XXXXProxy,它们会由 ADT 根据我们编写的 aidl 脚本自动生成。但是最好能掌握手撕什么相关的类实现,这样对于更好的理解和掌握 BInd 非常有帮助的。用户只需继承 XXXXNative 编写一个具体的 XXXXService 即可,这个 XXXXService 就是远程通信的服务实体类,而 XXXXProxy 则是其对应的代理类。
   关于 Java 层次的 binder 组件,我们就先说这么多,主要是先介绍一个大概。就研究跨进程通信而言,其实质内容基本上都在 C++ 层次,Java 层次只是一个壳而已。以后我会写专文来打通 Java 层次和 C++ 层次,看看它们是如何通过 JNI 技术关联起来的。现在我们还是把注意力集中在 C++ 层次吧。


2. C++ 层次的相关接口和类

   在 C++ 层次,就能看到各种关于 Binder 博客中经常反复肯定会被提到的 BpBinder 类和 BBinder 了,这两个类都继承于 IBinder。当然还有 IInterface,BpInterface,BnInterface,BpRefBase,ProcessState ,IPCThreadState ,下面我们来分别进行简单的介绍,在正式介绍前先奉上一关于上述几个接口和类之前的关系图,这就好比相亲之前得让介绍人先给个对方的照片,看过以后才能确定是否有进一步发展的空间不是!

在这里插入图片描述

2.1 IBinder

   它定义在 frameworks/native/include/binder/IBinder.h 中。IBinder 也是一个抽象出来的类,它包括了 localBinder (), remoteBinder () 和 transact () 等非常重要的接口。IBinder 有两个直接子类类:BpBinder 和 BBinder。

class IBinder : public virtual RefBase
{
   
   
   
public:
	...
    IBinder();
    virtual sp<IInterface>  queryLocalInterface(const String16& descriptor);
    virtual const String16& getInterfaceDescriptor() const = 0;

    virtual bool            isBinderAlive() const = 0;
    virtual status_t        pingBinder() = 0;
    virtual status_t        dump(int fd, const Vector<String16>& args) = 0;
    static  status_t        shellCommand(const sp<IBinder>& target, int in, int out, int err,
                                         Vector<String16>& args,
                                         const sp<IResultReceiver>& resultReceiver);

    virtual status_t        transact(   uint32_t code,
                                        const Parcel& data,
                                        Parcel* reply,
                                        uint32_t flags = 0) = 0;

    class DeathRecipient : public virtual RefBase
    {
   
   
   
    public:
        virtual void binderDied(const wp<IBinder>& who) = 0;
    };
    virtual status_t        linkToDeath(const sp<DeathRecipient>& recipient,
                                        void* cookie = NULL,
                                        uint32_t flags = 0) = 0;
    virtual status_t        unlinkToDeath(  const wp<DeathRecipient>& recipient,
                                            void* cookie = NULL,
                                            uint32_t flags = 0,
                                            wp<DeathRecipient>* outRecipient = NULL) = 0;

    virtual bool            checkSubclass(const void* subclassID) const;

    typedef void (*object_cleanup_func)(const void* id, void* obj, void* cleanupCookie);

    virtual void            attachObject(   const void* objectID,
                                            void* object,
                                            void* cleanupCookie,
                                            object_cleanup_func func) = 0;
    virtual void*           findObject(const void* objectID) const = 0;
    virtual void            detachObject(const void* objectID) = 0;

    virtual BBinder*        localBinder();
    virtual BpBinder*       remoteBinder();

protected:
    virtual          ~IBinder();

private:
};

2.2 BpBinder 和 BBinder

   BpBinder 和 BBinder 是相互对应的,可以算是一对兄弟组合,下面分别来介绍一下:
(1). BpBinder:是 Binder 代理类。通过 remoteBinder () 可以获取 BpBinder 对象;而且,对于 C++ 层而言,它相当于一个远程 Binder。BpBinder 的事务接口 transact () 会调用 IPCThreadState 的 transact (),进而实现与 Binder 驱动的事务交互。此外,BpBinder 中有一个 mHandle 句柄成员,它用来保存 Server 位于 Binder 驱动中的 "Binder 引用的描述"。句柄 0 是 ServiceManager 的句柄。

class BpBinder : public IBinder
{
   
   
   
public:
	                        BpBinder(int32_t handle);

    inline  int32_t     handle() const {
   
   
    return mHandle; }
    ...
    virtual status_t    transact(   uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);
    ...
	virtual BpBinder*   remoteBinder();

private:
    const   int32_t             mHandle;
    ...
}

(2).BBinder:是本地 Binder。通过 localBinder () 可以获取 BBinder 对象。当 Server 收到请求之后,会调用 BBinder 的 onTransact () 函数进行处理。而不同的 Server 会重载 onTransact () 函数,从而可以根据各自的情况对事务进行处理。

class BBinder : public IBinder
{
   
   
   
public:
                        BBinder();

    virtual const String16& getInterfaceDescriptor() const;
    virtual bool        isBinderAlive() const;
    virtual status_t    pingBinder();
	...

    virtual status_t    transact(   uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);

	...

    virtual BBinder*    localBinder();

protected:
    virtual             ~BBinder();

    virtual status_t    onTransact( uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);

private:
                        BBinder(const BBinder& o);
	...
};

2.3 RefBase 和 BpRefBase

   如果说 BpBinder 和 BBinder 是兄弟组合,那么 RefBase 和 BpRefBase 就是父子组合了,下面分别就两位来一个全方位的展示:
(1).RefBase:它定义在 system/core/include/utils/RefBase.h 中。RefBase 是一个公共父类,它声明了许多常用的接口。包括增加引用计数,获取引用计数,新增对象的弱引用等接口,其中比较重要的方法是 onFirstRef (), 在 Android 的 Native 世界里面你会惊奇的发现许多 C++ 的初始化工作都是在 onFirstRef () 里面执行的,不信可以搜搜试试。

class RefBase
{
   
   
   
public:
            void            incStrong(const void* id) const;
            void            decStrong(const void* id) const;
            void            forceIncStrong(const void* id) const;
            int32_t         getStrongCount() const;

    class weakref_type
    {
   
   
   
    public:
        RefBase*            refBase() const;
        
        void                incWeak(const void* id);
        void                decWeak(const void* id);
        
  		...
    };
    
	...

protected:
                            RefBase();
    virtual                 ~RefBase();
    
	...
    virtual void            onFirstRef();
	...
};

(2).BpRefBase:它定义在 frameworks/native/include/binder/Binder.h 中。BpRefBase 继承于 RefBase,它有一个 IBinder * 类型的成员 mRemote,同时提供了获取该 mRemote 的方法。实际上,该 mRemote 就是 BpBinder 对象。

class BpRefBase : public virtual RefBase
{
   
   
   
protected:
                            BpRefBase(const sp<IBinder>& o);
    virtual                 ~BpRefBase();
    virtual void            onFirstRef();
    virtual void            onLastStrongRef(const void* id);
    virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);

    inline  IBinder*        remote()                {
   
   
    return mRemote; }
    inline  IBinder*        remote() const          {
   
   
    return mRemote; }

private:
                            BpRefBase(const BpRefBase& o);
    BpRefBase&              operator=(const BpRefBase& o);

    IBinder* const          mRemote;//这就是那个很重要的mRemote
    RefBase::weakref_type*  mRefs;
    std::atomic<int32_t>    mState;
};

2.4 IInterface

   它定义在 frameworks/native/include/binder/IInterface.h 中。和 RefBase 类似,它也是一个公共父类,IInterface 中声明了 asBinder () 方法,用于获取对象的 IBinder 对象。

class IInterface : public virtual RefBase
{
   
   
   
public:
            IInterface();
            static sp<IBinder>  asBinder(const IInterface*);
            static sp<IBinder>  asBinder(const sp<IInterface>&);

protected:
    virtual                     ~IInterface();
    virtual IBinder*            onAsBinder() = 0;
};

2.5 BpInterface 和 BnInterface

(1).BpInterface:它定义在 frameworks/native/include/binder/IInterface.h 中。实际上,BpInterface 是一个模板类,同时继承了 BpRefBase 和 INTERFACE,这里的 INTERFACE 是模板。像 IServiceManager,IMediaPlayerService 等 Server 都是通过继承模板类是实现的,相关的代码如下:

template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase
{
   
   
   
public:
                                BpInterface(const sp<IBinder>& remote);

protected:
    virtual IBinder*            onAsBinder();
};

(2).BnInterface:它定义在 frameworks/native/include/binder/IInterface.h 中。和 BpInterface 类似,BnInterface 也是一个模板类,它同时继承了 BBinder 和 INTERFACE。像 BnServiceManager,BnMediaPlayerService 等本地 Server 都是通过继承模板类是实现的,相关的代码如下:

template<typename INTERFACE>
class BnInterface : public INTERFACE, public BBinder
{
   
   
   
public:
    virtual sp<IInterface>      queryLocalInterface(const String16& _descriptor);
    virtual const String16&     getInterfaceDescriptor() const;

protected:
    virtual IBinder*            onAsBinder();
};

   前面篇幅的章节一和章节二让我们对 Java 层和 C++ 层的 Binder 有关的类有了一个比较清晰的认识,但是还是比较模糊是不,那么可以通过下面的示意图来一个清晰的整体概括,通过该示意图我们应该能大致上了解 Java 和 C++ 层的 Binder 怎么关联起来了。
在这里插入图片描述

3.ProcessState

   它的源码定义在它定义在 frameworks/native/libs/binder/ProcessState.cpp 中。对于开发 Android app 的读者来说,在 Android 上层架构中,谷歌妈咪已经很大幅度地弱化了进程的概念了。应用开发的小伙伴能看到的主要是四大组件的概念了,再也找不到以前熟悉的 main () 函数了。然而,底层程序(C++ 层次)毕竟还是得跑在一个个进程之上,现在我们就来看底层进程是如何运用 Binder 机制来完成跨进程通信的。
   在每个进程中,会有一个全局的 ProcessState 对象。这个很容易理解,ProcessState 的字面意思不就是 “进程状态” 吗,ProcessState 的实例是采用单例模式实现的,我们截选其中的一部分重要的:

class ProcessState : public virtual RefBase
{
   
   
   
public:
    static  sp<ProcessState>    self();
    ...
    void                startThreadPool();
    ...
    void                spawnPooledThread(bool isMain);
    status_t            setThreadPoolMaxThreadCount(size_t maxThreads);

private:
    friend class IPCThreadState;
    ...
    
    struct handle_entry 
    {
   
   
   
        IBinder* binder;
        RefBase::weakref_type* refs;
    };
    handle_entry*       lookupHandleLocked(int32_t handle);
    int                 mDriverFD;
    void*               mVMStart;
    mutable Mutex       mLock;  // protects everything below.
    
    Vector<handle_entry> mHandleToObject;
    ...
    KeyedVector<String16, sp<IBinder> > mContexts;
    ...
};

它拥有两个非常重要的成员:mDriverFD 和 mHandleToObject,我们知道,Binder 内核被设计成一个驱动程序,所以 ProcessState 里专门搞了个 mDriverFD 域,来记录 binder 驱动对应的句柄值,以便随时和 binder 驱动通信。ProcessState 对象采用了典型的单例模式,在一个应用进程中,只会有唯一的一个 ProcessState 对象,它将被进程中的多个线程共用,因此每个进程里的线程其实是共用所打开的那个驱动句柄(mDriverFD)的,示意图如下:
在这里插入图片描述
每个进程基本上都是这样的结构,组合起来的示意图就是:
在这里插入图片描述
而 mHandleToObject 是一个 Vector 矢量数组,它的定义如下:

Vector<handle_entry> mHandleToObject;

矢量数组中的每个元素都保存了两个变量:Server 的句柄,以及 Server 对应的 BpBinder 对象。实际上,Server 的句柄是 "Server 在 Binder 驱动中的 Binder 引用的描述";句柄 0 是 ServiceManager 的句柄。其中的 binder 域,记录的就是 BpBinder 对象。
在这里插入图片描述


4.IPCThreadState

   它定义在 frameworks/native/libs/binder/IPCThreadState.cpp 中中。IPCThreadState 的实例也是采用单例模式实现的,它是正在与 Binder 驱动进行交互的类,和 Binder 内核层的 binder_thread 相对应

class IPCThreadState
{
   
   
   
public:
    static  IPCThreadState*     self();
			...
            sp<ProcessState>    process();
            ...
            void                joinThreadPool(bool isMain = true);
            
            // Stop the local process.
            void                stopProcess(bool immediate = true);
            
            status_t            transact(int32_t handle,
                                         uint32_t code, const Parcel& data,
                                         Parcel* reply, uint32_t flags);
			...
private:
                                IPCThreadState();
                                ~IPCThreadState();

            status_t            sendReply(const Parcel& reply, uint32_t flags);
            status_t            waitForResponse(Parcel *reply,
                                                status_t *acquireResult=NULL);
            status_t            talkWithDriver(bool doReceive=true);
            status_t            writeTransactionData(int32_t cmd,
                                                     uint32_t binderFlags,
                                                     int32_t handle,
                                                     uint32_t code,
                                                     const Parcel& data,
                                                     status_t* statusBuffer);
            status_t            getAndExecuteCommand();
            status_t            executeCommand(int32_t command);
            void                processPendingDerefs();

            void                clearCaller();

    static  void                threadDestructor(void *st);
    static  void                freeBuffer(Parcel* parcel,
                                           const uint8_t* data, size_t dataSize,
                                           const binder_size_t* objects, size_t objectsSize,
                                           void* cookie);
    
    const   sp<ProcessState>    mProcess;
    const   pid_t               mMyThreadId;
	...
};

总结

   理解上面的基本概念之后,我们现在就从整体上对涉及到的 Binder 概念对它们进行一下总结和概括!对于一个 Server 而言,它都会存在一个 "远程 BpBinder 对象" 和 "本地 BBinder 对象"。
(01) 远程 BpBinder 对象的作用:是和 Binder 驱动进行交互。具体的方式是,当 Server 要向 Binder 发起事务请求时,会调用 BpBinder 的 transact () 接口,而该接口会调用到 IPCThreadState::transact () 接口,通过 IPCThreadState 类来和 Binder 驱动交互。此外,该 BpBinder 在 Binder 驱动中的 Binder 引用的描述会被保存到 ProcessState 的 mHandleToObject 矢量缓冲数组中。
(02) 本地 BBinder 对象的作用: 是 Server 响应 Client 请求的类。当 Client 有请求发送给 Server 时,都会调用到 BBinder 的 onTransact () 函数,而每个 Server 都会覆盖 onTransact () 函数。这样,每个 Server 就可以在 onTransact () 中根据自己的情况对请求进行处理。

本文同步分享在 博客 “IT 先森”(CSDN)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与 “OSC 源创计划”,欢迎正在阅读的你也加入,一起分享。

关于源码解析----aidl Binder框架binder源码分析的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于Android : 跟我学Binder --- (2) AIDL分析及手动实现、Android aidl Binder 框架浅析、Android aidl Binder框架浅析、Android Binder 框架实现之 Binder 相关的接口和类等相关知识的信息别忘了在本站进行查找喔。

本文标签: