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

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

上一篇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

BpSoundTriggerHw会被castFrom成BpHwSoundTriggerHw

::android::hardware::Return<int32_t> BpHwSoundTriggerHw::startRecognition(
  int32_t modelHandle, const ISoundTriggerHw::RecognitionConfig& config, 
  const ::android::sp<ISoundTriggerHwCallback>& callback, 
  int32_t cookie)
{
    ::android::hardware::Return<int32_t>  _hidl_out = 
    ::android::hardware::soundtrigger::V2_0::BpHwSoundTriggerHw::
    _hidl_startRecognition(this, this, modelHandle, 
                            config, callback, cookie);

    return _hidl_out;
}


::android::hardware::Return<int32_t> 
BpHwSoundTriggerHw::_hidl_startRecognition(
 ::android::hardware::IInterface *_hidl_this, 
 ::android::hardware::details::HidlInstrumentor *_hidl_this_inst, 
 int32_t modelHandle, 
 const ISoundTriggerHw::RecognitionConfig& config, 
 const ::android::sp<ISoundTriggerHwCallback>& callback, 
 int32_t cookie) {
    ......
    ::android::hardware::Parcel _hidl_data;
    ::android::hardware::Parcel _hidl_reply;
    ::android::status_t _hidl_err;
    ::android::hardware::Status _hidl_status;
    int32_t _hidl_out_retval;
    _hidl_err = _hidl_data.writeInterfaceToken(
                            BpHwSoundTriggerHw::descriptor);
    
    _hidl_err = _hidl_data.writeInt32(modelHandle);
    
    size_t _hidl_config_parent;
    _hidl_err = _hidl_data.writeBuffer(&config, 
                        sizeof(config), &_hidl_config_parent);

    _hidl_err = writeEmbeddedToParcel(
            config,
            &_hidl_data,
            _hidl_config_parent,
            0 /* parentOffset */);

    if (callback == nullptr) {
        _hidl_err = _hidl_data.writeStrongBinder(nullptr);
    } else {
        ::android::sp<::android::hardware::IBinder> _hidl_binder = 
                ::android::hardware::toBinder<
                                ISoundTriggerHwCallback>(callback);
        if (_hidl_binder.get() != nullptr) {
            _hidl_err = _hidl_data.writeStrongBinder(_hidl_binder);
        } else {
            _hidl_err = ::android::UNKNOWN_ERROR;
        }
    }
    _hidl_err = _hidl_data.writeInt32(cookie);

    ::android::hardware::ProcessState::self()->startThreadPool();
    _hidl_err = ::android::hardware::IInterface::
        asBinder(_hidl_this)->transact(5 /* startRecognition */, 
                                        _hidl_data, &_hidl_reply);
    if (_hidl_err != ::android::OK) { goto _hidl_error; }
    .....

_hidl_error:
    _hidl_status.setFromStatusT(_hidl_err);
    return ::android::hardware::Return<int32_t>(_hidl_status);
}

BpHwSoundTriggerHw::startRecognitiond的第3个参数:const ::android::sp& callback, 这里就是 SoundTriggerHalHidl对象this指针(SoundTriggerHalHidl.h可以看到它继承了ISoundTriggerHwCallback)。先记住这一点。

transact(5 /* startRecognition */, _hidl_data, &_hidl_reply); 就是binder通信发给服务端BnHwSoundTriggerHw,它的onTransact输到_hidl_code == 5,就调用_hidl_startRecognition(this, _hidl_data, _hidl_reply, _hidl_cb); 最终函数里调用了:int32_t _hidl_out_retval = static_cast(_hidl_this)->_hidl_mImpl->startRecognition(modelHandle, *config, callback, cookie);也就是BnHwSoundTriggerHw的具体实现类SoundTriggerHalImpl::startRecognition();

./hardware/interfaces/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp

Return<int32_t> SoundTriggerHalImpl::startRecognition(
        SoundModelHandle modelHandle,
        const ISoundTriggerHw::RecognitionConfig& config,
        const sp<ISoundTriggerHwCallback>& callback __unused,
       ISoundTriggerHwCallback::CallbackCookie cookie __unused)
{
    int32_t ret;
    sp<SoundModelClient> client;
    struct sound_trigger_recognition_config *halConfig;
    ......
    {
        AutoMutex lock(mLock);
        client = mClients.valueFor(modelHandle);
        if (client == 0) {
            ret = -ENOSYS;
            goto exit;
        }
    }
    halConfig = convertRecognitionConfigToHal(&config);
    ret = mHwDevice->start_recognition(mHwDevice, 
                     client->mHalHandle, halConfig,
                     recognitionCallback, 
                     client.get());

    free(halConfig);

exit:
    return ret;
}


// static
void SoundTriggerHalImpl::recognitionCallback(
          struct sound_trigger_recognition_event *halEvent,
                                               void *cookie)
{
    if (halEvent == NULL) {
        ALOGW("recognitionCallback call NULL event");
        return;
    }
    sp<SoundModelClient> client = 
      wp<SoundModelClient>(static_cast<SoundModelClient *>(
                                              cookie)).promote();

    ISoundTriggerHwCallback::RecognitionEvent *event = 
                     convertRecognitionEventFromHal(halEvent);
    event->model = client->mId;
    if (halEvent->type == SOUND_MODEL_TYPE_KEYPHRASE) {
        client->mCallback->phraseRecognitionCallback(
                (event)), client->mCookie);
    } else {
        client->mCallback->recognitionCallback(*event, client->mCookie);
    }
    delete event;
}

需要注意的一点是 binder客户端传过来的callback被弃用,置成了__unused, 取而代之的是自己的静态函数static void SoundTriggerHalImpl::recognitionCallback传递下去。调用mHwDevice->start_recognition(,,,recognitionCallback,);也就是最开始的 stdev_start_recognition函数。可见model->mRecognitionCallback = recognitionCallback;

所以,唤醒事件路径就变成:收到内核消息解析匹配后调用send_event(EVENT_RECOGNITION); ==> model_context->recognition_callback ==> SoundTriggerHalImpl::recognitionCallback {

sp<SoundModelClient> client;    

client->mCallback->recognitionCallback(*event, client->mCookie);

}  那接下来就要搞定这client是在哪里被创建,mCallBack又是哪里被赋值的。

loadSoundModel 

APK层调用startRecognition到了Java Framework层实际被分成了三个步骤:

./frameworks/base/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java 、./frameworks/base/core/java/android/hardware/soundtrigger/SoundTriggerModule.java

SoundTriggerHelper类收到startRecognition请求后,实际分了3个步骤:

① attachModule,③ startRecognitionLocked 前面篇章都已经讲过

② loadSoundModel 这个漏掉了,本次重点讲解。它定义在SoundTriggerModule类中,调用的是native方法, 即JNI方法 android_hardware_SoundTrigger_loadSoundModel来自./frameworks/base/core/jni/android_hardware_SoundTrigger.cpp 

static jint
android_hardware_SoundTrigger_loadSoundModel(
          JNIEnv *env, jobject thiz,
          jobject jSoundModel, jintArray jHandle)
{
    ......
    sp<SoundTrigger> module = getSoundTrigger(env, thiz);
    ......
    if (type == SOUND_MODEL_TYPE_GENERIC) {
        /* No initialization needed */
		ALOGD("loadSoundModel::GENERIC No initialization needed");
    }
    status = module->loadSoundModel(memory, &handle);
    ALOGD("loadSoundModel status %d handle %d", status, handle);

exit:
    ......
    return status;
}

sp module = getSoundTrigger(env, thiz); 得到了BpSoundTrigger

然后module ->loadSoundModel 也就是走./frameworks/av/soundtrigger/ISoundTrigger.cpp

BpSoundTrigger::transaction(LOAD_SOUND_MODEL) 被送达服务端 BnSoundTrigger::onTransaction(LOAD_SOUND_MODEL)调用对应实现类SoundTriggerHwService::ModuleClient::loadSoundModel ,再由SoundTriggerHwService::Module::loadSoundModel 走到Hal层的SoundTriggerHalHidl::loadSoundModel()

./frameworks/av/services/soundtrigger/SoundTriggerHwService.cpp
./frameworks/av/services/soundtrigger/SoundTriggerHalHidl.cpp
./hardware/interfaces/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp

SoundTriggerHalHidl::loadSoundModel(, 
            SoundTriggerHwService::soundModelCallback, , ) 
{
   sp<ISoundTriggerHw> soundtrigger = getService();
   hidlReturn = soundtrigger->loadSoundModel(*halSoundModel,
                 this, modelId, [&](int32_t retval, auto res) {
                 ret = retval;
                 halHandle = res;
               });
   if (hidlReturn ) { 
        sp<SoundModel> model = new SoundModel(*handle, 
                                soundModelCallback, 
                                cookie, halHandle); 
   }
}

上面已经提到sp soundtrigger = getService(); 得到的是BpHwSoundTriggerHw,注意第2个参数 soundtrigger->loadSoundModel(,  this, , , )

::android::hardware::Return<void> BpHwSoundTriggerHw::loadSoundModel(
    const ISoundTriggerHw::SoundModel& soundModel, 
    const ::android::sp<ISoundTriggerHwCallback>& callback, 
    int32_t cookie, loadSoundModel_cb _hidl_cb){
    ::android::hardware::Return<void>  _hidl_out = 
    ::android::hardware::soundtrigger::V2_0::BpHwSoundTriggerHw::
    _hidl_loadSoundModel(this, this, soundModel, callback, cookie, _hidl_cb);

    return _hidl_out;
}

::android::hardware::Return<void> 
  BpHwSoundTriggerHw::_hidl_loadSoundModel(
   ::android::hardware::IInterface *_hidl_this, 
  ::android::hardware::details::HidlInstrumentor *_hidl_this_inst, 
  const ISoundTriggerHw::SoundModel& soundModel, 
  const ::android::sp<ISoundTriggerHwCallback>& callback, 
  int32_t cookie, loadSoundModel_cb _hidl_cb) {
    ......
    ::android::hardware::Parcel _hidl_data;
    ::android::hardware::Parcel _hidl_reply;
    ::android::status_t _hidl_err;
    ::android::hardware::Status _hidl_status;

    _hidl_err = _hidl_data.writeInterfaceToken(
                                   BpHwSoundTriggerHw::descriptor);
 
    size_t _hidl_soundModel_parent;
    _hidl_err = _hidl_data.writeBuffer(&soundModel, 
                      sizeof(soundModel), &_hidl_soundModel_parent);

    _hidl_err = writeEmbeddedToParcel(
            soundModel,
            &_hidl_data,
            _hidl_soundModel_parent,
            0 /* parentOffset */);

    if (callback == nullptr) {
        _hidl_err = _hidl_data.writeStrongBinder(nullptr);
    } else {
        ::android::sp<::android::hardware::IBinder> _hidl_binder =
                  ::android::hardware::toBinder<
                                ISoundTriggerHwCallback>(callback);
        if (_hidl_binder.get() != nullptr) {
            _hidl_err = _hidl_data.writeStrongBinder(_hidl_binder);
        } else {
            _hidl_err = ::android::UNKNOWN_ERROR;
        }
    }
    _hidl_err = _hidl_data.writeInt32(cookie);

    ::android::hardware::ProcessState::self()->startThreadPool();
    _hidl_err = ::android::hardware::IInterface::asBinder(
                _hidl_this)->transact(2 /* loadSoundModel */, 
                                         _hidl_data, &_hidl_reply);

    ......
_hidl_error:
    _hidl_status.setFromStatusT(_hidl_err);
    return ::android::hardware::Return<void>(_hidl_status);
}

和上面的startRecognition一样的逻辑,BpHwSoundTriggerHw::loadSoundModel的第2个参数:const ::android::sp& callback, 这里就是 SoundTriggerHalHidl对象this指针(SoundTriggerHalHidl.h可以看到它继承了ISoundTriggerHwCallback)。先记住这一点。

到了服务端后它的具体实现类SoundTriggerHalImpl::loadSoundModel();

./hardware/interfaces/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp

调用内部方法doLoadSoundModel:

int SoundTriggerHalImpl::doLoadSoundModel(
      const ISoundTriggerHw::SoundModel& soundModel,
      const sp<ISoundTriggerHwCallback>& callback,            
      ISoundTriggerHwCallback::CallbackCookie cookie,                        
      uint32_t *modelId)
{
    int32_t ret = 0;
    struct sound_trigger_sound_model *halSoundModel;
    *modelId = 0;
    sp<SoundModelClient> client;
    client = new SoundModelClient(*modelId, callback, cookie);

    ret = mHwDevice->load_sound_model(mHwDevice, halSoundModel, 
                                    soundModelCallback, 
                               client.get(), &client->mHalHandle);
    ......
exit:
    return ret;
}

class SoundModelClient : public RefBase {
public:
	SoundModelClient(uint32_t id, sp<ISoundTriggerHwCallback> callback,
					 ISoundTriggerHwCallback::CallbackCookie cookie)
		: mId(id), mCallback(callback), mCookie(cookie) {
	}
	virtual ~SoundModelClient() {}

	uint32_t mId;
	sound_model_handle_t mHalHandle;
	sp<ISoundTriggerHwCallback> mCallback;
	ISoundTriggerHwCallback::CallbackCookie mCookie;
};

这里终于找到了SoundModelClient创建的地方。而且callback被传了进去。

所以,唤醒事件路径就变成:收到内核消息解析匹配后调用send_event(EVENT_RECOGNITION); ==> model_context->recognition_callback ==> SoundTriggerHalImpl::recognitionCallback ==> SoundTriggerHalHidl::recognitionCallback

::android::hardware::Return<void> SoundTriggerHalHidl::recognitionCallback(
        const ISoundTriggerHwCallback::RecognitionEvent& halEvent,
        CallbackCookie cookie)
{
    sp<SoundModel> model;
    {
        AutoMutex lock(mLock);
        model = mSoundModels.valueFor((SoundModelHandle)cookie);
        if (model == 0) {
            return Return<void>();
        }
    }
    struct sound_trigger_recognition_event *event = 
 convertRecognitionEventFromHal(&halEvent);
    if (event == NULL) {
        return Return<void>();
    }
    event->model = model->mHandle;
    model->mRecognitionCallback(event, model->mRecognitionCookie);

    free(event);

    return Return<void>();
}

最后走的是model->mRecognitionCallback(event, model->mRecognitionCookie);这个model是在SoundTriggerHalHidl::loadSoundModel函数里面创建的sp model = new SoundModel(*handle, soundModelcallback, cookie, halHandle);但是构造函数里面mRecognitionCallback被默认设置成了NULL。所以还需要找到它赋值的地方。

实际mRecognitinCallBack需要等到startRecogniton的时候做赋值

SoundTriggerHalHidl::startRecognition(, ,  
    recognition_callback_t callback,  
    void *cookie)  {
   ......
   model->mRecognitionCallback = callback;
   ......
}  

结合上一章节的内容,这个callback实际就是静态函数SoundTriggerHwService::recognitionCallback。

所以,唤醒事件路径就变成:收到内核消息解析匹配后调用send_event(EVENT_RECOGNITION); ==> model_context->recognition_callback ==> SoundTriggerHalImpl::recognitionCallback ==> SoundTriggerHalHidl::recognitionCallback ==> SoundTriggerHwService::recognitionCallback

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

SoundTriggerHwService::recognitionCallback => SoundTriggerHwService::sendRecognitionEvent 会将mCallbackThread唤醒,接着就看mCallbackThread->sendCallbackEvent  =>SoundTriggerHwService::Module::onCallbackEvent(TYPE_RECOGNITION)

void SoundTriggerHwService::Module::onCallbackEvent(
                        const sp<CallbackEvent>& event)
{
    ......
    switch (event->mType) {
    case CallbackEvent::TYPE_RECOGNITION: {
       struct sound_trigger_recognition_event *recognitionEvent =
       (struct sound_trigger_recognition_event *)eventMemory->pointer();
       sp<ISoundTriggerClient> client;
       {
            AutoMutex lock(mLock);
            sp<Model> model = getModel(recognitionEvent->model);
            if (model == 0) {
                ALOGW("%s model == 0", __func__);
                return;
            }
            if (model->mState != Model::STATE_ACTIVE) {
                return;
            }

            recognitionEvent->capture_session = model->mCaptureSession;
            model->mState = Model::STATE_IDLE;
            client = model->mModuleClient->client();
       }
       if (client != 0) {
          client->onRecognitionEvent(eventMemory);
       }
    } break;
    .......
    default:
        LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", 
                            event->mType);
    }
}

./frameworks/av/soundtrigger/ISoundTriggerClient.cpp
./frameworks/av/soundtrigger/SoundTrigger.cpp 

sp client->onRecognitionEvent实际是BpSoundTriggerClient::onRecognitionEvent => remote()->transact(ON_RECOGNITION_EVENT,,)  到达服务端 BnSoundTriggerClient::onRecognitionEvent 其对应的具体实现类是class SoundTrigger::onRecognitionEvent => spmCallback->onRecognitionEvent, 所以接下来任务就是【mCallback】是在哪里赋值的了。


./frameworks/base/core/jni/android_hardware_SoundTrigger.cpp
./frameworks/av/soundtrigger/SoundTrigger.cpp 
./frameworks/av/services/soundtrigger/SoundTriggerHwService.cpp
./frameworks/av/soundtrigger/ISoundTriggerHwService.cpp 

APK层的startRecognition到了JNI层,调用的是 android_hardware_SoundTrigger_setup函数创建了一个callback = new JNISoundTriggerCallback(env, thiz, weak_this); 然后调用SoundTrigger::attach(handle, callback);在静态方法attach函数里创建soundTrigger = new SoundTrigger(module, callback); 注意它继承了BnSoundTriggerClient。所以【mCallback】就是JNISoundTriggerCallback。

所以,唤醒事件路径就变成:收到内核消息解析匹配后调用send_event(EVENT_RECOGNITION); ==> model_context->recognition_callback ==> SoundTriggerHalImpl::recognitionCallback ==> SoundTriggerHalHidl::recognitionCallback ==> SoundTriggerHwService::recognitionCallback ==> JNISoundTriggerCallback::onRecognitionEvent

接下来就要看APK层和Java Framework层是怎么把它们的callback和 这里JNI层的callback关联起来的。

JAVA 层

APK层的SoundTriggerTestService.java类实现的startRecognition方法如下图,

实际是通过Java Framework层的SoundTriggerManager它创建SoundTriggerDetector对象,再由detector来调用startRecognition 。

./frameworks/base/media/java/android/media/soundtrigger/SoundTriggerManager.java
./frameworks/base/media/java/android/media/soundtrigger/SoundTriggerDetector.java


创建detector对象的时候,APK的callback入参被写到mCallback,然后自己又创建了mRecognitionCallback

可这和我们要讲的JNISoundTriggerCallback似乎没关联呀,所以还得继续往下看。

./frameworks/base/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
.../voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java

这里看到detector的mRecognitionCallback被传给了 SoundTriggerService::startRecognition走的是BpSoundTriggerService::mRemote.transact(Stub.TRANSACTION_startRecognition, _data, _reply, 0); 到了服务端BnSoundTriggerService调用SoundTriggerHelper类的startGenericRecogniton(, , callback, )

startGenericRecogniton(, , callback, ) { 
    startRecogniton(, modelData, callback, ,) {   
        SoundTrigger.attachModule(, this, ); 
        modelData.setCallback(callback);   
        startRecognitionLocked(modelData, false);
    } 
}

./frameworks/base/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
./frameworks/base/core/java/android/hardware/soundtrigger/SoundTrigger.java
./frameworks/base/core/jni/android_hardware_SoundTrigger.cpp

SoundTrigger.attachModule(, this, );  => this最终给了SoundTriggerModule类         modelData.setCallback(callback);  =>把上层(detector的mRecognitionCallback)的callback存到了modelData对象中。

SoundTriggerModule的Java类对象this指针被存到了JNISoundTriggerCallback::mObject中。

JNISoundTriggerCallback收到onRecognitionEvent后调用了CallStaticVoidMethod的gPostEventFromNative方法参数就包含了mObject。  gPostEventFromNative = GetStaticMethodIDOrDie(env, moduleClass, "postEventFromNative",   "(Ljava/lang/Object;IIILjava/lang/Object;)V"); 实际也就是调用了SoundTriggerModule::postEventFromNative

SoundTriggerModule::postEventFromNative最后就和NativeEventHandlerDelegate对接上了。 一个负责发消息,一个负责接收消息。
delegate收到消息后调了listener.onRecognition 而这个listener就是SoundTriggerHelper对象实例。它的onRecognition会调用内部方法:onGenericRecognitionSuccessLocked

onGenericRecognitionSuccessLocked() {   
     ModelData model = getModelDataForLocked(event.soundModelHandle);  
     IRecognitionStatusCallback callback = model.getCallback(); 
	 callback.onGenericSoundTriggerDetected(...); 
}

之前SoundTriggerHelper类的startRecognition -> startGenericRecogniton已经把上层(SoundTriggerDetector的mRecognitionCallback)的callback存到了modelData对象中, 这里被get出来,然后调了onGenericSoundTriggerDetected(), 也就等于调用了SoundTriggerDetector::mRecognitionCallback.onGenericSoundTriggerDetected(); 

./frameworks/base/media/java/android/media/soundtrigger/SoundTriggerDetector.java

创建detector对象的时候,APK的callback入参被写到mCallback,然后detector自己创建了mRecognitionCallback。其中 class RecognitionCallback extends IRecognitionStatusCallback.Stub(/frameworks/base/core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl

还创建了 mHandler = new MyHandler(); 用到了Handler机制。

当detector收到onGenericSoundTriggerDetected消息后使用Handler机制将消息传给mCallBack.onDetected实际就是APK层创建的new DetectorCallBack(modelInfo);

小结

所以,唤醒事件路径(自下而上)就最终变成:收到内核消息解析匹配后调用send_event(EVENT_RECOGNITION); ==> model_context->recognition_callback ==> SoundTriggerHalImpl::recognitionCallback ==> SoundTriggerHalHidl::recognitionCallback  (把this指针通过binder传给了前者) ==> SoundTriggerHwService::recognitionCallback  => BpSoundTriggerClient::onRecognitionEvent  => SoundTrigger::onRecognitionEvent(binder服务端,BnSoundTriggerClient)  【C++ Framework层】  ==> JNISoundTriggerCallback::onRecognitionEvent 【JNI层】 ==》SoundTriggerModule::postEventFromNative (把this指针通过JNI方式传给了前者) -> SoundTriggerHelper::onRecognition (把this指针传给了前者) => SoundTriggerDetector::onGenericSoundTriggerDetected 【Java Framework层】 => DetectorCallBack::onDetected 【APK层】

这个路径是相对复杂了,各种函数指针,类对象this指针的传递,而且还用到Handler机制。

总结

这个唤醒事件上报流程分析完, 整个soundtrigger框架(主要负责的是声学唤醒词的识别)就基本搞定:

也就是APK层负责attachModule、loadSoundModel,startRecognition,同时创建好回调callback。等startRecognition成功后,HAL层就在等待驱动唤醒事件,如果驱动识别到唤醒词,唤醒事件就会通过callback告诉APK层。APK层收到事件后,就开始通过AudioRecord的方式来读取后续的音频数据。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值