Android binder介绍(下)

Posted 北落不吉

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android binder介绍(下)相关的知识,希望对你有一定的参考价值。

上一篇: <Android binder介绍(上)>

5. Java Binder

android中也实现了Java层的binder接口

主要代码如下

/framework/base/core/java/android/os/
    - IInterface.java
    - IBinder.java
    - Parcel.java
    - IServiceManager.java
    - ServiceManager.java
    - ServiceManagerNative.java
    - Binder.java

/framework/base/core/jni/
    - android_os_Parcel.cpp
    - AndroidRuntime.cpp
    - android_util_Binder.cpp

5.1 基础类

/*
 * package android.os;
 * 
 */
IInterface         - Binder接口基类
IBinder            - 远程对象接口基类
IServiceManager    - ServiceManager代理接口, 继承自IInterface

Binder             - 本地Binder, 继承自IBinder, 对应native层的BnBinder
BinderProxy        - 远程Binder, 继承自IBinder, 对应native层的BpBinder

class_ServiceManager

5.2 ServiceManager

ServiceManager类是servicemanager在Jave层代理, 对应native层的IServiceManager

public final class ServiceManager {
    private static IServiceManager getIServiceManager() {
    }

    public static IBinder getService(String name) {
    }

    public static void addService(String name, IBinder service) {
    }

    public static IBinder checkService(String name) {
    }

    public static String[] listServices() {
    }

    public static void initServiceCache(Map<String, IBinder> cache) {
    }
}

ServiceManager::getIServiceManager()
    /*
     * 实际是Binder.allowBlocking(BinderInternal.getContextObject())
     * 获取ServiceManagerProxy(BinderProxy)
     */
    IBinder binder = BinderInternal.getContextObject()
        // JNI method in android_util_Binder.cpp
        android_os_BinderInternal_getContextObject()
            // Get a native BpBinder
            ProcessState::self()
                new ProcessState("/dev/binder")
                    open_driver("/dev/binder")
                    mmap()
            ProcessState::getContextObject(NULL)
                getStrongProxyForHandle(0)
                    BpBinder::create(NULL)
                        new BpBinder(NULL, uid)
            // Transform the native BpBinder to BinderProxy
            javaObjectForIBinder(, new BpBinder())
    /*
     * 将Binder对象转化为IServiceManager对象
     */
    ServiceManagerNative.asInterface(binder)
        // 这里似乎没有使用
        binder.queryLocalInterface("android.os.IServiceManager")
        // 这是实际的返回值
        new ServiceManagerProxy(binder)

ServiceManager::getService(name)
    ServiceManager::rawGetService(name)
        ServiceManager::getIServiceManager().getService(name)
            ServiceManagerProxy::getService(name)
            BinderProxy::transact(GET_SERVICE_TRANSACTION, , , )
            // JNI method in android_util_Binder.cpp
            android_os_BinderProxy_transact(GET_SERVICE_TRANSACTION)
                BpBinder::transact(GET_SERVICE_TRANSACTION)
                IPCThreadState::transact(GET_SERVICE_TRANSACTION)
                    IPCThreadState::waitForResponse()
                        IPCThreadState::talkWithDriver()
                            ioctl(binder_fd, BINDER_WRITE_READ, )

ServiceManager::addService(name, )
    ServiceManager::getIServiceManager().addService(name, )
        ServiceManagerProxy::addService(name, )
            BinderProxy::transact(ADD_SERVICE_TRANSACTION, , , )
            ...

5.3 实例

这里介绍以下在Java framework层实现server和client的方法,以IFixMe为例

接口实现

// IFixMe.java
package com.test.binder;

import android.os.IInterface;
import android.os.RemoteException;

public interface IFixMe extends android.os.IInterface {
    static final int TRANSACTION_FUNC = android.os.IBinder.FIRST_CALL_TRANSACTION;
    static final java.lang.String DESCRIPTOR = "com.test.binder.IFixMe";
    public void func(String str) throws RemoteException ;
}

Server实现

// FixMe.java
package com.test.binder;

import android.os.Binder;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;

public class FixMe extends android.os.Binder implements IFixMe{ 
    public FixMe() {
        this.attachInterface(this, DESCRIPTOR);
    }

    @Override
    public IBinder asBinder() {
        return this;
    }

    public static com.test.binder.IFixMe asInterface(android.os.IBinder obj) {
        if ((obj == null)) {
            return null;
        }
        android.os.IInterface iInterface = obj.queryLocalInterface(DESCRIPTOR);
        if (((iInterface != null) && (iInterface instanceof com.test.binder.IFixMe))) {
            return ((com.test.binder.IFixMe)iInterface);
        }
        return null;
    }

    @Override
    protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
        switch (code) {
        case INTERFACE_TRANSACTION: {
            reply.writeString(DESCRIPTOR);
            return true;
        }
        case TRANSACTION_FUNC: {
            data.enforceInterface(DESCRIPTOR);
            String str = data.readString();
            func1(str);
            reply.writeNoException();
            return true;
        }
        }
        return super.onTransact(code, data, reply, flags);
    }

    @Override
    public void func(String str) {
        // Do something...
    }
}

Proxy实现

// FixMeProxy.java
package com.test.binder;

import android.os.IBinder;
import android.os.RemoteException;

public class FixMeProxy implements IFixMe {
    private android.os.IBinder mRemote;

    public FixMeProxy(android.os.IBinder remote) {
        mRemote = remote;
    }

    public java.lang.String getInterfaceDescriptor() {
        return DESCRIPTOR;
    }

    @Override
    public void func(String str) throws 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(TRANSACTION_FUNC, _data, _reply, 0);
            _reply.readException();
        } finally {
            _reply.recycle();
            _data.recycle();
        }
    }

    @Override
    public IBinder asBinder() {
        return mRemote;
    }
}

测试程序

package com.test.binder;

import android.os.Looper;
import android.os.ServiceManager;
import android.os.RemoteException;

// server test demo
public class ServerDemo {
    public static void main(String[] args) {
        Looper.prepareMainLooper();
        android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_FOREGROUND);
        ServiceManager.addService("FixMe", newFixMe());
        Looper.loop();
    }
}

// client test demo
public class ClientDemo {
    public static void main(String[] args) throws RemoteException {
        IBinder binder = ServiceManager.getService("FixMe");
        IFixMe myService = newFixMeProxy(binder);
        myService.func("binder");
    }
}

其他实例可参考 <BinderSample>

6. AIDL

从前面看出编写一个Java/C++层面的binder通信比较复杂,在Android中为了简化这种操作提出了AIDL的概念,简单来说就是按照一定的规则编写AIDL接口让编译器来自动生成Proxy和Server端相关代码

下面分别介绍一下Java和C++使用AIDL的实例

6.1 Java AIDL

在Android中使用AIDL有两种方式,一种是注册为系统服务(多在framework中使用),另一种是普通服务方式(在应用中使用);但是不管是哪种,AIDL接口定义是保持一致的。

6.1.1 AIDL接口

// IFixMe.aidl
package com.test.binder;

interface IFixMe {
    int func(String msg);
}

可以使用android build-tools中的aidl工具将其转化为java代码

$ aidl.exe com/test/binder/IFixMe.aidl

// IFixMe.java内容如下
interface IFixMe
    func()
    // Server端
    class Stub
        asInterface
        asBinder
        onTransact
    // Proxy端
    class Proxy
        asBinder
        getInterfaceDescriptor
        func

6.1.2 系统服务方式

Server实现

import com.test.binder;

public class FixMeService extends IFixMe.Stub {
    @Override
    public int func() throws android.os.RemoteException {
        // Do something
        return 0;
    }
}

测试程序

package com.test.binder;

import android.os.Looper;
import android.os.ServiceManager;
import android.os.RemoteException;

// register server
public class ServerDemo {
    public static void main(String[] args) {
        Looper.prepareMainLooper();
        android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_FOREGROUND);
        ServiceManager.addService("FixMe", new FixMeService());
        Looper.loop();
    }
}

// client use service
public class ClientDemo {
    public static void main(String[] args) throws RemoteException {
        IBinder binder = ServiceManager.getService("FixMe");
        IFixMe myService = IFixMe.Stub.asInterface(binder);
        myService.func("binder");
    }
}

TIP:值得一说的是ServiceManager相关接口只能在framework中使用

6.1.3 普通服务方式

Server实现

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

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_NOT_STICKY;
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
          return mStub;
    }

    IFixMe.Stub mStub = new IFixMe.Stub() {
        @Override
        public int func() {
            // Do something
            return 0;
        }
    };
}

客户端程序

    private IFixMe mFixMe;
 
    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mFixMe = IFixMe.Stub.asInterface(service);
            mFixMe.func();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mFixMe = null;
        }
    };
    
    // --- 本地调用 ---
    Intent intent = new Intent(this, FixMeService.class);
    bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
    
    /* 
     * --- 远程调用 ---
     * 需要在service所有的AndroidManifest.xml
     * 
     * <service android:name=".FixMeService">
     *      <intent-filter>
     *          <action android:name="com.test.intent.fixme"></action>
     *      </intent-filter>
     * </service>
     */
    Intent intent = new Intent();
    intent.setAction("com.test.fixme");
    intent.setPackage("com.test.fixmeclient");
    bindService(intent, mServiceConnection, BIND_AUTO_CREATE);

Java AIDL使用方法参考<AIDLDemo>

6.2 C++ AIDL

AIDL接口

// IFixMe.aidl
package com.test.binder;

interface IFixMe {
    int func(String msg);
}

使用android build-tools中的aidl-cpp工具将其转化为C++代码

$ aidl-cpp com/test/binder/IFixMe.aidl . com/test/binder/FixMe.cpp

在com/test/binder/生成如下文件
IFixMe.h
    class IFixMe : public android::IInterface
        DECLARE_META_INTERFACE(FixMe)
        func()
BnFixMe.h
    class BnFixMe : public android::BnInterface<IFixMe>
        onTransact()
BpFixMe.h
    class BpFixMe : public android::BpInterface<IFixMe>
        func()
FixMe.cpp
    // 实现如下方法
    BnFixMe::onTransact()
    BpFixMe::func()

Server实现

// FixMeService.h
class FixMeService : public os::BnFixMe {
public:
    int func(String msg);
}

// FixMeService.cpp
int FixMeService::func(String msg) {
    // Do something
    return 0;
}

测试程序这里不再累述,值得一说是的native层面封装了BinderService来简化添加服务的操作

可参考NetdNativeService(system/netd)和VoldNativeService(system/vold)

7. HIDL

这里就不详叙了,以后有需要再添加

参考:
<Binder系列>
<Android HIDL>
<AIDL的基本使用>
<HAL接口定义语言(HIDL)>
<Android接口定义语言(AIDL)>

以上是关于Android binder介绍(下)的主要内容,如果未能解决你的问题,请参考以下文章

Android Binder机制介绍

Android Binder 的主要内容概述以及特性和原理

Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析

Android课程---Android Studio使用小技巧:提取方法代码片段

千里马Android Framework实战开发-binder驱动常见binder_open,binder_mmap介绍

千里马Android Framework实战开发-binder驱动常见binder_open,binder_mmap介绍