Android binder学习笔记(一)AIDL流程分析

引言

IPC,全称Inter-Process Communication,含义为进程间通信或者跨进程通信,是指两个进程之间进行数据交换的过程。
实现IPC的方法有Socket,Binder,管道等,这篇文章主要介绍Binder,通过AIDL的使用来展开分析。

有关Binder的技术文章,推荐看看下面这篇:
Android中Binder学习

AIDL

定义一个简单的AIDL接口:


interface IBinderListener {
    void update(in String str);
}

编译后,会在app/build/generated/source/aidl下生成一个IBinderListener.java的类

/**
 * {@hide}
 */
public interface IBinderListener extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.test.bindercserver.IBinderListener
{
private static final java.lang.String DESCRIPTOR = "com.test.bindercserver.IBinderListener";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
 * Cast an IBinder object into an com.test.bindercserver.IBinderListener interface,
 * generating a proxy if needed.
 */
public static com.test.bindercserver.IBinderListener asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.test.bindercserver.IBinderListener))) {
return ((com.test.bindercserver.IBinderListener)iin);
}
return new com.test.bindercserver.IBinderListener.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_update:
{
data.enforceInterface(descriptor);
java.lang.String _arg0;
_arg0 = data.readString();
this.update(_arg0);
reply.writeNoException();
return true;
}
default:
{
return super.onTransact(code, data, reply, flags);
}
}
}
private static class Proxy implements com.test.bindercserver.IBinderListener
{
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 void update(java.lang.String str) 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.writeString(str);
mRemote.transact(Stub.TRANSACTION_update, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_update = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
public void update(java.lang.String str) throws android.os.RemoteException;
}

Android studio会帮我们生成这个文件,使用的时候只需要继承IBinderListener.Stub这个抽象类,在Service的onBinder()方法里面返回它,就实现了AIDL。

AIDL过程分析

主要分析一下aidl的实现过程,不依赖Android studio的编译自动生成,而是自己手动敲出接口的java文件。

首先定义接口文件

import android.os.IBinder;
import android.os.IInterface;

public interface IJustKidding extends IInterface{
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    public int add(int a, int b) throws android.os.RemoteException;
    public int sub(int a, int b) throws android.os.RemoteException;

    static final int TRANSACTION_add = IBinder.FIRST_CALL_TRANSACTION;
    static final int TRANSACTION_sub = IBinder.FIRST_CALL_TRANSACTION + 1;

    static final String DESCRIPTOR = "com.test.BinderTest.IJustKidding";
}

add(int a, int b)和sub(int a, int b)是IJustKidding接口里面的两个方法,TRANSACTION_add 和TRANSACTION_sub 分别代表两个方法在接口文件中的排列顺序,DESCRIPTOR 作为接口的描述符。

接下来敲aidl的实现过程

import android.os.Binder;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;

public abstract class JustKiddingNative extends Binder implements IJustKidding {
	//JustKiddingNative相当于IJustKidding.Stub
    public JustKiddingNative(){
        this.attachInterface(this, IJustKidding.DESCRIPTOR);
    }

    public static IJustKidding asInterface(IBinder obj){
        if (obj == null){
            return null;
        }
		//通过接口标识符DESCRIPTOR到本地查找
        IInterface iInterface = obj.queryLocalInterface(IJustKidding.DESCRIPTOR);
        if (iInterface != null && iInterface instanceof IJustKidding){
            Log.d("***", "same process");
            //相同进程,直接返回
            return (IJustKidding) iInterface;
        }
        Log.d("***", "different process");
        //不同进程,返回代理类IJustKiddingProxy
        return new IJustKiddingProxy(obj);
    }
	//来自接口IJustKidding类的父类IInterface
    @Override
    public IBinder asBinder(){
        return this;
    }
	//onTransact()方法运行在服务端
    @Override
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        Log.d("***", "Stub --> onTransact()");
        int arg0;
        int arg1;
        int result;

        switch (code){
            case INTERFACE_TRANSACTION:
                reply.writeString(IJustKidding.DESCRIPTOR);
                return true;
            case TRANSACTION_add:
                Log.d("***", "Stub --> onTransact() TRANSACTION_add");
                data.enforceInterface(IJustKidding.DESCRIPTOR);
                arg0 = data.readInt();
                arg1 = data.readInt();
                result = this.add(arg0, arg1);
                Log.d("***", "Stub --> onTransact() TRANSACTION_add result = " + result);
                reply.writeNoException();
                reply.writeInt(result);
                return true;
            case TRANSACTION_sub:
                Log.d("***", "Stub --> onTransact() TRANSACTION_sub");
                data.enforceInterface(IJustKidding.DESCRIPTOR);
                arg0 = data.readInt();
                arg1 = data.readInt();
                result = this.sub(arg0, arg1);
                Log.d("***", "Stub --> onTransact() TRANSACTION_sub result = " + result);
                reply.writeNoException();
                reply.writeInt(result);
                return true;
        }
        return super.onTransact(code, data, reply, flags);
    }
}
//IJustKidding的代理类,实现了IJustKidding接口
class IJustKiddingProxy implements IJustKidding{
    private IBinder mRemote;

    IJustKiddingProxy(IBinder iBinder){
        mRemote = iBinder;
    }
	//来自接口IJustKidding类的父类IInterface
    @Override
    public IBinder asBinder() {
        return mRemote;
    }
	//接口描述符
    public String getInterfaceDescriptor() {
        return IJustKidding.DESCRIPTOR;
    }

    @Override
    public int add(int a, int b) throws RemoteException {
        Log.d("***", "Proxy --> add()");
        Parcel _data = Parcel.obtain();
        Parcel _reply = Parcel.obtain();
        int _result;
        try {
            _data.writeInterfaceToken(IJustKidding.DESCRIPTOR);
            Log.d("***", "Proxy --> add() --> writeInt()");
            _data.writeInt(a);
            _data.writeInt(b);
            Log.d("***", "Proxy --> add() --> mRemote.transact()");
            mRemote.transact(TRANSACTION_add, _data, _reply, 0);

            Log.d("***", "Proxy --> add() --> _reply.readException()");
            _reply.readException();
            _result = _reply.readInt();
        } finally {
            _reply.recycle();
            _data.recycle();
        }
        Log.d("***", "Proxy --> add() --> _result = " + _result);
        return _result;
    }

    @Override
    public int sub(int a, int b) throws RemoteException {
        Log.d("***", "Proxy --> sub()");
        Parcel _data = Parcel.obtain();
        Parcel _reply = Parcel.obtain();
        int _result;
        try {
            _data.writeInterfaceToken(IJustKidding.DESCRIPTOR);
            Log.d("***", "Proxy --> sub() --> writeInt()");
            _data.writeInt(a);
            _data.writeInt(b);
            Log.d("***", "Proxy --> sub() --> mRemote.transact()");
            mRemote.transact(TRANSACTION_sub, _data, _reply, 0);

            Log.d("***", "Proxy --> sub() --> _reply.readException()");
            _reply.readException();
            _result = _reply.readInt();
        } finally {
            _reply.recycle();
            _data.recycle();
        }
        Log.d("***", "Proxy --> sub() --> _result = " + _result);
        return _result;
    }
}

服务端口的代码就更简单了:

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

public class JustKiddingService extends Service {
    public JustKiddingService() {}

    //JustKiddingNative相当于IJustKidding.Stub
    private final JustKiddingNative mBinder = new JustKiddingNative() {

        @Override
        public int add(int a, int b) throws RemoteException {
            Log.d("***", "JustKiddingService IJustKiddingInterface.Stub --> add()");
            return a + b;
        }

        @Override
        public int sub(int a, int b) throws RemoteException {
            Log.d("***", "JustKiddingService IJustKiddingInterface.Stub --> sub()");
            return a - b;
        }
    };

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        Log.d("***", "JustKiddingService --> onBind()");
        return mBinder;
    }
}

客户端重点部分的代码:

private IBinder mPlusBinder;
private IJustKidding iJustKidding;

private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            Log.d("***", "onServiceConnected() componentName = " + componentName
                    + " iBinder = " + iBinder);
            mPlusBinder = iBinder;
            try {
                iBinder.linkToDeath(deathRecipient, 0);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Log.d("***", "onServiceDisconnected() componentName = " + componentName);
            mPlusBinder = null;
            iJustKidding = null;
        }
    };

	IBinder.DeathRecipient deathRecipient = new IBinder.DeathRecipient() {
        @Override
        public void binderDied() {
            if (iJustKidding == null){
                return;
            }
            iJustKidding.asBinder().unlinkToDeath(deathRecipient, 0);
            iJustKidding = null;
            bindService();
        }
    };

	public void bindService(){
        Intent intent = new Intent(this, JustKiddingService.class);
        bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
    }

				//客户端调用add()和sub()方法
				if (mPlusBinder != null){
                    try {
                        iJustKidding = JustKiddingNative.asInterface(mPlusBinder);
                        if (iJustKidding != null) {
                            int add = iJustKidding.add(2, 1);
                            int sub = iJustKidding.sub(2, 1);
                            Log.d("***", "add = " + add + "  sub = " + sub);
                        }
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }

调用bindService()后,会在ServiceConnection对象的onServiceConnected()方法中回调,返回IBInder对象,可以理解为IJustKidding接口的句柄,是由驱动返回的。
然后调用JustKiddingNative.asInterface(mPlusBinder)方法(这里的JustKiddingNative相当于IJustKidding.Stub),将IBInder句柄转换为本地对象或代理对象。

    public static IJustKidding asInterface(IBinder obj){
        if (obj == null){
            return null;
        }

        IInterface iInterface = obj.queryLocalInterface(IJustKidding.DESCRIPTOR);
        if (iInterface != null && iInterface instanceof IJustKidding){
            Log.d("***", "same process");
            return (IJustKidding) iInterface;
        }
        Log.d("***", "different process");
        return new IJustKiddingProxy(obj);
    }

根据IBinder的obj对象,现在本地查找,如果能找到,就强制转换为IJustKidding对象,然后返回;如果不能找到,就返回接口的代理对象IJustKiddingProxy,传参obj。

分别设置JustKiddingService服务为相同进程和不同进程,抓取日志,分析流程。
设置不同进程,只需要在标签中增加android:process=":remote"属性值,进程名remote可以自己取。

不同进程:

2021-07-12 09:38:04.846 31620-31620/com.Test D/djw: BinderTestActivity --> bindService()
2021-07-12 09:38:05.162 31724-31724/? D/djw: JustKiddingService --> onBind()
2021-07-12 09:38:05.165 31620-31620/com.Test D/djw: onServiceConnected() componentName = ComponentInfo{com.Test/com.test.BinderTest.JustKiddingService} iBinder = android.os.BinderProxy@a208bfb
2021-07-12 09:39:10.403 31620-31620/com.Test D/djw: different process
2021-07-12 09:39:10.404 31620-31620/com.Test D/djw: Proxy --> add()
2021-07-12 09:39:10.404 31620-31620/com.Test D/djw: Proxy --> add() --> writeInt()
2021-07-12 09:39:10.404 31620-31620/com.Test D/djw: Proxy --> add() --> mRemote.transact()
2021-07-12 09:39:10.405 31724-31737/com.Test:remote D/djw: Stub --> onTransact()
2021-07-12 09:39:10.405 31724-31737/com.Test:remote D/djw: Stub --> onTransact() TRANSACTION_add
2021-07-12 09:39:10.405 31724-31737/com.Test:remote D/djw: JustKiddingService IJustKiddingInterface.Stub --> add()
2021-07-12 09:39:10.405 31724-31737/com.Test:remote D/djw: Stub --> onTransact() TRANSACTION_add result = 3
2021-07-12 09:39:10.406 31620-31620/com.Test D/djw: Proxy --> add() --> _reply.readException()
2021-07-12 09:39:10.406 31620-31620/com.Test D/djw: Proxy --> add() --> _result = 3


2021-07-12 09:39:10.406 31620-31620/com.Test D/djw: Proxy --> sub()
2021-07-12 09:39:10.406 31620-31620/com.Test D/djw: Proxy --> sub() --> writeInt()
2021-07-12 09:39:10.406 31620-31620/com.Test D/djw: Proxy --> sub() --> mRemote.transact()
2021-07-12 09:39:10.406 31724-31737/com.Test:remote D/djw: Stub --> onTransact()
2021-07-12 09:39:10.406 31724-31737/com.Test:remote D/djw: Stub --> onTransact() TRANSACTION_sub
2021-07-12 09:39:10.407 31724-31737/com.Test:remote D/djw: JustKiddingService IJustKiddingInterface.Stub --> sub()
2021-07-12 09:39:10.407 31724-31737/com.Test:remote D/djw: Stub --> onTransact() TRANSACTION_sub result = 1
2021-07-12 09:39:10.407 31620-31620/com.Test D/djw: Proxy --> sub() --> _reply.readException()
2021-07-12 09:39:10.408 31620-31620/com.Test D/djw: Proxy --> sub() --> _result = 1
2021-07-12 09:39:10.408 31620-31620/com.Test D/djw: add = 3  sub = 1

日志第一行和第二行,可以知道调用方和JustKiddingService不在同一进程,第五行的日志different process也能说明它们不在同一进程;
调用binderServer()之后,JustKiddingService服务的onBind()会被调用,返回接口的IBinder对象。

调用JustKiddingNative.asInterface(mPlusBinder)时,返回的是IJustKiddingProxy代理对象,add()里面_data写入接口描述符和参数数据,再调用mRemote.transact(TRANSACTION_add, _data, _reply, 0)方法,mRemote是驱动返回的IBInder句柄。

_data数据被Parcel序列化之后,经过Native、驱动,进入内核态,挂起等待返回。驱动完成一系列操作之后,唤醒Server进程,调用Server进程本地对象的onTransact方法(onTransact()方法运行在Server端),然后根据方法在接口中的顺序标识符识别到相应的方法,鉴别接口描述符,取出对应参数进行计算,调用到JustKiddingService里面JustKiddingNative实例对象的add()方法,计算完成返回结果,由replyParcel序列化后,返回结果到调用端,这样就完成了一次跨进程调用。

这里涉及到Binder驱动的流程,没有展开来讲解,有兴趣的可以看看文章开头提到的技术文章。

同一进程

2021-07-12 11:52:29.256 3615-3615/com.Test D/djw: BinderTestActivity --> bindService()
2021-07-12 11:52:29.279 3615-3615/com.Test D/djw: JustKiddingService --> onBind()
2021-07-12 11:52:29.359 3615-3615/com.Test D/djw: onServiceConnected() componentName = ComponentInfo{com.Test/com.test.BinderTest.JustKiddingService} iBinder = com.szzt.test.BinderTest.JustKiddingService$1@6b50a0b
2021-07-12 11:52:32.437 3615-3615/com.Test D/djw: same process
2021-07-12 11:52:32.438 3615-3615/com.Test D/djw: JustKiddingService IJustKiddingInterface.Stub --> add()
2021-07-12 11:52:32.438 3615-3615/com.Test D/djw: JustKiddingService IJustKiddingInterface.Stub --> sub()
2021-07-12 11:52:32.438 3615-3615/com.Test D/djw: add = 3  sub = 1

相同进程的情况下,直接调用到JustKiddingService里面JustKiddingNative实例对象的add()方法。

至此,aidl调用流程分析完成。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android BinderAndroid操作系统中的一个IPC(进程间通信)机制,用于实现进程之间的通信和数据传输。Binder的源码主要位于frameworks/native目录下。 在Binder的源码中,最核心的部分是Binder驱动和Binder服务。Binder驱动是位于内核空间的组件,负责处理进程间的数据传输和交互。Binder服务是位于用户空间的组件,负责提供接口和功能来进行进程间通信。 在Binder的源码中,主要涉及到以下几个重要的文件和目录: 1. drivers目录:包含了Binder驱动的代码,其中最重要的文件是binder.c,它实现Binder驱动的核心逻辑。 2. include目录:包含了Binder的头文件,其中最重要的文件是binder.h,它定义了Binder的接口和数据结构。 3. libbinder目录:包含了Binder服务的代码,其中最重要的文件是IBinder.cpp和BpBinder.cpp,它们分别实现Binder服务的接口和代理类。 4. services目录:包含了一些系统级别的Binder服务,例如Package Manager Service和Activity Manager Service。 如果你想深入了解Android Binder的源码,可以参考以下资源: 1. Android 源码:你可以从Android官网或者GitHub上获取Android源码,并在frameworks/native目录下查看Binder相关的代码。 2. Android系统架构指南:Android官网提供了关于Android系统架构的详细文档,其中有关IPC和Binder的章节对于理解Binder实现原理和源码结构很有帮助。 3. 《深入理解Android:卷2》一书中有关于Binder的详细介绍和源码解析,可以作为参考资料。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值