通过ConsumerIrService看完整的系统服务调用流程(二)

本篇是衔接上一篇:通过ConsumerIrService看完整的系统服务调用流程(一)。如不关心应用层的调用流程可继续阅读,不然建议先移步第一篇。

Frameworks层衔接Hal:

接下来我们看下具体定义和具体实现。
frameworks/native/libs/binder/aidl/android/os/IServiceManager.aidl

// 定义AIDL接口
interface IConsumerIrService
{
    boolean hasIrEmitter();
    void transmit(String packageName, int carrierFrequency, in int[] pattern);
    int[] getCarrierFrequencies();
}

以及对其进行的实现:
frameworks/base/services/core/java/com/android/server/ConsumerIrService.java

// 实现系统服务
public class ConsumerIrService extends IConsumerIrService.Stub {
    // 系统服务集成JNI
    private static native boolean halOpen();
    private static native int halTransmit(int carrierFrequency, int[] pattern);
    private static native int[] halGetCarrierFrequencies();
    ...
    ConsumerIrService(Context context) {
    ...
        mHasNativeHal = halOpen(); // this
    ...
    }  
    
    @Override
    public boolean hasIrEmitter() {
        return mHasNativeHal;
    }
    ...
        @Override
    public void transmit(String packageName, int carrierFrequency, int[] pattern) {
         // 这里有权限的校验
        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.TRANSMIT_IR)
                != PackageManager.PERMISSION_GRANTED) {
            throw new SecurityException("Requires TRANSMIT_IR permission");
        }
        ...
        synchronized (mHalLock) {
            int err = halTransmit(carrierFrequency, pattern); // this
        ...
        }
    }
    
        @Override
    public int[] getCarrierFrequencies() {
        // 这里有权限的校验
        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.TRANSMIT_IR)
                != PackageManager.PERMISSION_GRANTED) {
            throw new SecurityException("Requires TRANSMIT_IR permission");
        }
        throwIfNoIrEmitter();
        synchronized(mHalLock) {
            return halGetCarrierFrequencies(); // this
        }
    }
}

权限的添加在frameworks/base/core/res/AndroidManifest.xml中。

 <permission android:name="android.permission.TRANSMIT_IR"
        android:label="@string/permlab_transmitIr"
        android:description="@string/permdesc_transmitIr"
        android:protectionLevel="normal" />

如果对JNI了解的,就能看出。这部分具体就是桥接了JNI的方法。在看jni的部分之前,还有重要的注册部分。
frameworks/base/services/java/com/android/server/SystemServer.java

// 在SystemServer中注册服务
public static void main(String[] args) {
    new SystemServer().run();
}

private void run() {
    ...
        startBootstrapServices(t);
        startCoreServices(t);
        startOtherServices(t);
    ...
}

private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
    ...
           if (!isWatch && !tinySystem) {
                t.traceBegin("StartConsumerIrService");
                consumerIr = new ConsumerIrService(context);
                ServiceManager.addService(Context.CONSUMER_IR_SERVICE, consumerIr);
                t.traceEnd();
            }
    ...
}

SystemServer.java具体实现感兴趣的可以继续去追,其实也是通过AIDL来代理的。贴出部分路径供参考。
frameworks/base/core/java/android/os/ServiceManager.java
frameworks/base/core/java/android/os/ServiceManagerNative.java
frameworks/native/libs/binder/aidl/android/os/IServiceManager.aidl

JNI桥接部分:

让我们回来接着看JNI的实现。
frameworks/base/services/core/jni/com_android_server_ConsumerIrService.cpp

using ::android::hardware::ir::V1_0::IConsumerIr;
using ::android::hardware::ir::V1_0::ConsumerIrFreqRange;
using ::android::hardware::hidl_vec;

namespace android {
static sp<IConsumerIr> mHal;

static jboolean halOpen(JNIEnv* /* env */, jobject /* obj */) {
    mHal = IConsumerIr::getService();
    return mHal != nullptr;
}

static jint halTransmit(JNIEnv *env, jobject /* obj */, jint carrierFrequency,
    ...
    bool success = mHal->transmit(carrierFrequency, patternVec);
    ...
}

static jintArray halGetCarrierFrequencies(JNIEnv *env, jobject /* obj */) {
    ...
    mHal->getCarrierFreqs(cb);
    ...
}

static const JNINativeMethod method_table[] = {
    { "halOpen", "()Z", (void *)halOpen },
    { "halTransmit", "(I[I)I", (void *)halTransmit },
    { "halGetCarrierFrequencies", "()[I", (void *)halGetCarrierFrequencies},
};

int register_android_server_ConsumerIrService(JNIEnv *env) {
    return jniRegisterNativeMethods(env, "com/android/server/ConsumerIrService",
            method_table, NELEM(method_table));
}
};
HIDL部分:

具体的实现是通过HIDL来代理承接的,原理和AIDL类似。
hardware/interfaces/ir/1.0/IConsumerIr.hal

// 定义HIDL接口
package android.hardware.ir@1.0;
interface IConsumerIr {
    transmit(int32_t carrierFreq, vec<int32_t> pattern) generates (bool success);
    getCarrierFreqs() generates (bool success, vec<ConsumerIrFreqRange> ranges);
};

我接着看在Hardware层的实现。
hardware/interfaces/ir/1.0/default/ConsumerIr.h

#include <android/hardware/ir/1.0/IConsumerIr.h>
#include <hardware/consumerir.h>
...

using ::android::hardware::ir::V1_0::ConsumerIrFreqRange;
using ::android::hardware::ir::V1_0::IConsumerIr;
...

struct ConsumerIr : public IConsumerIr {
    ConsumerIr(consumerir_device_t *device);
    // Methods from ::android::hardware::ir::V1_0::IConsumerIr follow.
    Return<bool> transmit(int32_t carrierFreq, const hidl_vec<int32_t>& pattern) override;
    Return<void> getCarrierFreqs(getCarrierFreqs_cb _hidl_cb) override;
private:
    consumerir_device_t *mDevice;
};
...

hardware/interfaces/ir/1.0/default/ConsumerIr.cpp

#include <hardware/hardware.h>
#include <hardware/consumerir.h>
...
ConsumerIr::ConsumerIr(consumerir_device_t *device) {
    mDevice = device;
}

// Methods from ::android::hardware::consumerir::V1_0::IConsumerIr follow.
Return<bool> ConsumerIr::transmit(int32_t carrierFreq, const hidl_vec<int32_t>& pattern) {
    // 调用设备驱动函数
    return mDevice->transmit(mDevice, carrierFreq, pattern.data(), pattern.size()) == 0; 
}

Return<void> ConsumerIr::getCarrierFreqs(getCarrierFreqs_cb _hidl_cb) {
    int32_t len = mDevice->get_num_carrier_freqs(mDevice); // 调用设备驱动函数
    ...
    consumerir_freq_range_t *rangeAr = new consumerir_freq_range_t[len];
    bool success = (mDevice->get_carrier_freqs(mDevice, len, rangeAr) >= 0);
    ...
    return Void();
}
...

还有基础关键的地方。
hardware/interfaces/ir/1.0/default/service.cpp
直通模式:

#define LOG_TAG "android.hardware.ir@1.0-service"

#include <android/hardware/ir/1.0/IConsumerIr.h>
#include <hidl/LegacySupport.h>

using android::hardware::ir::V1_0::IConsumerIr;
using android::hardware::defaultPassthroughServiceImplementation;

int main() {
    // 核心注册函数:自动加载HAL实现库
    return defaultPassthroughServiceImplementation<IConsumerIr>();
}

通过直通模式及“ 服务与调用者处于同一进程 ” ,还有一种模式是 绑定式服务运行在独立进程
绑定模式:举例

// hardware/interfaces/hello/1.0/default/HelloService.cpp
#include <hidl/HidlTransportSupport.h>

using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;

int main() {
    configureRpcThreadpool(4, true); // 配置Binder线程池
    
    // 创建Binderized服务
    android::sp<IHello> service = new HelloImpl();
    service->registerAsService(); // 注册到hwservicemanager
    
    joinRpcThreadpool(); // 进入Binder循环
    return 0;
}

针对这一层还有.rc.bp 的配置,感兴趣的自己去找源码看。

驱动部分:

最后的最后我们简单看看实际调用的驱动部分,由于不同模组驱动有所不同这里仅做参考。
hardware/libhardware/include/hardware/consumerir.h
hardware/libhardware/modules/consumerir/consumerir.c

#include <hardware/consumerir.h>
#include <hardware/hardware.h>
...
static int consumerir_open(const hw_module_t* module, const char* name,
        hw_device_t** device){
  ...
    dev->transmit = consumerir_transmit; // 指向实际驱动函数
    dev->get_num_carrier_freqs = consumerir_get_num_carrier_freqs;
    dev->get_carrier_freqs = consumerir_get_carrier_freqs; // 指向实际驱动函数
 ...
}
...
// 向系统注册HAL    
static struct hw_module_methods_t consumerir_module_methods = {.open = consumerir_open,};
consumerir_module_t HAL_MODULE_INFO_SYM = {
    .common = {
        ...
        .methods            = &consumerir_module_methods,
    },
};

如果反这来看,其实就是完整的通过自定义系统服务来大同应用端和硬件设备端的调用。
这里特别提醒,为了保证API 的可见性。我们还需要更新current.txt
frameworks/base/api/current.txt

 public final class ConsumerIrManager.CarrierFrequencyRange {
    ctor public ConsumerIrManager.CarrierFrequencyRange(int, int);
    method public int getMaxFrequency();
    method public int getMinFrequency();
 }

部分还需要在frameworks/base/core/res/res/values/public.xml中注册新资源。
在系统源码中关于HIDL都会使用vts进行HIDL自动化测试。例子在源码中有很多自行参考。

有部分细节没有照顾到,还望补充和指正,谢谢~

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容