Ryan Life is Simple

关于AIDL在Native层的简介

2019-01-24

AIDL常被用来快速创建Binder服务,但大多应用在Java层的客户端、服务端接口代码生成,其实它也可以用来创建Native层的接口服务。当前网上关于Native层AIDL使用的说明和资料并不是很多,本文将会简单的介绍下相关的使用方式。

关于AIDL在Java层的应用

AIDL作为一种DSL语言,通过代码生成的方式,让开发者用相对简单的方式,将Binder客户端和服务端的接口代码给生成,使得开发者可以将更多的精力放在接口的实现方面。

一般我们接触Java相关的代码生成会比较多,如下图所示 AIDL代码生成

创建的Binder服务我们可以通过下面的方式使用 Java服务的使用

关于AIDL在Native层的应用

由于工作的需要,需要创建Native层的Binder服务,供Native层的系统服务使用。但是网上关于AIDL生成Binder的资料少之又少,最具有参考价值的就是Google doc里面关于AIDL-CPP的介绍,https://android.googlesource.com/platform/system/tools/aidl/+/brillo-m10-dev/docs/aidl-cpp.md

Google关于AIDL-CPP这篇文档是非常有价值去仔细研读的。上面大致介绍了hidl-cpp的引入时间,什么时候会生成Java的代码,什么条件下又是生成CPP的代码,Java与C++的一些基本类型的转换等等。 但是即使有这篇Doc,想要自己通过AIDL创建Native层的Binder服务,还是需要花费不少的时间,踩不少的坑。

AOSP中常见的一些Native层服务

既然没有现成的资料可以参考,那么只有通过阅读和学习AOSP的代码,参考Google是如何直接或者通过AIDL创建Native层服务的。本文参考的是Andorid 8.1的代码。

PowerManager服务

frameworks/base/core/java/android/os/IPowerManager.aidl frameworks/native/include/powermanager/IPowerManager.h
frameworks/native/services/powermanager/IPowerManager.cpp

虽然PowerManager定义了IPowerManager.aidl,但是这个AIDL只会生成Java层的代码,因为包含这个文件的模块最终生成的是frameworks.jar。但是由于PowerManager很多服务需要被Native层的服务所使用。

所以PowerManager在Native层定义了IPowerManager.h和IPowerManager.cpp文件,能够让Native的代码调用PowerManagerService的服务。比如说某个Native代码想要通过PowerManagerService申请WakeLock,这一通过下面的代码获取PowerManagerService的服务实例。

frameworks/av/media/libstagefright/foundation/AWakeLock.cpp

if (mPowerManager == NULL) {
    // use checkService() to avoid blocking if power service is not up yet
    //获取PowerManager的服务
    sp<IBinder> binder =
        defaultServiceManager()->checkService(String16("power"));
    if (binder == NULL) {
        ALOGW("could not get the power manager service");
    } else {
        mPowerManager = interface_cast<IPowerManager>(binder);
        binder->linkToDeath(mDeathRecipient);
    }
}
if (mPowerManager != NULL) {
    sp<IBinder> binder = new BBinder();
    int64_t token = IPCThreadState::self()->clearCallingIdentity();
    //申请Wakelock
    status_t status = mPowerManager->acquireWakeLock(
            POWERMANAGER_PARTIAL_WAKE_LOCK,
            binder, String16("AWakeLock"), String16("media"));
}

通过对PowerManager实现的参考,首先实现了在不通过AIDL创建Native层的服务,后续介绍如何自定义服务。

CameraService服务

frameworks/av/camera/aidl/android/hardware/ICameraService.aidl frameworks/av/services/camera/libcameraservice/CameraService.h frameworks/av/services/camera/libcameraservice/CameraService.cpp

Camera在Java层只有一个CameraManager,其服务的实现都是在Native层。无论是API1还是API2,最终都会调用到Native层的CameraService,由CameraService作为入口对Camera的HAL1或者HAL3进行操作。 frameworks/av/camera/aidl/android/hardware/ICameraService.aidl最终会在下面路径下(64位的路径)生成Binder所需要的接口文件 out/soong/.intermediates/frameworks/av/camera/libcamera_client/android_arm64_armv8-a_cortex-a53_shared_core/gen/aidl 会生成下面几个文件 ICameraService.h 功能接口文件 BpCameraService.h 客户端 BnCameraService.h 用来被服务端继承 ICameraService.cpp Binder通讯的实现

这些类在CameraService.h和CameraService.cpp被继承使用,类的关系如下图所示

当然Native层还有许多的典型服务,如MediaPlayerService,这里不再一一介绍。我在本地实现的Native服务,无论是手写的接口还是通过AIDL生成的,参考借鉴了PowerManager和CameraService的实现方式。

小结

本文通过AOSP的服务大致介绍了Native层Service的创建方式

后续计划

  1. 自定义Native Service的实现
  2. 自定义server的实现,如何启动自定义的Native Service
  3. 自定义Server和Service的sepolicy的处理

Comments

Content