Binder进程间通信机制的Java接口

概述

Java代码可以通过JNI方法来调用C/C++代码,因此,Android系统在应用程序框架层中提供了Binder进程间通信机制的Java接口,它们通过JNI方法来调用Binder库的C/C++接口,从而提供了执行Binder进程间通信的能力。
主要从以下几个使用场景来分析Binder进程间通信机制的Java接口:

  1. ServiceManager的Java代理对象的获取过程。
  2. Java服务接口的定义和解析。
  3. Java服务的启动过程。
  4. Java服务代理对象的获取过程。
  5. Java服务的调用过程。

为了方便描述,在Java层中,我们将Service组件成为Java服务;相应的,将Service组建的代理对象称为Java服务代理对象。

Service Manager的Java代理对象获取过程

在Java层中,Service Manager的Java代理对象类型为ServiceManagerProxy,它实现了IServiceManager接口,如下图所示:

Java服务接口的定义和解析

在实现自己的Java服务之前,首先要定义这个Java服务要实现的接口,即定义自己的Java服务接口。在Android应用程序中,我们可以通过Android接口描述语言(Android Interface Definition Language, AIDL)来定义Java服务接口。AIDL是一种Binder进程间通信接口的描述语言,通过它来定义的Java服务接口具有执行Binder进程间通信的能力。
以AIDL定义的Java服务接口保存在一个以”.aidl”为后缀名的文件中,在编译时,它们会被转化为使用Java语言描述的Java服务接口。这里,我以一个音乐播放器的例子,来介绍一下Java服务的实现。
音乐播放器服务接口IRemoteService定义在文件IRemoteService.aidl中,文件内容如下所示:

package com.example.photocrop.service;

public interface IRemoteService extends android.os.IInterface {
    /** Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements com.example.photocrop.service.IRemoteService {
        private static final java.lang.String DESCRIPTOR = "com.example.photocrop.service.IRemoteService";

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

        /** * Cast an IBinder object into an * com.example.photocrop.service.IRemoteService interface, generating a * proxy if needed. */
        public static com.example.photocrop.service.IRemoteService asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.example.photocrop.service.IRemoteService))) {
                return ((com.example.photocrop.service.IRemoteService) iin);
            }
            return new com.example.photocrop.service.IRemoteService.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_play: {
                data.enforceInterface(DESCRIPTOR);
                this.play();
                reply.writeNoException();
                return true;
            }
            case TRANSACTION_stop: {
                data.enforceInterface(DESCRIPTOR);
                this.stop();
                reply.writeNoException();
                return true;
            }
            }
            return super.onTransact(code, data, reply, flags);
        }

        private static class Proxy implements com.example.photocrop.service.IRemoteService {
            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 play() 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_play, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

            @Override
            public void stop() 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_stop, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
        }

        static final int TRANSACTION_play = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_stop = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    }

    public void play() throws android.os.RemoteException;

    public void stop() throws android.os.RemoteException;
}

文件定义了一个Java接口IRemoteService,一个Java抽象类IRemoteService.Stub和一个Java类IRemoteService.Stub.Proxy,其中,Java抽象类IRemoteService.Stub是在Java接口IRemoteService内部定义的,而Java类IRemoteService.Stub.Proxy是在Java抽象类IRemoteService.Stub内部定义的。
IRemoteService.Stub和IRemoteService.Stub.Proxy类都实现了IRemoteService接口,其中,IRemoteService.Stub类用来描述一个Java服务,IRemoteService.Stub.Proxy类用来描述一个Java服务代理对象。我们要实现的音乐播放服务PlayerService就是以IRemoteService.Stub为父类的。
IRemoteService.Stub类的静态成员函数asInterface通常用来将一个Java服务代理对象,即一个BinderProxy对象封装成一个IRemoteService.Stub.Proxy对象,即一个实现了IRemoteService接口的Java服务代理对象。
IRemoteService.Stub类的成员函数onTransact是用来接收和分发进程间通信请求的。当Client进程向一个实现了IRemoteService接口的Java服务发送一个类型为TRANSACTION_setVal或者TRANSACTION_getVal的进程间通信请求时,IRemoteService.Stub类的成员函数onTransact就会被调用,它分别将这两种类型的进程间通信请求分发给由其子类所重写的两个成员函数setVal和getVal来处理。
IRemoteService.Stub.Proxy类内部有一个成员变量mRemote,它指向的是一个Java服务代理对象,即一个BinderProxy对象,用来向一个实现了IRemoteSrvice接口的Java服务发送进程间通信请求。
IRemoteService.Stub.Proxy类实现了IRemoteService接口的两个成员函数:setVal和getVal,它们分别向一个实现了IRemoteService接口的Java服务发送一个类型为TRANSACTION_setVal和TRANSACTION_getVal的进程间通信请求。
得到了使用Java语言描述的Java服务接口之后,接下来我们继续分析Java服务的启动过程、Java服务代理对象的获取过程,以及Java服务的调用过程。

你可能感兴趣的:(java,Binder)