AndroidQ 打通应用层到HAL层---(JNI服务和AIDL服务实现)

AndroidQ 打通应用层到HAL层---(JNI服务和AIDL服务实现),第1张

概述前面两篇文章实现了自定义HAL和HIDL服务,本篇接着往上层实现,这篇文章要写的是JNI服务和framework层AIDL服务实现,由AIDL服务调用JNI层的服务的函数,为了提供给上层APP使用同样我们参照系统其他服务的方式来写,来到frameworks/base/services/core/jni目录下,这下面有许多JNI的服

前面两篇文章实现了自定义HAL和HIDL服务,本篇接着往上层实现,这篇文章要写的是JNI服务和framework层AIDL服务实现,由AIDL服务调用JNI层的服务的函数,为了提供给上层APP使用

同样我们参照系统其他服务的方式来写,来到frameworks/base/services/core/jni目录下,这下面有许多JNI的服务,创建cpp文件com_androID_server_am_HelloService.cpp,为什么要叫这个名字,因为等下我们实现的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("dongjiao...androID_server_am_HelloService_nativeAdd.....");      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 */) {      ALOGW("dongjiao...androID_server_am_HelloService_nativeInit.....");      hw_device = IHello::getService();        if (hw_device == nullptr) {              ALOGW("dongjiao...Failed to get IHello service");              return;     }     ALOGW("dongjiao...success to get IHello service");}/* * JNI registration. */static const JNINativeMethod gMethods[] = {    { "nativeAdd", "(II)I", (voID*) androID_server_am_HelloService_nativeAdd },    { "nativeInit", "()V", (voID*) androID_server_am_HelloService_nativeInit },};int register_androID_server_am_HelloService(jnienv* env){    return jniRegisterNativeMethods(env, "com/androID/server/am/HelloService",            gMethods, NELEM(gMethods));}}; // namespace androID

这个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;}

其实这个文件和我们用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“,代码已经添加完毕,总的修改就是如下部分:

开始进行编译 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 [email protected]::IHello/default (start delay of 52ms)
04-14 23:58:58.762 9279 9279 I ServiceManagement: Removing namespace from process name [email protected] to [email protected].
04-14 23:58:58.762 9279 9279 I [email protected]: Registration complete for [email protected]::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的函数了

下一篇文章我将写一个APP通过AIDL调用HIDL的addition_hIDl函数

总结

以上是内存溢出为你收集整理的AndroidQ 打通应用层到HAL层---(JNI服务和AIDL服务实现)全部内容,希望文章能够帮你解决AndroidQ 打通应用层到HAL层---(JNI服务和AIDL服务实现)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1062227.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存