JNI层和Aidl层的实现

参照系统的其他服务方式来写,来到frameworks/base/services/core/jni目录下,这里面有很多的JNI服务,创建cpp文件com_android_server_am_HelloService.app,这个名字和AIDL服务包名com.android.server.am相同。

#include <jni.h>
#include <nativehelper/JNIHelp.h>
#include <binder/IServiceManager.h>
#include <android/hardware/hello_hidl/1.0/IHello.h>
#include <log/log.h>

using android::sp;
using android::hardware::hello_hidl::V1_0::IHello;

namespace android{
sp<IHello> hw_device;
static jint android_server_am_HelloService_nativeAdd(JNIEnv* env,jobject /*clazz*/,jint a,jint b){
 ALOGW("android_server_am_HelloService_nativeAdd.....");
 //uint32_t  == typedef unsign int uint32_t 
 uint32_t total = hw_device->addition_hidl(a,b);
 return reinterpret_cast<jlong>(total);
}
static void android_server_am_HelloService_nativeInit(JNIEnv* /*env*/,jobject /*clazz*/){
hw_device = IHello::getService();
if(hw_device == nullptr){
	ALOG("failed to get IHello service");
	return;
}
ALOG("success to get IHello service");
}
/**
*JNI registration
*通过此方法将c++的方法和java的method方法进行联系在一起
*/
static const JNINativeMethod gMethods[]= {
	{"nativeAdd","(II)I",(void*)android_server_am_HelloService_nativeAdd},
	{"nativeInit","()V",(void*)android_server_am_HelloService_nativeInit},
};
//这个放会被注册到framework文件下的一个文件
int register_android_server_am_HelloService(JNIEnv* env){
	//还提供了一个计算方法映射表长度的宏定义
	//#ifndef NELEM
	//# define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
	//#endif 
	return jniRegisterNativeMethods(env,"com/android/server/am/HelloService",gMethods,NELEM(gMethods));
  }
};

这个JNI服务中定义两个函数,android_server_am_HelloService_nativeAdd和android_server_am_HelloService_nativeInit函数,这两个函数是提供给framework层AIDL调用的,添加了一些log方便验证,对应等下要实现的AIDL服务中的nativeAdd和nativeInit
android_server_am_HelloService_nativeInit函数作用是获取我们上一篇文章实现的HIDL服务IHello
android_server_am_HelloService_nativeAdd函数作用是调用HIDL服务中定义的addition_hidl函数
JNI服务中的函数想要被framework调用还需要通过register_android_server_am_HelloService函数进行注册,"com/android/server/am/HelloService"这个是我们要实现的framework层的AIDL服务
接着需要将这个自定义JNI服务添加到onload.cpp中开机注册,打开frameworks/base/services/core/jni/onload.cpp,添加如下代码在这里插入图片描述接着需要修改Android.bp文件,打开frameworks/base/services/core/jni/Android.bp,添加如下代码:
在这里插入图片描述主要就是将新增文件添加进编译和添加hello_hidl的依赖库,JNI服务已经创建好了,接着,需要创建framework层AIDL服务
首先到frameworks/base/core/java/android/app/目录下创建IHelloService.aidl文件:

package android.app;
interface IHelloService{
int add(int a,int b);
}

想要编译这个文件还需要修改Android.bp,在frameworks/base/Android.bp中添加如下代码:

在这里插入图片描述
然后就可以编译了,mmm frameworks/base
在这里插入图片描述
编译成功后我们可以去out目录下看看IHelloService.aidl编出来的IHelloService.java文件:

/*
 * This file is auto-generated.  DO NOT MODIFY.
 */
package android.app;
public interface IHelloService extends android.os.IInterface
{
  /** Default implementation for IHelloService. */
  public static class Default implements android.app.IHelloService
  {
    @Override public int add(int a, int b) throws android.os.RemoteException
    {
      return 0;
    }
    @Override
    public android.os.IBinder asBinder() {
      return null;
    }
  }
  /** Local-side IPC implementation stub class. */
  public static abstract class Stub extends android.os.Binder implements android.app.IHelloService
  {
    private static final java.lang.String DESCRIPTOR = "android.app.IHelloService";
    /** Construct the stub at attach it to the interface. */
    public Stub()
    {
      this.attachInterface(this, DESCRIPTOR);
    }
    /**
     * Cast an IBinder object into an android.app.IHelloService interface,
     * generating a proxy if needed.
     */
    public static android.app.IHelloService asInterface(android.os.IBinder obj)
    {
      if ((obj==null)) {
        return null;
      }
      android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
      if (((iin!=null)&&(iin instanceof android.app.IHelloService))) {
        return ((android.app.IHelloService)iin);
      }
      return new android.app.IHelloService.Stub.Proxy(obj);
    }
    @Override public android.os.IBinder asBinder()
    {
      return this;
    }
    /** @hide */
    public static java.lang.String getDefaultTransactionName(int transactionCode)
    {
      switch (transactionCode)
      {
        case TRANSACTION_add:
        {
          return "add";
        }
        default:
        {
          return null;
        }
      }
    }
    /** @hide */
    public java.lang.String getTransactionName(int transactionCode)
    {
      return this.getDefaultTransactionName(transactionCode);
    }
    @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_add:
        {
          data.enforceInterface(descriptor);
          int _arg0;
          _arg0 = data.readInt();
          int _arg1;
          _arg1 = data.readInt();
          int _result = this.add(_arg0, _arg1);
          reply.writeNoException();
          reply.writeInt(_result);
          return true;
        }
        default:
        {
          return super.onTransact(code, data, reply, flags);
        }
      }
    }
    private static class Proxy implements android.app.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 int add(int a, int b) 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.writeInt(a);
          _data.writeInt(b);
          boolean _status = mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
          if (!_status && getDefaultImpl() != null) {
            return getDefaultImpl().add(a, b);
          }
          _reply.readException();
          _result = _reply.readInt();
        }
        finally {
          _reply.recycle();
          _data.recycle();
        }
        return _result;
      }
      public static android.app.IHelloService sDefaultImpl;
    }
    static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    public static boolean setDefaultImpl(android.app.IHelloService impl) {
      if (Stub.Proxy.sDefaultImpl == null && impl != null) {
        Stub.Proxy.sDefaultImpl = impl;
        return true;
      }
      return false;
    }
    public static android.app.IHelloService getDefaultImpl() {
      return Stub.Proxy.sDefaultImpl;
    }
  }
  public int add(int a, int b) throws android.os.RemoteException;
}

这个文件和AS(android studio)创建AIDL服务生成中间文件差不多,都是统一的AIDL框架:有一个Stub抽象类,继承IBinder,实现IHelloService,还有一个代理类Proxy继承IHelloService,通过asInterface方法获取
了解了,IHelloService.aidl生成的中间文件,我们在实现HelloService.java的时候就清晰了,在frameworks/base/services/core/java/com/android/server/am/目录下创建HelloService.java文件:

package com.android.server.am;
import android.app.IHelloService;
public class HelloService extends IHelloService.Stub {
    public HelloService(){
      android.util.Log.d("dongjiao","Start HelloService...");
      nativeInit();
    }
    @Override 
    public int add(int a, int b){
      android.util.Log.d("dongjiao","HelloService add()...a = :"+a+",b = :"+b);
      return nativeAdd(a,b);
    }
    private static native void nativeInit();
    private static native int nativeAdd(int a,int b);
}

这个HelloService继承自IHelloService.Stub,它作为Binder的具体实现端,里面定义了两个native方法,这两个方法和之前创建的JNI服务中的那两个函数一一对应,HelloService构造方法中调用nativeInit,add方法提供给外界访问,它里面调用nativeAdd

好了这个AIDL服务已经创建好了,接着我们到SystemServer中去添加开机注册此服务的代码,打开frameworks/base/services/java/com/android/server/SystemServer.java随便在其他某个服务下添加如下代码:
在这里插入图片描述
SystemServer启动时就会将HelloService添加到ServiceManager,名字自定义为”helloService“,代码已经添加完毕,总的修改就是如下部分:
在这里插入图片描述好了这个AIDL服务已经创建好了,接着我们到SystemServer中去添加开机注册此服务的代码,打开frameworks/base/services/java/com/android/server/SystemServer.java随便在其他某个服务下添加如下代码:
在这里插入图片描述
SystemServer启动时就会将HelloService添加到ServiceManager,名字自定义为”helloService“,代码已经添加完毕,总的修改就是如下部分:
在这里插入图片描述

开始进行编译 mmm frameworks/base/

编译成功后需要将/system/framework/下所有文件push进手机
adb push out/target/product/TOKYO_TF_arm64/system/framework/ /system/

另外定义的JIN服务相关代码会被编译到libandroid_servers.so这个so中,还需push这个so
adb push out/target/product/TOKYO_TF_arm64/system/lib64/libandroid_servers.so /system/lib64/

重启手机发现了如下错误:
在这里插入图片描述这是因为缺少了SELinux权限,实际开发中添加自定义AIDL,HIDL服务都需要SELinux权限,我们这里重点不在SELinux,所以采用规避方案,直接将SELinux关闭adb shell setenforce 0,这需要root权限

我们发现如下log,这是因为我的HIDL服务还没启动

在这里插入图片描述
启动一下前一篇文章实现的HIDL服务:

在这里插入图片描述我们重新将SystemServer杀掉,为了再看一遍log:

在这里插入图片描述
04-14 23:58:58.760 9279 9279 E : hello_hidl service is init success…
04-14 23:58:58.761 9279 9279 I ServiceManagement: Registered android.hardware.hello_hidl@1.0::IHello/default (start delay of 52ms)
04-14 23:58:58.762 9279 9279 I ServiceManagement: Removing namespace from process name android.hardware.hello_hidl@1.0-service to hello_hidl@1.0-service.
04-14 23:58:58.762 9279 9279 I android.hardware.hello_hidl@1.0-service: Registration complete for android.hardware.hello_hidl@1.0::IHello/default.
这一段代表的是HIDL服务的启动注册

04-14 23:59:38.881 328 328 I ServiceManager: service ‘helloService’ died
04-14 23:59:41.582 14037 14037 W : JNI_OnLoad…hello…
04-14 23:59:41.594 14037 14037 W : register_android_server_am_HelloService…
04-14 23:59:44.978 14037 14037 D dongjiao: SystemServer…addService(helloService)…
04-14 23:59:44.978 14037 14037 D dongjiao: Start HelloService…
04-14 23:59:44.978 14037 14037 W : HelloService…nativeInit…
04-14 23:59:44.980 14037 14037 W : success to get IHello service
这一段代表AIDL服务的启动注册

可以看到关闭了SELinux权限之后,HIDL和AIDL服务都注册成功了,并且在AIDL服务初始化时也能成功通过JNI服务获取到HIDL服务了,后面如果调用HIDL的addition_hidl函数也应该是很简单了

其实整个调用逻辑还是比较清晰的,从AIDL到JNI到HIDL,在AIDL服务初始化中调用JNI服务的nativeInit函数,JNI服务的nativeInit函数中获取到HIDL服务,之后就可以随意调用HIDL的函数了

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值