Merge "Adding getModelState to soundtrigger with build fix. original cl was ag/4879522"

This commit is contained in:
Michael Dooley 2018-09-28 06:24:44 +00:00 committed by Android (Google) Code Review
commit b4a7ab6561
9 changed files with 469 additions and 2 deletions

View file

@ -247,7 +247,7 @@ exit:
}
SoundTriggerHalImpl::SoundTriggerHalImpl()
: mModuleName("primary"), mHwDevice(NULL), mNextModelId(1) {}
: mModuleName("primary"), mNextModelId(1), mHwDevice(NULL) {}
void SoundTriggerHalImpl::onFirstRef() {
const hw_module_t* mod;

View file

@ -167,8 +167,11 @@ class SoundTriggerHalImpl : public RefBase {
static void recognitionCallback(struct sound_trigger_recognition_event* halEvent, void* cookie);
const char* mModuleName;
struct sound_trigger_hw_device* mHwDevice;
volatile atomic_uint_fast32_t mNextModelId;
protected:
struct sound_trigger_hw_device* mHwDevice;
DefaultKeyedVector<int32_t, sp<SoundModelClient> > mClients;
Mutex mLock;
};

View file

@ -0,0 +1,20 @@
// This file is autogenerated by hidl-gen -Landroidbp.
hidl_interface {
name: "android.hardware.soundtrigger@2.2",
root: "android.hardware",
vndk: {
enabled: true,
},
srcs: [
"ISoundTriggerHw.hal",
],
interfaces: [
"android.hardware.audio.common@2.0",
"android.hardware.soundtrigger@2.0",
"android.hardware.soundtrigger@2.1",
"android.hidl.base@1.0",
],
gen_java: false,
}

View file

@ -0,0 +1,40 @@
/*
* Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.hardware.soundtrigger@2.2;
import @2.1::ISoundTriggerHw;
import @2.0::SoundModelHandle;
import @2.0::ISoundTriggerHwCallback.RecognitionEvent;
/**
* SoundTrigger HAL interface. Used for hardware recognition of hotwords.
*/
interface ISoundTriggerHw extends @2.1::ISoundTriggerHw {
/**
* Get the state of a given model.
* The model state is returned as a RecognitionEvent.
* @param modelHandle The handle of the sound model to use for recognition
* @return retval Operation completion status: 0 in case of success,
* -ENOSYS in case of invalid model handle,
* -ENOMEM in case of memory allocation failure,
* -ENODEV in case of initialization error.
* @return state RecognitionEvent in case of success
*/
getModelState(SoundModelHandle modelHandle)
generates (int32_t retval, RecognitionEvent state);
};

View file

@ -0,0 +1,50 @@
#
# Copyright (C) 2018 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := android.hardware.soundtrigger@2.2-impl
LOCAL_VENDOR_MODULE := true
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_SRC_FILES := \
SoundTriggerHw.cpp
LOCAL_CFLAGS := -Wall -Werror
LOCAL_SHARED_LIBRARIES := \
libhardware \
libhidlbase \
libhidlmemory \
libhidltransport \
liblog \
libutils \
android.hardware.soundtrigger@2.2 \
android.hardware.soundtrigger@2.1 \
android.hardware.soundtrigger@2.0 \
android.hardware.soundtrigger@2.0-core \
android.hidl.allocator@1.0 \
android.hidl.memory@1.0
LOCAL_C_INCLUDE_DIRS := $(LOCAL_PATH)
ifeq ($(strip $(AUDIOSERVER_MULTILIB)),)
LOCAL_MULTILIB := 32
else
LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
endif
include $(BUILD_SHARED_LIBRARY)

View file

@ -0,0 +1,110 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "SoundTriggerHw"
#include "SoundTriggerHw.h"
#include <android/log.h>
#include <utility>
namespace android {
namespace hardware {
namespace soundtrigger {
namespace V2_2 {
namespace implementation {
Return<void> SoundTriggerHw::getModelState_2_2(int32_t modelHandle, getModelState_cb hidl_cb) {
sp<SoundModelClient> client;
if (mHwDevice == NULL) {
hidl_cb(-ENODEV, NULL);
return Void();
}
{
AutoMutex lock(mLock);
client = mClients.valueFor(modelHandle);
if (client == 0) {
hidl_cb(-ENOSYS, NULL);
return Void();
}
}
if (mHwDevice->get_model_state == NULL) {
ALOGE("Failed to get model state from device, no such method");
hidl_cb(-ENODEV, NULL);
return Void();
}
// Get the state from the device (as a recognition event)
struct sound_trigger_recognition_event* event =
mHwDevice->get_model_state(mHwDevice, client->getHalHandle());
if (event == NULL) {
ALOGE("Failed to get model state from device");
hidl_cb(-ENODEV, NULL);
return Void();
}
// Allocate shared memory to return to the client
sp<IAllocator> alloc = IAllocator::getService("ashmem");
if (alloc == 0) {
ALOGE("Failed to retrieve ashmem allocator service");
free(event);
hidl_cb(-ENOMEM, NULL);
return Void();
}
// Note: Only generic recognition events are currently supported
int n_bytes = sizeof(struct sound_trigger_generic_recognition_event);
bool success = false;
const hidl_memory& mem;
Return<void> r = ashmem->allocate(n_bytes, [&](bool s, const hidl_memory& m) {
success = s;
if (success) mem = m;
});
if (r.isOk() && success) {
// Copy the event data to the shared memory
sp<IMemory> memory = mapMemory(mem);
if (memory != 0) {
struct sound_trigger_generic_recognition_event* data =
(struct sound_trigger_generic_recognition_event*)memory->getPointer();
memory->update();
*data = *event;
memory->commit();
// Return the event memory via this callback
hidl_cb(0, memory);
} else {
ALOGE("Failed to map memory for recognition event");
hidl_cb(-ENOMEM, NULL);
}
} else {
ALOGE("Failed to allocate %d bytes from ashmem allocator service", n_bytes);
hidl_cb(-ENOMEM, NULL);
}
free(event);
return Void();
}
ISoundTriggerHw* HIDL_FETCH_ISoundTriggerHw(const char* /* name */) {
return (new SoundTriggerHw())->getInterface();
}
} // namespace implementation
} // namespace V2_2
} // namespace soundtrigger
} // namespace hardware
} // namespace android

View file

@ -0,0 +1,114 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_HARDWARE_SOUNDTRIGGER_V2_2_SOUNDTRIGGERHW_H
#define ANDROID_HARDWARE_SOUNDTRIGGER_V2_2_SOUNDTRIGGERHW_H
#include <SoundTriggerHalImpl.h>
#include <android/hardware/soundtrigger/2.1/ISoundTriggerHw.h>
#include <android/hardware/soundtrigger/2.2/ISoundTriggerHw.h>
#include <hidl/Status.h>
namespace android {
namespace hardware {
namespace soundtrigger {
namespace V2_2 {
namespace implementation {
using ::android::sp;
using ::android::hardware::Return;
struct SoundTriggerHw : public V2_1::implementation::SoundTriggerHw {
SoundTriggerHw() = default;
ISoundTriggerHw* getInterface() { return new TrampolineSoundTriggerHw_2_2(this); }
protected:
virtual ~SoundTriggerHw() = default;
Return<sp<struct sound_trigger_recognition_event>> getModelState_2_2(
V2_0::SoundModelHandle modelHandle modelHandle);
private:
struct TrampolineSoundTriggerHw_2_2 : public ISoundTriggerHw {
explicit TrampolineSoundTriggerHw_2_2(sp<SoundTriggerHw> impl) : mImpl(impl) {}
// Methods from ::android::hardware::soundtrigger::V2_0::ISoundTriggerHw follow.
Return<void> getProperties(getProperties_cb _hidl_cb) override {
return mImpl->getProperties(_hidl_cb);
}
Return<void> loadSoundModel(const V2_0::ISoundTriggerHw::SoundModel& soundModel,
const sp<V2_0::ISoundTriggerHwCallback>& callback,
int32_t cookie, loadSoundModel_cb _hidl_cb) override {
return mImpl->loadSoundModel(soundModel, callback, cookie, _hidl_cb);
}
Return<void> loadPhraseSoundModel(const V2_0::ISoundTriggerHw::PhraseSoundModel& soundModel,
const sp<V2_0::ISoundTriggerHwCallback>& callback,
int32_t cookie,
loadPhraseSoundModel_cb _hidl_cb) override {
return mImpl->loadPhraseSoundModel(soundModel, callback, cookie, _hidl_cb);
}
Return<int32_t> unloadSoundModel(V2_0::SoundModelHandle modelHandle) override {
return mImpl->unloadSoundModel(modelHandle);
}
Return<int32_t> startRecognition(int32_t modelHandle,
const V2_0::ISoundTriggerHw::RecognitionConfig& config,
const sp<V2_0::ISoundTriggerHwCallback>& /*callback*/,
int32_t /*cookie*/) override {
return mImpl->startRecognition(modelHandle, config);
}
Return<int32_t> stopRecognition(V2_0::SoundModelHandle modelHandle) override {
return mImpl->stopRecognition(modelHandle);
}
Return<int32_t> stopAllRecognitions() override { return mImpl->stopAllRecognitions(); }
// Methods from V2_1::ISoundTriggerHw follow.
Return<void> loadSoundModel_2_1(const V2_1::ISoundTriggerHw::SoundModel& soundModel,
const sp<V2_1::ISoundTriggerHwCallback>& callback,
int32_t cookie, loadSoundModel_2_1_cb _hidl_cb) override {
return mImpl->loadSoundModel_2_1(soundModel, callback, cookie, _hidl_cb);
}
Return<void> loadPhraseSoundModel_2_1(
const V2_1::ISoundTriggerHw::PhraseSoundModel& soundModel,
const sp<V2_1::ISoundTriggerHwCallback>& callback, int32_t cookie,
loadPhraseSoundModel_2_1_cb _hidl_cb) override {
return mImpl->loadPhraseSoundModel_2_1(soundModel, callback, cookie, _hidl_cb);
}
Return<int32_t> startRecognition_2_1(int32_t modelHandle,
const V2_1::ISoundTriggerHw::RecognitionConfig& config,
const sp<V2_1::ISoundTriggerHwCallback>& /*callback*/,
int32_t /*cookie*/) override {
return mImpl->startRecognition_2_1(modelHandle, config);
}
// Methods from V2_2::ISoundTriggerHw follow.
Return<void> getModelState(int32_t modelHandle, getModelState_cb hidl_cb) override {
return mImpl->getModelState_2_2(modelHandle, hidl_cb);
}
private:
sp<SoundTriggerHw> mImpl;
};
};
extern "C" ISoundTriggerHw* HIDL_FETCH_ISoundTriggerHw(const char* name);
} // namespace implementation
} // namespace V2_2
} // namespace soundtrigger
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_SOUNDTRIGGER_V2_2_SOUNDTRIGGERHW_H

View file

@ -0,0 +1,29 @@
//
// Copyright (C) 2018 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
cc_test {
name: "VtsHalSoundtriggerV2_2TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalSoundtriggerV2_2TargetTest.cpp"],
static_libs: [
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
"android.hardware.soundtrigger@2.0",
"android.hardware.soundtrigger@2.1",
"android.hardware.soundtrigger@2.2",
"libhidlmemory"
],
}

View file

@ -0,0 +1,101 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "SoundTriggerHidlHalTest"
#include <stdlib.h>
#include <time.h>
#include <condition_variable>
#include <mutex>
#include <android/log.h>
#include <cutils/native_handle.h>
#include <log/log.h>
#include <android/hardware/audio/common/2.0/types.h>
#include <android/hardware/soundtrigger/2.0/ISoundTriggerHw.h>
#include <android/hardware/soundtrigger/2.2/ISoundTriggerHw.h>
#include <VtsHalHidlTargetTestBase.h>
#include <VtsHalHidlTargetTestEnvBase.h>
using ::android::sp;
using ::android::hardware::Return;
using ::android::hardware::soundtrigger::V2_0::ISoundTriggerHwCallback;
using ::android::hardware::soundtrigger::V2_0::SoundModelHandle;
using ::android::hardware::soundtrigger::V2_2::ISoundTriggerHw;
// Test environment for SoundTrigger HIDL HAL.
class SoundTriggerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
public:
// get the test environment singleton
static SoundTriggerHidlEnvironment* Instance() {
static SoundTriggerHidlEnvironment* instance = new SoundTriggerHidlEnvironment;
return instance;
}
void registerTestServices() override { registerTestService<ISoundTriggerHw>(); }
private:
SoundTriggerHidlEnvironment() {}
};
// The main test class for Sound Trigger HIDL HAL.
class SoundTriggerHidlTest : public ::testing::VtsHalHidlTargetTestBase {
public:
void SetUp() override {
mSoundTriggerHal = ::testing::VtsHalHidlTargetTestBase::getService<ISoundTriggerHw>(
SoundTriggerHidlEnvironment::Instance()->getServiceName<ISoundTriggerHw>());
ASSERT_NE(nullptr, mSoundTriggerHal.get());
}
static void SetUpTestCase() { srand(1234); }
void TearDown() override {}
protected:
sp<ISoundTriggerHw> mSoundTriggerHal;
};
/**
* Test ISoundTriggerHw::getModelState() method
*
* Verifies that:
* - the implementation returns -EINVAL with invalid model handle
*
*/
TEST_F(SoundTriggerHidlTest, GetModelStateInvalidModel) {
int ret = android::OK;
ISoundTriggerHwCallback::RecognitionEvent event;
SoundModelHandle handle = 0;
Return<void> hidlReturn =
mSoundTriggerHal->getModelState(handle, [&](int32_t retval, auto res) {
ret = retval;
event = res;
});
EXPECT_TRUE(hidlReturn.isOk());
EXPECT_EQ(-ENOSYS, ret);
}
int main(int argc, char** argv) {
::testing::AddGlobalTestEnvironment(SoundTriggerHidlEnvironment::Instance());
::testing::InitGoogleTest(&argc, argv);
SoundTriggerHidlEnvironment::Instance()->init(&argc, argv);
int status = RUN_ALL_TESTS();
ALOGI("Test result = %d", status);
return status;
}