diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2023-04-14 00:32:15 -0700 |
---|---|---|
committer | Linux Build Service Account <lnxbuild@localhost> | 2023-04-14 00:32:15 -0700 |
commit | 8053558411d145636e2bb05f443e3436dc53e4bd (patch) | |
tree | a904a685549ff97ac2ddca34d30d43f25905d433 | |
parent | 8b512e583f760373db8176137ebe0e6b725185ee (diff) | |
parent | cd9798f40fec23835b0f75119d88505235666e29 (diff) |
Merge cd9798f40fec23835b0f75119d88505235666e29 on remote branch
Change-Id: I6fbbec55edb31324cbe59052f6838905f0ddcfaa
16 files changed, 722 insertions, 46 deletions
diff --git a/audio/common/all-versions/default/service/android.hardware.audio.service.rc b/audio/common/all-versions/default/service/android.hardware.audio.service.rc index 45fef9a936..0de4eea373 100644 --- a/audio/common/all-versions/default/service/android.hardware.audio.service.rc +++ b/audio/common/all-versions/default/service/android.hardware.audio.service.rc @@ -3,7 +3,9 @@ service vendor.audio-hal /vendor/bin/hw/android.hardware.audio.service user audioserver # media gid needed for /dev/fm (radio) and for /data/misc/media (tee) group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct wakelock context_hub - capabilities BLOCK_SUSPEND + capabilities BLOCK_SUSPEND SYS_NICE + # setting RLIMIT_RTPRIO allows binder RT priority inheritance + rlimit rtprio 10 10 ioprio rt 4 task_profiles ProcessCapacityHigh HighPerformance onrestart restart audioserver diff --git a/audio/core/all-versions/default/Device.cpp b/audio/core/all-versions/default/Device.cpp index b954fcd6f8..d03118ae5d 100644 --- a/audio/core/all-versions/default/Device.cpp +++ b/audio/core/all-versions/default/Device.cpp @@ -30,6 +30,7 @@ #include <algorithm> #include <android/log.h> +#include <hidl/HidlTransportSupport.h> #include <mediautils/MemoryLeakTrackUtil.h> #include <memunreachable/memunreachable.h> @@ -183,6 +184,7 @@ std::tuple<Result, sp<IStreamOut>> Device::openOutputStreamCore(int32_t ioHandle if (status == OK) { streamOut = new StreamOut(this, halStream); ++mOpenedStreamsCount; + android::hardware::setMinSchedulerPolicy(streamOut, SCHED_NORMAL, ANDROID_PRIORITY_AUDIO); } status_t convertStatus = HidlUtils::audioConfigFromHal(halConfig, false /*isInput*/, suggestedConfig); @@ -220,6 +222,7 @@ std::tuple<Result, sp<IStreamIn>> Device::openInputStreamCore( if (status == OK) { streamIn = new StreamIn(this, halStream); ++mOpenedStreamsCount; + android::hardware::setMinSchedulerPolicy(streamIn, SCHED_NORMAL, ANDROID_PRIORITY_AUDIO); } status_t convertStatus = HidlUtils::audioConfigFromHal(halConfig, true /*isInput*/, suggestedConfig); diff --git a/audio/core/all-versions/default/DevicesFactory.cpp b/audio/core/all-versions/default/DevicesFactory.cpp index f44daf0b0e..011f9ac4c2 100644 --- a/audio/core/all-versions/default/DevicesFactory.cpp +++ b/audio/core/all-versions/default/DevicesFactory.cpp @@ -23,6 +23,8 @@ #include <string.h> #include <android/log.h> +#include <hidl/HidlTransportSupport.h> +#include <system/thread_defs.h> namespace android { namespace hardware { @@ -103,6 +105,7 @@ Return<void> DevicesFactory::openDevice(const char* moduleName, Callback _hidl_c int halStatus = loadAudioInterface(moduleName, &halDevice); if (halStatus == OK) { result = new DeviceShim(halDevice); + android::hardware::setMinSchedulerPolicy(result, SCHED_NORMAL, ANDROID_PRIORITY_AUDIO); retval = Result::OK; } else if (halStatus == -EINVAL) { retval = Result::NOT_INITIALIZED; diff --git a/audio/effect/all-versions/default/Effect.cpp b/audio/effect/all-versions/default/Effect.cpp index 5dc42dc70d..87e1ab7a7d 100644 --- a/audio/effect/all-versions/default/Effect.cpp +++ b/audio/effect/all-versions/default/Effect.cpp @@ -25,8 +25,11 @@ #define ATRACE_TAG ATRACE_TAG_AUDIO #include <HidlUtils.h> #include <android/log.h> +#include <cutils/properties.h> #include <media/EffectsFactoryApi.h> #include <mediautils/ScopedStatistics.h> +#include <sys/syscall.h> +#include <system/audio_effects/effect_spatializer.h> #include <util/EffectUtils.h> #include <utils/Trace.h> @@ -47,6 +50,160 @@ using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementati namespace { +/** + * Some basic scheduling tools. + */ +namespace scheduler { + +int getCpu() { + return sched_getcpu(); +} + +uint64_t getAffinity(pid_t tid) { + cpu_set_t set; + CPU_ZERO_S(sizeof(set), &set); + + if (sched_getaffinity(tid, sizeof(set), &set)) { + ALOGW("%s: for tid:%d returning 0, failed %s", __func__, tid, strerror(errno)); + return 0; + } + const int count = CPU_COUNT_S(sizeof(set), &set); + uint64_t mask = 0; + for (int i = 0; i < CPU_SETSIZE; ++i) { + if (CPU_ISSET_S(i, sizeof(set), &set)) { + mask |= 1 << i; + } + } + ALOGV("%s: for tid:%d returning cpu count %d mask %llu", __func__, tid, count, + (unsigned long long)mask); + return mask; +} + +status_t setAffinity(pid_t tid, uint64_t mask) { + cpu_set_t set; + CPU_ZERO_S(sizeof(set), &set); + + for (uint64_t m = mask; m != 0;) { + uint64_t tz = __builtin_ctz(m); + CPU_SET_S(tz, sizeof(set), &set); + m &= ~(1 << tz); + } + if (sched_setaffinity(tid, sizeof(set), &set)) { + ALOGW("%s: for tid:%d setting cpu mask %llu failed %s", __func__, tid, + (unsigned long long)mask, strerror(errno)); + return -errno; + } + ALOGV("%s: for tid:%d setting cpu mask %llu", __func__, tid, (unsigned long long)mask); + return OK; +} + +__unused status_t setPriority(pid_t tid, int policy, int priority) { + struct sched_param param { + .sched_priority = priority, + }; + if (sched_setscheduler(tid, policy, ¶m) != 0) { + ALOGW("%s: Cannot set FIFO priority for tid %d to policy %d priority %d %s", __func__, tid, + policy, priority, strerror(errno)); + return -errno; + } + ALOGV("%s: Successfully set priority for tid %d to policy %d priority %d", __func__, tid, + policy, priority); + return NO_ERROR; +} + +status_t setUtilMin(pid_t tid, uint32_t utilMin) { + // Currently, there is no wrapper in bionic: b/183240349. + struct { + uint32_t size; + uint32_t sched_policy; + uint64_t sched_flags; + int32_t sched_nice; + uint32_t sched_priority; + uint64_t sched_runtime; + uint64_t sched_deadline; + uint64_t sched_period; + uint32_t sched_util_min; + uint32_t sched_util_max; + } attr{ + .size = sizeof(attr), + .sched_flags = SCHED_FLAG_KEEP_ALL | SCHED_FLAG_UTIL_CLAMP_MIN, + .sched_util_min = utilMin, + }; + + if (syscall(__NR_sched_setattr, tid, &attr, 0 /* flags */)) { + ALOGW("%s: Cannot set sched_util_min for pid %d to %u %s", __func__, tid, utilMin, + strerror(errno)); + return -errno; + } + ALOGV("%s: Successfully set sched_util_min for pid %d to %u", __func__, tid, utilMin); + return NO_ERROR; +} + +/* + Attempts to raise the priority and usage of tid for spatialization. + Returns OK if everything works. +*/ +status_t updateSpatializerPriority(pid_t tid) { + status_t status = OK; + + const int cpu = getCpu(); + ALOGV("%s: current CPU:%d", __func__, cpu); + + const auto currentAffinity = getAffinity(tid); + ALOGV("%s: current Affinity:%llx", __func__, (unsigned long long)currentAffinity); + + // Set the desired CPU core affinity. + // Typically this would be done to move the Spatializer effect off of the little cores. + // The mid cores and large cores typically have more FP/NEON units + // and will advantageously reduce power and prevent glitches due CPU limitations. + // + // Since this is SOC dependent, we do not set the core affinity here but + // prefer to set the util_clamp_min below. + // + constexpr uint64_t kDefaultAffinity = 0; + const int32_t desiredAffinity = + property_get_int32("audio.spatializer.effect.affinity", kDefaultAffinity); + if (desiredAffinity != 0 && (desiredAffinity & ~currentAffinity) == 0) { + const status_t localStatus = setAffinity(tid, desiredAffinity); + status = status ? status : localStatus; + } + + // Set the util_clamp_min. + // This is beneficial to reduce glitches when starting up, or due to scheduler + // thread statistics reset (e.g. core migration), which cause the CPU frequency to drop + // to minimum. + // + // Experimentation has found that moving to a mid core over a little core reduces + // power if the mid core (e.g. A76/78) has more (e.g. 2x) FP/NEON units + // than the little core (e.g. A55). + // A possible value is 300. + // + constexpr uint32_t kUtilMin = 0; + const int32_t utilMin = property_get_int32("audio.spatializer.effect.util_clamp_min", kUtilMin); + if (utilMin > 0 && utilMin <= 1024) { + const status_t localStatus = setUtilMin(tid, utilMin); + status = status ? status : localStatus; + } + +#if 0 + // Provided for local vendor testing but not enabled as audioserver does this for us. + // + // Set priority if specified. + constexpr int32_t kRTPriorityMin = 1; + constexpr int32_t kRTPriorityMax = 3; + const int32_t priorityBoost = + property_get_int32("audio.spatializer.priority", kRTPriorityMin); + if (priorityBoost >= kRTPriorityMin && priorityBoost <= kRTPriorityMax) { + const status_t localStatus = scheduler::setPriority(threadId, SCHED_FIFO, priorityBoost); + status = status ? status : localStatus; + } +#endif + + return status; +} + +} // namespace scheduler + #define SCOPED_STATS() \ ::android::mediautils::ScopedStatistics scopedStatistics { \ std::string("EffectHal::").append(__func__), mEffectHal->mStatistics \ @@ -83,6 +240,16 @@ class ProcessThread : public Thread { }; bool ProcessThread::threadLoop() { + // For a spatializer effect, we perform scheduler adjustments to reduce glitches and power. + { + effect_descriptor_t halDescriptor{}; + if ((*mEffect)->get_descriptor(mEffect, &halDescriptor) == NO_ERROR && + memcmp(&halDescriptor.type, FX_IID_SPATIALIZER, sizeof(effect_uuid_t)) == 0) { + const status_t status = scheduler::updateSpatializerPriority(gettid()); + ALOGW_IF(status != OK, "Failed to update Spatializer priority"); + } + } + // This implementation doesn't return control back to the Thread until it decides to stop, // as the Thread uses mutexes, and this can lead to priority inversion. while (!std::atomic_load_explicit(mStop, std::memory_order_acquire)) { diff --git a/audio/effect/all-versions/default/EffectsFactory.cpp b/audio/effect/all-versions/default/EffectsFactory.cpp index e93ad893a8..9bf309c224 100644 --- a/audio/effect/all-versions/default/EffectsFactory.cpp +++ b/audio/effect/all-versions/default/EffectsFactory.cpp @@ -32,6 +32,7 @@ #include <UuidUtils.h> #include <android/log.h> +#include <hidl/HidlTransportSupport.h> #include <media/EffectsFactoryApi.h> #include <system/audio_effects/effect_aec.h> #include <system/audio_effects/effect_agc.h> @@ -44,6 +45,7 @@ #include <system/audio_effects/effect_presetreverb.h> #include <system/audio_effects/effect_virtualizer.h> #include <system/audio_effects/effect_visualizer.h> +#include <system/thread_defs.h> #include <util/EffectUtils.h> namespace android { @@ -189,6 +191,7 @@ Return<void> EffectsFactory::createEffectImpl(const Uuid& uuid, int32_t session, status = (*handle)->get_descriptor(handle, &halDescriptor); if (status == OK) { effect = dispatchEffectInstanceCreation(halDescriptor, handle); + android::hardware::setMinSchedulerPolicy(effect, SCHED_NORMAL, ANDROID_PRIORITY_AUDIO); effectId = EffectMap::getInstance().add(handle); } else { ALOGE("Error querying effect descriptor for %s: %s", diff --git a/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h b/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h index 9a93e1a11a..622846a301 100644 --- a/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h +++ b/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h @@ -190,6 +190,40 @@ const std::vector<ConfigDeclaration> kVehicleProperties = { }, .initialValue = {.int32Values = {toInt(VehicleUnit::KILOWATT_HOUR)}}}, + {.config = {.prop = toInt(VehicleProperty::SEAT_MEMORY_SELECT), + .access = VehiclePropertyAccess::WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT, + .minInt32Value = 0, + .maxInt32Value = 3}, + VehicleAreaConfig{.areaId = SEAT_1_RIGHT, + .minInt32Value = 0, + .maxInt32Value = 3}, + VehicleAreaConfig{.areaId = SEAT_2_LEFT, + .minInt32Value = 0, + .maxInt32Value = 3}, + VehicleAreaConfig{.areaId = SEAT_2_RIGHT, + .minInt32Value = 0, + .maxInt32Value = 3}}}, + .initialValue = {.int32Values = {1}}}, + + {.config = {.prop = toInt(VehicleProperty::SEAT_MEMORY_SET), + .access = VehiclePropertyAccess::WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT, + .minInt32Value = 0, + .maxInt32Value = 3}, + VehicleAreaConfig{.areaId = SEAT_1_RIGHT, + .minInt32Value = 0, + .maxInt32Value = 3}, + VehicleAreaConfig{.areaId = SEAT_2_LEFT, + .minInt32Value = 0, + .maxInt32Value = 3}, + VehicleAreaConfig{.areaId = SEAT_2_RIGHT, + .minInt32Value = 0, + .maxInt32Value = 3}}}, + .initialValue = {.int32Values = {1}}}, + {.config = {.prop = toInt(VehicleProperty::SEAT_BELT_BUCKLED), .access = VehiclePropertyAccess::READ_WRITE, .changeMode = VehiclePropertyChangeMode::ON_CHANGE, diff --git a/automotive/vehicle/aidl/impl/utils/common/include/RecurrentTimer.h b/automotive/vehicle/aidl/impl/utils/common/include/RecurrentTimer.h index 5f0f7161c2..cd2b72713c 100644 --- a/automotive/vehicle/aidl/impl/utils/common/include/RecurrentTimer.h +++ b/automotive/vehicle/aidl/impl/utils/common/include/RecurrentTimer.h @@ -83,8 +83,9 @@ class RecurrentTimer final { // each time we might introduce outdated elements to the top. We must make sure the heap is // always valid from the top. void removeInvalidCallbackLocked() REQUIRES(mLock); - // Pops the next closest callback (must be valid) from the heap. - std::unique_ptr<CallbackInfo> popNextCallbackLocked() REQUIRES(mLock); + // Gets the next calblack to run (must be valid) from the heap, update its nextTime and put + // it back to the heap. + std::shared_ptr<Callback> getNextCallbackLocked(int64_t now) REQUIRES(mLock); }; } // namespace vehicle diff --git a/automotive/vehicle/aidl/impl/utils/common/src/RecurrentTimer.cpp b/automotive/vehicle/aidl/impl/utils/common/src/RecurrentTimer.cpp index 2eca6b7a17..908564c2ff 100644 --- a/automotive/vehicle/aidl/impl/utils/common/src/RecurrentTimer.cpp +++ b/automotive/vehicle/aidl/impl/utils/common/src/RecurrentTimer.cpp @@ -101,68 +101,71 @@ void RecurrentTimer::removeInvalidCallbackLocked() { } } -std::unique_ptr<RecurrentTimer::CallbackInfo> RecurrentTimer::popNextCallbackLocked() { +std::shared_ptr<RecurrentTimer::Callback> RecurrentTimer::getNextCallbackLocked(int64_t now) { std::pop_heap(mCallbackQueue.begin(), mCallbackQueue.end(), CallbackInfo::cmp); - std::unique_ptr<CallbackInfo> info = std::move(mCallbackQueue[mCallbackQueue.size() - 1]); - mCallbackQueue.pop_back(); + auto& callbackInfo = mCallbackQueue[mCallbackQueue.size() - 1]; + auto nextCallback = callbackInfo->callback; + // intervalCount is the number of interval we have to advance until we pass now. + size_t intervalCount = (now - callbackInfo->nextTime) / callbackInfo->interval + 1; + callbackInfo->nextTime += intervalCount * callbackInfo->interval; + std::push_heap(mCallbackQueue.begin(), mCallbackQueue.end(), CallbackInfo::cmp); + // Make sure the first element is always valid. removeInvalidCallbackLocked(); - return info; + + return nextCallback; } void RecurrentTimer::loop() { - std::unique_lock<std::mutex> uniqueLock(mLock); - + std::vector<std::shared_ptr<Callback>> callbacksToRun; while (true) { - // Wait until the timer exits or we have at least one recurrent callback. - mCond.wait(uniqueLock, [this] { - ScopedLockAssertion lockAssertion(mLock); - return mStopRequested || mCallbackQueue.size() != 0; - }); - - int64_t interval; { + std::unique_lock<std::mutex> uniqueLock(mLock); ScopedLockAssertion lockAssertion(mLock); + // Wait until the timer exits or we have at least one recurrent callback. + mCond.wait(uniqueLock, [this] { + ScopedLockAssertion lockAssertion(mLock); + return mStopRequested || mCallbackQueue.size() != 0; + }); + + int64_t interval; if (mStopRequested) { return; } // The first element is the nearest next event. int64_t nextTime = mCallbackQueue[0]->nextTime; int64_t now = uptimeNanos(); + if (nextTime > now) { interval = nextTime - now; } else { interval = 0; } - } - // Wait for the next event or the timer exits. - if (mCond.wait_for(uniqueLock, std::chrono::nanoseconds(interval), [this] { - ScopedLockAssertion lockAssertion(mLock); - return mStopRequested; - })) { - return; - } + // Wait for the next event or the timer exits. + if (mCond.wait_for(uniqueLock, std::chrono::nanoseconds(interval), [this] { + ScopedLockAssertion lockAssertion(mLock); + return mStopRequested; + })) { + return; + } - { - ScopedLockAssertion lockAssertion(mLock); - int64_t now = uptimeNanos(); + now = uptimeNanos(); + callbacksToRun.clear(); while (mCallbackQueue.size() > 0) { int64_t nextTime = mCallbackQueue[0]->nextTime; if (nextTime > now) { break; } - std::unique_ptr<CallbackInfo> info = popNextCallbackLocked(); - info->nextTime += info->interval; - - auto callback = info->callback; - mCallbackQueue.push_back(std::move(info)); - std::push_heap(mCallbackQueue.begin(), mCallbackQueue.end(), CallbackInfo::cmp); - - (*callback)(); + callbacksToRun.push_back(getNextCallbackLocked(now)); } } + + // Do not execute the callback while holding the lock. + for (size_t i = 0; i < callbacksToRun.size(); i++) { + (*callbacksToRun[i])(); + } } } diff --git a/automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp b/automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp index a033a248cd..141efc135b 100644 --- a/automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp +++ b/automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp @@ -186,6 +186,33 @@ TEST_F(RecurrentTimerTest, testRegisterSameCallbackMultipleTimes) { ASSERT_EQ(countTimerCallbackQueue(&timer), static_cast<size_t>(0)); } +TEST_F(RecurrentTimerTest, testRegisterCallbackMultipleTimesNoDeadLock) { + // We want to avoid the following situation: + // Caller holds a lock while calling registerTimerCallback, registerTimerCallback will try + // to obtain an internal lock inside timer. + // Meanwhile an recurrent action happens with timer holding an internal lock. The action + // tries to obtain the lock currently hold by the caller. + // The solution is that while calling recurrent actions, timer must not hold the internal lock. + + std::unique_ptr<RecurrentTimer> timer = std::make_unique<RecurrentTimer>(); + std::mutex lock; + for (size_t i = 0; i < 1000; i++) { + std::scoped_lock<std::mutex> lockGuard(lock); + auto action = std::make_shared<RecurrentTimer::Callback>([&lock] { + // While calling this function, the timer must not hold lock in order not to dead + // lock. + std::scoped_lock<std::mutex> lockGuard(lock); + }); + // 10ms + int64_t interval = 10'000'000; + timer->registerTimerCallback(interval, action); + // Sleep for a little while to let the recurrent actions begin. + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + // Make sure we stop the timer before we destroy lock. + timer.reset(); +} + } // namespace vehicle } // namespace automotive } // namespace hardware diff --git a/bluetooth/audio/utils/Android.bp b/bluetooth/audio/utils/Android.bp index 674dd116cf..70797a7aaf 100644 --- a/bluetooth/audio/utils/Android.bp +++ b/bluetooth/audio/utils/Android.bp @@ -63,6 +63,31 @@ cc_library_shared { generated_headers: ["le_audio_codec_capabilities"], } +cc_test { + name: "BluetoothLeAudioCodecsProviderTest", + srcs: [ + "aidl_session/BluetoothLeAudioCodecsProvider.cpp", + "aidl_session/BluetoothLeAudioCodecsProviderTest.cpp", + ], + header_libs: [ + "libxsdc-utils", + ], + shared_libs: [ + "libbase", + "libbinder_ndk", + "android.hardware.bluetooth.audio-V2-ndk", + "libxml2", + ], + test_suites: [ + "general-tests", + ], + test_options: { + unit_test: false, + }, + generated_sources: ["le_audio_codec_capabilities"], + generated_headers: ["le_audio_codec_capabilities"], +} + xsd_config { name: "le_audio_codec_capabilities", srcs: ["le_audio_codec_capabilities/le_audio_codec_capabilities.xsd"], diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp index 855dd28718..faebbbf32b 100644 --- a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp +++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp @@ -398,8 +398,11 @@ BluetoothAudioCodecs::GetLeAudioOffloadCodecCapabilities( } if (kDefaultOffloadLeAudioCapabilities.empty()) { + auto le_audio_offload_setting = + BluetoothLeAudioCodecsProvider::ParseFromLeAudioOffloadSettingFile(); kDefaultOffloadLeAudioCapabilities = - BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities(); + BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities( + le_audio_offload_setting); } return kDefaultOffloadLeAudioCapabilities; diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp index bf492706c8..1dec900aed 100644 --- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp +++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp @@ -34,20 +34,40 @@ static const AudioLocation kMonoAudio = AudioLocation::UNKNOWN; static std::vector<LeAudioCodecCapabilitiesSetting> leAudioCodecCapabilities; +static bool isInvalidFileContent = false; + +std::optional<setting::LeAudioOffloadSetting> +BluetoothLeAudioCodecsProvider::ParseFromLeAudioOffloadSettingFile() { + if (!leAudioCodecCapabilities.empty() || isInvalidFileContent) { + return std::nullopt; + } + auto le_audio_offload_setting = + setting::readLeAudioOffloadSetting(kLeAudioCodecCapabilitiesFile); + if (!le_audio_offload_setting.has_value()) { + LOG(ERROR) << __func__ << ": Failed to read " + << kLeAudioCodecCapabilitiesFile; + } + return le_audio_offload_setting; +} + std::vector<LeAudioCodecCapabilitiesSetting> -BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities() { +BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities( + const std::optional<setting::LeAudioOffloadSetting>& + le_audio_offload_setting) { if (!leAudioCodecCapabilities.empty()) { return leAudioCodecCapabilities; } - const auto le_audio_offload_setting = - setting::readLeAudioOffloadSetting(kLeAudioCodecCapabilitiesFile); if (!le_audio_offload_setting.has_value()) { - LOG(ERROR) << __func__ << ": Failed to read " - << kLeAudioCodecCapabilitiesFile; + LOG(ERROR) + << __func__ + << ": input le_audio_offload_setting content need to be non empty"; return {}; } + ClearLeAudioCodecCapabilities(); + isInvalidFileContent = true; + std::vector<setting::Scenario> supported_scenarios = GetScenarios(le_audio_offload_setting); if (supported_scenarios.empty()) { @@ -79,9 +99,18 @@ BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities() { leAudioCodecCapabilities = ComposeLeAudioCodecCapabilities(supported_scenarios); + isInvalidFileContent = leAudioCodecCapabilities.empty(); + return leAudioCodecCapabilities; } +void BluetoothLeAudioCodecsProvider::ClearLeAudioCodecCapabilities() { + leAudioCodecCapabilities.clear(); + configuration_map_.clear(); + codec_configuration_map_.clear(); + strategy_configuration_map_.clear(); +} + std::vector<setting::Scenario> BluetoothLeAudioCodecsProvider::GetScenarios( const std::optional<setting::LeAudioOffloadSetting>& le_audio_offload_setting) { diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h index 402235f0cd..e8799843ef 100644 --- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h +++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h @@ -31,8 +31,13 @@ namespace audio { class BluetoothLeAudioCodecsProvider { public: + static std::optional<setting::LeAudioOffloadSetting> + ParseFromLeAudioOffloadSettingFile(); static std::vector<LeAudioCodecCapabilitiesSetting> - GetLeAudioCodecCapabilities(); + GetLeAudioCodecCapabilities( + const std::optional<setting::LeAudioOffloadSetting>& + le_audio_offload_setting); + static void ClearLeAudioCodecCapabilities(); private: static inline std::unordered_map<std::string, setting::Configuration> diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProviderTest.cpp b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProviderTest.cpp new file mode 100644 index 0000000000..5393cd70e8 --- /dev/null +++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProviderTest.cpp @@ -0,0 +1,373 @@ +/* + * Copyright (C) 2022 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 <gtest/gtest.h> + +#include <optional> +#include <tuple> + +#include "BluetoothLeAudioCodecsProvider.h" + +using aidl::android::hardware::bluetooth::audio::BluetoothLeAudioCodecsProvider; +using aidl::android::hardware::bluetooth::audio:: + LeAudioCodecCapabilitiesSetting; +using aidl::android::hardware::bluetooth::audio::setting::AudioLocation; +using aidl::android::hardware::bluetooth::audio::setting::CodecConfiguration; +using aidl::android::hardware::bluetooth::audio::setting:: + CodecConfigurationList; +using aidl::android::hardware::bluetooth::audio::setting::CodecType; +using aidl::android::hardware::bluetooth::audio::setting::Configuration; +using aidl::android::hardware::bluetooth::audio::setting::ConfigurationList; +using aidl::android::hardware::bluetooth::audio::setting::LeAudioOffloadSetting; +using aidl::android::hardware::bluetooth::audio::setting::Scenario; +using aidl::android::hardware::bluetooth::audio::setting::ScenarioList; +using aidl::android::hardware::bluetooth::audio::setting::StrategyConfiguration; +using aidl::android::hardware::bluetooth::audio::setting:: + StrategyConfigurationList; + +typedef std::tuple<std::vector<ScenarioList>, std::vector<ConfigurationList>, + std::vector<CodecConfigurationList>, + std::vector<StrategyConfigurationList>> + OffloadSetting; + +// Define valid components for each list +// Scenario +static const Scenario kValidScenario(std::make_optional("OneChanStereo_16_1"), + std::make_optional("OneChanStereo_16_1")); +// Configuration +static const Configuration kValidConfigOneChanStereo_16_1( + std::make_optional("OneChanStereo_16_1"), std::make_optional("LC3_16k_1"), + std::make_optional("STEREO_ONE_CIS_PER_DEVICE")); +// CodecConfiguration +static const CodecConfiguration kValidCodecLC3_16k_1( + std::make_optional("LC3_16k_1"), std::make_optional(CodecType::LC3), + std::nullopt, std::make_optional(16000), std::make_optional(7500), + std::make_optional(30), std::nullopt); +// StrategyConfiguration +static const StrategyConfiguration kValidStrategyStereoOneCis( + std::make_optional("STEREO_ONE_CIS_PER_DEVICE"), + std::make_optional(AudioLocation::STEREO), std::make_optional(2), + std::make_optional(1)); +static const StrategyConfiguration kValidStrategyStereoTwoCis( + std::make_optional("STEREO_TWO_CISES_PER_DEVICE"), + std::make_optional(AudioLocation::STEREO), std::make_optional(1), + std::make_optional(2)); +static const StrategyConfiguration kValidStrategyMonoOneCis( + std::make_optional("MONO_ONE_CIS_PER_DEVICE"), + std::make_optional(AudioLocation::MONO), std::make_optional(1), + std::make_optional(1)); + +// Define valid test list built from above valid components +// Scenario, Configuration, CodecConfiguration, StrategyConfiguration +static const std::vector<ScenarioList> kValidScenarioList = { + ScenarioList(std::vector<Scenario>{kValidScenario})}; +static const std::vector<ConfigurationList> kValidConfigurationList = { + ConfigurationList( + std::vector<Configuration>{kValidConfigOneChanStereo_16_1})}; +static const std::vector<CodecConfigurationList> kValidCodecConfigurationList = + {CodecConfigurationList( + std::vector<CodecConfiguration>{kValidCodecLC3_16k_1})}; +static const std::vector<StrategyConfigurationList> + kValidStrategyConfigurationList = { + StrategyConfigurationList(std::vector<StrategyConfiguration>{ + kValidStrategyStereoOneCis, kValidStrategyStereoTwoCis, + kValidStrategyMonoOneCis})}; + +class BluetoothLeAudioCodecsProviderTest + : public ::testing::TestWithParam<OffloadSetting> { + public: + static std::vector<OffloadSetting> CreateTestCases( + const std::vector<ScenarioList>& scenario_lists, + const std::vector<ConfigurationList>& configuration_lists, + const std::vector<CodecConfigurationList>& codec_configuration_lists, + const std::vector<StrategyConfigurationList>& + strategy_configuration_lists) { + // make each vector in output test_cases has only one element + // to match the input of test params + // normally only one vector in input has multiple elements + // we just split elements in this vector to several vector + std::vector<OffloadSetting> test_cases; + for (const auto& scenario_list : scenario_lists) { + for (const auto& configuration_list : configuration_lists) { + for (const auto& codec_configuration_list : codec_configuration_lists) { + for (const auto& strategy_configuration_list : + strategy_configuration_lists) { + test_cases.push_back(CreateTestCase( + scenario_list, configuration_list, codec_configuration_list, + strategy_configuration_list)); + } + } + } + } + return test_cases; + } + + protected: + void Initialize() { + BluetoothLeAudioCodecsProvider::ClearLeAudioCodecCapabilities(); + } + + std::vector<LeAudioCodecCapabilitiesSetting> RunTestCase() { + auto& [scenario_lists, configuration_lists, codec_configuration_lists, + strategy_configuration_lists] = GetParam(); + LeAudioOffloadSetting le_audio_offload_setting( + scenario_lists, configuration_lists, codec_configuration_lists, + strategy_configuration_lists); + auto le_audio_codec_capabilities = + BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities( + std::make_optional(le_audio_offload_setting)); + return le_audio_codec_capabilities; + } + + private: + static inline OffloadSetting CreateTestCase( + const ScenarioList& scenario_list, + const ConfigurationList& configuration_list, + const CodecConfigurationList& codec_configuration_list, + const StrategyConfigurationList& strategy_configuration_list) { + return std::make_tuple( + std::vector<ScenarioList>{scenario_list}, + std::vector<ConfigurationList>{configuration_list}, + std::vector<CodecConfigurationList>{codec_configuration_list}, + std::vector<StrategyConfigurationList>{strategy_configuration_list}); + } +}; + +class GetScenariosTest : public BluetoothLeAudioCodecsProviderTest { + public: + static std::vector<ScenarioList> CreateInvalidScenarios() { + std::vector<ScenarioList> invalid_scenario_test_cases; + invalid_scenario_test_cases.push_back(ScenarioList(std::vector<Scenario>{ + Scenario(std::nullopt, std::make_optional("OneChanStereo_16_1"))})); + + invalid_scenario_test_cases.push_back(ScenarioList(std::vector<Scenario>{ + Scenario(std::make_optional("OneChanStereo_16_1"), std::nullopt)})); + + invalid_scenario_test_cases.push_back(ScenarioList( + std::vector<Scenario>{Scenario(std::nullopt, std::nullopt)})); + + invalid_scenario_test_cases.push_back( + ScenarioList(std::vector<Scenario>{})); + + return invalid_scenario_test_cases; + } +}; + +TEST_P(GetScenariosTest, InvalidScenarios) { + Initialize(); + auto le_audio_codec_capabilities = RunTestCase(); + ASSERT_TRUE(le_audio_codec_capabilities.empty()); +} + +class UpdateConfigurationsToMapTest + : public BluetoothLeAudioCodecsProviderTest { + public: + static std::vector<ConfigurationList> CreateInvalidConfigurations() { + std::vector<ConfigurationList> invalid_configuration_test_cases; + invalid_configuration_test_cases.push_back( + ConfigurationList(std::vector<Configuration>{ + Configuration(std::nullopt, std::make_optional("LC3_16k_1"), + std::make_optional("STEREO_ONE_CIS_PER_DEVICE"))})); + + invalid_configuration_test_cases.push_back( + ConfigurationList(std::vector<Configuration>{Configuration( + std::make_optional("OneChanStereo_16_1"), std::nullopt, + std::make_optional("STEREO_ONE_CIS_PER_DEVICE"))})); + + invalid_configuration_test_cases.push_back( + ConfigurationList(std::vector<Configuration>{ + Configuration(std::make_optional("OneChanStereo_16_1"), + std::make_optional("LC3_16k_1"), std::nullopt)})); + + invalid_configuration_test_cases.push_back( + ConfigurationList(std::vector<Configuration>{})); + + return invalid_configuration_test_cases; + } +}; + +TEST_P(UpdateConfigurationsToMapTest, InvalidConfigurations) { + Initialize(); + auto le_audio_codec_capabilities = RunTestCase(); + ASSERT_TRUE(le_audio_codec_capabilities.empty()); +} + +class UpdateCodecConfigurationsToMapTest + : public BluetoothLeAudioCodecsProviderTest { + public: + static std::vector<CodecConfigurationList> + CreateInvalidCodecConfigurations() { + std::vector<CodecConfigurationList> invalid_codec_configuration_test_cases; + invalid_codec_configuration_test_cases.push_back(CodecConfigurationList( + std::vector<CodecConfiguration>{CodecConfiguration( + std::nullopt, std::make_optional(CodecType::LC3), std::nullopt, + std::make_optional(16000), std::make_optional(7500), + std::make_optional(30), std::nullopt)})); + + invalid_codec_configuration_test_cases.push_back(CodecConfigurationList( + std::vector<CodecConfiguration>{CodecConfiguration( + std::make_optional("LC3_16k_1"), std::nullopt, std::nullopt, + std::make_optional(16000), std::make_optional(7500), + std::make_optional(30), std::nullopt)})); + + invalid_codec_configuration_test_cases.push_back(CodecConfigurationList( + std::vector<CodecConfiguration>{CodecConfiguration( + std::make_optional("LC3_16k_1"), std::make_optional(CodecType::LC3), + std::nullopt, std::nullopt, std::make_optional(7500), + std::make_optional(30), std::nullopt)})); + + invalid_codec_configuration_test_cases.push_back(CodecConfigurationList( + std::vector<CodecConfiguration>{CodecConfiguration( + std::make_optional("LC3_16k_1"), std::make_optional(CodecType::LC3), + std::nullopt, std::make_optional(16000), std::nullopt, + std::make_optional(30), std::nullopt)})); + + invalid_codec_configuration_test_cases.push_back(CodecConfigurationList( + std::vector<CodecConfiguration>{CodecConfiguration( + std::make_optional("LC3_16k_1"), std::make_optional(CodecType::LC3), + std::nullopt, std::make_optional(16000), std::make_optional(7500), + std::nullopt, std::nullopt)})); + + invalid_codec_configuration_test_cases.push_back( + CodecConfigurationList(std::vector<CodecConfiguration>{})); + + return invalid_codec_configuration_test_cases; + } +}; + +TEST_P(UpdateCodecConfigurationsToMapTest, InvalidCodecConfigurations) { + Initialize(); + auto le_audio_codec_capabilities = RunTestCase(); + ASSERT_TRUE(le_audio_codec_capabilities.empty()); +} + +class UpdateStrategyConfigurationsToMapTest + : public BluetoothLeAudioCodecsProviderTest { + public: + static std::vector<StrategyConfigurationList> + CreateInvalidStrategyConfigurations() { + std::vector<StrategyConfigurationList> + invalid_strategy_configuration_test_cases; + invalid_strategy_configuration_test_cases.push_back( + StrategyConfigurationList( + std::vector<StrategyConfiguration>{StrategyConfiguration( + std::make_optional("STEREO_ONE_CIS_PER_DEVICE"), + std::make_optional(AudioLocation::STEREO), + std::make_optional(2), std::make_optional(2))})); + + invalid_strategy_configuration_test_cases.push_back( + StrategyConfigurationList( + std::vector<StrategyConfiguration>{StrategyConfiguration( + std::make_optional("MONO_ONE_CIS_PER_DEVICE"), + std::make_optional(AudioLocation::STEREO), + std::make_optional(2), std::make_optional(2))})); + + invalid_strategy_configuration_test_cases.push_back( + StrategyConfigurationList( + std::vector<StrategyConfiguration>{StrategyConfiguration( + std::nullopt, std::make_optional(AudioLocation::STEREO), + std::make_optional(2), std::make_optional(1))})); + + invalid_strategy_configuration_test_cases.push_back( + StrategyConfigurationList( + std::vector<StrategyConfiguration>{StrategyConfiguration( + std::make_optional("STEREO_ONE_CIS_PER_DEVICE"), std::nullopt, + std::make_optional(2), std::make_optional(1))})); + + invalid_strategy_configuration_test_cases.push_back( + StrategyConfigurationList( + std::vector<StrategyConfiguration>{StrategyConfiguration( + std::make_optional("STEREO_ONE_CIS_PER_DEVICE"), + std::make_optional(AudioLocation::STEREO), std::nullopt, + std::make_optional(1))})); + + invalid_strategy_configuration_test_cases.push_back( + StrategyConfigurationList( + std::vector<StrategyConfiguration>{StrategyConfiguration( + std::make_optional("STEREO_ONE_CIS_PER_DEVICE"), + std::make_optional(AudioLocation::STEREO), + std::make_optional(2), std::nullopt)})); + + invalid_strategy_configuration_test_cases.push_back( + StrategyConfigurationList(std::vector<StrategyConfiguration>{})); + + return invalid_strategy_configuration_test_cases; + } +}; + +TEST_P(UpdateStrategyConfigurationsToMapTest, InvalidStrategyConfigurations) { + Initialize(); + auto le_audio_codec_capabilities = RunTestCase(); + ASSERT_TRUE(le_audio_codec_capabilities.empty()); +} + +class ComposeLeAudioCodecCapabilitiesTest + : public BluetoothLeAudioCodecsProviderTest { + public: +}; + +TEST_P(ComposeLeAudioCodecCapabilitiesTest, CodecCapabilitiesNotEmpty) { + Initialize(); + auto le_audio_codec_capabilities = RunTestCase(); + ASSERT_TRUE(!le_audio_codec_capabilities.empty()); +} + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GetScenariosTest); +INSTANTIATE_TEST_SUITE_P( + BluetoothLeAudioCodecsProviderTest, GetScenariosTest, + ::testing::ValuesIn(BluetoothLeAudioCodecsProviderTest::CreateTestCases( + GetScenariosTest::CreateInvalidScenarios(), kValidConfigurationList, + kValidCodecConfigurationList, kValidStrategyConfigurationList))); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UpdateConfigurationsToMapTest); +INSTANTIATE_TEST_SUITE_P( + BluetoothLeAudioCodecsProviderTest, UpdateConfigurationsToMapTest, + ::testing::ValuesIn(BluetoothLeAudioCodecsProviderTest::CreateTestCases( + kValidScenarioList, + UpdateConfigurationsToMapTest::CreateInvalidConfigurations(), + kValidCodecConfigurationList, kValidStrategyConfigurationList))); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST( + UpdateCodecConfigurationsToMapTest); +INSTANTIATE_TEST_SUITE_P( + BluetoothLeAudioCodecsProviderTest, UpdateCodecConfigurationsToMapTest, + ::testing::ValuesIn(BluetoothLeAudioCodecsProviderTest::CreateTestCases( + kValidScenarioList, kValidConfigurationList, + UpdateCodecConfigurationsToMapTest::CreateInvalidCodecConfigurations(), + kValidStrategyConfigurationList))); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST( + UpdateStrategyConfigurationsToMapTest); +INSTANTIATE_TEST_SUITE_P( + BluetoothLeAudioCodecsProviderTest, UpdateStrategyConfigurationsToMapTest, + ::testing::ValuesIn(BluetoothLeAudioCodecsProviderTest::CreateTestCases( + kValidScenarioList, kValidConfigurationList, + kValidCodecConfigurationList, + UpdateStrategyConfigurationsToMapTest:: + CreateInvalidStrategyConfigurations()))); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST( + ComposeLeAudioCodecCapabilitiesTest); +INSTANTIATE_TEST_SUITE_P( + BluetoothLeAudioCodecsProviderTest, ComposeLeAudioCodecCapabilitiesTest, + ::testing::ValuesIn(BluetoothLeAudioCodecsProviderTest::CreateTestCases( + kValidScenarioList, kValidConfigurationList, + kValidCodecConfigurationList, kValidStrategyConfigurationList))); + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/gnss/aidl/default/Gnss.cpp b/gnss/aidl/default/Gnss.cpp index cf2c90d359..2d6490c832 100644 --- a/gnss/aidl/default/Gnss.cpp +++ b/gnss/aidl/default/Gnss.cpp @@ -68,7 +68,7 @@ ScopedAStatus Gnss::setCallback(const std::shared_ptr<IGnssCallback>& callback) IGnssCallback::GnssSystemInfo systemInfo = { .yearOfHw = 2022, - .name = "Google Mock GNSS Implementation AIDL v2", + .name = "Google, Cuttlefish, AIDL v2", }; status = sGnssCallback->gnssSetSystemInfoCb(systemInfo); if (!status.isOk()) { diff --git a/wifi/1.6/default/hidl_struct_util.cpp b/wifi/1.6/default/hidl_struct_util.cpp index ff3105dd77..9c4d881aad 100644 --- a/wifi/1.6/default/hidl_struct_util.cpp +++ b/wifi/1.6/default/hidl_struct_util.cpp @@ -156,10 +156,8 @@ bool convertLegacyFeaturesToHidlChipCapabilities(uint64_t legacy_feature_set, } } - // There are no flags for these 3 in the legacy feature set. Adding them to + // There is no flag for this in the legacy feature set. Adding this to // the set because all the current devices support it. - *hidl_caps |= HidlChipCaps::DEBUG_RING_BUFFER_VENDOR_DATA; - *hidl_caps |= HidlChipCaps::DEBUG_HOST_WAKE_REASON_STATS; *hidl_caps |= HidlChipCaps::DEBUG_ERROR_ALERTS; return true; } |