From 458a13bc052d3497034d8e009cfdc45d7dd4f940 Mon Sep 17 00:00:00 2001 From: seanhong Date: Mon, 29 Aug 2022 18:43:23 +0000 Subject: DO NOT MERGE Add missing seat memory properties to DefaultConfig.h for CTS tests Test: atest CarPropertyManagerTest Bug: 239613431 Change-Id: I000a3f918f8f2c3ceb90710f88a18f91a56d2479 --- .../impl/default_config/include/DefaultConfig.h | 34 ++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h b/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h index 384b87d4fc..7006a75d4f 100644 --- a/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h +++ b/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h @@ -183,6 +183,40 @@ const std::vector 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, -- cgit v1.2.3 From 7d5eb5c8371cd881d8d2fd7b57a6d2803206fd59 Mon Sep 17 00:00:00 2001 From: Andy Hung Date: Tue, 18 Oct 2022 18:03:54 -0700 Subject: EffectHal: Support retrieving worker thread tid Use 'gtid' as the command, returns the worker thread tid. Test: see bug Bug: 253276925 Change-Id: Ia4fa129c62cf6df97821c34876b517944bc5322f --- audio/effect/all-versions/default/Effect.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/audio/effect/all-versions/default/Effect.cpp b/audio/effect/all-versions/default/Effect.cpp index b57dc63368..5dc42dc70d 100644 --- a/audio/effect/all-versions/default/Effect.cpp +++ b/audio/effect/all-versions/default/Effect.cpp @@ -700,8 +700,21 @@ Return Effect::command(uint32_t commandId, const hidl_vec& data, void* dataPtr = halDataSize > 0 ? &halData[0] : NULL; void* resultPtr = halResultSize > 0 ? &halResult[0] : NULL; - status_t status = - (*mHandle)->command(mHandle, commandId, halDataSize, dataPtr, &halResultSize, resultPtr); + status_t status = BAD_VALUE; + switch (commandId) { + case 'gtid': // retrieve the tid, used for spatializer priority boost + if (halDataSize == 0 && resultMaxSize == sizeof(int32_t)) { + auto ptid = (int32_t*)resultPtr; + ptid[0] = mProcessThread ? mProcessThread->getTid() : -1; + status = OK; + break; // we have handled 'gtid' here. + } + [[fallthrough]]; // allow 'gtid' overload (checked halDataSize and resultMaxSize). + default: + status = (*mHandle)->command(mHandle, commandId, halDataSize, dataPtr, &halResultSize, + resultPtr); + break; + } hidl_vec result; if (status == OK && resultPtr != NULL) { result.setToExternal(&halResult[0], halResultSize); -- cgit v1.2.3 From 4d5f3b7e0b4229240a04a0216bf4861b2ed14bd6 Mon Sep 17 00:00:00 2001 From: shihchienc Date: Fri, 14 Oct 2022 13:45:37 +0000 Subject: Add BluetoothLeAudioCodecsProvider Unit Test Add unit test for BluetoothLeAudioCodecsProvider and simplify the public interface of BluetoothLeAudioCodecsProvider class Bug: 253569201 Test: atest VtsHalBluetoothAudioTargetTest Test: atest BluetoothLeAudioCodecsProviderTest Test: manual test Change-Id: I064eb4058b129a571cf9dbb91b85bafe7236b735 Merged-In: I064eb4058b129a571cf9dbb91b85bafe7236b735 (cherry picked from commit d7f565a943c5c6bf08a16c22ea15c2c6b628a00e) --- bluetooth/audio/utils/Android.bp | 25 ++ .../utils/aidl_session/BluetoothAudioCodecs.cpp | 5 +- .../BluetoothLeAudioCodecsProvider.cpp | 39 ++- .../aidl_session/BluetoothLeAudioCodecsProvider.h | 7 +- .../BluetoothLeAudioCodecsProviderTest.cpp | 373 +++++++++++++++++++++ 5 files changed, 442 insertions(+), 7 deletions(-) create mode 100644 bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProviderTest.cpp 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 leAudioCodecCapabilities; +static bool isInvalidFileContent = false; + +std::optional +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 -BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities() { +BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities( + const std::optional& + 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 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 BluetoothLeAudioCodecsProvider::GetScenarios( const std::optional& 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 + ParseFromLeAudioOffloadSettingFile(); static std::vector - GetLeAudioCodecCapabilities(); + GetLeAudioCodecCapabilities( + const std::optional& + le_audio_offload_setting); + static void ClearLeAudioCodecCapabilities(); private: static inline std::unordered_map 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 + +#include +#include + +#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, + std::vector, + std::vector> + 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 kValidScenarioList = { + ScenarioList(std::vector{kValidScenario})}; +static const std::vector kValidConfigurationList = { + ConfigurationList( + std::vector{kValidConfigOneChanStereo_16_1})}; +static const std::vector kValidCodecConfigurationList = + {CodecConfigurationList( + std::vector{kValidCodecLC3_16k_1})}; +static const std::vector + kValidStrategyConfigurationList = { + StrategyConfigurationList(std::vector{ + kValidStrategyStereoOneCis, kValidStrategyStereoTwoCis, + kValidStrategyMonoOneCis})}; + +class BluetoothLeAudioCodecsProviderTest + : public ::testing::TestWithParam { + public: + static std::vector CreateTestCases( + const std::vector& scenario_lists, + const std::vector& configuration_lists, + const std::vector& codec_configuration_lists, + const std::vector& + 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 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 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{scenario_list}, + std::vector{configuration_list}, + std::vector{codec_configuration_list}, + std::vector{strategy_configuration_list}); + } +}; + +class GetScenariosTest : public BluetoothLeAudioCodecsProviderTest { + public: + static std::vector CreateInvalidScenarios() { + std::vector invalid_scenario_test_cases; + invalid_scenario_test_cases.push_back(ScenarioList(std::vector{ + Scenario(std::nullopt, std::make_optional("OneChanStereo_16_1"))})); + + invalid_scenario_test_cases.push_back(ScenarioList(std::vector{ + Scenario(std::make_optional("OneChanStereo_16_1"), std::nullopt)})); + + invalid_scenario_test_cases.push_back(ScenarioList( + std::vector{Scenario(std::nullopt, std::nullopt)})); + + invalid_scenario_test_cases.push_back( + ScenarioList(std::vector{})); + + 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 CreateInvalidConfigurations() { + std::vector invalid_configuration_test_cases; + invalid_configuration_test_cases.push_back( + ConfigurationList(std::vector{ + 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( + 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(std::make_optional("OneChanStereo_16_1"), + std::make_optional("LC3_16k_1"), std::nullopt)})); + + invalid_configuration_test_cases.push_back( + ConfigurationList(std::vector{})); + + 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 + CreateInvalidCodecConfigurations() { + std::vector invalid_codec_configuration_test_cases; + invalid_codec_configuration_test_cases.push_back(CodecConfigurationList( + std::vector{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( + 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( + 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( + 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( + 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{})); + + 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 + CreateInvalidStrategyConfigurations() { + std::vector + invalid_strategy_configuration_test_cases; + invalid_strategy_configuration_test_cases.push_back( + StrategyConfigurationList( + std::vector{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( + 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( + 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( + 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( + 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( + 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{})); + + 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(); +} -- cgit v1.2.3 From 08e0d7dfb073085e16b19862e9bee37833fe7d81 Mon Sep 17 00:00:00 2001 From: Zhanghao Wen Date: Mon, 14 Nov 2022 21:29:46 -0800 Subject: Update Cuttlefish mock GNSS hardware model name Test: atest GnssHardwareInfoTest Bug: 258680584 Change-Id: I17c877848aee4b607cd0d798e7c91a1987fd6286 Merged-In: I17c877848aee4b607cd0d798e7c91a1987fd6286 --- gnss/aidl/default/Gnss.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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& 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()) { -- cgit v1.2.3 From 2c7c34e466586c927d16aa44be8da97574040194 Mon Sep 17 00:00:00 2001 From: Andy Hung Date: Fri, 2 Dec 2022 17:22:59 -0800 Subject: audio HAL: Enable RT priority inheritance Test: instrumented Bug: 181148259 Bug: 260918856 Change-Id: If56e449a9c6f1a49e372591893d8714534574e3a --- .../all-versions/default/service/android.hardware.audio.service.rc | 2 ++ 1 file changed, 2 insertions(+) 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..f859f21683 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 @@ -4,6 +4,8 @@ service vendor.audio-hal /vendor/bin/hw/android.hardware.audio.service # 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 + # setting RLIMIT_RTPRIO allows binder RT priority inheritance + rlimit rtprio 10 10 ioprio rt 4 task_profiles ProcessCapacityHigh HighPerformance onrestart restart audioserver -- cgit v1.2.3 From 7a9e483f4b45fb7682e61812c1819e80f61b3d37 Mon Sep 17 00:00:00 2001 From: Michael Butler Date: Thu, 1 Dec 2022 16:42:22 -0800 Subject: Add additional bounds checks to NNAPI FMQ deserialize utility functions This CL adds the following additional bounds checks: * Adds additional checks of the index of the std::vector before accessing the element at the index * Changes the array index operator [] to the checked std::vector::at method Bug: 256589724 Test: mma Merged-In: I6bfb02a5cd76258284cc4d797a4508b21e672c4b Change-Id: I6bfb02a5cd76258284cc4d797a4508b21e672c4b --- .../1.2/utils/src/ExecutionBurstUtils.cpp | 56 +++++++++++++--------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/neuralnetworks/1.2/utils/src/ExecutionBurstUtils.cpp b/neuralnetworks/1.2/utils/src/ExecutionBurstUtils.cpp index 1bdde1e71a..38710cf3fd 100644 --- a/neuralnetworks/1.2/utils/src/ExecutionBurstUtils.cpp +++ b/neuralnetworks/1.2/utils/src/ExecutionBurstUtils.cpp @@ -192,12 +192,13 @@ nn::Result, V1_2::MeasureTiming>> size_t index = 0; // validate packet information - if (data.size() == 0 || data[index].getDiscriminator() != discriminator::packetInformation) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::packetInformation) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage packet information - const FmqRequestDatum::PacketInformation& packetInfo = data[index].packetInformation(); + const FmqRequestDatum::PacketInformation& packetInfo = data.at(index).packetInformation(); index++; const uint32_t packetSize = packetInfo.packetSize; const uint32_t numberOfInputOperands = packetInfo.numberOfInputOperands; @@ -214,13 +215,14 @@ nn::Result, V1_2::MeasureTiming>> inputs.reserve(numberOfInputOperands); for (size_t operand = 0; operand < numberOfInputOperands; ++operand) { // validate input operand information - if (data[index].getDiscriminator() != discriminator::inputOperandInformation) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::inputOperandInformation) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage operand information const FmqRequestDatum::OperandInformation& operandInfo = - data[index].inputOperandInformation(); + data.at(index).inputOperandInformation(); index++; const bool hasNoValue = operandInfo.hasNoValue; const V1_0::DataLocation location = operandInfo.location; @@ -231,12 +233,13 @@ nn::Result, V1_2::MeasureTiming>> dimensions.reserve(numberOfDimensions); for (size_t i = 0; i < numberOfDimensions; ++i) { // validate dimension - if (data[index].getDiscriminator() != discriminator::inputOperandDimensionValue) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::inputOperandDimensionValue) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage dimension - const uint32_t dimension = data[index].inputOperandDimensionValue(); + const uint32_t dimension = data.at(index).inputOperandDimensionValue(); index++; // store result @@ -253,13 +256,14 @@ nn::Result, V1_2::MeasureTiming>> outputs.reserve(numberOfOutputOperands); for (size_t operand = 0; operand < numberOfOutputOperands; ++operand) { // validate output operand information - if (data[index].getDiscriminator() != discriminator::outputOperandInformation) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::outputOperandInformation) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage operand information const FmqRequestDatum::OperandInformation& operandInfo = - data[index].outputOperandInformation(); + data.at(index).outputOperandInformation(); index++; const bool hasNoValue = operandInfo.hasNoValue; const V1_0::DataLocation location = operandInfo.location; @@ -270,12 +274,13 @@ nn::Result, V1_2::MeasureTiming>> dimensions.reserve(numberOfDimensions); for (size_t i = 0; i < numberOfDimensions; ++i) { // validate dimension - if (data[index].getDiscriminator() != discriminator::outputOperandDimensionValue) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::outputOperandDimensionValue) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage dimension - const uint32_t dimension = data[index].outputOperandDimensionValue(); + const uint32_t dimension = data.at(index).outputOperandDimensionValue(); index++; // store result @@ -292,12 +297,13 @@ nn::Result, V1_2::MeasureTiming>> slots.reserve(numberOfPools); for (size_t pool = 0; pool < numberOfPools; ++pool) { // validate input operand information - if (data[index].getDiscriminator() != discriminator::poolIdentifier) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::poolIdentifier) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage operand information - const int32_t poolId = data[index].poolIdentifier(); + const int32_t poolId = data.at(index).poolIdentifier(); index++; // store result @@ -305,17 +311,17 @@ nn::Result, V1_2::MeasureTiming>> } // validate measureTiming - if (data[index].getDiscriminator() != discriminator::measureTiming) { + if (index >= data.size() || data.at(index).getDiscriminator() != discriminator::measureTiming) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage measureTiming - const V1_2::MeasureTiming measure = data[index].measureTiming(); + const V1_2::MeasureTiming measure = data.at(index).measureTiming(); index++; // validate packet information if (index != packetSize) { - return NN_ERROR() << "FMQ Result packet ill-formed"; + return NN_ERROR() << "FMQ Request packet ill-formed"; } // return request @@ -330,12 +336,13 @@ nn::Result, V1_2::T size_t index = 0; // validate packet information - if (data.size() == 0 || data[index].getDiscriminator() != discriminator::packetInformation) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::packetInformation) { return NN_ERROR() << "FMQ Result packet ill-formed"; } // unpackage packet information - const FmqResultDatum::PacketInformation& packetInfo = data[index].packetInformation(); + const FmqResultDatum::PacketInformation& packetInfo = data.at(index).packetInformation(); index++; const uint32_t packetSize = packetInfo.packetSize; const V1_0::ErrorStatus errorStatus = packetInfo.errorStatus; @@ -351,12 +358,13 @@ nn::Result, V1_2::T outputShapes.reserve(numberOfOperands); for (size_t operand = 0; operand < numberOfOperands; ++operand) { // validate operand information - if (data[index].getDiscriminator() != discriminator::operandInformation) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::operandInformation) { return NN_ERROR() << "FMQ Result packet ill-formed"; } // unpackage operand information - const FmqResultDatum::OperandInformation& operandInfo = data[index].operandInformation(); + const FmqResultDatum::OperandInformation& operandInfo = data.at(index).operandInformation(); index++; const bool isSufficient = operandInfo.isSufficient; const uint32_t numberOfDimensions = operandInfo.numberOfDimensions; @@ -366,12 +374,13 @@ nn::Result, V1_2::T dimensions.reserve(numberOfDimensions); for (size_t i = 0; i < numberOfDimensions; ++i) { // validate dimension - if (data[index].getDiscriminator() != discriminator::operandDimensionValue) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::operandDimensionValue) { return NN_ERROR() << "FMQ Result packet ill-formed"; } // unpackage dimension - const uint32_t dimension = data[index].operandDimensionValue(); + const uint32_t dimension = data.at(index).operandDimensionValue(); index++; // store result @@ -383,12 +392,13 @@ nn::Result, V1_2::T } // validate execution timing - if (data[index].getDiscriminator() != discriminator::executionTiming) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::executionTiming) { return NN_ERROR() << "FMQ Result packet ill-formed"; } // unpackage execution timing - const V1_2::Timing timing = data[index].executionTiming(); + const V1_2::Timing timing = data.at(index).executionTiming(); index++; // validate packet information -- cgit v1.2.3 From 4668f30dcfdf418e7fcbc0d9c98b2eabbddb5099 Mon Sep 17 00:00:00 2001 From: Michael Butler Date: Thu, 1 Dec 2022 16:42:22 -0800 Subject: Add additional bounds checks to NNAPI FMQ deserialize utility functions This CL adds the following additional bounds checks: * Adds additional checks of the index of the std::vector before accessing the element at the index * Changes the array index operator [] to the checked std::vector::at method Bug: 256589724 Test: mma Merged-In: I6bfb02a5cd76258284cc4d797a4508b21e672c4b Change-Id: I6bfb02a5cd76258284cc4d797a4508b21e672c4b --- .../1.2/utils/src/ExecutionBurstUtils.cpp | 56 +++++++++++++--------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/neuralnetworks/1.2/utils/src/ExecutionBurstUtils.cpp b/neuralnetworks/1.2/utils/src/ExecutionBurstUtils.cpp index 1bdde1e71a..38710cf3fd 100644 --- a/neuralnetworks/1.2/utils/src/ExecutionBurstUtils.cpp +++ b/neuralnetworks/1.2/utils/src/ExecutionBurstUtils.cpp @@ -192,12 +192,13 @@ nn::Result, V1_2::MeasureTiming>> size_t index = 0; // validate packet information - if (data.size() == 0 || data[index].getDiscriminator() != discriminator::packetInformation) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::packetInformation) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage packet information - const FmqRequestDatum::PacketInformation& packetInfo = data[index].packetInformation(); + const FmqRequestDatum::PacketInformation& packetInfo = data.at(index).packetInformation(); index++; const uint32_t packetSize = packetInfo.packetSize; const uint32_t numberOfInputOperands = packetInfo.numberOfInputOperands; @@ -214,13 +215,14 @@ nn::Result, V1_2::MeasureTiming>> inputs.reserve(numberOfInputOperands); for (size_t operand = 0; operand < numberOfInputOperands; ++operand) { // validate input operand information - if (data[index].getDiscriminator() != discriminator::inputOperandInformation) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::inputOperandInformation) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage operand information const FmqRequestDatum::OperandInformation& operandInfo = - data[index].inputOperandInformation(); + data.at(index).inputOperandInformation(); index++; const bool hasNoValue = operandInfo.hasNoValue; const V1_0::DataLocation location = operandInfo.location; @@ -231,12 +233,13 @@ nn::Result, V1_2::MeasureTiming>> dimensions.reserve(numberOfDimensions); for (size_t i = 0; i < numberOfDimensions; ++i) { // validate dimension - if (data[index].getDiscriminator() != discriminator::inputOperandDimensionValue) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::inputOperandDimensionValue) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage dimension - const uint32_t dimension = data[index].inputOperandDimensionValue(); + const uint32_t dimension = data.at(index).inputOperandDimensionValue(); index++; // store result @@ -253,13 +256,14 @@ nn::Result, V1_2::MeasureTiming>> outputs.reserve(numberOfOutputOperands); for (size_t operand = 0; operand < numberOfOutputOperands; ++operand) { // validate output operand information - if (data[index].getDiscriminator() != discriminator::outputOperandInformation) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::outputOperandInformation) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage operand information const FmqRequestDatum::OperandInformation& operandInfo = - data[index].outputOperandInformation(); + data.at(index).outputOperandInformation(); index++; const bool hasNoValue = operandInfo.hasNoValue; const V1_0::DataLocation location = operandInfo.location; @@ -270,12 +274,13 @@ nn::Result, V1_2::MeasureTiming>> dimensions.reserve(numberOfDimensions); for (size_t i = 0; i < numberOfDimensions; ++i) { // validate dimension - if (data[index].getDiscriminator() != discriminator::outputOperandDimensionValue) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::outputOperandDimensionValue) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage dimension - const uint32_t dimension = data[index].outputOperandDimensionValue(); + const uint32_t dimension = data.at(index).outputOperandDimensionValue(); index++; // store result @@ -292,12 +297,13 @@ nn::Result, V1_2::MeasureTiming>> slots.reserve(numberOfPools); for (size_t pool = 0; pool < numberOfPools; ++pool) { // validate input operand information - if (data[index].getDiscriminator() != discriminator::poolIdentifier) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::poolIdentifier) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage operand information - const int32_t poolId = data[index].poolIdentifier(); + const int32_t poolId = data.at(index).poolIdentifier(); index++; // store result @@ -305,17 +311,17 @@ nn::Result, V1_2::MeasureTiming>> } // validate measureTiming - if (data[index].getDiscriminator() != discriminator::measureTiming) { + if (index >= data.size() || data.at(index).getDiscriminator() != discriminator::measureTiming) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage measureTiming - const V1_2::MeasureTiming measure = data[index].measureTiming(); + const V1_2::MeasureTiming measure = data.at(index).measureTiming(); index++; // validate packet information if (index != packetSize) { - return NN_ERROR() << "FMQ Result packet ill-formed"; + return NN_ERROR() << "FMQ Request packet ill-formed"; } // return request @@ -330,12 +336,13 @@ nn::Result, V1_2::T size_t index = 0; // validate packet information - if (data.size() == 0 || data[index].getDiscriminator() != discriminator::packetInformation) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::packetInformation) { return NN_ERROR() << "FMQ Result packet ill-formed"; } // unpackage packet information - const FmqResultDatum::PacketInformation& packetInfo = data[index].packetInformation(); + const FmqResultDatum::PacketInformation& packetInfo = data.at(index).packetInformation(); index++; const uint32_t packetSize = packetInfo.packetSize; const V1_0::ErrorStatus errorStatus = packetInfo.errorStatus; @@ -351,12 +358,13 @@ nn::Result, V1_2::T outputShapes.reserve(numberOfOperands); for (size_t operand = 0; operand < numberOfOperands; ++operand) { // validate operand information - if (data[index].getDiscriminator() != discriminator::operandInformation) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::operandInformation) { return NN_ERROR() << "FMQ Result packet ill-formed"; } // unpackage operand information - const FmqResultDatum::OperandInformation& operandInfo = data[index].operandInformation(); + const FmqResultDatum::OperandInformation& operandInfo = data.at(index).operandInformation(); index++; const bool isSufficient = operandInfo.isSufficient; const uint32_t numberOfDimensions = operandInfo.numberOfDimensions; @@ -366,12 +374,13 @@ nn::Result, V1_2::T dimensions.reserve(numberOfDimensions); for (size_t i = 0; i < numberOfDimensions; ++i) { // validate dimension - if (data[index].getDiscriminator() != discriminator::operandDimensionValue) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::operandDimensionValue) { return NN_ERROR() << "FMQ Result packet ill-formed"; } // unpackage dimension - const uint32_t dimension = data[index].operandDimensionValue(); + const uint32_t dimension = data.at(index).operandDimensionValue(); index++; // store result @@ -383,12 +392,13 @@ nn::Result, V1_2::T } // validate execution timing - if (data[index].getDiscriminator() != discriminator::executionTiming) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::executionTiming) { return NN_ERROR() << "FMQ Result packet ill-formed"; } // unpackage execution timing - const V1_2::Timing timing = data[index].executionTiming(); + const V1_2::Timing timing = data.at(index).executionTiming(); index++; // validate packet information -- cgit v1.2.3 From 082cefe34080b89e18868d8df5a97bd01f87b39c Mon Sep 17 00:00:00 2001 From: Michael Butler Date: Thu, 1 Dec 2022 16:42:22 -0800 Subject: Add additional bounds checks to NNAPI FMQ deserialize utility functions This CL adds the following additional bounds checks: * Adds additional checks of the index of the std::vector before accessing the element at the index * Changes the array index operator [] to the checked std::vector::at method Bug: 256589724 Test: mma Merged-In: I6bfb02a5cd76258284cc4d797a4508b21e672c4b Change-Id: I6bfb02a5cd76258284cc4d797a4508b21e672c4b --- .../1.2/utils/src/ExecutionBurstUtils.cpp | 56 +++++++++++++--------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/neuralnetworks/1.2/utils/src/ExecutionBurstUtils.cpp b/neuralnetworks/1.2/utils/src/ExecutionBurstUtils.cpp index 1bdde1e71a..38710cf3fd 100644 --- a/neuralnetworks/1.2/utils/src/ExecutionBurstUtils.cpp +++ b/neuralnetworks/1.2/utils/src/ExecutionBurstUtils.cpp @@ -192,12 +192,13 @@ nn::Result, V1_2::MeasureTiming>> size_t index = 0; // validate packet information - if (data.size() == 0 || data[index].getDiscriminator() != discriminator::packetInformation) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::packetInformation) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage packet information - const FmqRequestDatum::PacketInformation& packetInfo = data[index].packetInformation(); + const FmqRequestDatum::PacketInformation& packetInfo = data.at(index).packetInformation(); index++; const uint32_t packetSize = packetInfo.packetSize; const uint32_t numberOfInputOperands = packetInfo.numberOfInputOperands; @@ -214,13 +215,14 @@ nn::Result, V1_2::MeasureTiming>> inputs.reserve(numberOfInputOperands); for (size_t operand = 0; operand < numberOfInputOperands; ++operand) { // validate input operand information - if (data[index].getDiscriminator() != discriminator::inputOperandInformation) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::inputOperandInformation) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage operand information const FmqRequestDatum::OperandInformation& operandInfo = - data[index].inputOperandInformation(); + data.at(index).inputOperandInformation(); index++; const bool hasNoValue = operandInfo.hasNoValue; const V1_0::DataLocation location = operandInfo.location; @@ -231,12 +233,13 @@ nn::Result, V1_2::MeasureTiming>> dimensions.reserve(numberOfDimensions); for (size_t i = 0; i < numberOfDimensions; ++i) { // validate dimension - if (data[index].getDiscriminator() != discriminator::inputOperandDimensionValue) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::inputOperandDimensionValue) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage dimension - const uint32_t dimension = data[index].inputOperandDimensionValue(); + const uint32_t dimension = data.at(index).inputOperandDimensionValue(); index++; // store result @@ -253,13 +256,14 @@ nn::Result, V1_2::MeasureTiming>> outputs.reserve(numberOfOutputOperands); for (size_t operand = 0; operand < numberOfOutputOperands; ++operand) { // validate output operand information - if (data[index].getDiscriminator() != discriminator::outputOperandInformation) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::outputOperandInformation) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage operand information const FmqRequestDatum::OperandInformation& operandInfo = - data[index].outputOperandInformation(); + data.at(index).outputOperandInformation(); index++; const bool hasNoValue = operandInfo.hasNoValue; const V1_0::DataLocation location = operandInfo.location; @@ -270,12 +274,13 @@ nn::Result, V1_2::MeasureTiming>> dimensions.reserve(numberOfDimensions); for (size_t i = 0; i < numberOfDimensions; ++i) { // validate dimension - if (data[index].getDiscriminator() != discriminator::outputOperandDimensionValue) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::outputOperandDimensionValue) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage dimension - const uint32_t dimension = data[index].outputOperandDimensionValue(); + const uint32_t dimension = data.at(index).outputOperandDimensionValue(); index++; // store result @@ -292,12 +297,13 @@ nn::Result, V1_2::MeasureTiming>> slots.reserve(numberOfPools); for (size_t pool = 0; pool < numberOfPools; ++pool) { // validate input operand information - if (data[index].getDiscriminator() != discriminator::poolIdentifier) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::poolIdentifier) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage operand information - const int32_t poolId = data[index].poolIdentifier(); + const int32_t poolId = data.at(index).poolIdentifier(); index++; // store result @@ -305,17 +311,17 @@ nn::Result, V1_2::MeasureTiming>> } // validate measureTiming - if (data[index].getDiscriminator() != discriminator::measureTiming) { + if (index >= data.size() || data.at(index).getDiscriminator() != discriminator::measureTiming) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage measureTiming - const V1_2::MeasureTiming measure = data[index].measureTiming(); + const V1_2::MeasureTiming measure = data.at(index).measureTiming(); index++; // validate packet information if (index != packetSize) { - return NN_ERROR() << "FMQ Result packet ill-formed"; + return NN_ERROR() << "FMQ Request packet ill-formed"; } // return request @@ -330,12 +336,13 @@ nn::Result, V1_2::T size_t index = 0; // validate packet information - if (data.size() == 0 || data[index].getDiscriminator() != discriminator::packetInformation) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::packetInformation) { return NN_ERROR() << "FMQ Result packet ill-formed"; } // unpackage packet information - const FmqResultDatum::PacketInformation& packetInfo = data[index].packetInformation(); + const FmqResultDatum::PacketInformation& packetInfo = data.at(index).packetInformation(); index++; const uint32_t packetSize = packetInfo.packetSize; const V1_0::ErrorStatus errorStatus = packetInfo.errorStatus; @@ -351,12 +358,13 @@ nn::Result, V1_2::T outputShapes.reserve(numberOfOperands); for (size_t operand = 0; operand < numberOfOperands; ++operand) { // validate operand information - if (data[index].getDiscriminator() != discriminator::operandInformation) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::operandInformation) { return NN_ERROR() << "FMQ Result packet ill-formed"; } // unpackage operand information - const FmqResultDatum::OperandInformation& operandInfo = data[index].operandInformation(); + const FmqResultDatum::OperandInformation& operandInfo = data.at(index).operandInformation(); index++; const bool isSufficient = operandInfo.isSufficient; const uint32_t numberOfDimensions = operandInfo.numberOfDimensions; @@ -366,12 +374,13 @@ nn::Result, V1_2::T dimensions.reserve(numberOfDimensions); for (size_t i = 0; i < numberOfDimensions; ++i) { // validate dimension - if (data[index].getDiscriminator() != discriminator::operandDimensionValue) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::operandDimensionValue) { return NN_ERROR() << "FMQ Result packet ill-formed"; } // unpackage dimension - const uint32_t dimension = data[index].operandDimensionValue(); + const uint32_t dimension = data.at(index).operandDimensionValue(); index++; // store result @@ -383,12 +392,13 @@ nn::Result, V1_2::T } // validate execution timing - if (data[index].getDiscriminator() != discriminator::executionTiming) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::executionTiming) { return NN_ERROR() << "FMQ Result packet ill-formed"; } // unpackage execution timing - const V1_2::Timing timing = data[index].executionTiming(); + const V1_2::Timing timing = data.at(index).executionTiming(); index++; // validate packet information -- cgit v1.2.3 From 67d9ebe9e6f0b661978b86f561f36865abeb0c37 Mon Sep 17 00:00:00 2001 From: Michael Butler Date: Mon, 14 Nov 2022 19:00:25 -0800 Subject: Add additional bounds checks to NNAPI FMQ deserialize utility functions This CL adds the following additional bounds checks: * Adds additional checks of the index of the std::vector before accessing the element at the index * Changes the array index operator [] to the checked std::vector::at method Bug: 256589724 Test: mma Merged-In: I6bfb02a5cd76258284cc4d797a4508b21e672c4b Change-Id: I6bfb02a5cd76258284cc4d797a4508b21e672c4b --- neuralnetworks/1.2/utils/src/BurstUtils.cpp | 56 +++++++++++++++++------------ 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/neuralnetworks/1.2/utils/src/BurstUtils.cpp b/neuralnetworks/1.2/utils/src/BurstUtils.cpp index b589c468ce..c4c096da2d 100644 --- a/neuralnetworks/1.2/utils/src/BurstUtils.cpp +++ b/neuralnetworks/1.2/utils/src/BurstUtils.cpp @@ -190,12 +190,13 @@ nn::Result, V1_2::MeasureTiming>> size_t index = 0; // validate packet information - if (data.size() == 0 || data[index].getDiscriminator() != discriminator::packetInformation) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::packetInformation) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage packet information - const FmqRequestDatum::PacketInformation& packetInfo = data[index].packetInformation(); + const FmqRequestDatum::PacketInformation& packetInfo = data.at(index).packetInformation(); index++; const uint32_t packetSize = packetInfo.packetSize; const uint32_t numberOfInputOperands = packetInfo.numberOfInputOperands; @@ -212,13 +213,14 @@ nn::Result, V1_2::MeasureTiming>> inputs.reserve(numberOfInputOperands); for (size_t operand = 0; operand < numberOfInputOperands; ++operand) { // validate input operand information - if (data[index].getDiscriminator() != discriminator::inputOperandInformation) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::inputOperandInformation) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage operand information const FmqRequestDatum::OperandInformation& operandInfo = - data[index].inputOperandInformation(); + data.at(index).inputOperandInformation(); index++; const bool hasNoValue = operandInfo.hasNoValue; const V1_0::DataLocation location = operandInfo.location; @@ -229,12 +231,13 @@ nn::Result, V1_2::MeasureTiming>> dimensions.reserve(numberOfDimensions); for (size_t i = 0; i < numberOfDimensions; ++i) { // validate dimension - if (data[index].getDiscriminator() != discriminator::inputOperandDimensionValue) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::inputOperandDimensionValue) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage dimension - const uint32_t dimension = data[index].inputOperandDimensionValue(); + const uint32_t dimension = data.at(index).inputOperandDimensionValue(); index++; // store result @@ -251,13 +254,14 @@ nn::Result, V1_2::MeasureTiming>> outputs.reserve(numberOfOutputOperands); for (size_t operand = 0; operand < numberOfOutputOperands; ++operand) { // validate output operand information - if (data[index].getDiscriminator() != discriminator::outputOperandInformation) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::outputOperandInformation) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage operand information const FmqRequestDatum::OperandInformation& operandInfo = - data[index].outputOperandInformation(); + data.at(index).outputOperandInformation(); index++; const bool hasNoValue = operandInfo.hasNoValue; const V1_0::DataLocation location = operandInfo.location; @@ -268,12 +272,13 @@ nn::Result, V1_2::MeasureTiming>> dimensions.reserve(numberOfDimensions); for (size_t i = 0; i < numberOfDimensions; ++i) { // validate dimension - if (data[index].getDiscriminator() != discriminator::outputOperandDimensionValue) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::outputOperandDimensionValue) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage dimension - const uint32_t dimension = data[index].outputOperandDimensionValue(); + const uint32_t dimension = data.at(index).outputOperandDimensionValue(); index++; // store result @@ -290,12 +295,13 @@ nn::Result, V1_2::MeasureTiming>> slots.reserve(numberOfPools); for (size_t pool = 0; pool < numberOfPools; ++pool) { // validate input operand information - if (data[index].getDiscriminator() != discriminator::poolIdentifier) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::poolIdentifier) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage operand information - const int32_t poolId = data[index].poolIdentifier(); + const int32_t poolId = data.at(index).poolIdentifier(); index++; // store result @@ -303,17 +309,17 @@ nn::Result, V1_2::MeasureTiming>> } // validate measureTiming - if (data[index].getDiscriminator() != discriminator::measureTiming) { + if (index >= data.size() || data.at(index).getDiscriminator() != discriminator::measureTiming) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage measureTiming - const V1_2::MeasureTiming measure = data[index].measureTiming(); + const V1_2::MeasureTiming measure = data.at(index).measureTiming(); index++; // validate packet information if (index != packetSize) { - return NN_ERROR() << "FMQ Result packet ill-formed"; + return NN_ERROR() << "FMQ Request packet ill-formed"; } // return request @@ -328,12 +334,13 @@ nn::Result, V1_2::T size_t index = 0; // validate packet information - if (data.size() == 0 || data[index].getDiscriminator() != discriminator::packetInformation) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::packetInformation) { return NN_ERROR() << "FMQ Result packet ill-formed"; } // unpackage packet information - const FmqResultDatum::PacketInformation& packetInfo = data[index].packetInformation(); + const FmqResultDatum::PacketInformation& packetInfo = data.at(index).packetInformation(); index++; const uint32_t packetSize = packetInfo.packetSize; const V1_0::ErrorStatus errorStatus = packetInfo.errorStatus; @@ -349,12 +356,13 @@ nn::Result, V1_2::T outputShapes.reserve(numberOfOperands); for (size_t operand = 0; operand < numberOfOperands; ++operand) { // validate operand information - if (data[index].getDiscriminator() != discriminator::operandInformation) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::operandInformation) { return NN_ERROR() << "FMQ Result packet ill-formed"; } // unpackage operand information - const FmqResultDatum::OperandInformation& operandInfo = data[index].operandInformation(); + const FmqResultDatum::OperandInformation& operandInfo = data.at(index).operandInformation(); index++; const bool isSufficient = operandInfo.isSufficient; const uint32_t numberOfDimensions = operandInfo.numberOfDimensions; @@ -364,12 +372,13 @@ nn::Result, V1_2::T dimensions.reserve(numberOfDimensions); for (size_t i = 0; i < numberOfDimensions; ++i) { // validate dimension - if (data[index].getDiscriminator() != discriminator::operandDimensionValue) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::operandDimensionValue) { return NN_ERROR() << "FMQ Result packet ill-formed"; } // unpackage dimension - const uint32_t dimension = data[index].operandDimensionValue(); + const uint32_t dimension = data.at(index).operandDimensionValue(); index++; // store result @@ -381,12 +390,13 @@ nn::Result, V1_2::T } // validate execution timing - if (data[index].getDiscriminator() != discriminator::executionTiming) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::executionTiming) { return NN_ERROR() << "FMQ Result packet ill-formed"; } // unpackage execution timing - const V1_2::Timing timing = data[index].executionTiming(); + const V1_2::Timing timing = data.at(index).executionTiming(); index++; // validate packet information -- cgit v1.2.3 From 9b17e6485b12e20cd73c4b0b71e5798e608a177a Mon Sep 17 00:00:00 2001 From: Michael Butler Date: Mon, 14 Nov 2022 19:00:25 -0800 Subject: Add additional bounds checks to NNAPI FMQ deserialize utility functions This CL adds the following additional bounds checks: * Adds additional checks of the index of the std::vector before accessing the element at the index * Changes the array index operator [] to the checked std::vector::at method Bug: 256589724 Test: mma Merged-In: I6bfb02a5cd76258284cc4d797a4508b21e672c4b Change-Id: I6bfb02a5cd76258284cc4d797a4508b21e672c4b --- neuralnetworks/1.2/utils/src/BurstUtils.cpp | 56 +++++++++++++++++------------ 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/neuralnetworks/1.2/utils/src/BurstUtils.cpp b/neuralnetworks/1.2/utils/src/BurstUtils.cpp index b589c468ce..c4c096da2d 100644 --- a/neuralnetworks/1.2/utils/src/BurstUtils.cpp +++ b/neuralnetworks/1.2/utils/src/BurstUtils.cpp @@ -190,12 +190,13 @@ nn::Result, V1_2::MeasureTiming>> size_t index = 0; // validate packet information - if (data.size() == 0 || data[index].getDiscriminator() != discriminator::packetInformation) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::packetInformation) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage packet information - const FmqRequestDatum::PacketInformation& packetInfo = data[index].packetInformation(); + const FmqRequestDatum::PacketInformation& packetInfo = data.at(index).packetInformation(); index++; const uint32_t packetSize = packetInfo.packetSize; const uint32_t numberOfInputOperands = packetInfo.numberOfInputOperands; @@ -212,13 +213,14 @@ nn::Result, V1_2::MeasureTiming>> inputs.reserve(numberOfInputOperands); for (size_t operand = 0; operand < numberOfInputOperands; ++operand) { // validate input operand information - if (data[index].getDiscriminator() != discriminator::inputOperandInformation) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::inputOperandInformation) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage operand information const FmqRequestDatum::OperandInformation& operandInfo = - data[index].inputOperandInformation(); + data.at(index).inputOperandInformation(); index++; const bool hasNoValue = operandInfo.hasNoValue; const V1_0::DataLocation location = operandInfo.location; @@ -229,12 +231,13 @@ nn::Result, V1_2::MeasureTiming>> dimensions.reserve(numberOfDimensions); for (size_t i = 0; i < numberOfDimensions; ++i) { // validate dimension - if (data[index].getDiscriminator() != discriminator::inputOperandDimensionValue) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::inputOperandDimensionValue) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage dimension - const uint32_t dimension = data[index].inputOperandDimensionValue(); + const uint32_t dimension = data.at(index).inputOperandDimensionValue(); index++; // store result @@ -251,13 +254,14 @@ nn::Result, V1_2::MeasureTiming>> outputs.reserve(numberOfOutputOperands); for (size_t operand = 0; operand < numberOfOutputOperands; ++operand) { // validate output operand information - if (data[index].getDiscriminator() != discriminator::outputOperandInformation) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::outputOperandInformation) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage operand information const FmqRequestDatum::OperandInformation& operandInfo = - data[index].outputOperandInformation(); + data.at(index).outputOperandInformation(); index++; const bool hasNoValue = operandInfo.hasNoValue; const V1_0::DataLocation location = operandInfo.location; @@ -268,12 +272,13 @@ nn::Result, V1_2::MeasureTiming>> dimensions.reserve(numberOfDimensions); for (size_t i = 0; i < numberOfDimensions; ++i) { // validate dimension - if (data[index].getDiscriminator() != discriminator::outputOperandDimensionValue) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::outputOperandDimensionValue) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage dimension - const uint32_t dimension = data[index].outputOperandDimensionValue(); + const uint32_t dimension = data.at(index).outputOperandDimensionValue(); index++; // store result @@ -290,12 +295,13 @@ nn::Result, V1_2::MeasureTiming>> slots.reserve(numberOfPools); for (size_t pool = 0; pool < numberOfPools; ++pool) { // validate input operand information - if (data[index].getDiscriminator() != discriminator::poolIdentifier) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::poolIdentifier) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage operand information - const int32_t poolId = data[index].poolIdentifier(); + const int32_t poolId = data.at(index).poolIdentifier(); index++; // store result @@ -303,17 +309,17 @@ nn::Result, V1_2::MeasureTiming>> } // validate measureTiming - if (data[index].getDiscriminator() != discriminator::measureTiming) { + if (index >= data.size() || data.at(index).getDiscriminator() != discriminator::measureTiming) { return NN_ERROR() << "FMQ Request packet ill-formed"; } // unpackage measureTiming - const V1_2::MeasureTiming measure = data[index].measureTiming(); + const V1_2::MeasureTiming measure = data.at(index).measureTiming(); index++; // validate packet information if (index != packetSize) { - return NN_ERROR() << "FMQ Result packet ill-formed"; + return NN_ERROR() << "FMQ Request packet ill-formed"; } // return request @@ -328,12 +334,13 @@ nn::Result, V1_2::T size_t index = 0; // validate packet information - if (data.size() == 0 || data[index].getDiscriminator() != discriminator::packetInformation) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::packetInformation) { return NN_ERROR() << "FMQ Result packet ill-formed"; } // unpackage packet information - const FmqResultDatum::PacketInformation& packetInfo = data[index].packetInformation(); + const FmqResultDatum::PacketInformation& packetInfo = data.at(index).packetInformation(); index++; const uint32_t packetSize = packetInfo.packetSize; const V1_0::ErrorStatus errorStatus = packetInfo.errorStatus; @@ -349,12 +356,13 @@ nn::Result, V1_2::T outputShapes.reserve(numberOfOperands); for (size_t operand = 0; operand < numberOfOperands; ++operand) { // validate operand information - if (data[index].getDiscriminator() != discriminator::operandInformation) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::operandInformation) { return NN_ERROR() << "FMQ Result packet ill-formed"; } // unpackage operand information - const FmqResultDatum::OperandInformation& operandInfo = data[index].operandInformation(); + const FmqResultDatum::OperandInformation& operandInfo = data.at(index).operandInformation(); index++; const bool isSufficient = operandInfo.isSufficient; const uint32_t numberOfDimensions = operandInfo.numberOfDimensions; @@ -364,12 +372,13 @@ nn::Result, V1_2::T dimensions.reserve(numberOfDimensions); for (size_t i = 0; i < numberOfDimensions; ++i) { // validate dimension - if (data[index].getDiscriminator() != discriminator::operandDimensionValue) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::operandDimensionValue) { return NN_ERROR() << "FMQ Result packet ill-formed"; } // unpackage dimension - const uint32_t dimension = data[index].operandDimensionValue(); + const uint32_t dimension = data.at(index).operandDimensionValue(); index++; // store result @@ -381,12 +390,13 @@ nn::Result, V1_2::T } // validate execution timing - if (data[index].getDiscriminator() != discriminator::executionTiming) { + if (index >= data.size() || + data.at(index).getDiscriminator() != discriminator::executionTiming) { return NN_ERROR() << "FMQ Result packet ill-formed"; } // unpackage execution timing - const V1_2::Timing timing = data[index].executionTiming(); + const V1_2::Timing timing = data.at(index).executionTiming(); index++; // validate packet information -- cgit v1.2.3 From 43966208b7ef50c51a58e82c6d7c10ee9e115860 Mon Sep 17 00:00:00 2001 From: Andy Hung Date: Mon, 5 Dec 2022 13:55:31 -0800 Subject: audio HAL: set minimum Binder access priority Use setMinSchedulerPolicy to enforce minimum thread priority when accessing the audio HAL to ANDROID_PRIORITY_AUDIO Test: instrumented Bug: 261496726 Change-Id: I700b04d3060e9405b1445206882a6131cea0d045 --- audio/core/all-versions/default/Device.cpp | 3 +++ audio/core/all-versions/default/DevicesFactory.cpp | 3 +++ audio/effect/all-versions/default/EffectsFactory.cpp | 3 +++ 3 files changed, 9 insertions(+) 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 #include +#include #include #include @@ -183,6 +184,7 @@ std::tuple> 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> 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 #include +#include +#include namespace android { namespace hardware { @@ -103,6 +105,7 @@ Return 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/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 #include +#include #include #include #include @@ -44,6 +45,7 @@ #include #include #include +#include #include namespace android { @@ -189,6 +191,7 @@ Return 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", -- cgit v1.2.3 From 417ca2541aad2f4a639408da2f9d1e01acf42e08 Mon Sep 17 00:00:00 2001 From: Yu Shan Date: Thu, 8 Dec 2022 11:39:26 -0800 Subject: Avoid holding lock while calling recurrent actions. This CL fixes a dead lock issue caused by RecurrentTimer holding internal locks while calling actions. The dead lock is caused by the following situation: 1. Caller holds a lock, call RecurrentTimer.registerCallback which waits for RecurrentTimer's lock. 2. Another recurrent action happens at the same time. Recurrent timer holds lock before calling the client action. The client action is now waiting for the lock that is currently hold by 1. Test: atest RecurrentTimerTest Bug: 255574557 Change-Id: I3999f4e9cdf581cb851d5f49341dbcc0c160f234 (cherry picked from commit 93a821077effec224d3880875d98c13ef1787e4c) --- .../impl/utils/common/include/RecurrentTimer.h | 5 +- .../aidl/impl/utils/common/src/RecurrentTimer.cpp | 67 +++++++++++----------- .../impl/utils/common/test/RecurrentTimerTest.cpp | 27 +++++++++ 3 files changed, 65 insertions(+), 34 deletions(-) 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 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 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::popNextCallbackLocked() { +std::shared_ptr RecurrentTimer::getNextCallbackLocked(int64_t now) { std::pop_heap(mCallbackQueue.begin(), mCallbackQueue.end(), CallbackInfo::cmp); - std::unique_ptr 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 uniqueLock(mLock); - + std::vector> 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 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 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(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 timer = std::make_unique(); + std::mutex lock; + for (size_t i = 0; i < 1000; i++) { + std::scoped_lock lockGuard(lock); + auto action = std::make_shared([&lock] { + // While calling this function, the timer must not hold lock in order not to dead + // lock. + std::scoped_lock 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 -- cgit v1.2.3 From afc2da8e8b01d95ddd472d9b1a8b6b273a41ff68 Mon Sep 17 00:00:00 2001 From: Andy Hung Date: Thu, 1 Dec 2022 13:46:55 -0800 Subject: audio HAL: Optimize for Spatial Audio Add CAP_SYS_NICE. Allow util_clamp_min for Spatializer Effect worker thread. Reduce glitches caused by core migration. Reduce power consumption as Spatializer Effect is DSP compute bound. This change only affects Spatial Audio Effect processing. Test: instrumented Test: adb shell 'uclampset -a -p $(pgrep -of android.hardware.audio.service)' Test: adb shell cat "/proc/$(adb shell pgrep -of android.hardware.audio.service)/status" Test: adb shell 'ps -Tl -p $(pgrep -of android.hardware.audio.service)' Bug: 181148259 Bug: 260918856 Bug: 261228892 Bug: 261686532 Bug: 262803152 Change-Id: I59ea99e8a1720f61954747f6c29e14cfea9a0f56 --- .../service/android.hardware.audio.service.rc | 2 +- audio/effect/all-versions/default/Effect.cpp | 167 +++++++++++++++++++++ 2 files changed, 168 insertions(+), 1 deletion(-) 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 f859f21683..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,7 @@ 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 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 #include +#include #include #include +#include +#include #include #include @@ -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)) { -- cgit v1.2.3