| /* |
| * Copyright 2018 Google Inc. All Rights Reserved. |
| * |
| * 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 "oslo_sound_model" |
| |
| #include <ctype.h> |
| #include <cutils/properties.h> |
| #include <hardware/sound_trigger.h> |
| #include <inttypes.h> |
| #include <log/log.h> |
| #include <pthread.h> |
| #include <stdbool.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <unistd.h> |
| |
| #include <android/hardware/soundtrigger/2.0/ISoundTriggerHw.h> |
| |
| #include "oslo_sound_model_control.h" |
| #include "sound_trigger_hw_iaxxx.h" |
| |
| using android::sp; |
| using android::hardware::Return; |
| using android::hardware::soundtrigger::V2_0::ISoundTriggerHw; |
| using android::hardware::soundtrigger::V2_0::SoundModelHandle; |
| using android::hardware::soundtrigger::V2_0::SoundModelType; |
| |
| #define OSLO_SOUND_MODEL_HANDLE_PROP "vendor.oslo.sm.hndl" |
| |
| static SoundModelHandle osloSoundModelHandle = 0; |
| |
| static bool strToUuid(const char* uuid_str, sound_trigger_uuid_t* uuid) { |
| if (uuid_str == NULL) { |
| ALOGI("Invalid str_to_uuid input."); |
| return false; |
| } |
| |
| int tmp[10]; |
| if (sscanf(uuid_str, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x", |
| tmp, tmp+1, tmp+2, tmp+3, tmp+4, tmp+5, |
| tmp+6, tmp+7, tmp+8, tmp+9) < 10) { |
| ALOGI("Invalid UUID, got: %s", uuid_str); |
| return false; |
| } |
| uuid->timeLow = (unsigned int)tmp[0]; |
| uuid->timeMid = (unsigned short)tmp[1]; |
| uuid->timeHiAndVersion = (unsigned short)tmp[2]; |
| uuid->clockSeq = (unsigned short)tmp[3]; |
| uuid->node[0] = (unsigned char)tmp[4]; |
| uuid->node[1] = (unsigned char)tmp[5]; |
| uuid->node[2] = (unsigned char)tmp[6]; |
| uuid->node[3] = (unsigned char)tmp[7]; |
| uuid->node[4] = (unsigned char)tmp[8]; |
| uuid->node[5] = (unsigned char)tmp[9]; |
| |
| return true; |
| } |
| |
| /** |
| * Loads oslo sound model via the SoundTrigger HAL HIDL service. |
| * |
| * @return true if oslo was enabled successfully, false otherwise. |
| */ |
| static bool osloLoadSoundModel(SoundModelHandle *hndl) { |
| ALOGD("Loading oslo sound model"); |
| |
| sound_trigger_uuid_t uuid; |
| strToUuid(SENSOR_MANAGER_MODEL, &uuid); |
| ISoundTriggerHw::SoundModel soundModel; |
| soundModel.type = SoundModelType::GENERIC; |
| soundModel.vendorUuid.timeLow = uuid.timeLow; |
| soundModel.vendorUuid.timeMid = uuid.timeMid; |
| soundModel.vendorUuid.versionAndTimeHigh = uuid.timeHiAndVersion; |
| soundModel.vendorUuid.variantAndClockSeqHigh = uuid.clockSeq; |
| |
| memcpy(&soundModel.vendorUuid.node[0], &uuid.node[0], sizeof(uuid.node)); |
| soundModel.data.resize(1); // Insert a dummy byte to bypass HAL NULL checks. |
| |
| bool loaded = false; |
| sp<ISoundTriggerHw> stHal = ISoundTriggerHw::getService(); |
| if (stHal == nullptr) { |
| ALOGE("Failed to get ST HAL service for oslo load"); |
| } else { |
| int32_t loadResult; |
| Return<void> hidlResult = stHal->loadSoundModel(soundModel, NULL, 0, |
| [&](int32_t retval, SoundModelHandle handle) { |
| loadResult = retval; |
| *hndl = handle; |
| }); |
| |
| if (hidlResult.isOk()) { |
| if (loadResult == 0) { |
| ALOGI("Loaded oslo %d", *hndl); |
| loaded = true; |
| } else { |
| ALOGE("Failed to load oslo with %" PRId32, loadResult); |
| } |
| } else { |
| ALOGE("Failed to load oslo due to hidl error %s", |
| hidlResult.description().c_str()); |
| } |
| } |
| |
| return loaded; |
| } |
| |
| /** |
| * Unloads oslo sound model via the SoundTrigger HAL HIDL service. |
| */ |
| static void osloUnloadSoundModel(SoundModelHandle hndl) { |
| ALOGD("Unloading oslo sound model %d", hndl); |
| |
| sp<ISoundTriggerHw> stHal = ISoundTriggerHw::getService(); |
| if (stHal == nullptr) { |
| ALOGE("Failed to get ST HAL service for oslo unload"); |
| } else { |
| Return<int32_t> hidlResult = stHal->unloadSoundModel(hndl); |
| |
| if (hidlResult.isOk()) { |
| if (hidlResult == 0) { |
| ALOGI("Unloaded oslo"); |
| } else { |
| ALOGE("Failed to unload oslo with %" PRId32, int32_t(hidlResult)); |
| } |
| } else { |
| ALOGE("Failed to unload oslo due to hidl error %s", |
| hidlResult.description().c_str()); |
| } |
| } |
| } |
| |
| void osloSoundModelEnable(bool enable) { |
| if (enable) { |
| if (!osloLoadSoundModel(&osloSoundModelHandle)) { |
| ALOGE("%s: Failed to load oslo sound model", __func__); |
| } |
| } |
| else { |
| if (osloSoundModelHandle == 0) { |
| char prop[PROPERTY_VALUE_MAX]; |
| property_get(OSLO_SOUND_MODEL_HANDLE_PROP, prop, "0"); |
| osloSoundModelHandle = atoi(prop); |
| } |
| |
| if (osloSoundModelHandle != 0) { |
| osloUnloadSoundModel(osloSoundModelHandle); |
| osloSoundModelHandle = 0; |
| } |
| } |
| |
| property_set(OSLO_SOUND_MODEL_HANDLE_PROP, |
| std::to_string(osloSoundModelHandle).c_str()); |
| } |