Merge "Move Keymaster wrapper into support library."
diff --git a/automotive/vehicle/2.0/IVehicle.hal b/automotive/vehicle/2.0/IVehicle.hal
index d962de0..1b1d391 100644
--- a/automotive/vehicle/2.0/IVehicle.hal
+++ b/automotive/vehicle/2.0/IVehicle.hal
@@ -43,7 +43,7 @@
* For VehiclePropertyChangeMode::ON_CHANGE properties, it must return the
* latest available value.
*
- * Some properties like AUDIO_VOLUME requires to pass additional data in
+ * Some properties like RADIO_PRESET requires to pass additional data in
* GET request in VehiclePropValue object.
*
* If there is no data available yet, which can happen during initial stage,
diff --git a/camera/device/3.2/default/CameraDevice.cpp b/camera/device/3.2/default/CameraDevice.cpp
index 295ee32..dfbb976 100644
--- a/camera/device/3.2/default/CameraDevice.cpp
+++ b/camera/device/3.2/default/CameraDevice.cpp
@@ -40,9 +40,11 @@
mCameraDeviceNames(cameraDeviceNames) {
mCameraIdInt = atoi(mCameraId.c_str());
// Should not reach here as provider also validate ID
- if (mCameraIdInt < 0 || mCameraIdInt >= module->getNumberOfCameras()) {
+ if (mCameraIdInt < 0) {
ALOGE("%s: Invalid camera id: %s", __FUNCTION__, mCameraId.c_str());
mInitFail = true;
+ } else if (mCameraIdInt >= mModule->getNumberOfCameras()) {
+ ALOGI("%s: Adding a new camera id: %s", __FUNCTION__, mCameraId.c_str());
}
mDeviceVersion = mModule->getDeviceVersion(mCameraIdInt);
diff --git a/camera/provider/2.4/default/CameraProvider.cpp b/camera/provider/2.4/default/CameraProvider.cpp
index ed974a5..e9588a7 100644
--- a/camera/provider/2.4/default/CameraProvider.cpp
+++ b/camera/provider/2.4/default/CameraProvider.cpp
@@ -66,6 +66,46 @@
using ::android::hardware::camera::common::V1_0::CameraMetadataType;
using ::android::hardware::camera::common::V1_0::Status;
+void CameraProvider::addDeviceNames(int camera_id, CameraDeviceStatus status, bool cam_new)
+{
+ char cameraId[kMaxCameraIdLen];
+ snprintf(cameraId, sizeof(cameraId), "%d", camera_id);
+ std::string cameraIdStr(cameraId);
+
+ mCameraIds.add(cameraIdStr);
+
+ // initialize mCameraDeviceNames and mOpenLegacySupported
+ mOpenLegacySupported[cameraIdStr] = false;
+ int deviceVersion = mModule->getDeviceVersion(camera_id);
+ auto deviceNamePair = std::make_pair(cameraIdStr,
+ getHidlDeviceName(cameraIdStr, deviceVersion));
+ mCameraDeviceNames.add(deviceNamePair);
+ if (cam_new) {
+ mCallbacks->cameraDeviceStatusChange(deviceNamePair.second, status);
+ }
+ if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_2 &&
+ mModule->isOpenLegacyDefined()) {
+ // try open_legacy to see if it actually works
+ struct hw_device_t* halDev = nullptr;
+ int ret = mModule->openLegacy(cameraId, CAMERA_DEVICE_API_VERSION_1_0, &halDev);
+ if (ret == 0) {
+ mOpenLegacySupported[cameraIdStr] = true;
+ halDev->close(halDev);
+ deviceNamePair = std::make_pair(cameraIdStr,
+ getHidlDeviceName(cameraIdStr, CAMERA_DEVICE_API_VERSION_1_0));
+ mCameraDeviceNames.add(deviceNamePair);
+ if (cam_new) {
+ mCallbacks->cameraDeviceStatusChange(deviceNamePair.second, status);
+ }
+ } else if (ret == -EBUSY || ret == -EUSERS) {
+ // Looks like this provider instance is not initialized during
+ // system startup and there are other camera users already.
+ // Not a good sign but not fatal.
+ ALOGW("%s: open_legacy try failed!", __FUNCTION__);
+ }
+ }
+}
+
/**
* static callback forwarding methods from HAL to instance
*/
@@ -75,6 +115,7 @@
int new_status) {
CameraProvider* cp = const_cast<CameraProvider*>(
static_cast<const CameraProvider*>(callbacks));
+ bool found = false;
if (cp == nullptr) {
ALOGE("%s: callback ops is null", __FUNCTION__);
@@ -92,8 +133,13 @@
if (cameraIdStr.compare(deviceNamePair.first) == 0) {
cp->mCallbacks->cameraDeviceStatusChange(
deviceNamePair.second, status);
+ found = true;
}
}
+
+ if (!found) {
+ cp->addDeviceNames(camera_id, status, true);
+ }
}
}
@@ -251,32 +297,8 @@
snprintf(cameraId, sizeof(cameraId), "%d", i);
std::string cameraIdStr(cameraId);
mCameraStatusMap[cameraIdStr] = CAMERA_DEVICE_STATUS_PRESENT;
- mCameraIds.add(cameraIdStr);
- // initialize mCameraDeviceNames and mOpenLegacySupported
- mOpenLegacySupported[cameraIdStr] = false;
- int deviceVersion = mModule->getDeviceVersion(i);
- mCameraDeviceNames.add(
- std::make_pair(cameraIdStr,
- getHidlDeviceName(cameraIdStr, deviceVersion)));
- if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_2 &&
- mModule->isOpenLegacyDefined()) {
- // try open_legacy to see if it actually works
- struct hw_device_t* halDev = nullptr;
- int ret = mModule->openLegacy(cameraId, CAMERA_DEVICE_API_VERSION_1_0, &halDev);
- if (ret == 0) {
- mOpenLegacySupported[cameraIdStr] = true;
- halDev->close(halDev);
- mCameraDeviceNames.add(
- std::make_pair(cameraIdStr,
- getHidlDeviceName(cameraIdStr, CAMERA_DEVICE_API_VERSION_1_0)));
- } else if (ret == -EBUSY || ret == -EUSERS) {
- // Looks like this provider instance is not initialized during
- // system startup and there are other camera users already.
- // Not a good sign but not fatal.
- ALOGW("%s: open_legacy try failed!", __FUNCTION__);
- }
- }
+ addDeviceNames(i);
}
return false; // mInitFailed
diff --git a/camera/provider/2.4/default/CameraProvider.h b/camera/provider/2.4/default/CameraProvider.h
index 4980711..2cf251e 100644
--- a/camera/provider/2.4/default/CameraProvider.h
+++ b/camera/provider/2.4/default/CameraProvider.h
@@ -112,6 +112,9 @@
const struct camera_module_callbacks* callbacks,
const char* camera_id,
int new_status);
+
+ void addDeviceNames(int camera_id, CameraDeviceStatus status = CameraDeviceStatus::PRESENT,
+ bool cam_new = false);
};
extern "C" ICameraProvider* HIDL_FETCH_ICameraProvider(const char* name);
diff --git a/health/2.0/Android.bp b/health/2.0/Android.bp
index 97704bf..c444165 100644
--- a/health/2.0/Android.bp
+++ b/health/2.0/Android.bp
@@ -18,6 +18,7 @@
types: [
"Result",
"DiskStats",
+ "HealthInfo",
"StorageAttribute",
"StorageInfo",
],
diff --git a/health/2.0/IHealth.hal b/health/2.0/IHealth.hal
index fbcc89f..230b5d0 100644
--- a/health/2.0/IHealth.hal
+++ b/health/2.0/IHealth.hal
@@ -160,4 +160,15 @@
* The mapping is index 0->sda, 1->sdb and so on.
*/
getDiskStats() generates (Result result, vec<DiskStats> value);
+
+ /**
+ * Get Health Information.
+ *
+ * @return result SUCCESS if successful,
+ * NOT_SUPPORTED if this API is not supported,
+ * UNKNOWN for other errors.
+ * @return value Health information, to be ignored if result is not
+ * SUCCESS.
+ */
+ getHealthInfo() generates (Result result, @2.0::HealthInfo value);
};
diff --git a/health/2.0/IHealthInfoCallback.hal b/health/2.0/IHealthInfoCallback.hal
index 8e17bb9..737ea72 100644
--- a/health/2.0/IHealthInfoCallback.hal
+++ b/health/2.0/IHealthInfoCallback.hal
@@ -28,5 +28,5 @@
* registered callbacks after health info changes.
* @param info the updated HealthInfo
*/
- oneway healthInfoChanged(HealthInfo info);
+ oneway healthInfoChanged(@1.0::HealthInfo info);
};
diff --git a/health/2.0/default/Health.cpp b/health/2.0/default/Health.cpp
index e67cdb4..b1227a3 100644
--- a/health/2.0/default/Health.cpp
+++ b/health/2.0/default/Health.cpp
@@ -18,6 +18,7 @@
#include <health2/Health.h>
+#include <hal_conversion.h>
#include <hidl/HidlTransportSupport.h>
extern void healthd_battery_update_internal(bool);
@@ -199,6 +200,39 @@
return Void();
}
+Return<void> Health::getHealthInfo(getHealthInfo_cb _hidl_cb) {
+ using android::hardware::health::V1_0::hal_conversion::convertToHealthInfo;
+
+ update();
+ struct android::BatteryProperties p = getBatteryProperties(battery_monitor_.get());
+
+ V1_0::HealthInfo batteryInfo;
+ convertToHealthInfo(&p, batteryInfo);
+
+ std::vector<StorageInfo> info;
+ get_storage_info(info);
+
+ std::vector<DiskStats> stats;
+ get_disk_stats(stats);
+
+ int32_t currentAvg = 0;
+
+ struct BatteryProperty prop;
+ status_t ret = battery_monitor_->getProperty(BATTERY_PROP_CURRENT_AVG, &prop);
+ if (ret == OK) {
+ currentAvg = static_cast<int32_t>(prop.valueInt64);
+ }
+
+ V2_0::HealthInfo healthInfo = {};
+ healthInfo.legacy = std::move(batteryInfo);
+ healthInfo.batteryCurrentAverage = currentAvg;
+ healthInfo.diskStats = stats;
+ healthInfo.storageInfos = info;
+
+ _hidl_cb(Result::SUCCESS, healthInfo);
+ return Void();
+}
+
void Health::serviceDied(uint64_t /* cookie */, const wp<IBase>& who) {
(void)unregisterCallbackInternal(who.promote());
}
diff --git a/health/2.0/default/include/health2/Health.h b/health/2.0/default/include/health2/Health.h
index 41ba9e9..fc86789 100644
--- a/health/2.0/default/include/health2/Health.h
+++ b/health/2.0/default/include/health2/Health.h
@@ -52,6 +52,7 @@
Return<void> getChargeStatus(getChargeStatus_cb _hidl_cb) override;
Return<void> getStorageInfo(getStorageInfo_cb _hidl_cb) override;
Return<void> getDiskStats(getDiskStats_cb _hidl_cb) override;
+ Return<void> getHealthInfo(getHealthInfo_cb _hidl_cb) override;
// Methods from ::android::hidl::base::V1_0::IBase follow.
Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args) override;
diff --git a/health/2.0/libhealthhalutils/Android.bp b/health/2.0/libhealthhalutils/Android.bp
index 1bd934b..5686520 100644
--- a/health/2.0/libhealthhalutils/Android.bp
+++ b/health/2.0/libhealthhalutils/Android.bp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+// Convenience library for (hwbinder) clients to choose the correct health
+// service instance.
cc_library_static {
name: "libhealthhalutils",
srcs: ["HealthHalUtils.cpp"],
diff --git a/health/2.0/libstoragehealthdefault/Android.bp b/health/2.0/libstoragehealthdefault/Android.bp
index 986e1ef..cef04fe 100644
--- a/health/2.0/libstoragehealthdefault/Android.bp
+++ b/health/2.0/libstoragehealthdefault/Android.bp
@@ -1,5 +1,22 @@
-// Copyright 2018 The Android Open Source Project
+/*
+ * 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.
+ */
+// Default implementation for (passthrough) clients that statically links to
+// android.hardware.health@2.0-impl but do no query for storage related
+// information.
cc_library_static {
srcs: ["StorageHealthDefault.cpp"],
name: "libhealthstoragedefault",
diff --git a/health/2.0/types.hal b/health/2.0/types.hal
index 4e7a081..c74076e 100644
--- a/health/2.0/types.hal
+++ b/health/2.0/types.hal
@@ -124,3 +124,31 @@
*/
StorageAttribute attr;
};
+
+/**
+ * Combined Health Information.
+ */
+struct HealthInfo {
+ /**
+ * V1.0 HealthInfo.
+ * If a member is unsupported, it is filled with:
+ * - 0 (for integers);
+ * - false (for booleans);
+ * - empty string (for strings);
+ * - UNKNOWN (for BatteryStatus and BatteryHealth).
+ */
+ @1.0::HealthInfo legacy;
+ /**
+ * Average battery current in uA. Will be 0 if unsupported.
+ */
+ int64_t batteryCurrentAverage;
+ /**
+ * Disk Statistics. Will be an empty vector if unsupported.
+ */
+ vec<DiskStats> diskStats;
+ /**
+ * Information on storage devices. Will be an empty vector if
+ * unsupported.
+ */
+ vec<StorageInfo> storageInfos;
+};
diff --git a/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp b/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
index b2c6160..85dab44 100644
--- a/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
+++ b/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
@@ -35,7 +35,6 @@
namespace V2_0 {
using V1_0::BatteryStatus;
-using V1_0::HealthInfo;
// Test environment for graphics.composer
class HealthHidlEnvironment : public VtsHalHidlTargetTestEnvBase {
@@ -69,7 +68,7 @@
class Callback : public IHealthInfoCallback {
public:
- Return<void> healthInfoChanged(const HealthInfo&) override {
+ Return<void> healthInfoChanged(const V1_0::HealthInfo&) override {
std::lock_guard<std::mutex> lock(mMutex);
mInvoked = true;
mInvokedNotify.notify_all();
@@ -203,6 +202,43 @@
return true;
}
+template <typename T>
+bool verifyEnum(T value) {
+ for (auto it : hidl_enum_iterator<T>()) {
+ if (it == value) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool verifyHealthInfo(const HealthInfo& health_info) {
+ if (!verifyStorageInfo(health_info.storageInfos) || !verifyDiskStats(health_info.diskStats)) {
+ return false;
+ }
+
+ using V1_0::BatteryStatus;
+ using V1_0::BatteryHealth;
+
+ if (!((health_info.legacy.batteryChargeCounter > 0) &&
+ (health_info.legacy.batteryCurrent != INT32_MIN) &&
+ (0 <= health_info.legacy.batteryLevel && health_info.legacy.batteryLevel <= 100) &&
+ verifyEnum<BatteryHealth>(health_info.legacy.batteryHealth) &&
+ (health_info.legacy.batteryStatus != BatteryStatus::UNKNOWN) &&
+ verifyEnum<BatteryStatus>(health_info.legacy.batteryStatus))) {
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * Tests the values returned by getChargeCounter(),
+ * getCurrentNow(), getCurrentAverage(), getCapacity(), getEnergyCounter(),
+ * getChargeStatus(), getStorageInfo(), getDiskStats() and getHealthInfo() from
+ * interface IHealth.
+ */
TEST_F(HealthHidlTest, Properties) {
EXPECT_OK(mHealth->getChargeCounter([](auto result, auto value) {
EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value > 0);
@@ -222,15 +258,17 @@
EXPECT_OK(mHealth->getChargeStatus([](auto result, auto value) {
EXPECT_VALID_OR_UNSUPPORTED_PROP(
result, toString(value),
- value == BatteryStatus::CHARGING || value == BatteryStatus::DISCHARGING ||
- value == BatteryStatus::NOT_CHARGING || value == BatteryStatus::FULL);
+ value != BatteryStatus::UNKNOWN && verifyEnum<BatteryStatus>(value));
}));
EXPECT_OK(mHealth->getStorageInfo([](auto result, auto& value) {
- EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), (verifyStorageInfo(value)));
+ EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), verifyStorageInfo(value));
}));
EXPECT_OK(mHealth->getDiskStats([](auto result, auto& value) {
EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), verifyDiskStats(value));
}));
+ EXPECT_OK(mHealth->getHealthInfo([](auto result, auto& value) {
+ EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), verifyHealthInfo(value));
+ }));
}
} // namespace V2_0
diff --git a/soundtrigger/2.0/default/Android.bp b/soundtrigger/2.0/default/Android.bp
new file mode 100644
index 0000000..cc20f91
--- /dev/null
+++ b/soundtrigger/2.0/default/Android.bp
@@ -0,0 +1,43 @@
+//
+// 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_library_shared {
+ name: "android.hardware.soundtrigger@2.0-core",
+ defaults: ["hidl_defaults"],
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "SoundTriggerHalImpl.cpp",
+ ],
+
+ export_include_dirs: ["."],
+
+ shared_libs: [
+ "libhidlbase",
+ "libhidltransport",
+ "liblog",
+ "libutils",
+ "libhardware",
+ "android.hardware.soundtrigger@2.0",
+ "android.hardware.audio.common@2.0",
+ ],
+
+ header_libs: [
+ "libaudio_system_headers",
+ "libhardware_headers",
+ ],
+}
diff --git a/soundtrigger/2.0/default/Android.mk b/soundtrigger/2.0/default/Android.mk
index 9262858..835a020 100644
--- a/soundtrigger/2.0/default/Android.mk
+++ b/soundtrigger/2.0/default/Android.mk
@@ -18,23 +18,20 @@
include $(CLEAR_VARS)
LOCAL_MODULE := android.hardware.soundtrigger@2.0-impl
-LOCAL_PROPRIETARY_MODULE := true
+LOCAL_VENDOR_MODULE := true
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_SRC_FILES := \
- SoundTriggerHalImpl.cpp
+ FetchISoundTriggerHw.cpp
LOCAL_CFLAGS := -Wall -Werror
LOCAL_SHARED_LIBRARIES := \
- libhidlbase \
- libhidltransport \
- liblog \
- libutils \
libhardware \
+ libutils \
android.hardware.soundtrigger@2.0 \
- android.hardware.audio.common@2.0
+ android.hardware.soundtrigger@2.0-core
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
+LOCAL_C_INCLUDE_DIRS := $(LOCAL_PATH)
ifeq ($(strip $(AUDIOSERVER_MULTILIB)),)
LOCAL_MULTILIB := 32
diff --git a/soundtrigger/2.0/default/FetchISoundTriggerHw.cpp b/soundtrigger/2.0/default/FetchISoundTriggerHw.cpp
new file mode 100644
index 0000000..bd99221
--- /dev/null
+++ b/soundtrigger/2.0/default/FetchISoundTriggerHw.cpp
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+#include "SoundTriggerHalImpl.h"
+
+extern "C" ::android::hardware::soundtrigger::V2_0::ISoundTriggerHw* HIDL_FETCH_ISoundTriggerHw(
+ const char* /* name */) {
+ return (new ::android::hardware::soundtrigger::V2_0::implementation::SoundTriggerHalImpl())
+ ->getInterface();
+}
diff --git a/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp b/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp
index f963fb1..612772c 100644
--- a/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp
+++ b/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp
@@ -17,9 +17,8 @@
#define LOG_TAG "SoundTriggerHalImpl"
//#define LOG_NDEBUG 0
-#include <android/log.h>
#include "SoundTriggerHalImpl.h"
-
+#include <android/log.h>
namespace android {
namespace hardware {
@@ -28,64 +27,45 @@
namespace implementation {
// static
-void SoundTriggerHalImpl::soundModelCallback(struct sound_trigger_model_event *halEvent,
- void *cookie)
-{
+void SoundTriggerHalImpl::soundModelCallback(struct sound_trigger_model_event* halEvent,
+ void* cookie) {
if (halEvent == NULL) {
ALOGW("soundModelCallback called with NULL event");
return;
}
sp<SoundModelClient> client =
- wp<SoundModelClient>(static_cast<SoundModelClient *>(cookie)).promote();
+ wp<SoundModelClient>(static_cast<SoundModelClient*>(cookie)).promote();
if (client == 0) {
ALOGW("soundModelCallback called on stale client");
return;
}
- if (halEvent->model != client->mHalHandle) {
+ if (halEvent->model != client->getHalHandle()) {
ALOGW("soundModelCallback call with wrong handle %d on client with handle %d",
- (int)halEvent->model, (int)client->mHalHandle);
+ (int)halEvent->model, (int)client->getHalHandle());
return;
}
- ISoundTriggerHwCallback::ModelEvent event;
- convertSoundModelEventFromHal(&event, halEvent);
- event.model = client->mId;
-
- client->mCallback->soundModelCallback(event, client->mCookie);
+ client->soundModelCallback(halEvent);
}
// static
-void SoundTriggerHalImpl::recognitionCallback(struct sound_trigger_recognition_event *halEvent,
- void *cookie)
-{
+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();
+ wp<SoundModelClient>(static_cast<SoundModelClient*>(cookie)).promote();
if (client == 0) {
ALOGW("soundModelCallback called on stale client");
return;
}
- ISoundTriggerHwCallback::RecognitionEvent *event = convertRecognitionEventFromHal(halEvent);
- event->model = client->mId;
- if (halEvent->type == SOUND_MODEL_TYPE_KEYPHRASE) {
- client->mCallback->phraseRecognitionCallback(
- *(reinterpret_cast<ISoundTriggerHwCallback::PhraseRecognitionEvent *>(event)),
- client->mCookie);
- } else {
- client->mCallback->recognitionCallback(*event, client->mCookie);
- }
- delete event;
+ client->recognitionCallback(halEvent);
}
-
-
-// Methods from ::android::hardware::soundtrigger::V2_0::ISoundTriggerHw follow.
-Return<void> SoundTriggerHalImpl::getProperties(getProperties_cb _hidl_cb)
-{
+Return<void> SoundTriggerHalImpl::getProperties(ISoundTriggerHw::getProperties_cb _hidl_cb) {
ALOGV("getProperties() mHwDevice %p", mHwDevice);
int ret;
struct sound_trigger_properties halProperties;
@@ -100,8 +80,8 @@
convertPropertiesFromHal(&properties, &halProperties);
- ALOGV("getProperties implementor %s recognitionModes %08x",
- properties.implementor.c_str(), properties.recognitionModes);
+ ALOGV("getProperties implementor %s recognitionModes %08x", properties.implementor.c_str(),
+ properties.recognitionModes);
exit:
_hidl_cb(ret, properties);
@@ -109,14 +89,9 @@
}
int SoundTriggerHalImpl::doLoadSoundModel(const ISoundTriggerHw::SoundModel& soundModel,
- const sp<ISoundTriggerHwCallback>& callback,
- ISoundTriggerHwCallback::CallbackCookie cookie,
- uint32_t *modelId)
-{
+ sp<SoundModelClient> client) {
int32_t ret = 0;
- struct sound_trigger_sound_model *halSoundModel;
- *modelId = 0;
- sp<SoundModelClient> client;
+ struct sound_trigger_sound_model* halSoundModel;
ALOGV("doLoadSoundModel() data size %zu", soundModel.data.size());
@@ -131,19 +106,9 @@
goto exit;
}
- {
- AutoMutex lock(mLock);
- do {
- *modelId = nextUniqueId();
- } while (mClients.valueFor(*modelId) != 0 && *modelId != 0);
- }
- LOG_ALWAYS_FATAL_IF(*modelId == 0,
- "wrap around in sound model IDs, num loaded models %zu", mClients.size());
-
- client = new SoundModelClient(*modelId, callback, cookie);
-
- ret = mHwDevice->load_sound_model(mHwDevice, halSoundModel, soundModelCallback,
- client.get(), &client->mHalHandle);
+ sound_model_handle_t halHandle;
+ ret = mHwDevice->load_sound_model(mHwDevice, halSoundModel, soundModelCallback, client.get(),
+ &halHandle);
free(halSoundModel);
@@ -151,9 +116,10 @@
goto exit;
}
+ client->setHalHandle(halHandle);
{
AutoMutex lock(mLock);
- mClients.add(*modelId, client);
+ mClients.add(client->getId(), client);
}
exit:
@@ -163,31 +129,23 @@
Return<void> SoundTriggerHalImpl::loadSoundModel(const ISoundTriggerHw::SoundModel& soundModel,
const sp<ISoundTriggerHwCallback>& callback,
ISoundTriggerHwCallback::CallbackCookie cookie,
- loadSoundModel_cb _hidl_cb)
-{
- uint32_t modelId = 0;
- int32_t ret = doLoadSoundModel(soundModel, callback, cookie, &modelId);
-
- _hidl_cb(ret, modelId);
+ ISoundTriggerHw::loadSoundModel_cb _hidl_cb) {
+ sp<SoundModelClient> client = new SoundModelClient_2_0(nextUniqueModelId(), cookie, callback);
+ _hidl_cb(doLoadSoundModel(soundModel, client), client->getId());
return Void();
}
Return<void> SoundTriggerHalImpl::loadPhraseSoundModel(
- const ISoundTriggerHw::PhraseSoundModel& soundModel,
- const sp<ISoundTriggerHwCallback>& callback,
- ISoundTriggerHwCallback::CallbackCookie cookie,
- ISoundTriggerHw::loadPhraseSoundModel_cb _hidl_cb)
-{
- uint32_t modelId = 0;
- int32_t ret = doLoadSoundModel((const ISoundTriggerHw::SoundModel&)soundModel,
- callback, cookie, &modelId);
-
- _hidl_cb(ret, modelId);
+ const ISoundTriggerHw::PhraseSoundModel& soundModel,
+ const sp<ISoundTriggerHwCallback>& callback, ISoundTriggerHwCallback::CallbackCookie cookie,
+ ISoundTriggerHw::loadPhraseSoundModel_cb _hidl_cb) {
+ sp<SoundModelClient> client = new SoundModelClient_2_0(nextUniqueModelId(), cookie, callback);
+ _hidl_cb(doLoadSoundModel((const ISoundTriggerHw::SoundModel&)soundModel, client),
+ client->getId());
return Void();
}
-Return<int32_t> SoundTriggerHalImpl::unloadSoundModel(SoundModelHandle modelHandle)
-{
+Return<int32_t> SoundTriggerHalImpl::unloadSoundModel(SoundModelHandle modelHandle) {
int32_t ret;
sp<SoundModelClient> client;
@@ -205,7 +163,7 @@
}
}
- ret = mHwDevice->unload_sound_model(mHwDevice, client->mHalHandle);
+ ret = mHwDevice->unload_sound_model(mHwDevice, client->getHalHandle());
mClients.removeItem(modelHandle);
@@ -213,14 +171,11 @@
return ret;
}
-Return<int32_t> SoundTriggerHalImpl::startRecognition(SoundModelHandle modelHandle,
- const ISoundTriggerHw::RecognitionConfig& config,
- const sp<ISoundTriggerHwCallback>& callback __unused,
- ISoundTriggerHwCallback::CallbackCookie cookie __unused)
-{
+Return<int32_t> SoundTriggerHalImpl::startRecognition(
+ SoundModelHandle modelHandle, const ISoundTriggerHw::RecognitionConfig& config) {
int32_t ret;
sp<SoundModelClient> client;
- struct sound_trigger_recognition_config *halConfig;
+ struct sound_trigger_recognition_config* halConfig;
if (mHwDevice == NULL) {
ret = -ENODEV;
@@ -236,15 +191,14 @@
}
}
-
halConfig = convertRecognitionConfigToHal(&config);
if (halConfig == NULL) {
ret = -EINVAL;
goto exit;
}
- ret = mHwDevice->start_recognition(mHwDevice, client->mHalHandle, halConfig,
- recognitionCallback, client.get());
+ ret = mHwDevice->start_recognition(mHwDevice, client->getHalHandle(), halConfig,
+ recognitionCallback, client.get());
free(halConfig);
@@ -252,8 +206,7 @@
return ret;
}
-Return<int32_t> SoundTriggerHalImpl::stopRecognition(SoundModelHandle modelHandle)
-{
+Return<int32_t> SoundTriggerHalImpl::stopRecognition(SoundModelHandle modelHandle) {
int32_t ret;
sp<SoundModelClient> client;
if (mHwDevice == NULL) {
@@ -270,14 +223,13 @@
}
}
- ret = mHwDevice->stop_recognition(mHwDevice, client->mHalHandle);
+ ret = mHwDevice->stop_recognition(mHwDevice, client->getHalHandle());
exit:
return ret;
}
-Return<int32_t> SoundTriggerHalImpl::stopAllRecognitions()
-{
+Return<int32_t> SoundTriggerHalImpl::stopAllRecognitions() {
int32_t ret;
if (mHwDevice == NULL) {
ret = -ENODEV;
@@ -285,7 +237,7 @@
}
if (mHwDevice->common.version >= SOUND_TRIGGER_DEVICE_API_VERSION_1_1 &&
- mHwDevice->stop_all_recognitions) {
+ mHwDevice->stop_all_recognitions) {
ret = mHwDevice->stop_all_recognitions(mHwDevice);
} else {
ret = -ENOSYS;
@@ -295,19 +247,16 @@
}
SoundTriggerHalImpl::SoundTriggerHalImpl()
- : mModuleName("primary"), mHwDevice(NULL), mNextModelId(1)
-{
-}
+ : mModuleName("primary"), mHwDevice(NULL), mNextModelId(1) {}
-void SoundTriggerHalImpl::onFirstRef()
-{
- const hw_module_t *mod;
+void SoundTriggerHalImpl::onFirstRef() {
+ const hw_module_t* mod;
int rc;
rc = hw_get_module_by_class(SOUND_TRIGGER_HARDWARE_MODULE_ID, mModuleName, &mod);
if (rc != 0) {
- ALOGE("couldn't load sound trigger module %s.%s (%s)",
- SOUND_TRIGGER_HARDWARE_MODULE_ID, mModuleName, strerror(-rc));
+ ALOGE("couldn't load sound trigger module %s.%s (%s)", SOUND_TRIGGER_HARDWARE_MODULE_ID,
+ mModuleName, strerror(-rc));
return;
}
rc = sound_trigger_hw_device_open(mod, &mHwDevice);
@@ -318,7 +267,7 @@
return;
}
if (mHwDevice->common.version < SOUND_TRIGGER_DEVICE_API_VERSION_1_0 ||
- mHwDevice->common.version > SOUND_TRIGGER_DEVICE_API_VERSION_CURRENT) {
+ mHwDevice->common.version > SOUND_TRIGGER_DEVICE_API_VERSION_CURRENT) {
ALOGE("wrong sound trigger hw device version %04x", mHwDevice->common.version);
sound_trigger_hw_device_close(mHwDevice);
mHwDevice = NULL;
@@ -328,22 +277,27 @@
ALOGI("onFirstRef() mModuleName %s mHwDevice %p", mModuleName, mHwDevice);
}
-SoundTriggerHalImpl::~SoundTriggerHalImpl()
-{
+SoundTriggerHalImpl::~SoundTriggerHalImpl() {
if (mHwDevice != NULL) {
sound_trigger_hw_device_close(mHwDevice);
}
}
-uint32_t SoundTriggerHalImpl::nextUniqueId()
-{
- return (uint32_t) atomic_fetch_add_explicit(&mNextModelId,
- (uint_fast32_t) 1, memory_order_acq_rel);
+uint32_t SoundTriggerHalImpl::nextUniqueModelId() {
+ uint32_t modelId = 0;
+ {
+ AutoMutex lock(mLock);
+ do {
+ modelId =
+ atomic_fetch_add_explicit(&mNextModelId, (uint_fast32_t)1, memory_order_acq_rel);
+ } while (mClients.valueFor(modelId) != 0 && modelId != 0);
+ }
+ LOG_ALWAYS_FATAL_IF(modelId == 0, "wrap around in sound model IDs, num loaded models %zu",
+ mClients.size());
+ return modelId;
}
-void SoundTriggerHalImpl::convertUuidFromHal(Uuid *uuid,
- const sound_trigger_uuid_t *halUuid)
-{
+void SoundTriggerHalImpl::convertUuidFromHal(Uuid* uuid, const sound_trigger_uuid_t* halUuid) {
uuid->timeLow = halUuid->timeLow;
uuid->timeMid = halUuid->timeMid;
uuid->versionAndTimeHigh = halUuid->timeHiAndVersion;
@@ -351,9 +305,7 @@
memcpy(&uuid->node[0], &halUuid->node[0], 6);
}
-void SoundTriggerHalImpl::convertUuidToHal(sound_trigger_uuid_t *halUuid,
- const Uuid *uuid)
-{
+void SoundTriggerHalImpl::convertUuidToHal(sound_trigger_uuid_t* halUuid, const Uuid* uuid) {
halUuid->timeLow = uuid->timeLow;
halUuid->timeMid = uuid->timeMid;
halUuid->timeHiAndVersion = uuid->versionAndTimeHigh;
@@ -362,9 +314,7 @@
}
void SoundTriggerHalImpl::convertPropertiesFromHal(
- ISoundTriggerHw::Properties *properties,
- const struct sound_trigger_properties *halProperties)
-{
+ ISoundTriggerHw::Properties* properties, const struct sound_trigger_properties* halProperties) {
properties->implementor = halProperties->implementor;
properties->description = halProperties->description;
properties->version = halProperties->version;
@@ -378,13 +328,10 @@
properties->concurrentCapture = halProperties->concurrent_capture;
properties->triggerInEvent = halProperties->trigger_in_event;
properties->powerConsumptionMw = halProperties->power_consumption_mw;
-
}
-void SoundTriggerHalImpl::convertTriggerPhraseToHal(
- struct sound_trigger_phrase *halTriggerPhrase,
- const ISoundTriggerHw::Phrase *triggerPhrase)
-{
+void SoundTriggerHalImpl::convertTriggerPhraseToHal(struct sound_trigger_phrase* halTriggerPhrase,
+ const ISoundTriggerHw::Phrase* triggerPhrase) {
halTriggerPhrase->id = triggerPhrase->id;
halTriggerPhrase->recognition_mode = triggerPhrase->recognitionModes;
unsigned int i;
@@ -395,39 +342,35 @@
halTriggerPhrase->users[i] = triggerPhrase->users[i];
}
- strlcpy(halTriggerPhrase->locale,
- triggerPhrase->locale.c_str(), SOUND_TRIGGER_MAX_LOCALE_LEN);
- strlcpy(halTriggerPhrase->text,
- triggerPhrase->text.c_str(), SOUND_TRIGGER_MAX_STRING_LEN);
+ strlcpy(halTriggerPhrase->locale, triggerPhrase->locale.c_str(), SOUND_TRIGGER_MAX_LOCALE_LEN);
+ strlcpy(halTriggerPhrase->text, triggerPhrase->text.c_str(), SOUND_TRIGGER_MAX_STRING_LEN);
}
-struct sound_trigger_sound_model *SoundTriggerHalImpl::convertSoundModelToHal(
- const ISoundTriggerHw::SoundModel *soundModel)
-{
- struct sound_trigger_sound_model *halModel = NULL;
+struct sound_trigger_sound_model* SoundTriggerHalImpl::convertSoundModelToHal(
+ const ISoundTriggerHw::SoundModel* soundModel) {
+ struct sound_trigger_sound_model* halModel = NULL;
if (soundModel->type == SoundModelType::KEYPHRASE) {
size_t allocSize =
- sizeof(struct sound_trigger_phrase_sound_model) + soundModel->data.size();
- struct sound_trigger_phrase_sound_model *halKeyPhraseModel =
- static_cast<struct sound_trigger_phrase_sound_model *>(malloc(allocSize));
+ sizeof(struct sound_trigger_phrase_sound_model) + soundModel->data.size();
+ struct sound_trigger_phrase_sound_model* halKeyPhraseModel =
+ static_cast<struct sound_trigger_phrase_sound_model*>(malloc(allocSize));
LOG_ALWAYS_FATAL_IF(halKeyPhraseModel == NULL,
- "malloc failed for size %zu in convertSoundModelToHal PHRASE", allocSize);
+ "malloc failed for size %zu in convertSoundModelToHal PHRASE",
+ allocSize);
- const ISoundTriggerHw::PhraseSoundModel *keyPhraseModel =
- reinterpret_cast<const ISoundTriggerHw::PhraseSoundModel *>(soundModel);
+ const ISoundTriggerHw::PhraseSoundModel* keyPhraseModel =
+ reinterpret_cast<const ISoundTriggerHw::PhraseSoundModel*>(soundModel);
size_t i;
for (i = 0; i < keyPhraseModel->phrases.size() && i < SOUND_TRIGGER_MAX_PHRASES; i++) {
- convertTriggerPhraseToHal(&halKeyPhraseModel->phrases[i],
- &keyPhraseModel->phrases[i]);
+ convertTriggerPhraseToHal(&halKeyPhraseModel->phrases[i], &keyPhraseModel->phrases[i]);
}
halKeyPhraseModel->num_phrases = (unsigned int)i;
- halModel = reinterpret_cast<struct sound_trigger_sound_model *>(halKeyPhraseModel);
+ halModel = reinterpret_cast<struct sound_trigger_sound_model*>(halKeyPhraseModel);
halModel->data_offset = sizeof(struct sound_trigger_phrase_sound_model);
} else {
- size_t allocSize =
- sizeof(struct sound_trigger_sound_model) + soundModel->data.size();
- halModel = static_cast<struct sound_trigger_sound_model *>(malloc(allocSize));
+ size_t allocSize = sizeof(struct sound_trigger_sound_model) + soundModel->data.size();
+ halModel = static_cast<struct sound_trigger_sound_model*>(malloc(allocSize));
LOG_ALWAYS_FATAL_IF(halModel == NULL,
"malloc failed for size %zu in convertSoundModelToHal GENERIC",
allocSize);
@@ -438,17 +381,15 @@
convertUuidToHal(&halModel->uuid, &soundModel->uuid);
convertUuidToHal(&halModel->vendor_uuid, &soundModel->vendorUuid);
halModel->data_size = soundModel->data.size();
- uint8_t *dst = reinterpret_cast<uint8_t *>(halModel) + halModel->data_offset;
- const uint8_t *src = reinterpret_cast<const uint8_t *>(&soundModel->data[0]);
+ uint8_t* dst = reinterpret_cast<uint8_t*>(halModel) + halModel->data_offset;
+ const uint8_t* src = reinterpret_cast<const uint8_t*>(&soundModel->data[0]);
memcpy(dst, src, soundModel->data.size());
return halModel;
}
void SoundTriggerHalImpl::convertPhraseRecognitionExtraToHal(
- struct sound_trigger_phrase_recognition_extra *halExtra,
- const PhraseRecognitionExtra *extra)
-{
+ struct sound_trigger_phrase_recognition_extra* halExtra, const PhraseRecognitionExtra* extra) {
halExtra->id = extra->id;
halExtra->recognition_modes = extra->recognitionModes;
halExtra->confidence_level = extra->confidenceLevel;
@@ -461,16 +402,14 @@
halExtra->num_levels = i;
}
-struct sound_trigger_recognition_config *SoundTriggerHalImpl::convertRecognitionConfigToHal(
- const ISoundTriggerHw::RecognitionConfig *config)
-{
+struct sound_trigger_recognition_config* SoundTriggerHalImpl::convertRecognitionConfigToHal(
+ const ISoundTriggerHw::RecognitionConfig* config) {
size_t allocSize = sizeof(struct sound_trigger_recognition_config) + config->data.size();
- struct sound_trigger_recognition_config *halConfig =
- static_cast<struct sound_trigger_recognition_config *>(malloc(allocSize));
+ struct sound_trigger_recognition_config* halConfig =
+ static_cast<struct sound_trigger_recognition_config*>(malloc(allocSize));
LOG_ALWAYS_FATAL_IF(halConfig == NULL,
- "malloc failed for size %zu in convertRecognitionConfigToHal",
- allocSize);
+ "malloc failed for size %zu in convertRecognitionConfigToHal", allocSize);
halConfig->capture_handle = (audio_io_handle_t)config->captureHandle;
halConfig->capture_device = (audio_devices_t)config->captureDevice;
@@ -478,57 +417,43 @@
unsigned int i;
for (i = 0; i < config->phrases.size() && i < SOUND_TRIGGER_MAX_PHRASES; i++) {
- convertPhraseRecognitionExtraToHal(&halConfig->phrases[i],
- &config->phrases[i]);
+ convertPhraseRecognitionExtraToHal(&halConfig->phrases[i], &config->phrases[i]);
}
halConfig->num_phrases = i;
halConfig->data_offset = sizeof(struct sound_trigger_recognition_config);
halConfig->data_size = config->data.size();
- uint8_t *dst = reinterpret_cast<uint8_t *>(halConfig) + halConfig->data_offset;
- const uint8_t *src = reinterpret_cast<const uint8_t *>(&config->data[0]);
+ uint8_t* dst = reinterpret_cast<uint8_t*>(halConfig) + halConfig->data_offset;
+ const uint8_t* src = reinterpret_cast<const uint8_t*>(&config->data[0]);
memcpy(dst, src, config->data.size());
return halConfig;
}
// static
-void SoundTriggerHalImpl::convertSoundModelEventFromHal(ISoundTriggerHwCallback::ModelEvent *event,
- const struct sound_trigger_model_event *halEvent)
-{
+void SoundTriggerHalImpl::convertSoundModelEventFromHal(
+ ISoundTriggerHwCallback::ModelEvent* event, const struct sound_trigger_model_event* halEvent) {
event->status = (ISoundTriggerHwCallback::SoundModelStatus)halEvent->status;
// event->model to be remapped by called
event->data.setToExternal(
- const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(halEvent)) + halEvent->data_offset,
- halEvent->data_size);
+ const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(halEvent)) + halEvent->data_offset,
+ halEvent->data_size);
}
// static
-ISoundTriggerHwCallback::RecognitionEvent *SoundTriggerHalImpl::convertRecognitionEventFromHal(
- const struct sound_trigger_recognition_event *halEvent)
-{
- ISoundTriggerHwCallback::RecognitionEvent * event;
-
- if (halEvent->type == SOUND_MODEL_TYPE_KEYPHRASE) {
- const struct sound_trigger_phrase_recognition_event *halPhraseEvent =
- reinterpret_cast<const struct sound_trigger_phrase_recognition_event *>(halEvent);
- ISoundTriggerHwCallback::PhraseRecognitionEvent *phraseEvent =
- new ISoundTriggerHwCallback::PhraseRecognitionEvent();
-
- PhraseRecognitionExtra *phraseExtras =
- new PhraseRecognitionExtra[halPhraseEvent->num_phrases];
- for (unsigned int i = 0; i < halPhraseEvent->num_phrases; i++) {
- convertPhraseRecognitionExtraFromHal(&phraseExtras[i],
- &halPhraseEvent->phrase_extras[i]);
- }
- phraseEvent->phraseExtras.setToExternal(phraseExtras, halPhraseEvent->num_phrases);
- // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
- phraseEvent->phraseExtras.resize(halPhraseEvent->num_phrases);
- delete[] phraseExtras;
- event = reinterpret_cast<ISoundTriggerHwCallback::RecognitionEvent *>(phraseEvent);
- } else {
- event = new ISoundTriggerHwCallback::RecognitionEvent();
+void SoundTriggerHalImpl::convertPhaseRecognitionEventFromHal(
+ ISoundTriggerHwCallback::PhraseRecognitionEvent* event,
+ const struct sound_trigger_phrase_recognition_event* halEvent) {
+ event->phraseExtras.resize(halEvent->num_phrases);
+ for (unsigned int i = 0; i < halEvent->num_phrases; i++) {
+ convertPhraseRecognitionExtraFromHal(&event->phraseExtras[i], &halEvent->phrase_extras[i]);
}
+ convertRecognitionEventFromHal(&event->common, &halEvent->common);
+}
+// static
+void SoundTriggerHalImpl::convertRecognitionEventFromHal(
+ ISoundTriggerHwCallback::RecognitionEvent* event,
+ const struct sound_trigger_recognition_event* halEvent) {
event->status = static_cast<ISoundTriggerHwCallback::RecognitionStatus>(halEvent->status);
event->type = static_cast<SoundModelType>(halEvent->type);
// event->model to be remapped by called
@@ -539,45 +464,53 @@
event->triggerInData = halEvent->trigger_in_data;
event->audioConfig.sampleRateHz = halEvent->audio_config.sample_rate;
event->audioConfig.channelMask =
- (audio::common::V2_0::AudioChannelMask)halEvent->audio_config.channel_mask;
+ (audio::common::V2_0::AudioChannelMask)halEvent->audio_config.channel_mask;
event->audioConfig.format = (audio::common::V2_0::AudioFormat)halEvent->audio_config.format;
event->data.setToExternal(
- const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(halEvent)) + halEvent->data_offset,
- halEvent->data_size);
-
- return event;
+ const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(halEvent)) + halEvent->data_offset,
+ halEvent->data_size);
}
// static
void SoundTriggerHalImpl::convertPhraseRecognitionExtraFromHal(
- PhraseRecognitionExtra *extra,
- const struct sound_trigger_phrase_recognition_extra *halExtra)
-{
+ PhraseRecognitionExtra* extra, const struct sound_trigger_phrase_recognition_extra* halExtra) {
extra->id = halExtra->id;
extra->recognitionModes = halExtra->recognition_modes;
extra->confidenceLevel = halExtra->confidence_level;
- ConfidenceLevel *levels =
- new ConfidenceLevel[halExtra->num_levels];
- for (unsigned int i = 0; i < halExtra->num_levels; i++) {
- levels[i].userId = halExtra->levels[i].user_id;
- levels[i].levelPercent = halExtra->levels[i].level;
- }
- extra->levels.setToExternal(levels, halExtra->num_levels);
- // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
extra->levels.resize(halExtra->num_levels);
- delete[] levels;
+ for (unsigned int i = 0; i < halExtra->num_levels; i++) {
+ extra->levels[i].userId = halExtra->levels[i].user_id;
+ extra->levels[i].levelPercent = halExtra->levels[i].level;
+ }
}
-ISoundTriggerHw *HIDL_FETCH_ISoundTriggerHw(const char* /* name */)
-{
- return new SoundTriggerHalImpl();
+void SoundTriggerHalImpl::SoundModelClient_2_0::recognitionCallback(
+ struct sound_trigger_recognition_event* halEvent) {
+ if (halEvent->type == SOUND_MODEL_TYPE_KEYPHRASE) {
+ ISoundTriggerHwCallback::PhraseRecognitionEvent event;
+ convertPhaseRecognitionEventFromHal(
+ &event, reinterpret_cast<sound_trigger_phrase_recognition_event*>(halEvent));
+ event.common.model = mId;
+ mCallback->phraseRecognitionCallback(event, mCookie);
+ } else {
+ ISoundTriggerHwCallback::RecognitionEvent event;
+ convertRecognitionEventFromHal(&event, halEvent);
+ event.model = mId;
+ mCallback->recognitionCallback(event, mCookie);
+ }
}
-} // namespace implementation
+
+void SoundTriggerHalImpl::SoundModelClient_2_0::soundModelCallback(
+ struct sound_trigger_model_event* halEvent) {
+ ISoundTriggerHwCallback::ModelEvent event;
+ convertSoundModelEventFromHal(&event, halEvent);
+ event.model = mId;
+ mCallback->soundModelCallback(event, mCookie);
+}
+
+} // namespace implementation
} // namespace V2_0
} // namespace soundtrigger
} // namespace hardware
} // namespace android
-
-
-
diff --git a/soundtrigger/2.0/default/SoundTriggerHalImpl.h b/soundtrigger/2.0/default/SoundTriggerHalImpl.h
index 4769590..5a9f0e1 100644
--- a/soundtrigger/2.0/default/SoundTriggerHalImpl.h
+++ b/soundtrigger/2.0/default/SoundTriggerHalImpl.h
@@ -19,12 +19,12 @@
#include <android/hardware/soundtrigger/2.0/ISoundTriggerHw.h>
#include <android/hardware/soundtrigger/2.0/ISoundTriggerHwCallback.h>
+#include <hardware/sound_trigger.h>
#include <hidl/Status.h>
#include <stdatomic.h>
-#include <utils/threads.h>
-#include <utils/KeyedVector.h>
#include <system/sound_trigger.h>
-#include <hardware/sound_trigger.h>
+#include <utils/KeyedVector.h>
+#include <utils/threads.h>
namespace android {
namespace hardware {
@@ -35,96 +35,144 @@
using ::android::hardware::audio::common::V2_0::Uuid;
using ::android::hardware::soundtrigger::V2_0::ISoundTriggerHwCallback;
+class SoundTriggerHalImpl : public RefBase {
+ public:
+ SoundTriggerHalImpl();
+ ISoundTriggerHw* getInterface() { return new TrampolineSoundTriggerHw_2_0(this); }
-class SoundTriggerHalImpl : public ISoundTriggerHw {
-public:
- SoundTriggerHalImpl();
+ protected:
+ class SoundModelClient : public RefBase {
+ public:
+ SoundModelClient(uint32_t id, ISoundTriggerHwCallback::CallbackCookie cookie)
+ : mId(id), mCookie(cookie) {}
+ virtual ~SoundModelClient() {}
+
+ uint32_t getId() const { return mId; }
+ sound_model_handle_t getHalHandle() const { return mHalHandle; }
+ void setHalHandle(sound_model_handle_t handle) { mHalHandle = handle; }
+
+ virtual void recognitionCallback(struct sound_trigger_recognition_event* halEvent) = 0;
+ virtual void soundModelCallback(struct sound_trigger_model_event* halEvent) = 0;
+
+ protected:
+ const uint32_t mId;
+ sound_model_handle_t mHalHandle;
+ ISoundTriggerHwCallback::CallbackCookie mCookie;
+ };
+
+ static void convertPhaseRecognitionEventFromHal(
+ ISoundTriggerHwCallback::PhraseRecognitionEvent* event,
+ const struct sound_trigger_phrase_recognition_event* halEvent);
+ static void convertRecognitionEventFromHal(
+ ISoundTriggerHwCallback::RecognitionEvent* event,
+ const struct sound_trigger_recognition_event* halEvent);
+ static void convertSoundModelEventFromHal(ISoundTriggerHwCallback::ModelEvent* event,
+ const struct sound_trigger_model_event* halEvent);
+
+ virtual ~SoundTriggerHalImpl();
+
+ Return<void> getProperties(ISoundTriggerHw::getProperties_cb _hidl_cb);
+ Return<void> loadSoundModel(const ISoundTriggerHw::SoundModel& soundModel,
+ const sp<ISoundTriggerHwCallback>& callback,
+ ISoundTriggerHwCallback::CallbackCookie cookie,
+ ISoundTriggerHw::loadSoundModel_cb _hidl_cb);
+ Return<void> loadPhraseSoundModel(const ISoundTriggerHw::PhraseSoundModel& soundModel,
+ const sp<ISoundTriggerHwCallback>& callback,
+ ISoundTriggerHwCallback::CallbackCookie cookie,
+ ISoundTriggerHw::loadPhraseSoundModel_cb _hidl_cb);
+ Return<int32_t> unloadSoundModel(SoundModelHandle modelHandle);
+ Return<int32_t> startRecognition(SoundModelHandle modelHandle,
+ const ISoundTriggerHw::RecognitionConfig& config);
+ Return<int32_t> stopRecognition(SoundModelHandle modelHandle);
+ Return<int32_t> stopAllRecognitions();
+
+ uint32_t nextUniqueModelId();
+ int doLoadSoundModel(const ISoundTriggerHw::SoundModel& soundModel,
+ sp<SoundModelClient> client);
+
+ // RefBase
+ void onFirstRef() override;
+
+ private:
+ struct TrampolineSoundTriggerHw_2_0 : public ISoundTriggerHw {
+ explicit TrampolineSoundTriggerHw_2_0(sp<SoundTriggerHalImpl> impl) : mImpl(impl) {}
// Methods from ::android::hardware::soundtrigger::V2_0::ISoundTriggerHw follow.
- Return<void> getProperties(getProperties_cb _hidl_cb) override;
+ Return<void> getProperties(getProperties_cb _hidl_cb) override {
+ return mImpl->getProperties(_hidl_cb);
+ }
Return<void> loadSoundModel(const ISoundTriggerHw::SoundModel& soundModel,
const sp<ISoundTriggerHwCallback>& callback,
ISoundTriggerHwCallback::CallbackCookie cookie,
- loadSoundModel_cb _hidl_cb) override;
+ loadSoundModel_cb _hidl_cb) override {
+ return mImpl->loadSoundModel(soundModel, callback, cookie, _hidl_cb);
+ }
Return<void> loadPhraseSoundModel(const ISoundTriggerHw::PhraseSoundModel& soundModel,
- const sp<ISoundTriggerHwCallback>& callback,
- ISoundTriggerHwCallback::CallbackCookie cookie,
- loadPhraseSoundModel_cb _hidl_cb) override;
+ const sp<ISoundTriggerHwCallback>& callback,
+ ISoundTriggerHwCallback::CallbackCookie cookie,
+ loadPhraseSoundModel_cb _hidl_cb) override {
+ return mImpl->loadPhraseSoundModel(soundModel, callback, cookie, _hidl_cb);
+ }
+ Return<int32_t> unloadSoundModel(SoundModelHandle modelHandle) override {
+ return mImpl->unloadSoundModel(modelHandle);
+ }
+ Return<int32_t> startRecognition(
+ SoundModelHandle modelHandle, const ISoundTriggerHw::RecognitionConfig& config,
+ const sp<ISoundTriggerHwCallback>& /*callback*/,
+ ISoundTriggerHwCallback::CallbackCookie /*cookie*/) override {
+ return mImpl->startRecognition(modelHandle, config);
+ }
+ Return<int32_t> stopRecognition(SoundModelHandle modelHandle) override {
+ return mImpl->stopRecognition(modelHandle);
+ }
+ Return<int32_t> stopAllRecognitions() override { return mImpl->stopAllRecognitions(); }
- Return<int32_t> unloadSoundModel(SoundModelHandle modelHandle) override;
- Return<int32_t> startRecognition(SoundModelHandle modelHandle,
- const ISoundTriggerHw::RecognitionConfig& config,
- const sp<ISoundTriggerHwCallback>& callback,
- ISoundTriggerHwCallback::CallbackCookie cookie) override;
- Return<int32_t> stopRecognition(SoundModelHandle modelHandle) override;
- Return<int32_t> stopAllRecognitions() override;
+ private:
+ sp<SoundTriggerHalImpl> mImpl;
+ };
- // RefBase
- virtual void onFirstRef();
+ class SoundModelClient_2_0 : public SoundModelClient {
+ public:
+ SoundModelClient_2_0(uint32_t id, ISoundTriggerHwCallback::CallbackCookie cookie,
+ sp<ISoundTriggerHwCallback> callback)
+ : SoundModelClient(id, cookie), mCallback(callback) {}
- static void soundModelCallback(struct sound_trigger_model_event *halEvent,
- void *cookie);
- static void recognitionCallback(struct sound_trigger_recognition_event *halEvent,
- void *cookie);
+ void recognitionCallback(struct sound_trigger_recognition_event* halEvent) override;
+ void soundModelCallback(struct sound_trigger_model_event* halEvent) override;
-private:
+ private:
+ sp<ISoundTriggerHwCallback> mCallback;
+ };
- class SoundModelClient : public RefBase {
- public:
- SoundModelClient(uint32_t id, sp<ISoundTriggerHwCallback> callback,
- ISoundTriggerHwCallback::CallbackCookie cookie)
- : mId(id), mCallback(callback), mCookie(cookie) {}
- virtual ~SoundModelClient() {}
+ void convertUuidFromHal(Uuid* uuid, const sound_trigger_uuid_t* halUuid);
+ void convertUuidToHal(sound_trigger_uuid_t* halUuid, const Uuid* uuid);
+ void convertPropertiesFromHal(ISoundTriggerHw::Properties* properties,
+ const struct sound_trigger_properties* halProperties);
+ void convertTriggerPhraseToHal(struct sound_trigger_phrase* halTriggerPhrase,
+ const ISoundTriggerHw::Phrase* triggerPhrase);
+ // returned HAL sound model must be freed by caller
+ struct sound_trigger_sound_model* convertSoundModelToHal(
+ const ISoundTriggerHw::SoundModel* soundModel);
+ void convertPhraseRecognitionExtraToHal(struct sound_trigger_phrase_recognition_extra* halExtra,
+ const PhraseRecognitionExtra* extra);
+ // returned recognition config must be freed by caller
+ struct sound_trigger_recognition_config* convertRecognitionConfigToHal(
+ const ISoundTriggerHw::RecognitionConfig* config);
- uint32_t mId;
- sound_model_handle_t mHalHandle;
- sp<ISoundTriggerHwCallback> mCallback;
- ISoundTriggerHwCallback::CallbackCookie mCookie;
- };
+ static void convertPhraseRecognitionExtraFromHal(
+ PhraseRecognitionExtra* extra,
+ const struct sound_trigger_phrase_recognition_extra* halExtra);
- uint32_t nextUniqueId();
- void convertUuidFromHal(Uuid *uuid,
- const sound_trigger_uuid_t *halUuid);
- void convertUuidToHal(sound_trigger_uuid_t *halUuid,
- const Uuid *uuid);
- void convertPropertiesFromHal(ISoundTriggerHw::Properties *properties,
- const struct sound_trigger_properties *halProperties);
- void convertTriggerPhraseToHal(struct sound_trigger_phrase *halTriggerPhrase,
- const ISoundTriggerHw::Phrase *triggerPhrase);
- // returned HAL sound model must be freed by caller
- struct sound_trigger_sound_model *convertSoundModelToHal(
- const ISoundTriggerHw::SoundModel *soundModel);
- void convertPhraseRecognitionExtraToHal(
- struct sound_trigger_phrase_recognition_extra *halExtra,
- const PhraseRecognitionExtra *extra);
- // returned recognition config must be freed by caller
- struct sound_trigger_recognition_config *convertRecognitionConfigToHal(
- const ISoundTriggerHw::RecognitionConfig *config);
+ static void soundModelCallback(struct sound_trigger_model_event* halEvent, void* cookie);
+ static void recognitionCallback(struct sound_trigger_recognition_event* halEvent, void* cookie);
-
- static void convertSoundModelEventFromHal(ISoundTriggerHwCallback::ModelEvent *event,
- const struct sound_trigger_model_event *halEvent);
- static ISoundTriggerHwCallback::RecognitionEvent *convertRecognitionEventFromHal(
- const struct sound_trigger_recognition_event *halEvent);
- static void convertPhraseRecognitionExtraFromHal(PhraseRecognitionExtra *extra,
- const struct sound_trigger_phrase_recognition_extra *halExtra);
-
- int doLoadSoundModel(const ISoundTriggerHw::SoundModel& soundModel,
- const sp<ISoundTriggerHwCallback>& callback,
- ISoundTriggerHwCallback::CallbackCookie cookie,
- uint32_t *modelId);
-
- virtual ~SoundTriggerHalImpl();
-
- const char * mModuleName;
- struct sound_trigger_hw_device* mHwDevice;
- volatile atomic_uint_fast32_t mNextModelId;
- DefaultKeyedVector<int32_t, sp<SoundModelClient> > mClients;
- Mutex mLock;
+ const char* mModuleName;
+ struct sound_trigger_hw_device* mHwDevice;
+ volatile atomic_uint_fast32_t mNextModelId;
+ DefaultKeyedVector<int32_t, sp<SoundModelClient> > mClients;
+ Mutex mLock;
};
-extern "C" ISoundTriggerHw *HIDL_FETCH_ISoundTriggerHw(const char *name);
-
} // namespace implementation
} // namespace V2_0
} // namespace soundtrigger
@@ -132,4 +180,3 @@
} // namespace android
#endif // ANDROID_HARDWARE_SOUNDTRIGGER_V2_0_IMPLEMENTATION_H
-
diff --git a/soundtrigger/2.1/Android.bp b/soundtrigger/2.1/Android.bp
new file mode 100644
index 0000000..ed1ec3d
--- /dev/null
+++ b/soundtrigger/2.1/Android.bp
@@ -0,0 +1,20 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.soundtrigger@2.1",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "ISoundTriggerHw.hal",
+ "ISoundTriggerHwCallback.hal",
+ ],
+ interfaces: [
+ "android.hardware.audio.common@2.0",
+ "android.hardware.soundtrigger@2.0",
+ "android.hidl.base@1.0",
+ ],
+ gen_java: false,
+}
+
diff --git a/soundtrigger/2.1/ISoundTriggerHw.hal b/soundtrigger/2.1/ISoundTriggerHw.hal
new file mode 100644
index 0000000..2f2e73a
--- /dev/null
+++ b/soundtrigger/2.1/ISoundTriggerHw.hal
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2017 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.1;
+
+import @2.0::ISoundTriggerHw;
+import @2.0::ISoundTriggerHwCallback.CallbackCookie;
+import @2.0::SoundModelHandle;
+
+import ISoundTriggerHwCallback;
+
+/**
+ * SoundTrigger HAL interface. Used for hardware recognition of hotwords.
+ */
+interface ISoundTriggerHw extends @2.0::ISoundTriggerHw {
+
+ /**
+ * Base sound model descriptor. This struct is the header of a larger block
+ * passed to loadSoundModel_2_1() and contains the binary data of the
+ * sound model.
+ */
+ struct SoundModel {
+ /** Sound model header. Any data contained in the 'header.data' field
+ * is ignored */
+ @2.0::ISoundTriggerHw.SoundModel header;
+ /** Opaque data transparent to Android framework */
+ memory data;
+ };
+
+ /**
+ * Specialized sound model for key phrase detection.
+ * Proprietary representation of key phrases in binary data must match
+ * information indicated by phrases field.
+ */
+ struct PhraseSoundModel {
+ /** Common part of sound model descriptor */
+ SoundModel common;
+ /** List of descriptors for key phrases supported by this sound model */
+ vec<Phrase> phrases;
+ };
+
+ /**
+ * Configuration for sound trigger capture session passed to
+ * startRecognition_2_1() method.
+ */
+ struct RecognitionConfig {
+ /** Configuration header. Any data contained in the 'header.data' field
+ * is ignored */
+ @2.0::ISoundTriggerHw.RecognitionConfig header;
+ /** Opaque capture configuration data transparent to the framework */
+ memory data;
+ };
+
+ /**
+ * Load a sound model. Once loaded, recognition of this model can be
+ * started and stopped. Only one active recognition per model at a time.
+ * The SoundTrigger service must handle concurrent recognition requests by
+ * different users/applications on the same model.
+ * The implementation returns a unique handle used by other functions
+ * (unloadSoundModel(), startRecognition*(), etc...
+ *
+ * Must have the exact same semantics as loadSoundModel from
+ * ISoundTriggerHw@2.0 except that the SoundModel uses shared memory
+ * instead of data.
+ *
+ * @param soundModel A SoundModel structure describing the sound model
+ * to load.
+ * @param callback The callback interface on which the soundmodelCallback*()
+ * method must be called upon completion.
+ * @param cookie The value of the cookie argument passed to the completion
+ * callback. This unique context information is assigned and
+ * used only by the framework.
+ * @return retval Operation completion status: 0 in case of success,
+ * -EINVAL in case of invalid sound model (e.g 0 data size),
+ * -ENOSYS in case of invalid operation (e.g max number of models
+ * exceeded),
+ * -ENOMEM in case of memory allocation failure,
+ * -ENODEV in case of initialization error.
+ * @return modelHandle A unique handle assigned by the HAL for use by the
+ * framework when controlling activity for this sound model.
+ */
+ @callflow(next={"startRecognition_2_1", "setSoundModelParameters", "unloadSoundModel"})
+ loadSoundModel_2_1(SoundModel soundModel,
+ ISoundTriggerHwCallback callback,
+ CallbackCookie cookie)
+ generates (int32_t retval, SoundModelHandle modelHandle);
+
+ /**
+ * Load a key phrase sound model. Once loaded, recognition of this model can
+ * be started and stopped. Only one active recognition per model at a time.
+ * The SoundTrigger service must handle concurrent recognition requests by
+ * different users/applications on the same model.
+ * The implementation returns a unique handle used by other functions
+ * (unloadSoundModel(), startRecognition*(), etc...
+ *
+ * Must have the exact same semantics as loadPhraseSoundModel from
+ * ISoundTriggerHw@2.0 except that the PhraseSoundModel uses shared memory
+ * instead of data.
+ *
+ * @param soundModel A PhraseSoundModel structure describing the sound model
+ * to load.
+ * @param callback The callback interface on which the soundmodelCallback*()
+ * method must be called upon completion.
+ * @param cookie The value of the cookie argument passed to the completion
+ * callback. This unique context information is assigned and
+ * used only by the framework.
+ * @return retval Operation completion status: 0 in case of success,
+ * -EINVAL in case of invalid sound model (e.g 0 data size),
+ * -ENOSYS in case of invalid operation (e.g max number of models
+ * exceeded),
+ * -ENOMEM in case of memory allocation failure,
+ * -ENODEV in case of initialization error.
+ * @return modelHandle A unique handle assigned by the HAL for use by the
+ * framework when controlling activity for this sound model.
+ */
+ @callflow(next={"startRecognition_2_1", "setSoundModelParameters", "unloadSoundModel"})
+ loadPhraseSoundModel_2_1(PhraseSoundModel soundModel,
+ ISoundTriggerHwCallback callback,
+ CallbackCookie cookie)
+ generates (int32_t retval, SoundModelHandle modelHandle);
+
+ /**
+ * Start recognition on a given model. Only one recognition active
+ * at a time per model. Once recognition succeeds of fails, the callback
+ * is called.
+ *
+ * Must have the exact same semantics as startRecognition from
+ * ISoundTriggerHw@2.0 except that the RecognitionConfig uses shared memory
+ * instead of data.
+ *
+ * @param modelHandle the handle of the sound model to use for recognition
+ * @param config A RecognitionConfig structure containing attributes of the
+ * recognition to perform
+ * @param callback The callback interface on which the recognitionCallback()
+ * method must be called upon recognition.
+ * @param cookie The value of the cookie argument passed to the recognition
+ * callback. This unique context information is assigned and
+ * used only by the framework.
+ * @return retval Operation completion status: 0 in case of success,
+ * -EINVAL in case of invalid recognition attributes,
+ * -ENOSYS in case of invalid model handle,
+ * -ENOMEM in case of memory allocation failure,
+ * -ENODEV in case of initialization error.
+ */
+ @callflow(next={"stopRecognition", "stopAllRecognitions"})
+ startRecognition_2_1(SoundModelHandle modelHandle,
+ RecognitionConfig config,
+ ISoundTriggerHwCallback callback,
+ CallbackCookie cookie)
+ generates (int32_t retval);
+
+
+ struct ParameterValue {
+ string key;
+ string value;
+ };
+
+ /**
+ * Generic method for retrieving vendor-specific parameter values.
+ * The framework does not interpret the parameters, they are passed
+ * in an opaque manner between a vendor application and HAL.
+ *
+ * @param keys parameter keys.
+ * @return retval Operation completion status: 0 in case of success,
+ * -EINVAL in case of invalid keys,
+ * -ENOSYS in case if this operation is not supported,
+ * -ENOMEM in case of memory allocation failure,
+ * -ENODEV in case of initialization error.
+ * @return parameters parameter key value pairs.
+ */
+ getParameters(vec<string> keys)
+ generates (int32_t retval, vec<ParameterValue> parameters);
+
+ /**
+ * Generic method for setting vendor-specific parameter values.
+ * The framework does not interpret the parameters, they are passed
+ * in an opaque manner between a vendor application and HAL.
+ *
+ * @param parameters parameter key value pairs.
+ * @return retval Operation completion status: 0 in case of success,
+ * -EINVAL in case of invalid keys,
+ * -ENOSYS in case if this operation is not supported,
+ * -ENOMEM in case of memory allocation failure,
+ * -ENODEV in case of initialization error.
+ */
+ setParameters(vec<ParameterValue> parameters) generates (int32_t retval);
+
+ /**
+ * Generic method for retrieving vendor-specific parameter values.
+ * The framework does not interpret the parameters, they are passed
+ * in an opaque manner between a vendor application and HAL.
+ *
+ * @param modelHandle the handle of the sound model to get parameters about.
+ * @param keys parameter keys.
+ * @return retval Operation completion status: 0 in case of success,
+ * -EINVAL in case of invalid keys,
+ * -ENOSYS in case if this operation is not supported,
+ * -ENOMEM in case of memory allocation failure,
+ * -ENODEV in case of initialization error.
+ * @return parameters parameter key value pairs.
+ */
+ getSoundModelParameters(SoundModelHandle modelHandle, vec<string> keys)
+ generates (int32_t retval, vec<ParameterValue> parameters);
+
+ /**
+ * Generic method for setting vendor-specific parameter values.
+ * The framework does not interpret the parameters, they are passed
+ * in an opaque manner between a vendor application and HAL.
+ *
+ * @param modelHandle the handle of the sound model to set parameters for.
+ * @param parameters parameter key value pairs.
+ * @return retval Operation completion status: 0 in case of success,
+ * -EINVAL in case of invalid keys,
+ * -ENOSYS in case if this operation is not supported,
+ * -ENOMEM in case of memory allocation failure,
+ * -ENODEV in case of initialization error.
+ */
+ setSoundModelParameters(
+ SoundModelHandle modelHandle, vec<ParameterValue> parameters)
+ generates (int32_t retval);
+};
diff --git a/soundtrigger/2.1/ISoundTriggerHwCallback.hal b/soundtrigger/2.1/ISoundTriggerHwCallback.hal
new file mode 100644
index 0000000..42e851b
--- /dev/null
+++ b/soundtrigger/2.1/ISoundTriggerHwCallback.hal
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2017 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.1;
+
+import @2.0::ISoundTriggerHwCallback;
+import @2.0::PhraseRecognitionExtra;
+
+/**
+ * SoundTrigger HAL Callback interface. Obtained during SoundTrigger setup.
+ */
+@hidl_callback
+interface ISoundTriggerHwCallback extends @2.0::ISoundTriggerHwCallback {
+
+ /**
+ * Generic recognition event sent via recognition callback.
+ */
+ struct RecognitionEvent {
+ /** Event header. Any data contained in the 'header.data' field
+ * is ignored */
+ @2.0::ISoundTriggerHwCallback.RecognitionEvent header;
+ /** Opaque event data */
+ memory data;
+ };
+
+ /**
+ * Specialized recognition event for key phrase recognitions.
+ */
+ struct PhraseRecognitionEvent {
+ /** Common part of the recognition event */
+ RecognitionEvent common;
+ /** List of descriptors for each recognized key phrase */
+ vec<PhraseRecognitionExtra> phraseExtras;
+ };
+
+ /**
+ * Event sent via load sound model callback.
+ */
+ struct ModelEvent {
+ /** Event header. Any data contained in the 'header.data' field
+ * is ignored */
+ @2.0::ISoundTriggerHwCallback.ModelEvent header;
+ /** Opaque event data, passed transparently by the framework */
+ memory data;
+ };
+
+ /**
+ * Callback method called by the HAL when the sound recognition triggers.
+ *
+ * @param event A RecognitionEvent structure containing detailed results
+ * of the recognition triggered
+ * @param cookie The cookie passed by the framework when recognition was
+ * started (see ISoundtriggerHw.startRecognition*())
+ */
+ recognitionCallback_2_1(RecognitionEvent event, CallbackCookie cookie);
+
+ /**
+ * Callback method called by the HAL when the sound recognition triggers
+ * for a key phrase sound model.
+ *
+ * @param event A RecognitionEvent structure containing detailed results
+ * of the recognition triggered
+ * @param cookie The cookie passed by the framework when recognition was
+ * started (see ISoundtriggerHw.startRecognition*())
+ */
+ phraseRecognitionCallback_2_1(PhraseRecognitionEvent event,
+ CallbackCookie cookie);
+
+ /**
+ * Callback method called by the HAL when the sound model loading completes.
+ *
+ * @param event A ModelEvent structure containing detailed results of the
+ * model loading operation
+ * @param cookie The cookie passed by the framework when loading was
+ * initiated (see ISoundtriggerHw.loadSoundModel*())
+ */
+ soundModelCallback_2_1(ModelEvent event, CallbackCookie cookie);
+};
diff --git a/soundtrigger/2.1/default/Android.mk b/soundtrigger/2.1/default/Android.mk
new file mode 100644
index 0000000..5851d63
--- /dev/null
+++ b/soundtrigger/2.1/default/Android.mk
@@ -0,0 +1,49 @@
+#
+# 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.1-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.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)
diff --git a/soundtrigger/2.1/default/SoundTriggerHw.cpp b/soundtrigger/2.1/default/SoundTriggerHw.cpp
new file mode 100644
index 0000000..246d2bc
--- /dev/null
+++ b/soundtrigger/2.1/default/SoundTriggerHw.cpp
@@ -0,0 +1,194 @@
+/*
+ * 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 <utility>
+
+#include <android/hidl/allocator/1.0/IAllocator.h>
+#include <android/log.h>
+#include <hidlmemory/mapping.h>
+
+using android::hardware::hidl_memory;
+using android::hidl::allocator::V1_0::IAllocator;
+using android::hidl::memory::V1_0::IMemory;
+
+namespace android {
+namespace hardware {
+namespace soundtrigger {
+namespace V2_1 {
+namespace implementation {
+
+namespace {
+
+// Backs up by the vector with the contents of shared memory.
+// It is assumed that the passed hidl_vector is empty, so it's
+// not cleared if the memory is a null object.
+// The caller needs to keep the returned sp<IMemory> as long as
+// the data is needed.
+std::pair<bool, sp<IMemory>> memoryAsVector(const hidl_memory& m, hidl_vec<uint8_t>* vec) {
+ sp<IMemory> memory;
+ if (m.size() == 0) {
+ return std::make_pair(true, memory);
+ }
+ memory = mapMemory(m);
+ if (memory != nullptr) {
+ memory->read();
+ vec->setToExternal(static_cast<uint8_t*>(static_cast<void*>(memory->getPointer())),
+ memory->getSize());
+ return std::make_pair(true, memory);
+ }
+ ALOGE("%s: Could not map HIDL memory to IMemory", __func__);
+ return std::make_pair(false, memory);
+}
+
+// Moves the data from the vector into allocated shared memory,
+// emptying the vector.
+// It is assumed that the passed hidl_memory is a null object, so it's
+// not reset if the vector is empty.
+// The caller needs to keep the returned sp<IMemory> as long as
+// the data is needed.
+std::pair<bool, sp<IMemory>> moveVectorToMemory(hidl_vec<uint8_t>* v, hidl_memory* mem) {
+ sp<IMemory> memory;
+ if (v->size() == 0) {
+ return std::make_pair(true, memory);
+ }
+ sp<IAllocator> ashmem = IAllocator::getService("ashmem");
+ if (ashmem == 0) {
+ ALOGE("Failed to retrieve ashmem allocator service");
+ return std::make_pair(false, memory);
+ }
+ bool success = false;
+ Return<void> r = ashmem->allocate(v->size(), [&](bool s, const hidl_memory& m) {
+ success = s;
+ if (success) *mem = m;
+ });
+ if (r.isOk() && success) {
+ memory = hardware::mapMemory(*mem);
+ if (memory != 0) {
+ memory->update();
+ memcpy(memory->getPointer(), v->data(), v->size());
+ memory->commit();
+ v->resize(0);
+ return std::make_pair(true, memory);
+ } else {
+ ALOGE("Failed to map allocated ashmem");
+ }
+ } else {
+ ALOGE("Failed to allocate %llu bytes from ashmem", (unsigned long long)v->size());
+ }
+ return std::make_pair(false, memory);
+}
+
+} // namespace
+
+Return<void> SoundTriggerHw::loadSoundModel_2_1(
+ const V2_1::ISoundTriggerHw::SoundModel& soundModel,
+ const sp<V2_1::ISoundTriggerHwCallback>& callback, int32_t cookie,
+ V2_1::ISoundTriggerHw::loadSoundModel_2_1_cb _hidl_cb) {
+ // It is assumed that legacy data vector is empty, thus making copy is cheap.
+ V2_0::ISoundTriggerHw::SoundModel soundModel_2_0(soundModel.header);
+ auto result = memoryAsVector(soundModel.data, &soundModel_2_0.data);
+ if (result.first) {
+ sp<SoundModelClient> client =
+ new SoundModelClient_2_1(nextUniqueModelId(), cookie, callback);
+ _hidl_cb(doLoadSoundModel(soundModel_2_0, client), client->getId());
+ return Void();
+ }
+ _hidl_cb(-ENOMEM, 0);
+ return Void();
+}
+
+Return<void> SoundTriggerHw::loadPhraseSoundModel_2_1(
+ const V2_1::ISoundTriggerHw::PhraseSoundModel& soundModel,
+ const sp<V2_1::ISoundTriggerHwCallback>& callback, int32_t cookie,
+ V2_1::ISoundTriggerHw::loadPhraseSoundModel_2_1_cb _hidl_cb) {
+ V2_0::ISoundTriggerHw::PhraseSoundModel soundModel_2_0;
+ // It is assumed that legacy data vector is empty, thus making copy is cheap.
+ soundModel_2_0.common = soundModel.common.header;
+ // Avoid copying phrases data.
+ soundModel_2_0.phrases.setToExternal(
+ const_cast<V2_0::ISoundTriggerHw::Phrase*>(soundModel.phrases.data()),
+ soundModel.phrases.size());
+ auto result = memoryAsVector(soundModel.common.data, &soundModel_2_0.common.data);
+ if (result.first) {
+ sp<SoundModelClient> client =
+ new SoundModelClient_2_1(nextUniqueModelId(), cookie, callback);
+ _hidl_cb(doLoadSoundModel((const V2_0::ISoundTriggerHw::SoundModel&)soundModel_2_0, client),
+ client->getId());
+ return Void();
+ }
+ _hidl_cb(-ENOMEM, 0);
+ return Void();
+}
+
+Return<int32_t> SoundTriggerHw::startRecognition_2_1(
+ int32_t modelHandle, const V2_1::ISoundTriggerHw::RecognitionConfig& config) {
+ // It is assumed that legacy data vector is empty, thus making copy is cheap.
+ V2_0::ISoundTriggerHw::RecognitionConfig config_2_0(config.header);
+ auto result = memoryAsVector(config.data, &config_2_0.data);
+ return result.first ? startRecognition(modelHandle, config_2_0) : Return<int32_t>(-ENOMEM);
+}
+
+void SoundTriggerHw::SoundModelClient_2_1::recognitionCallback(
+ struct sound_trigger_recognition_event* halEvent) {
+ if (halEvent->type == SOUND_MODEL_TYPE_KEYPHRASE) {
+ V2_0::ISoundTriggerHwCallback::PhraseRecognitionEvent event_2_0;
+ convertPhaseRecognitionEventFromHal(
+ &event_2_0, reinterpret_cast<sound_trigger_phrase_recognition_event*>(halEvent));
+ event_2_0.common.model = mId;
+ V2_1::ISoundTriggerHwCallback::PhraseRecognitionEvent event;
+ event.phraseExtras.setToExternal(event_2_0.phraseExtras.data(),
+ event_2_0.phraseExtras.size());
+ auto result = moveVectorToMemory(&event_2_0.common.data, &event.common.data);
+ if (result.first) {
+ // The data vector is now empty, thus copying is cheap.
+ event.common.header = event_2_0.common;
+ mCallback->phraseRecognitionCallback_2_1(event, mCookie);
+ }
+ } else {
+ V2_1::ISoundTriggerHwCallback::RecognitionEvent event;
+ convertRecognitionEventFromHal(&event.header, halEvent);
+ event.header.model = mId;
+ auto result = moveVectorToMemory(&event.header.data, &event.data);
+ if (result.first) {
+ mCallback->recognitionCallback_2_1(event, mCookie);
+ }
+ }
+}
+
+void SoundTriggerHw::SoundModelClient_2_1::soundModelCallback(
+ struct sound_trigger_model_event* halEvent) {
+ V2_1::ISoundTriggerHwCallback::ModelEvent event;
+ convertSoundModelEventFromHal(&event.header, halEvent);
+ event.header.model = mId;
+ auto result = moveVectorToMemory(&event.header.data, &event.data);
+ if (result.first) {
+ mCallback->soundModelCallback_2_1(event, mCookie);
+ }
+}
+
+ISoundTriggerHw* HIDL_FETCH_ISoundTriggerHw(const char* /* name */) {
+ return (new SoundTriggerHw())->getInterface();
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace soundtrigger
+} // namespace hardware
+} // namespace android
diff --git a/soundtrigger/2.1/default/SoundTriggerHw.h b/soundtrigger/2.1/default/SoundTriggerHw.h
new file mode 100644
index 0000000..855d1a6
--- /dev/null
+++ b/soundtrigger/2.1/default/SoundTriggerHw.h
@@ -0,0 +1,152 @@
+/*
+ * 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_1_SOUNDTRIGGERHW_H
+#define ANDROID_HARDWARE_SOUNDTRIGGER_V2_1_SOUNDTRIGGERHW_H
+
+#include <SoundTriggerHalImpl.h>
+#include <android/hardware/soundtrigger/2.1/ISoundTriggerHw.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace soundtrigger {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+struct SoundTriggerHw : public V2_0::implementation::SoundTriggerHalImpl {
+ SoundTriggerHw() = default;
+ ISoundTriggerHw* getInterface() { return new TrampolineSoundTriggerHw_2_1(this); }
+
+ protected:
+ virtual ~SoundTriggerHw() = default;
+
+ Return<void> loadSoundModel_2_1(const V2_1::ISoundTriggerHw::SoundModel& soundModel,
+ const sp<V2_1::ISoundTriggerHwCallback>& callback,
+ int32_t cookie,
+ V2_1::ISoundTriggerHw::loadSoundModel_2_1_cb _hidl_cb);
+ Return<void> loadPhraseSoundModel_2_1(
+ const V2_1::ISoundTriggerHw::PhraseSoundModel& soundModel,
+ const sp<V2_1::ISoundTriggerHwCallback>& callback, int32_t cookie,
+ V2_1::ISoundTriggerHw::loadPhraseSoundModel_2_1_cb _hidl_cb);
+ Return<int32_t> startRecognition_2_1(int32_t modelHandle,
+ const V2_1::ISoundTriggerHw::RecognitionConfig& config);
+
+ private:
+ struct TrampolineSoundTriggerHw_2_1 : public ISoundTriggerHw {
+ explicit TrampolineSoundTriggerHw_2_1(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);
+ }
+ Return<void> getParameters(const hidl_vec<hidl_string>& /*keys*/,
+ getParameters_cb _hidl_cb) override {
+ _hidl_cb(-ENOSYS, hidl_vec<ParameterValue>());
+ return Void();
+ }
+ Return<int32_t> setParameters(
+ const hidl_vec<V2_1::ISoundTriggerHw::ParameterValue>& /*parameters*/) override {
+ return -ENOSYS;
+ }
+ Return<void> getSoundModelParameters(int32_t /*modelHandle*/,
+ const hidl_vec<hidl_string>& /*keys*/,
+ getSoundModelParameters_cb _hidl_cb) override {
+ _hidl_cb(-ENOSYS, hidl_vec<ParameterValue>());
+ return Void();
+ }
+ Return<int32_t> setSoundModelParameters(
+ int32_t /*modelHandle*/,
+ const hidl_vec<V2_1::ISoundTriggerHw::ParameterValue>& /*parameters*/) override {
+ return -ENOSYS;
+ }
+
+ private:
+ sp<SoundTriggerHw> mImpl;
+ };
+
+ class SoundModelClient_2_1 : public SoundModelClient {
+ public:
+ SoundModelClient_2_1(uint32_t id, V2_1::ISoundTriggerHwCallback::CallbackCookie cookie,
+ sp<V2_1::ISoundTriggerHwCallback> callback)
+ : SoundModelClient(id, cookie), mCallback(callback) {}
+
+ void recognitionCallback(struct sound_trigger_recognition_event* halEvent) override;
+ void soundModelCallback(struct sound_trigger_model_event* halEvent) override;
+
+ private:
+ sp<V2_1::ISoundTriggerHwCallback> mCallback;
+ };
+};
+
+extern "C" ISoundTriggerHw* HIDL_FETCH_ISoundTriggerHw(const char* name);
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace soundtrigger
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_SOUNDTRIGGER_V2_1_SOUNDTRIGGERHW_H
diff --git a/soundtrigger/2.1/vts/functional/Android.bp b/soundtrigger/2.1/vts/functional/Android.bp
new file mode 100644
index 0000000..925a17c
--- /dev/null
+++ b/soundtrigger/2.1/vts/functional/Android.bp
@@ -0,0 +1,28 @@
+//
+// 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_1TargetTest",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: ["VtsHalSoundtriggerV2_1TargetTest.cpp"],
+ static_libs: [
+ "android.hidl.allocator@1.0",
+ "android.hidl.memory@1.0",
+ "android.hardware.soundtrigger@2.0",
+ "android.hardware.soundtrigger@2.1",
+ "libhidlmemory"
+ ],
+}
diff --git a/soundtrigger/2.1/vts/functional/VtsHalSoundtriggerV2_1TargetTest.cpp b/soundtrigger/2.1/vts/functional/VtsHalSoundtriggerV2_1TargetTest.cpp
new file mode 100644
index 0000000..9876cdd
--- /dev/null
+++ b/soundtrigger/2.1/vts/functional/VtsHalSoundtriggerV2_1TargetTest.cpp
@@ -0,0 +1,558 @@
+/*
+ * 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.0/types.h>
+#include <android/hardware/soundtrigger/2.1/ISoundTriggerHw.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
+#include <hidlmemory/mapping.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+#define SHORT_TIMEOUT_PERIOD (1)
+
+using ::android::sp;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::audio::common::V2_0::AudioDevice;
+using ::android::hardware::soundtrigger::V2_0::PhraseRecognitionExtra;
+using ::android::hardware::soundtrigger::V2_0::RecognitionMode;
+using ::android::hardware::soundtrigger::V2_0::SoundModelHandle;
+using ::android::hardware::soundtrigger::V2_0::SoundModelType;
+using V2_0_ISoundTriggerHw = ::android::hardware::soundtrigger::V2_0::ISoundTriggerHw;
+using V2_0_ISoundTriggerHwCallback =
+ ::android::hardware::soundtrigger::V2_0::ISoundTriggerHwCallback;
+using ::android::hardware::soundtrigger::V2_1::ISoundTriggerHw;
+using ParameterValue = ::android::hardware::soundtrigger::V2_1::ISoundTriggerHw::ParameterValue;
+using ::android::hardware::soundtrigger::V2_1::ISoundTriggerHwCallback;
+using ::android::hidl::allocator::V1_0::IAllocator;
+using ::android::hidl::memory::V1_0::IMemory;
+
+/**
+ * Test code uses this class to wait for notification from callback.
+ */
+class Monitor {
+ public:
+ Monitor() : mCount(0) {}
+
+ /**
+ * Adds 1 to the internal counter and unblocks one of the waiting threads.
+ */
+ void notify() {
+ std::unique_lock<std::mutex> lock(mMtx);
+ mCount++;
+ mCv.notify_one();
+ }
+
+ /**
+ * Blocks until the internal counter becomes greater than 0.
+ *
+ * If notified, this method decreases the counter by 1 and returns true.
+ * If timeout, returns false.
+ */
+ bool wait(int timeoutSeconds) {
+ auto deadline = std::chrono::system_clock::now() + std::chrono::seconds(timeoutSeconds);
+ std::unique_lock<std::mutex> lock(mMtx);
+ if (!mCv.wait_until(lock, deadline, [& count = mCount] { return count > 0; })) {
+ return false;
+ }
+ mCount--;
+ return true;
+ }
+
+ private:
+ std::mutex mMtx;
+ std::condition_variable mCv;
+ int mCount;
+};
+
+// The main test class for Sound Trigger HIDL HAL.
+class SoundTriggerHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+ public:
+ virtual void SetUp() override {
+ mSoundTriggerHal = ::testing::VtsHalHidlTargetTestBase::getService<ISoundTriggerHw>();
+ ASSERT_NE(nullptr, mSoundTriggerHal.get());
+ mCallback = new SoundTriggerHwCallback(*this);
+ ASSERT_NE(nullptr, mCallback.get());
+ }
+
+ static void SetUpTestCase() { srand(1234); }
+
+ class SoundTriggerHwCallback : public ISoundTriggerHwCallback {
+ private:
+ SoundTriggerHidlTest& mParent;
+
+ public:
+ SoundTriggerHwCallback(SoundTriggerHidlTest& parent) : mParent(parent) {}
+
+ Return<void> recognitionCallback(const V2_0_ISoundTriggerHwCallback::RecognitionEvent& event
+ __unused,
+ int32_t cookie __unused) override {
+ ALOGI("%s", __FUNCTION__);
+ return Void();
+ };
+
+ Return<void> phraseRecognitionCallback(
+ const V2_0_ISoundTriggerHwCallback::PhraseRecognitionEvent& event __unused,
+ int32_t cookie __unused) override {
+ ALOGI("%s", __FUNCTION__);
+ return Void();
+ };
+
+ Return<void> soundModelCallback(const V2_0_ISoundTriggerHwCallback::ModelEvent& event,
+ int32_t cookie __unused) override {
+ ALOGI("%s", __FUNCTION__);
+ mParent.lastModelEvent_2_0 = event;
+ mParent.monitor.notify();
+ return Void();
+ }
+
+ Return<void> recognitionCallback_2_1(const ISoundTriggerHwCallback::RecognitionEvent& event
+ __unused,
+ int32_t cookie __unused) override {
+ ALOGI("%s", __FUNCTION__);
+ return Void();
+ }
+
+ Return<void> phraseRecognitionCallback_2_1(
+ const ISoundTriggerHwCallback::PhraseRecognitionEvent& event __unused,
+ int32_t cookie __unused) override {
+ ALOGI("%s", __FUNCTION__);
+ return Void();
+ }
+
+ Return<void> soundModelCallback_2_1(const ISoundTriggerHwCallback::ModelEvent& event,
+ int32_t cookie __unused) {
+ ALOGI("%s", __FUNCTION__);
+ mParent.lastModelEvent = event;
+ mParent.monitor.notify();
+ return Void();
+ }
+ };
+
+ virtual void TearDown() override {}
+
+ Monitor monitor;
+ // updated by soundModelCallback()
+ V2_0_ISoundTriggerHwCallback::ModelEvent lastModelEvent_2_0;
+ // updated by soundModelCallback_2_1()
+ ISoundTriggerHwCallback::ModelEvent lastModelEvent;
+
+ protected:
+ sp<ISoundTriggerHw> mSoundTriggerHal;
+ sp<SoundTriggerHwCallback> mCallback;
+};
+
+/**
+ * Test ISoundTriggerHw::getProperties() method
+ *
+ * Verifies that:
+ * - the implementation implements the method
+ * - the method returns 0 (no error)
+ * - the implementation supports at least one sound model and one key phrase
+ * - the implementation supports at least VOICE_TRIGGER recognition mode
+ */
+TEST_F(SoundTriggerHidlTest, GetProperties) {
+ ISoundTriggerHw::Properties halProperties;
+ Return<void> hidlReturn;
+ int ret = -ENODEV;
+
+ hidlReturn = mSoundTriggerHal->getProperties([&](int rc, auto res) {
+ ret = rc;
+ halProperties = res;
+ });
+
+ EXPECT_TRUE(hidlReturn.isOk());
+ EXPECT_EQ(0, ret);
+ EXPECT_GT(halProperties.maxSoundModels, 0u);
+ EXPECT_GT(halProperties.maxKeyPhrases, 0u);
+ EXPECT_NE(0u, (halProperties.recognitionModes & (uint32_t)RecognitionMode::VOICE_TRIGGER));
+}
+
+/**
+ * Test ISoundTriggerHw::loadPhraseSoundModel() method
+ *
+ * Verifies that:
+ * - the implementation implements the method
+ * - the implementation returns an error when passed a malformed sound model
+ *
+ * There is no way to verify that implementation actually can load a sound model because each
+ * sound model is vendor specific.
+ */
+TEST_F(SoundTriggerHidlTest, LoadInvalidModelFail) {
+ Return<void> hidlReturn;
+ int ret = -ENODEV;
+ V2_0_ISoundTriggerHw::PhraseSoundModel model;
+ SoundModelHandle handle;
+
+ model.common.type = SoundModelType::UNKNOWN;
+
+ hidlReturn =
+ mSoundTriggerHal->loadPhraseSoundModel(model, mCallback, 0, [&](int32_t retval, auto res) {
+ ret = retval;
+ handle = res;
+ });
+
+ EXPECT_TRUE(hidlReturn.isOk());
+ EXPECT_NE(0, ret);
+ EXPECT_FALSE(monitor.wait(SHORT_TIMEOUT_PERIOD));
+}
+
+/**
+ * Test ISoundTriggerHw::loadPhraseSoundModel_2_1() method
+ *
+ * Verifies that:
+ * - the implementation implements the method
+ * - the implementation returns an error when passed a malformed sound model
+ *
+ * There is no way to verify that implementation actually can load a sound model because each
+ * sound model is vendor specific.
+ */
+TEST_F(SoundTriggerHidlTest, LoadInvalidModelFail_2_1) {
+ Return<void> hidlReturn;
+ int ret = -ENODEV;
+ ISoundTriggerHw::PhraseSoundModel model;
+ SoundModelHandle handle;
+
+ model.common.header.type = SoundModelType::UNKNOWN;
+
+ hidlReturn = mSoundTriggerHal->loadPhraseSoundModel_2_1(model, mCallback, 0,
+ [&](int32_t retval, auto res) {
+ ret = retval;
+ handle = res;
+ });
+
+ EXPECT_TRUE(hidlReturn.isOk());
+ EXPECT_NE(0, ret);
+ EXPECT_FALSE(monitor.wait(SHORT_TIMEOUT_PERIOD));
+}
+
+/**
+ * Test ISoundTriggerHw::loadSoundModel() method
+ *
+ * Verifies that:
+ * - the implementation returns an error when passed an empty sound model
+ */
+TEST_F(SoundTriggerHidlTest, LoadEmptyGenericSoundModelFail) {
+ int ret = -ENODEV;
+ V2_0_ISoundTriggerHw::SoundModel model;
+ SoundModelHandle handle = 0;
+
+ model.type = SoundModelType::GENERIC;
+
+ Return<void> loadReturn =
+ mSoundTriggerHal->loadSoundModel(model, mCallback, 0, [&](int32_t retval, auto res) {
+ ret = retval;
+ handle = res;
+ });
+
+ EXPECT_TRUE(loadReturn.isOk());
+ EXPECT_NE(0, ret);
+ EXPECT_FALSE(monitor.wait(SHORT_TIMEOUT_PERIOD));
+}
+
+/**
+ * Test ISoundTriggerHw::loadSoundModel() method
+ *
+ * Verifies that:
+ * - the implementation returns error when passed a sound model with random data.
+ */
+TEST_F(SoundTriggerHidlTest, LoadGenericSoundModelFail) {
+ int ret = -ENODEV;
+ V2_0_ISoundTriggerHw::SoundModel model;
+ SoundModelHandle handle = 0;
+
+ model.type = SoundModelType::GENERIC;
+ model.data.resize(100);
+ for (auto& d : model.data) {
+ d = rand();
+ }
+
+ Return<void> loadReturn =
+ mSoundTriggerHal->loadSoundModel(model, mCallback, 0, [&](int32_t retval, auto res) {
+ ret = retval;
+ handle = res;
+ });
+
+ EXPECT_TRUE(loadReturn.isOk());
+ EXPECT_NE(0, ret);
+ EXPECT_FALSE(monitor.wait(SHORT_TIMEOUT_PERIOD));
+}
+
+/**
+ * Test ISoundTriggerHw::loadSoundModel_2_1() method
+ *
+ * Verifies that:
+ * - the implementation returns error when passed a sound model with random data.
+ */
+TEST_F(SoundTriggerHidlTest, LoadEmptyGenericSoundModelFail_2_1) {
+ int ret = -ENODEV;
+ ISoundTriggerHw::SoundModel model;
+ SoundModelHandle handle = 0;
+
+ model.header.type = SoundModelType::GENERIC;
+
+ Return<void> loadReturn =
+ mSoundTriggerHal->loadSoundModel_2_1(model, mCallback, 0, [&](int32_t retval, auto res) {
+ ret = retval;
+ handle = res;
+ });
+
+ EXPECT_TRUE(loadReturn.isOk());
+ EXPECT_NE(0, ret);
+ EXPECT_FALSE(monitor.wait(SHORT_TIMEOUT_PERIOD));
+}
+
+/**
+ * Test ISoundTriggerHw::loadSoundModel_2_1() method
+ *
+ * Verifies that:
+ * - the implementation returns error when passed a sound model with random data.
+ */
+TEST_F(SoundTriggerHidlTest, LoadGenericSoundModelFail_2_1) {
+ int ret = -ENODEV;
+ ISoundTriggerHw::SoundModel model;
+ SoundModelHandle handle = 0;
+
+ model.header.type = SoundModelType::GENERIC;
+ sp<IAllocator> ashmem = IAllocator::getService("ashmem");
+ ASSERT_NE(nullptr, ashmem.get());
+ hidl_memory hmemory;
+ int size = 100;
+ Return<void> allocReturn = ashmem->allocate(size, [&](bool success, const hidl_memory& m) {
+ ASSERT_TRUE(success);
+ hmemory = m;
+ });
+ sp<IMemory> memory = ::android::hardware::mapMemory(hmemory);
+ ASSERT_NE(nullptr, memory.get());
+ memory->update();
+ for (uint8_t *p = static_cast<uint8_t*>(static_cast<void*>(memory->getPointer())); size >= 0;
+ p++, size--) {
+ *p = rand();
+ }
+
+ Return<void> loadReturn =
+ mSoundTriggerHal->loadSoundModel_2_1(model, mCallback, 0, [&](int32_t retval, auto res) {
+ ret = retval;
+ handle = res;
+ });
+
+ EXPECT_TRUE(loadReturn.isOk());
+ EXPECT_NE(0, ret);
+ EXPECT_FALSE(monitor.wait(SHORT_TIMEOUT_PERIOD));
+}
+
+/**
+ * Test ISoundTriggerHw::unloadSoundModel() method
+ *
+ * Verifies that:
+ * - the implementation implements the method
+ * - the implementation returns an error when called without a valid loaded sound model
+ *
+ */
+TEST_F(SoundTriggerHidlTest, UnloadModelNoModelFail) {
+ Return<int32_t> hidlReturn(0);
+ SoundModelHandle halHandle = 0;
+
+ hidlReturn = mSoundTriggerHal->unloadSoundModel(halHandle);
+
+ EXPECT_TRUE(hidlReturn.isOk());
+ EXPECT_NE(0, hidlReturn);
+}
+
+/**
+ * Test ISoundTriggerHw::startRecognition() method
+ *
+ * Verifies that:
+ * - the implementation implements the method
+ * - the implementation returns an error when called without a valid loaded sound model
+ *
+ * There is no way to verify that implementation actually starts recognition because no model can
+ * be loaded.
+ */
+TEST_F(SoundTriggerHidlTest, StartRecognitionNoModelFail) {
+ Return<int32_t> hidlReturn(0);
+ SoundModelHandle handle = 0;
+ PhraseRecognitionExtra phrase;
+ V2_0_ISoundTriggerHw::RecognitionConfig config;
+
+ config.captureHandle = 0;
+ config.captureDevice = AudioDevice::IN_BUILTIN_MIC;
+ phrase.id = 0;
+ phrase.recognitionModes = (uint32_t)RecognitionMode::VOICE_TRIGGER;
+ phrase.confidenceLevel = 0;
+
+ config.phrases.setToExternal(&phrase, 1);
+
+ hidlReturn = mSoundTriggerHal->startRecognition(handle, config, mCallback, 0);
+
+ EXPECT_TRUE(hidlReturn.isOk());
+ EXPECT_NE(0, hidlReturn);
+}
+
+/**
+ * Test ISoundTriggerHw::startRecognition_2_1() method
+ *
+ * Verifies that:
+ * - the implementation implements the method
+ * - the implementation returns an error when called without a valid loaded sound model
+ *
+ * There is no way to verify that implementation actually starts recognition because no model can
+ * be loaded.
+ */
+TEST_F(SoundTriggerHidlTest, StartRecognitionNoModelFail_2_1) {
+ Return<int32_t> hidlReturn(0);
+ SoundModelHandle handle = 0;
+ PhraseRecognitionExtra phrase;
+ ISoundTriggerHw::RecognitionConfig config;
+
+ config.header.captureHandle = 0;
+ config.header.captureDevice = AudioDevice::IN_BUILTIN_MIC;
+ phrase.id = 0;
+ phrase.recognitionModes = (uint32_t)RecognitionMode::VOICE_TRIGGER;
+ phrase.confidenceLevel = 0;
+
+ config.header.phrases.setToExternal(&phrase, 1);
+
+ hidlReturn = mSoundTriggerHal->startRecognition_2_1(handle, config, mCallback, 0);
+
+ EXPECT_TRUE(hidlReturn.isOk());
+ EXPECT_NE(0, hidlReturn);
+}
+
+/**
+ * Test ISoundTriggerHw::stopRecognition() method
+ *
+ * Verifies that:
+ * - the implementation implements the method
+ * - the implementation returns an error when called without an active recognition running
+ *
+ */
+TEST_F(SoundTriggerHidlTest, StopRecognitionNoAStartFail) {
+ Return<int32_t> hidlReturn(0);
+ SoundModelHandle handle = 0;
+
+ hidlReturn = mSoundTriggerHal->stopRecognition(handle);
+
+ EXPECT_TRUE(hidlReturn.isOk());
+ EXPECT_NE(0, hidlReturn);
+}
+
+/**
+ * Test ISoundTriggerHw::stopAllRecognitions() method
+ *
+ * Verifies that:
+ * - the implementation implements this optional method or indicates it is not supported by
+ * returning -ENOSYS
+ */
+TEST_F(SoundTriggerHidlTest, stopAllRecognitions) {
+ Return<int32_t> hidlReturn(0);
+
+ hidlReturn = mSoundTriggerHal->stopAllRecognitions();
+
+ EXPECT_TRUE(hidlReturn.isOk());
+ EXPECT_TRUE(hidlReturn == 0 || hidlReturn == -ENOSYS);
+}
+
+/**
+ * Test ISoundTriggerHw::getParameters() and setParameters() methods
+ *
+ * Verifies that:
+ * - the implementation implements these optional methods or indicates it is not supported by
+ * returning -ENOSYS
+ */
+TEST_F(SoundTriggerHidlTest, getAndSetParameters) {
+ hidl_vec<hidl_string> keys;
+ hidl_vec<ParameterValue> values;
+
+ int32_t ret = -ENODEV;
+ Return<void> hidlReturn =
+ mSoundTriggerHal->getParameters(keys, [&](int32_t retval, auto params) {
+ ret = retval;
+ values = params;
+ });
+ EXPECT_TRUE(hidlReturn.isOk());
+ EXPECT_TRUE(ret == 0 || ret == -ENOSYS);
+ if (ret == 0) {
+ Return<int32_t> hidlReturn = mSoundTriggerHal->setParameters(values);
+ EXPECT_TRUE(hidlReturn.isOk());
+ EXPECT_EQ(0, hidlReturn);
+ }
+}
+
+/**
+ * Test ISoundTriggerHw::setParameters() method
+ *
+ * Verifies that:
+ * - the implementation accepts empty parameters to be set or indicates it is not supported by
+ * returning -ENOSYS
+ */
+TEST_F(SoundTriggerHidlTest, setParameters) {
+ hidl_vec<ParameterValue> values;
+ Return<int32_t> hidlReturn = mSoundTriggerHal->setParameters(values);
+ EXPECT_TRUE(hidlReturn.isOk());
+ EXPECT_TRUE(hidlReturn == 0 || hidlReturn == -ENOSYS);
+}
+
+/**
+ * Test ISoundTriggerHw::getSoundModelParameters() and setSoundModelParameters() methods
+ *
+ * Verifies that:
+ * - the implementation implements these optional methods or indicates it is not supported by
+ * returning -ENOSYS;
+ * - if the methods are supported, the implementation returns an error when called without
+ * an active recognition running.
+ *
+ */
+TEST_F(SoundTriggerHidlTest, getAndSetSoundModelParameters) {
+ SoundModelHandle handle = 0;
+ hidl_vec<hidl_string> keys;
+ hidl_vec<ParameterValue> values;
+
+ {
+ int32_t ret = 0;
+ Return<void> hidlReturn = mSoundTriggerHal->getSoundModelParameters(
+ handle, keys, [&](int32_t retval, auto params) {
+ ret = retval;
+ values = params;
+ });
+ EXPECT_TRUE(hidlReturn.isOk());
+ EXPECT_NE(0, ret);
+ EXPECT_EQ(0u, values.size());
+ }
+
+ values.resize(0);
+ {
+ Return<int32_t> hidlReturn = mSoundTriggerHal->setSoundModelParameters(handle, values);
+ EXPECT_TRUE(hidlReturn.isOk());
+ EXPECT_NE(0, hidlReturn);
+ }
+}
diff --git a/wifi/1.2/Android.bp b/wifi/1.2/Android.bp
index 49752a1..14ea5b1 100644
--- a/wifi/1.2/Android.bp
+++ b/wifi/1.2/Android.bp
@@ -7,14 +7,19 @@
enabled: true,
},
srcs: [
+ "types.hal",
"IWifi.hal",
"IWifiChip.hal",
+ "IWifiNanIface.hal",
],
interfaces: [
"android.hardware.wifi@1.0",
"android.hardware.wifi@1.1",
"android.hidl.base@1.0",
],
+ types: [
+ "NanConfigRequestSupplemental",
+ ],
gen_java: true,
}
diff --git a/wifi/1.2/IWifiNanIface.hal b/wifi/1.2/IWifiNanIface.hal
new file mode 100644
index 0000000..7f7b4d0
--- /dev/null
+++ b/wifi/1.2/IWifiNanIface.hal
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2017 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.wifi@1.2;
+
+import @1.0::CommandIdShort;
+import @1.0::IWifiNanIface;
+import @1.0::NanConfigRequest;
+import @1.0::NanEnableRequest;
+import @1.0::WifiStatus;
+
+/**
+ * Interface used to represent a single NAN (Neighbour Aware Network) iface.
+ *
+ * References to "NAN Spec" are to the Wi-Fi Alliance "Wi-Fi Neighbor Awareness
+ * Networking (NAN) Technical Specification".
+ */
+interface IWifiNanIface extends @1.0::IWifiNanIface {
+ /**
+ * Enable NAN: configures and activates NAN clustering (does not start
+ * a discovery session or set up data-interfaces or data-paths). Use the
+ * |IWifiNanIface.configureRequest| method to change the configuration of an already enabled
+ * NAN interface.
+ * Asynchronous response is with |IWifiNanIfaceEventCallback.notifyEnableResponse|.
+ *
+ * Note: supersedes the @1.0::IWifiNanIface.enableRequest() method which is deprecated as of
+ * HAL version 1.2.
+ *
+ * @param cmdId command Id to use for this invocation.
+ * @param msg1 Instance of |NanEnableRequest|.
+ * @param msg2 Instance of |NanConfigRequestSupplemental|.
+ * @return status WifiStatus of the operation.
+ * Possible status codes:
+ * |WifiStatusCode.SUCCESS|,
+ * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+ * |WifiStatusCode.ERROR_INVALID_ARGS|,
+ * |WifiStatusCode.ERROR_UNKNOWN|
+ */
+ enableRequest_1_2(CommandIdShort cmdId, NanEnableRequest msg1,
+ NanConfigRequestSupplemental msg2)
+ generates (WifiStatus status);
+
+ /**
+ * Configure NAN: configures an existing NAN functionality (i.e. assumes
+ * |IWifiNanIface.enableRequest| already submitted and succeeded).
+ * Asynchronous response is with |IWifiNanIfaceEventCallback.notifyConfigResponse|.
+ *
+ * Note: supersedes the @1.0::IWifiNanIface.configRequest() method which is deprecated as of
+ * HAL version 1.2.
+ *
+ * @param cmdId command Id to use for this invocation.
+ * @param msg1 Instance of |NanConfigRequest|.
+ * @param msg1 Instance of |NanConfigRequestSupplemental|.
+ * @return status WifiStatus of the operation.
+ * Possible status codes:
+ * |WifiStatusCode.SUCCESS|,
+ * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+ * |WifiStatusCode.ERROR_INVALID_ARGS|,
+ * |WifiStatusCode.ERROR_UNKNOWN|
+ */
+ configRequest_1_2(CommandIdShort cmdId, NanConfigRequest msg1,
+ NanConfigRequestSupplemental msg2)
+ generates (WifiStatus status);
+};
diff --git a/wifi/1.2/default/hidl_struct_util.cpp b/wifi/1.2/default/hidl_struct_util.cpp
index 5d48109..b1b6f64 100644
--- a/wifi/1.2/default/hidl_struct_util.cpp
+++ b/wifi/1.2/default/hidl_struct_util.cpp
@@ -1118,6 +1118,33 @@
return true;
}
+bool convertHidlNanEnableRequest_1_2ToLegacy(
+ const NanEnableRequest& hidl_request1,
+ const NanConfigRequestSupplemental& hidl_request2,
+ legacy_hal::NanEnableRequest* legacy_request) {
+ if (!legacy_request) {
+ LOG(ERROR)
+ << "convertHidlNanEnableRequest_1_2ToLegacy: null legacy_request";
+ return false;
+ }
+
+ *legacy_request = {};
+ if (!convertHidlNanEnableRequestToLegacy(hidl_request1, legacy_request)) {
+ return false;
+ }
+
+ legacy_request->config_discovery_beacon_int = 1;
+ legacy_request->discovery_beacon_interval =
+ hidl_request2.discoveryBeaconIntervalMs;
+ legacy_request->config_nss = 1;
+ legacy_request->nss = hidl_request2.numberOfSpatialStreamsInDiscovery;
+ legacy_request->config_dw_early_termination = 1;
+ legacy_request->enable_dw_termination =
+ hidl_request2.enableDiscoveryWindowEarlyTermination;
+
+ return true;
+}
+
bool convertHidlNanPublishRequestToLegacy(
const NanPublishRequest& hidl_request,
legacy_hal::NanPublishRequest* legacy_request) {
@@ -1600,6 +1627,33 @@
return true;
}
+bool convertHidlNanConfigRequest_1_2ToLegacy(
+ const NanConfigRequest& hidl_request1,
+ const NanConfigRequestSupplemental& hidl_request2,
+ legacy_hal::NanConfigRequest* legacy_request) {
+ if (!legacy_request) {
+ LOG(ERROR) << "convertHidlNanConfigRequest_1_2ToLegacy: legacy_request "
+ "is null";
+ return false;
+ }
+
+ *legacy_request = {};
+ if (!convertHidlNanConfigRequestToLegacy(hidl_request1, legacy_request)) {
+ return false;
+ }
+
+ legacy_request->config_discovery_beacon_int = 1;
+ legacy_request->discovery_beacon_interval =
+ hidl_request2.discoveryBeaconIntervalMs;
+ legacy_request->config_nss = 1;
+ legacy_request->nss = hidl_request2.numberOfSpatialStreamsInDiscovery;
+ legacy_request->config_dw_early_termination = 1;
+ legacy_request->enable_dw_termination =
+ hidl_request2.enableDiscoveryWindowEarlyTermination;
+
+ return true;
+}
+
bool convertHidlNanDataPathInitiatorRequestToLegacy(
const NanInitiateDataPathRequest& hidl_request,
legacy_hal::NanDataPathInitiatorRequest* legacy_request) {
diff --git a/wifi/1.2/default/hidl_struct_util.h b/wifi/1.2/default/hidl_struct_util.h
index 6766b0f..e44ab7d 100644
--- a/wifi/1.2/default/hidl_struct_util.h
+++ b/wifi/1.2/default/hidl_struct_util.h
@@ -22,6 +22,7 @@
#include <android/hardware/wifi/1.0/IWifiChip.h>
#include <android/hardware/wifi/1.0/types.h>
#include <android/hardware/wifi/1.1/IWifiChip.h>
+#include <android/hardware/wifi/1.2/types.h>
#include "wifi_legacy_hal.h"
@@ -106,6 +107,14 @@
bool convertHidlNanConfigRequestToLegacy(
const NanConfigRequest& hidl_request,
legacy_hal::NanConfigRequest* legacy_request);
+bool convertHidlNanEnableRequest_1_2ToLegacy(
+ const NanEnableRequest& hidl_request1,
+ const NanConfigRequestSupplemental& hidl_request2,
+ legacy_hal::NanEnableRequest* legacy_request);
+bool convertHidlNanConfigRequest_1_2ToLegacy(
+ const NanConfigRequest& hidl_request1,
+ const NanConfigRequestSupplemental& hidl_request2,
+ legacy_hal::NanConfigRequest* legacy_request);
bool convertHidlNanPublishRequestToLegacy(
const NanPublishRequest& hidl_request,
legacy_hal::NanPublishRequest* legacy_request);
diff --git a/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp
index f73869b..1b082d0 100644
--- a/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp
+++ b/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp
@@ -117,8 +117,10 @@
});
} else if (type == IfaceType::NAN) {
chip_->createNanIface(
- [&iface_name](const WifiStatus& status,
- const sp<IWifiNanIface>& iface) {
+ [&iface_name](
+ const WifiStatus& status,
+ const sp<android::hardware::wifi::V1_0::IWifiNanIface>&
+ iface) {
if (WifiStatusCode::SUCCESS == status.code) {
ASSERT_NE(iface.get(), nullptr);
iface->getName([&iface_name](const WifiStatus& status,
diff --git a/wifi/1.2/default/wifi_nan_iface.cpp b/wifi/1.2/default/wifi_nan_iface.cpp
index 12e4d7b..e93e6be 100644
--- a/wifi/1.2/default/wifi_nan_iface.cpp
+++ b/wifi/1.2/default/wifi_nan_iface.cpp
@@ -628,6 +628,24 @@
hidl_status_cb, cmd_id, ndpInstanceId);
}
+Return<void> WifiNanIface::enableRequest_1_2(
+ uint16_t cmd_id, const NanEnableRequest& msg1,
+ const NanConfigRequestSupplemental& msg2,
+ enableRequest_1_2_cb hidl_status_cb) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiNanIface::enableRequest_1_2Internal,
+ hidl_status_cb, cmd_id, msg1, msg2);
+}
+
+Return<void> WifiNanIface::configRequest_1_2(
+ uint16_t cmd_id, const NanConfigRequest& msg1,
+ const NanConfigRequestSupplemental& msg2,
+ configRequest_1_2_cb hidl_status_cb) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiNanIface::configRequest_1_2Internal,
+ hidl_status_cb, cmd_id, msg1, msg2);
+}
+
std::pair<WifiStatus, std::string> WifiNanIface::getNameInternal() {
return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_};
}
@@ -650,28 +668,14 @@
return createWifiStatusFromLegacyError(legacy_status);
}
-WifiStatus WifiNanIface::enableRequestInternal(uint16_t cmd_id,
- const NanEnableRequest& msg) {
- legacy_hal::NanEnableRequest legacy_msg;
- if (!hidl_struct_util::convertHidlNanEnableRequestToLegacy(msg,
- &legacy_msg)) {
- return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
- }
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->nanEnableRequest(ifname_, cmd_id, legacy_msg);
- return createWifiStatusFromLegacyError(legacy_status);
+WifiStatus WifiNanIface::enableRequestInternal(
+ uint16_t /* cmd_id */, const NanEnableRequest& /* msg */) {
+ return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
}
-WifiStatus WifiNanIface::configRequestInternal(uint16_t cmd_id,
- const NanConfigRequest& msg) {
- legacy_hal::NanConfigRequest legacy_msg;
- if (!hidl_struct_util::convertHidlNanConfigRequestToLegacy(msg,
- &legacy_msg)) {
- return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
- }
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->nanConfigRequest(ifname_, cmd_id, legacy_msg);
- return createWifiStatusFromLegacyError(legacy_status);
+WifiStatus WifiNanIface::configRequestInternal(
+ uint16_t /* cmd_id */, const NanConfigRequest& /* msg */) {
+ return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
}
WifiStatus WifiNanIface::disableRequestInternal(uint16_t cmd_id) {
@@ -780,6 +784,32 @@
return createWifiStatusFromLegacyError(legacy_status);
}
+WifiStatus WifiNanIface::enableRequest_1_2Internal(
+ uint16_t cmd_id, const NanEnableRequest& msg1,
+ const NanConfigRequestSupplemental& msg2) {
+ legacy_hal::NanEnableRequest legacy_msg;
+ if (!hidl_struct_util::convertHidlNanEnableRequest_1_2ToLegacy(
+ msg1, msg2, &legacy_msg)) {
+ return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+ }
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->nanEnableRequest(ifname_, cmd_id, legacy_msg);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiNanIface::configRequest_1_2Internal(
+ uint16_t cmd_id, const NanConfigRequest& msg1,
+ const NanConfigRequestSupplemental& msg2) {
+ legacy_hal::NanConfigRequest legacy_msg;
+ if (!hidl_struct_util::convertHidlNanConfigRequest_1_2ToLegacy(
+ msg1, msg2, &legacy_msg)) {
+ return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+ }
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->nanConfigRequest(ifname_, cmd_id, legacy_msg);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
} // namespace implementation
} // namespace V1_2
} // namespace wifi
diff --git a/wifi/1.2/default/wifi_nan_iface.h b/wifi/1.2/default/wifi_nan_iface.h
index 6fa7b0c..2ded3a8 100644
--- a/wifi/1.2/default/wifi_nan_iface.h
+++ b/wifi/1.2/default/wifi_nan_iface.h
@@ -18,8 +18,8 @@
#define WIFI_NAN_IFACE_H_
#include <android-base/macros.h>
-#include <android/hardware/wifi/1.0/IWifiNanIface.h>
#include <android/hardware/wifi/1.0/IWifiNanIfaceEventCallback.h>
+#include <android/hardware/wifi/1.2/IWifiNanIface.h>
#include "hidl_callback_util.h"
#include "wifi_legacy_hal.h"
@@ -34,7 +34,7 @@
/**
* HIDL interface object used to control a NAN Iface instance.
*/
-class WifiNanIface : public V1_0::IWifiNanIface {
+class WifiNanIface : public V1_2::IWifiNanIface {
public:
WifiNanIface(const std::string& ifname,
const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
@@ -88,6 +88,15 @@
uint16_t cmd_id, uint32_t ndpInstanceId,
terminateDataPathRequest_cb hidl_status_cb) override;
+ Return<void> enableRequest_1_2(
+ uint16_t cmd_id, const NanEnableRequest& msg1,
+ const NanConfigRequestSupplemental& msg2,
+ enableRequest_1_2_cb hidl_status_cb) override;
+ Return<void> configRequest_1_2(
+ uint16_t cmd_id, const NanConfigRequest& msg1,
+ const NanConfigRequestSupplemental& msg2,
+ configRequest_1_2_cb hidl_status_cb) override;
+
private:
// Corresponding worker functions for the HIDL methods.
std::pair<WifiStatus, std::string> getNameInternal();
@@ -119,6 +128,13 @@
WifiStatus terminateDataPathRequestInternal(uint16_t cmd_id,
uint32_t ndpInstanceId);
+ WifiStatus enableRequest_1_2Internal(
+ uint16_t cmd_id, const NanEnableRequest& msg1,
+ const NanConfigRequestSupplemental& msg2);
+ WifiStatus configRequest_1_2Internal(
+ uint16_t cmd_id, const NanConfigRequest& msg,
+ const NanConfigRequestSupplemental& msg2);
+
std::set<sp<IWifiNanIfaceEventCallback>> getEventCallbacks();
std::string ifname_;
diff --git a/wifi/1.2/types.hal b/wifi/1.2/types.hal
new file mode 100644
index 0000000..9151295
--- /dev/null
+++ b/wifi/1.2/types.hal
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2017 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.wifi@1.2;
+
+/**
+ * NAN configuration request parameters added in the 1.2 HAL. These are supplemental to previous
+ * versions.
+ */
+struct NanConfigRequestSupplemental {
+ /**
+ * Specify the Discovery Beacon interval in ms. Specification only applicable if the device
+ * transmits Discovery Beacons (based on the Wi-Fi Aware protocol selection criteria). The value
+ * can be increased to reduce power consumption (on devices which would transmit Discovery
+ * Beacons), however - cluster synchronization time will likely increase.
+ * Values are:
+ * - A value of 0 indicates that the HAL sets the interval to a default (implementation specific)
+ * - A positive value
+ */
+ uint32_t discoveryBeaconIntervalMs;
+ /**
+ * The number of spatial streams to be used for transmitting NAN management frames (does NOT apply
+ * to data-path packets). A small value may reduce power consumption for small discovery packets.
+ * Values are:
+ * - A value of 0 indicates that the HAL sets the number to a default (implementation specific)
+ * - A positive value
+ */
+ uint32_t numberOfSpatialStreamsInDiscovery;
+ /**
+ * Controls whether the device may terminate listening on a Discovery Window (DW) earlier than the
+ * DW termination (16ms) if no information is received. Enabling the feature will result in
+ * lower power consumption, but may result in some missed messages and hence increased latency.
+ */
+ bool enableDiscoveryWindowEarlyTermination;
+};
+