上一篇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的方式来读取后续的音频数据。
本文深入剖析Android SoundTrigger框架的唤醒事件回调机制,从HAL层的callback_thread_loop到APK层的接收,详细解释了callback指针的传递和事件的逐级上报过程,涉及JNI、C++ Framework、Java Framework和APK层的关键步骤。

3624

被折叠的 条评论
为什么被折叠?



