Android Framework源码解读 - Audio - SoundTrigger(3) - Callback

本文深入剖析Android SoundTrigger框架的唤醒事件回调机制,从HAL层的callback_thread_loop到APK层的接收,详细解释了callback指针的传递和事件的逐级上报过程,涉及JNI、C++ Framework、Java Framework和APK层的关键步骤。
摘要由CSDN通过智能技术生成

上一篇Android Framework源码解读 - Audio - SoundTrigger(2)已经完成了SoundTrigger的初始化流程,并在HAL层启动了callback_thread_loop线程来监听内核事件(也就是驱动检测到唤醒词后会上报uevent)。接下来就讲讲这个唤醒事件是如何通过callback方式一层层上报,最终被APK层收到的。

既然是callback方式,肯定是会涉及函数或是对象指针,而且是要从源头 - APK层开始一层层把指针设置到HAL层,最终被HAL层的callback_thread_loop用到。

所以,分析这个流程,一方面是从上到下理清callback指针的传递,另一方面是自下而上理清event的传递。本文先从后者开始,逐级推衍。

callback_thread_loop

./hardware/libhardware/modules/soundtrigger/sound_trigger_hw.c

唤醒词检测线程收到消息后,parse_socket_data解析消息内容,如果和唤醒事件COMMAND_RECOGNITION_TRIGGER一致,则send_event(EVENT_RECOGNITION);

bool parse_socket_data(int conn_socket, struct stub_sound_trigger_device* stdev) {

    while(!input_done) {
        if (fgets(buffer, PARSE_BUF_LEN, input_fp) != NULL) {
            pthread_mutex_lock(&stdev->lock);
            char* command = strtok(buffer, " \r\n");
            if (command == NULL) {
                write_bad_command_error(conn_socket, command);
            } else if (strcmp(command, COMMAND_RECOGNITION_TRIGGER) == 0) {
                send_event(conn_socket, stdev, EVENT_RECOGNITION,
                           RECOGNITION_STATUS_SUCCESS);
            } 
            ......
        }
    }

}

send_event再call内部函数send_event_with_handle,这里使用type是SOUND_MODEL_TYPE_GENERIC,代码片段如下:

void send_event_with_handle(sound_model_handle_t* model_handle_str,
          struct stub_sound_trigger_device* stdev, int event_type,
          int status) {

    if (event_type == EVENT_RECOGNITION) {
        ......
        if (model_context->model_type == SOUND_MODEL_TYPE_GENERIC) {
           struct sound_trigger_generic_recognition_event *event;
           event = (struct sound_trigger_generic_recognition_event *)
               sound_trigger_generic_event_alloc(model_context->model_handle,
                                               model_context->config, status);
           if (event) {
             model_context->recognition_callback(
                    event, model_context->recognition_cookie);
             free(event);
           }
        }
        ......

    }

    ......

}

可见,最后调用的是model_context->recognition_callback,也就涉及到了主题 - callback。于是接下来就要搞清它是哪里赋值的。

startRecognition

static int stdev_start_recognition(const struct sound_trigger_hw_device *dev,
                    sound_model_handle_t handle,
                    const struct sound_trigger_recognition_config *config,
                    recognition_callback_t callback,
                    void *cookie) {
    ......
    struct recognition_context *model_context = get_model_context(stdev, handle);
    free(model_context->config);
    model_context->config = NULL;
    if (config) {
        model_context->config = malloc(sizeof(*config));
        memcpy(model_context->config, config, sizeof(*config));
    }
    model_context->recognition_callback = callback;
    model_context->recognition_cookie = cookie;
    model_context->model_started = true;
    ......
    return 0;
}

找到了model_context->recognition_callback = callback;也就是startRecognition带来的入参recognition_callback_t callback,于是接下来就要搞清谁调用了startRecognition。这个前两篇文章已经有提到过:APK层会主动调用startRecognition,显然也是一层层(Java Framework层 -> JNI 层  -> C++ Framework层  -> HAL层)调用下来。我们还是采用自下而上的方式。

HAL层

/frameworks/av/services/soundtrigger/SoundTriggerHwService.cpp

status_t SoundTriggerHwService::Module::startRecognition(
                                sound_model_handle_t handle,
                                 const sp<IMemory>& dataMemory)
{
    ......
    //TODO: get capture handle and device from audio policy service
    config->capture_handle = model->mCaptureIOHandle;
    config->capture_device = model->mCaptureDevice;
    status_t status = mHalInterface->startRecognition(handle, config,
                              SoundTriggerHwService::recognitionCallback,
                              this);
    ......
    return status;
}


// static
void SoundTriggerHwService::recognitionCallback(
        struct sound_trigger_recognition_event *event,
                                           void *cookie)
{
    Module *module = (Module *)cookie;
    sp<SoundTriggerHwService> service = module->service().promote();
    service->sendRecognitionEvent(event, module);
}

SoundTriggerHwService的startRecognition把自己的static成员函数recognitionCallback传给了mHalInterface->startRecognition。走到了./frameworks/av/services/soundtrigger/SoundTriggerHalHidl.cpp

int SoundTriggerHalHidl::startRecognition(sound_model_handle_t handle,
               const struct sound_trigger_recognition_config *config,
               recognition_callback_t callback,
               void *cookie)
{
    ......
    sp<ISoundTriggerHw> soundtrigger = getService();
    sp<SoundModel> model = getModel(handle);

    model->mRecognitionCallback = callback;
    model->mRecognitionCookie = cookie;

    ISoundTriggerHw::RecognitionConfig *halConfig =
            convertRecognitionConfigToHal(config);

    Return<int32_t> hidlReturn(0);
    {
        AutoMutex lock(mHalLock);
        hidlReturn = soundtrigger->startRecognition(
                                model->mHalHandle, 
                                *halConfig, 
                                this, 
                                handle);
    }
    ......
    return hidlReturn;
}

sp soundtrigger = getService(); 得到的是BpSoundTriggerHw,而callback则被保存给了SoundModel对象的成员mRecognitionCallback

model->mRecognitionCallback = callback; 

然后调用BpSoundTriggerHw::startRecognition, 注意这第3个参数是 this指针。

ISoundTriggerHw接口是通过/hardware/interfaces/soundtrigger/2.0/ISoundTriggerHw.hal 文件在编译过程自动生成的,out/soong/.intermediates/hardware/interfaces/soundtrigger/2.0/android.hardware.soundtrigger@2.0_genc++/gen/android/hardware/soundtrigger/2.0/SoundTriggerHwAll.cpp

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值