Android系统-进程-Binder3-Binder机制与实现

本文详细介绍了Android中的AIDL接口和Binder机制,包括从客户端到服务端的通信过程,涉及创建Binder对象、注册、请求处理和数据返回等步骤。重点展示了AIDL接口的实现和客户端与服务端如何通过Proxy与Stub交互。
摘要由CSDN通过智能技术生成

目录

引言:

AIDL的通信实现流程

AIDL接口:

从客户端到服务端通信过程:

客户端

服务端

小结


引言:

了解一下binder机制,通过AIDL的实现过程来加深对binder机制以及binder的理解。

Binder机制的实现过程如下:
1. 创建一个Binder对象:在服务端进程中,我们首先需要创建一个Binder对象,该对象继承自IBinder接口,用于向客户端进程提供服务。
2. 注册Binder对象:在服务端进程中,我们需要将Binder对象注册到系统服务管理器中,以便客户端进程可以访问该服务。
3. 获取Binder对象:在客户端进程中,我们需要获取服务端进程中注册的Binder对象,以便可以向其发送请求。
4. 发送请求:在客户端进程中,我们可以向服务端进程发送请求,请求数据或者调用服务。
5. 处理请求:在服务端进程中,我们需要处理来自客户端进程的请求,并返回相应的数据或者执行相应的服务。
6. 返回数据:在服务端进程中,我们需要将处理结果返回给客户端进程。
7. 接收数据:在客户端进程中,我们需要接收来自服务端进程的数据,并进行相应的处理。

Binder机制是Android系统中一种重要的进程间通信方式,其实现过程包括
服务端:创建Binder对象、注册Binder对象、处理请求、返回数据
客户端:获取Binder对象、发送请求和接收数据等步骤

AIDL的通信实现流程

AIDL接口:

interface IFile {
     Bitmap getBitmap(String path);
}

然后build过后,系统会自动生成一个IFile.java文件

public interface IFile extends android.os.IInterface {
    /**
     *继承binder,实现IFile接口,运行于服务端
     */
    public static abstract class Stub extends android.os.Binder implements com.android.hdemo.IFile {
        private static final java.lang.String DESCRIPTOR = "com.android.hdemo.IFile";

        /**
         * Construct the stub at attach it to the interface.
         */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an com.android.hdemo.IFile interface,
         * generating a proxy if needed.
         */
        public static com.android.hdemo.IFile asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.android.hdemo.IFile))) {
                return ((com.android.hdemo.IFile) iin);
            }
            return new com.android.hdemo.IFile.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_getBitmap: {
                    data.enforceInterface(DESCRIPTOR);
                    java.lang.String _arg0;
                    _arg0 = data.readString();
                    android.graphics.Bitmap _result = this.getBitmap(_arg0);
                    reply.writeNoException();
                    if ((_result != null)) {
                        reply.writeInt(1);
                        _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
                    } else {
                        reply.writeInt(0);
                    }
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }

        //实现IFile接口,运行于客户端
        private static class Proxy implements com.android.hdemo.IFile {
            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 android.graphics.Bitmap getBitmap(java.lang.String path) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                android.graphics.Bitmap _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeString(path);
                    mRemote.transact(Stub.TRANSACTION_getBitmap, _data, _reply, 0);
                    _reply.readException();
                    if ((0 != _reply.readInt())) {
                        _result = android.graphics.Bitmap.CREATOR.createFromParcel(_reply);
                    } else {
                        _result = null;
                    }
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }

        static final int TRANSACTION_getBitmap = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    }

    public android.graphics.Bitmap getBitmap(java.lang.String path) throws android.os.RemoteException;
}

IFile是一个接口,继承了android.os.IInterface,并加入了我们自定义的接口方法getBitmap

IFile中包含一个静态抽象类Stub,Stub又包含一个静态内部类Proxy

Stub继承binder,实现IFile接口,运行于服务端

Proxy实现IFile接口,运行于客户端

接着我们来看一下从客户端到服务端的整个流程:

从客户端到服务端通信过程:

客户端

获取Binder对象、发送请求和接收数据

Intent intent = new Intent(this,TestService.class);
this.bindService(intent, new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        try {
            IFile iFile = IFile.Stub.asInterface(service);
            iFile.getBitmap("");
        }catch (Exception e){
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
    }
}, Service.BIND_AUTO_CREATE);

asInterface是系统生成的代码,从注释1处可以看出,如果客户端和服务端在同一个进程,则直接将binder强转成本地接口对象,否则返回Proxy对象。如注释2所示,Proxy的getFile方法会调用mRemote.transact方法,mRemote是一个binder对象,其真正的实现是BinderProxy。

public static com.android.hdemo.IFile asInterface(android.os.IBinder obj) {
    if ((obj == null)) {
        return null;
    }
    //1.如果客户端和服务端在同一个进程,则直接调用,否则使用Proxy
    android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
    if (((iin != null) && (iin instanceof com.android.hdemo.IFile))) {
        return ((com.android.hdemo.IFile) iin);
    }
    return new com.android.hdemo.IFile.Stub.Proxy(obj);
}

//Proxy
private static class Proxy implements com.android.hdemo.IFile {
    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 android.graphics.Bitmap getBitmap(java.lang.String path) throws android.os.RemoteException {
        android.os.Parcel _data = android.os.Parcel.obtain();
        android.os.Parcel _reply = android.os.Parcel.obtain();
        android.graphics.Bitmap _result;
        try {
            _data.writeInterfaceToken(DESCRIPTOR);
            _data.writeString(path);
            //2.调用binder的transact方法
            mRemote.transact(Stub.TRANSACTION_getBitmap, _data, _reply, 0);
            _reply.readException();
            if ((0 != _reply.readInt())) {
                _result = android.graphics.Bitmap.CREATOR.createFromParcel(_reply);
            } else {
                _result = null;
            }
        } finally {
            _reply.recycle();
            _data.recycle();
        }
        return _result;
    }
}

BinderProxy的transact方法会调用transactNative方法,最终会调用native层的BpBinder的transact方法,然后由BpBinder和binder驱动进行交互。

//BinderProxy
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
    ......
    try {
        return transactNative(code, data, reply, flags);
    } finally {
        ......
    }
}

//Native层BpBinder
status_t BpBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    // Once a binder has died, it will never come back to life.
    if (mAlive) {
        bool privateVendor = flags & FLAG_PRIVATE_VENDOR;
        // don't send userspace flags to the kernel
        flags = flags & ~FLAG_PRIVATE_VENDOR;

        // user transactions require a given stability level
        if (code >= FIRST_CALL_TRANSACTION && code <= LAST_CALL_TRANSACTION) {
            using android::internal::Stability;

            auto stability = Stability::get(this);
            auto required = privateVendor ? Stability::VENDOR : Stability::kLocalStability;

            if (CC_UNLIKELY(!Stability::check(stability, required))) {
                ALOGE("Cannot do a user transaction on a %s binder in a %s context.",
                    Stability::stabilityString(stability).c_str(),
                    Stability::stabilityString(required).c_str());
                return BAD_TYPE;
            }
        }

        status_t status = IPCThreadState::self()->transact(
            mHandle, code, data, reply, flags);
        if (status == DEAD_OBJECT) mAlive = 0;

        return status;
    }

    return DEAD_OBJECT;
}

服务端

创建Binder对象、注册Binder对象、处理请求、返回数据

binder驱动收到请求之后会调用native层BBinder的onTransact方法

status_t BBinder::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t /*flags*/)
{
    switch (code) {
        case INTERFACE_TRANSACTION:
            reply->writeString16(getInterfaceDescriptor());
            return NO_ERROR;

        case DUMP_TRANSACTION: {
            int fd = data.readFileDescriptor();
            int argc = data.readInt32();
            Vector<String16> args;
            for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
               args.add(data.readString16());
            }
            return dump(fd, args);
        }

        case SHELL_COMMAND_TRANSACTION: {
            int in = data.readFileDescriptor();
            int out = data.readFileDescriptor();
            int err = data.readFileDescriptor();
            int argc = data.readInt32();
            Vector<String16> args;
            for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
               args.add(data.readString16());
            }
            sp<IShellCallback> shellCallback = IShellCallback::asInterface(
                    data.readStrongBinder());
            sp<IResultReceiver> resultReceiver = IResultReceiver::asInterface(
                    data.readStrongBinder());

            // XXX can't add virtuals until binaries are updated.
            //return shellCommand(in, out, err, args, resultReceiver);
            (void)in;
            (void)out;
            (void)err;

            if (resultReceiver != nullptr) {
                resultReceiver->send(INVALID_OPERATION);
            }

            return NO_ERROR;
        }

        case SYSPROPS_TRANSACTION: {
            report_sysprop_change();
            return NO_ERROR;
        }

        default:
            return UNKNOWN_TRANSACTION;
    }
}

接着会回掉到java层的onTransact方法,如下注释1所示,this.getBitmap(_arg0)为Stub类的方法,从服务端获取到图片,然后在注释2处,将bitmap写入到返回值。

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_getBitmap: {
            data.enforceInterface(DESCRIPTOR);
            java.lang.String _arg0;
            _arg0 = data.readString();
            //1.服务端获取的bitmap
            android.graphics.Bitmap _result = this.getBitmap(_arg0);
            reply.writeNoException();
            if ((_result != null)) {
                reply.writeInt(1);
                //2.将bitmap写入返回值
                _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
            } else {
                reply.writeInt(0);
            }
            return true;
        }
    }
    return super.onTransact(code, data, reply, flags);
}

我们再来看下service的定义,当绑定到一个service之后,返回的Stub对象,实现了getBitmap方法,返回了本地的bitmap。

public class TestService extends Service {

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new IFile.Stub() {
            @Override
            public Bitmap getBitmap(String path) throws RemoteException {
                //1.返回本地bitmap
                return mBitmap;
            }
        };
    }
}

这样从客户端到服务端的流程就走完了,我们看下它的流程图

小结

binder通信分为客户端和服务端,在整个实现框架中,Stub是服务端的实现,有个内部类Proxy,客户端通过Proxy对象来发起对服务端的通信。

服务端创建binder对象,注册binder对象,提供服务。客户端就是获取binder Proxy对象,调用BinderProxy的transact方法调用到native层的BpBinder,由BpBinder与binder驱动进行交互。binder驱动接到请求后,会调用服务端的native的BBinder的onTransact方法,回调到java层,然后回调到了服务端注册的Binder对象,Stub就是Binder的本地实现。由Stub对象来处理请求,并返回结果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值