sheldon_blogs

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


目录:

 

一、Java程序的编译和运行

 1.单步操作

 PC:Hello.java 编译成 Hello.class,运行于 jvm。

javac Hello.java
java Hello

  Android:Hello.java 编译成 Hello.class,通过dx指令转换成.dex格式,运行于 dalvikvm。

javac Hello.java
dx --dex --output=Hello.jar Hello.class
dalvikvm -cp /mnt/android_fs/pack.jar Pack (启动方法1)
CLASSPATH=/mnt/android_fs/pack.jar app_process /mnt/android_fs Pack(启动方法2)

 
启动方式的差别:
dalvikvm
app_process :会创建2个binder线程: Binder_1, Binder_2 (实现读数据、解析数据、返回等操作)

2.Android编译系统(Android.mk)

 把代码放到android源码中编译:
 添加Androd.mk,内容类似:  // 参考frameworks/base/cmds/am/Android.mk

include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_MODULE := pack
include $(BUILD_JAVA_LIBRARY)

 

3.使用java代码实现hello服务

 (1)IHelloService.aidl

    接口定义,编译生成IHelloService.java,里面有Stub  : onTransact, 它会分辨收到数据然后调用sayhello, sayhello_to;
  Proxy : 提供有sayhello, sayhello_to两个函数, 它们会构造数据然后发送给server。

/** {@hide} */
interface IHelloService
{
    void sayhello();
    int sayhello_to(String name);
}

 (2)IHelloService.java

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: frameworks/base/core/java/android/os/IHelloService.aidl
 */
/** {@hide} */
public interface IHelloService extends android.os.IInterface
{
    /** Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements IHelloService
    {
        private static final java.lang.String DESCRIPTOR = "IHelloService";
        /** Construct the stub at attach it to the interface. */
        public Stub()
        {
            this.attachInterface(this, DESCRIPTOR);
        }
        /**
         * Cast an IBinder object into an IHelloService interface,
         * generating a proxy if needed.
         */
        public static IHelloService asInterface(android.os.IBinder obj)
        {
            if ((obj==null)) {
            return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin!=null)&&(iin instanceof IHelloService))) {
            return ((IHelloService)iin);
            }
            return new IHelloService.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_sayhello:
                {
                    data.enforceInterface(DESCRIPTOR);
                    this.sayhello();
                    reply.writeNoException();
                    return true;
                }
                case TRANSACTION_sayhello_to:
                {
                    data.enforceInterface(DESCRIPTOR);
                    java.lang.String _arg0;
                    _arg0 = data.readString();
                    int _result = this.sayhello_to(_arg0);
                    reply.writeNoException();
                    reply.writeInt(_result);
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }

        
        private static class Proxy implements IHelloService
        {
            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 sayhello() 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_sayhello, _data, _reply, 0);
                    _reply.readException();
                }
                finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
            @Override public int sayhello_to(java.lang.String name) 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.writeString(name);
                    mRemote.transact(Stub.TRANSACTION_sayhello_to, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readInt();
                }
                finally {
                    _reply.recycle();
                    _data.recycle();
                }
                    return _result;
            }
        }
        
        static final int TRANSACTION_sayhello = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_sayhello_to = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
            
    }
    
    public void sayhello() throws android.os.RemoteException;
    public int sayhello_to(java.lang.String name) throws android.os.RemoteException;
}

 (3)HelloService.java

  实现服务类: HelloService.java,在里面定义sayhello, sayhello_to;

import android.util.Slog;

/* 实现Hello服务的函数 */

public class HelloService extends IHelloService.Stub {
    private static final String TAG = "HelloService";
    private int cnt1 = 0;
    private int cnt2 = 0;

    public void sayhello() throws android.os.RemoteException {
        cnt1++;
        Slog.i(TAG, "sayhello : cnt = "+cnt1);
    }
    
    public int sayhello_to(java.lang.String name) throws android.os.RemoteException {
        cnt2++;
        Slog.i(TAG, "sayhello_to "+name+" : cnt = "+cnt2);
        return cnt2;
    }
}

 (4)IGoodbyeService.aidl (同HelloService)

/** {@hide} */
interface IGoodbyeService
{
    void saygoodbye();
    int saygoodbye_to(String name);
}

 (5)IGoodbyeService.java

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: frameworks/base/core/java/android/os/IGoodbyeService.aidl
 */
/** {@hide} */
public interface IGoodbyeService extends android.os.IInterface
{
    /** Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements IGoodbyeService
    {
        private static final java.lang.String DESCRIPTOR = "IGoodbyeService";
        /** Construct the stub at attach it to the interface. */
        public Stub()
        {
            this.attachInterface(this, DESCRIPTOR);
        }
        /**
         * Cast an IBinder object into an IGoodbyeService interface,
         * generating a proxy if needed.
         */
        public static IGoodbyeService asInterface(android.os.IBinder obj)
        {
            if ((obj==null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin!=null)&&(iin instanceof IGoodbyeService))) {
                return ((IGoodbyeService)iin);
            }
            return new IGoodbyeService.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_saygoodbye:
                {
                    data.enforceInterface(DESCRIPTOR);
                    this.saygoodbye();
                    reply.writeNoException();
                    return true;
                }
                case TRANSACTION_saygoodbye_to:
                {
                    data.enforceInterface(DESCRIPTOR);
                    java.lang.String _arg0;
                    _arg0 = data.readString();
                    int _result = this.saygoodbye_to(_arg0);
                    reply.writeNoException();
                    reply.writeInt(_result);
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }
        private static class Proxy implements IGoodbyeService
        {
            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 saygoodbye() 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_saygoodbye, _data, _reply, 0);
                    _reply.readException();
                }
                finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
            @Override public int saygoodbye_to(java.lang.String name) 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.writeString(name);
                    mRemote.transact(Stub.TRANSACTION_saygoodbye_to, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readInt();
                }
                finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }
        static final int TRANSACTION_saygoodbye = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_saygoodbye_to = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    }
    public void saygoodbye() throws android.os.RemoteException;
    public int saygoodbye_to(java.lang.String name) throws android.os.RemoteException;
}

 (6)GoodbyeService.java

import android.util.Slog;

/* 实现Goodbye服务的函数 */

public class GoodbyeService extends IGoodbyeService.Stub {
    private static final String TAG = "GoodbyeService";
    private int cnt1 = 0;
    private int cnt2 = 0;

    public void saygoodbye() throws android.os.RemoteException {
        cnt1++;
        Slog.i(TAG, "saygoodbye : cnt = "+cnt1);
    }
    
    public int saygoodbye_to(java.lang.String name) throws android.os.RemoteException {
        cnt2++;
        Slog.i(TAG, "saygoodbye_to "+name+" : cnt = "+cnt2);
        return cnt2;
    }
}

 

 (7)TestServer.java (addService, 循环)

import android.util.Slog;
import android.os.ServiceManager;

/* 1. addService
 * 2. while(true) { read data, parse data, call function, reply }
 */

public class TestServer {
    private static final String TAG = "TestServer";

    public static void main(String args[])
    {
        /* add Service */
        Slog.i(TAG, "add hello service");
        ServiceManager.addService("hello", new HelloService());

        Slog.i(TAG, "add goodbye service");
        ServiceManager.addService("goodbye", new GoodbyeService());

        while (true)
        {
            try {
                Thread.sleep(100);
              } catch (Exception e){}
        }
        
    }
}

 (8)TestClient.java (getService, 调用sayhello,sayhello_to(来自Proxy))

import android.util.Slog;
import android.os.ServiceManager;
import android.os.IBinder;


/* 1. getService
 * 2. 调用服务的sayhello,sayhello_to
 *
 */

/* test_client <hello|goodbye> [name] */

public class TestClient {
    private static final String TAG = "TestClient";

    public static void main(String args[])
    {
        if (args.length == 0)
        {
            System.out.println("Usage: need parameter: <hello|goodbye> [name]");
            return;
        }

        if (args[0].equals("hello"))
        {
            /* 1. getService */
            IBinder binder = ServiceManager.getService("hello");
            if (binder == null)
            {
                System.out.println("can not get hello service");
                Slog.i(TAG, "can not get hello service");
                return;
            }

            IHelloService svr = IHelloService.Stub.asInterface(binder);

            if (args.length == 1)
            {
                    try {
                    svr.sayhello();
                    System.out.println("call sayhello");
                    Slog.i(TAG, "call sayhello");
                  } catch (Exception e) {}
            }
            else
            {
                    try {
                    int cnt = svr.sayhello_to(args[1]);
                    System.out.println("call sayhello_to "+args[1]+" : cnt = "+cnt);
                    Slog.i(TAG, "call sayhello_to "+args[1]+" : cnt = "+cnt);
                  } catch (Exception e) {
                        System.out.println("call sayhello_to , err :"+e);
                        Slog.i(TAG, "call sayhello_to , err : "+e);
                  }
            }
        }
        else if (args[0].equals("goodbye"))
        {
            /* 1. getService */
            IBinder binder = ServiceManager.getService("goodbye");
            if (binder == null)
            {
                System.out.println("can not get goodbye service");
                Slog.i(TAG, "can not get goodbye service");
                return;
            }

            IGoodbyeService svr = IGoodbyeService.Stub.asInterface(binder);

            if (args.length == 1)
            {
                    try {
                    svr.saygoodbye();
                    System.out.println("call saygoodbye");
                    Slog.i(TAG, "call saygoodbye");
                  } catch (Exception e) {}
            }
            else
            {
                    try {
                    int cnt = svr.saygoodbye_to(args[1]);
                    System.out.println("call saygoodbye_to "+args[1]+" : cnt = "+cnt);
                    Slog.i(TAG, "call saygoodbye_to "+args[1]+" : cnt = "+cnt);
                  } catch (Exception e) {}
            }
        }
    }
}

 

 (9)Android.mk

# Copyright 2008 The Android Open Source Project
#
LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_SRC_FILES := HelloService.java IHelloService.java GoodbyeService.java IGoodbyeService.java TestServer.java
LOCAL_MODULE := TestServer
include $(BUILD_JAVA_LIBRARY)

include $(CLEAR_VARS)
LOCAL_SRC_FILES := HelloService.java IHelloService.java GoodbyeService.java IGoodbyeService.java TestClient.java
LOCAL_MODULE := TestClient
include $(BUILD_JAVA_LIBRARY)

 

 编译&测试说明:

(1) AIDL
1. 把 IHelloService.aidl, IGoodbyeService.aidl 放入 frameworks/base/core/java/android/os
2. 修改 frameworks/base/Android.mk  添加一行
         core/java/android/os/IVibratorService.aidl \
+        core/java/android/os/IHelloService.aidl \
+        core/java/android/os/IGoodbyeService.aidl \

3. mmm frameworks/base

4. 它会生成: 
./out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/os/IHelloService.java
./out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/os/IGoodbyeService.java

(2) 编译:
把程序放到 /work/android-5.0.2/frameworks/testing/APP_0005_Binder_JAVA_App
执行:

cd /work/android-5.0.2
. setenv
lunch // 选择单板

mmm frameworks/testing/APP_0005_Binder_JAVA_App
它会生成 TestServer.jar, TestClient.jar

复制文件到NFS目录
cp /work/android-5.0.2/out/target/product/tiny4412/system/framework/Test*.jar /work/nfs_root/android_fs/

(3) 测试:
logcat TestServer:* TestClient:* HelloService:* *:S &
CLASSPATH=/mnt/android_fs/TestServer.jar app_process / TestServer &
CLASSPATH=/mnt/android_fs/TestClient.jar app_process / TestClient hello
CLASSPATH=/mnt/android_fs/TestClient.jar app_process / TestClient hello 100ask.taobao.com
CLASSPATH=/mnt/android_fs/TestClient.jar app_process / TestClient goodbye
CLASSPATH=/mnt/android_fs/TestClient.jar app_process / TestClient goodbye weidongshan

 

、内部机制

1.Client端
1.1 ServiceManagerProxy中mRemote的构造 (用于addService/getService)
   使用0直接构造出一个java BinderProxy对象
getIServiceManager().addService  / getIServiceManager().getService

getIServiceManager()
        return ServiceManagerNative.asInterface(BinderInternal.getContextObject())

a. BinderInternal.getContextObject()  // 得到了一个Java BinderProxy对象, 其中mObject指向new BpBinder(0);
   它是一个JNI调用,对应 android_os_BinderInternal_getContextObject // android_util_Binder.cpp
   
   android_os_BinderInternal_getContextObject
           sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
                                                                                               getStrongProxyForHandle(0);
                                                                                                       b = new BpBinder(handle);  // mHandle = 0
            return javaObjectForIBinder(env, b);        // b = new BpBinder(0), mHandle = 0
            
                                    // 使用c代码调用NewObject来创建JAVA BinderProxy对象
                                    object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
                                    
                                    // 设置该对象的mObject = val.get = b = new BpBinder(0)
                                    env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
                                    
                                    return object;

b. ServiceManagerNative.asInterface
            new ServiceManagerProxy(obj); // obj = BinderProxy对象
                            mRemote = obj = BinderProxy对象, 其中mObject指向new BpBinder(0);

1.2 hello服务里的mRemote如何构造
a. IBinder binder = ServiceManager.getService("hello");
 它的返回值就是一个java BinderProxy对象, 其中的mObject=new BpBinder(handle)
new ServiceManagerProxy().getService("hello")
            ....
            IBinder binder = reply.readStrongBinder();
                                                                nativeReadStrongBinder  // Parcel.java

nativeReadStrongBinder是一个JNI调用, 对应的代码是 android_os_Parcel_readStrongBinder                                                                
android_os_Parcel_readStrongBinder    
      // 把java Parce对象转换为c++ Parcel对象
      // client程序向sevice_manager发出getService请求,
      // 得到一个回复reply, 它里面含有flat_binder_object
      // 它被封装成一个c++ Parcel对象
        Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
        
        /* parcel->readStrongBinder()应该是一个 new BpBinder(handle)
         *             unflatten_binder(ProcessState::self(), *this, &val);
         *                  *out = proc->getStrongProxyForHandle(flat->handle);
         *                                  b = new BpBinder(handle);
         */
        
      // 它会创建一个java BinderProxy对象, 其中的mObject=new BpBinder(handle)对象
        return javaObjectForIBinder(env, parcel->readStrongBinder());

b. IHelloService svr = IHelloService.Stub.asInterface(binder);
                                                        new IHelloService.Stub.Proxy(obj);  // obj = 步骤a得到的binder
                                                                        mRemote = remote;        

1.3 现在知道了:mRemote就是一个java BinderProxy 对象
    看一下mRemote.transact()
                                    transactNative(code, data, reply, flags);
                                    它是一个JNI调用,对应android_os_BinderProxy_transact

  android_os_BinderProxy_transact
   // 从java BinderProxy对象中把mObject取出, 它就是一个BpBinder对象
    IBinder* target = (IBinder*)env->GetLongField(obj, gBinderProxyOffsets.mObject);                                    
    
    // 然后调用BpBinder的transact
    status_t err = target->transact(code, *data, reply, flags);

 

2.Server端

2.1 server如何读取数据
 使用app_process来启动server进程,

/*测试指令*/
logcat TestServer:* TestClient:* HelloService:* *:S & CLASSPATH=/mnt/android_fs/TestServer.jar app_process / TestServer & CLASSPATH=/mnt/android_fs/TestClient.jar app_process / TestClient hello CLASSPATH=/mnt/android_fs/TestClient.jar app_process / TestClient hello sheldon /*参考源码*/ // app_process: frameworks\base\cmds\app_process\app_main.cpp

它会先创建子线程(前面示例提到的两个binder线程:Binder_1, Binder_2):
AppRuntime::onStarted()
        proc->startThreadPool();
                        spawnPooledThread(true);
                                sp<Thread> t = new PoolThread(isMain);
                                t->run(name.string());
                                        // 它会创建子线程, 并执行threadLoop
                                           IPCThreadState::self()->joinThreadPool(mIsMain);
                                           {
                                                    do {
                                                                    result = getAndExecuteCommand();
                                                                                            result = talkWithDriver();
                                                                                            result = executeCommand(cmd);
                                                                                                                    对于BR_TRANSACTION数据,
                                                                                                                    sp<BBinder> b((BBinder*)tr.cookie); //将.cookie转换成BBinder对象
                                                                                                                    error = b->transact(tr.code, buffer, &reply, tr.flags); //并调用其transact方法
                                                 } while(...)
                                           }


2.2 server读到数据后怎么调用服务PRC层的onTransact函数
  在addService时设置.ptr/.cookie
  ServiceManager.addService("hello", new HelloService());

结论:
① addService会通过JNI调用c++函数:
        创建一个BBinder派生类JavaBBinder对象,
            它的.mObject指向JAVA对象: new HelloService()
            它含有onTransact函数
        把这个对象存入.cookie(最终存入binder驱动中该服务对应的binder_node.cookie)

② server进程从驱动中读到数据,里面含有.cookie
    把它转换为BBinder对象,
    调用它的transact函数
    最终调用到派生类JavaBBinder中定义的onTransact函数

③ JavaBBinder中定义的onTransact函数(c++)
    它通过JNI调用java Binder的execTransact方法,
    然后调用Binder派生类IHelloService.Stub中定义的onTransact函数(JAVA)

④ IHelloService.Stub中定义的onTransact函数(JAVA):
        分析数据
        调用sayhello/sayhello_to

源码阅读
(1) ServiceManager.addService("hello", new HelloService());
    ServiceManagerProxy.addService:
            // Parcel.java
            data.writeStrongBinder(service);
                            nativeWriteStrongBinder(mNativePtr, val); // val = service = new HelloService()
                            它是一个JNI调用,对应android_os_Parcel_writeStrongBinder(c++)

(2) android_os_Parcel_writeStrongBinder(c++)
    它会构造一个JavaBBinder对象(c++),.mObject=new HelloService() JAVA对象
    然后让.cookie=JavaBBinder对象(c++)
    
    // 把Java Parcel转换为c++ Parcel
    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    
    // .cookie = ibinderForJavaObject(env, object)得到一个JavaBBinder对象
    parcel->writeStrongBinder(ibinderForJavaObject(env, object))

(3) ibinderForJavaObject(env, object) //object = new HelloService()
    把一个Java对象(new HelloService())转换为c++ IBinder对象
    
    JavaBBinderHolder* jbh = (JavaBBinderHolder*)env->GetLongField(obj, gBinderOffsets.mObject);
    return jbh != NULL ? jbh->get(env, obj) : NULL;
                                                     b = new JavaBBinder(env, obj); // obj = new HelloService()
                                                                 mObject = new HelloService()


(4) 从驱动中得过了.cookie, 它是一个JavaBBinder对象
    调用它的transact函数,导致JavaBBinder对象的onTransact被调用
    
    JavaBBinder::onTransact (调用java里的某个函数)
    
            // mObject指向 HelloService对象
            // gBinderOffsets.mExecTransact指向: java Binder类中的execTransact方法
            // 调用HelloService(派生自Binder)对象中的execTransact方法
        jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
            code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);

(5) java Binder execTransact:  
                res = onTransact(code, data, reply, flags);
                                    调用HelloService中的onTransact方法(来自IHelloService.Stube)
                                        分辨数据
                                        调用sayhello/sayhello_to

 

 

 -end-

posted on 2019-03-13 14:16  sheldon_blogs  阅读(1680)  评论(0编辑  收藏  举报

导航