diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp index f9e3eb410f..4902497930 100644 --- a/audio/aidl/Android.bp +++ b/audio/aidl/Android.bp @@ -64,6 +64,9 @@ aidl_interface { ], min_sdk_version: "31", }, + rust: { + enabled: true, + }, }, versions_with_info: [ { @@ -112,6 +115,13 @@ cc_defaults { ], } +rust_defaults { + name: "latest_android_hardware_audio_common_rust", + rustlibs: [ + latest_android_hardware_audio_common + "-rust", + ], +} + aidl_interface_defaults { name: "latest_android_hardware_audio_common_import_interface", imports: [ diff --git a/audio/aidl/common/include/Utils.h b/audio/aidl/common/include/Utils.h index dd0c7e7393..ce29635088 100644 --- a/audio/aidl/common/include/Utils.h +++ b/audio/aidl/common/include/Utils.h @@ -50,6 +50,9 @@ inline std::string errorToString(const ScopedAStatus& s) { namespace aidl::android::hardware::audio::common { +// TODO: b/275135031 - move this string to AIDL interfaces. +static constexpr char kDumpFromAudioServerArgument[] = "dump_from_audioserver"; + // Some values are reserved for use by the system code only. // HALs must not accept or emit values outside from the provided list. constexpr std::array<::aidl::android::media::audio::common::AudioMode, 5> kValidAudioModes = { diff --git a/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp b/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp index b023df1403..0c201cc9b8 100644 --- a/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp +++ b/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp @@ -453,12 +453,11 @@ enum EngineArchitectureTestParamName { ENGINE_TEST_INSTANCE_NAME, ENGINE_TEST_RESOLUTION_PREFERENCE, ENGINE_TEST_PREFERRED_DURATION, - ENGINE_TEST_STAGE_ENABLEMENT, - ENGINE_TEST_LIMITER_IN_USE + ENGINE_TEST_STAGE_ENABLEMENT }; using EngineArchitectureTestParams = std::tuple, Descriptor>, DynamicsProcessing::ResolutionPreference, float, - DynamicsProcessing::StageEnablement, bool>; + DynamicsProcessing::StageEnablement>; void fillEngineArchConfig(DynamicsProcessing::EngineArchitecture& cfg, const EngineArchitectureTestParams& params) { @@ -466,7 +465,7 @@ void fillEngineArchConfig(DynamicsProcessing::EngineArchitecture& cfg, cfg.preferredProcessingDurationMs = std::get(params); cfg.preEqStage = cfg.postEqStage = cfg.mbcStage = std::get(params); - cfg.limiterInUse = std::get(params); + cfg.limiterInUse = true; } class DynamicsProcessingTestEngineArchitecture @@ -501,8 +500,8 @@ INSTANTIATE_TEST_SUITE_P( static_cast(-1)), // variant testing::Values(-10.f, 0.f, 10.f), // processing duration testing::ValuesIn( - DynamicsProcessingTestHelper::kStageEnablementTestSet), // preEQ/postEQ/mbc - testing::Bool()), // limiter enable + DynamicsProcessingTestHelper::kStageEnablementTestSet) // preEQ/postEQ/mbc + ), [](const auto& info) { auto descriptor = std::get(info.param).second; DynamicsProcessing::EngineArchitecture cfg; @@ -568,7 +567,6 @@ enum LimiterConfigTestParamName { LIMITER_CHANNEL, LIMITER_ENABLE, LIMITER_LINK_GROUP, - LIMITER_ENGINE_IN_USE, LIMITER_ADDITIONAL, }; enum LimiterConfigTestAdditionalParam { @@ -587,9 +585,8 @@ static constexpr std::array kLimiterConfigTestAd {1, -60, 2.5, -2, 3.14}, {1, 60, 2.5, -2, 3.14}}}; -using LimiterConfigTestParams = - std::tuple, Descriptor>, int32_t, bool, int32_t, bool, - LimiterConfigTestAdditional>; +using LimiterConfigTestParams = std::tuple, Descriptor>, + int32_t, bool, int32_t, LimiterConfigTestAdditional>; void fillLimiterConfig(DynamicsProcessing::LimiterConfig& cfg, const LimiterConfigTestParams& params) { @@ -609,8 +606,7 @@ class DynamicsProcessingTestLimiterConfig public DynamicsProcessingTestHelper { public: DynamicsProcessingTestLimiterConfig() - : DynamicsProcessingTestHelper(std::get(GetParam())), - mLimiterInUseEngine(std::get(GetParam())) { + : DynamicsProcessingTestHelper(std::get(GetParam())) { fillLimiterConfig(mCfg, GetParam()); } @@ -619,11 +615,9 @@ class DynamicsProcessingTestLimiterConfig void TearDown() override { TearDownDynamicsProcessingEffect(); } DynamicsProcessing::LimiterConfig mCfg; - bool mLimiterInUseEngine; }; TEST_P(DynamicsProcessingTestLimiterConfig, SetAndGetLimiterConfig) { - mEngineConfigPreset.limiterInUse = mLimiterInUseEngine; EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset)); EXPECT_NO_FATAL_FAILURE(addLimiterConfig({mCfg})); SetAndGetDynamicsProcessingParameters(); @@ -633,21 +627,18 @@ INSTANTIATE_TEST_SUITE_P( DynamicsProcessingTest, DynamicsProcessingTestLimiterConfig, ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors( IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())), - testing::Values(-1, 0, 1, 2), // channel count - testing::Bool(), // enable - testing::Values(3), // link group - testing::Bool(), // engine limiter enable + testing::Values(-1, 0, 1, 2), // channel count + testing::Bool(), // enable + testing::Values(3), // link group testing::ValuesIn(kLimiterConfigTestAdditionalParam)), // Additional [](const auto& info) { auto descriptor = std::get(info.param).second; DynamicsProcessing::LimiterConfig cfg; fillLimiterConfig(cfg, info.param); - std::string engineLimiterInUse = - std::to_string(std::get(info.param)); std::string name = "Implementor_" + descriptor.common.implementor + "_name_" + descriptor.common.name + "_UUID_" + toString(descriptor.common.id.uuid) + "_limiterConfig_" + - cfg.toString() + "_engineSetting_" + engineLimiterInUse; + cfg.toString(); std::replace_if( name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_'); return name; @@ -659,11 +650,10 @@ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingTestLimiterConfi */ enum ChannelConfigTestParamName { BAND_CHANNEL_TEST_INSTANCE_NAME, - BAND_CHANNEL_TEST_CHANNEL_CONFIG, - BAND_CHANNEL_TEST_ENGINE_IN_USE + BAND_CHANNEL_TEST_CHANNEL_CONFIG }; using ChannelConfigTestParams = std::tuple, Descriptor>, - std::vector, bool>; + std::vector>; class DynamicsProcessingTestChannelConfig : public ::testing::TestWithParam, @@ -671,33 +661,28 @@ class DynamicsProcessingTestChannelConfig public: DynamicsProcessingTestChannelConfig() : DynamicsProcessingTestHelper(std::get(GetParam())), - mCfg(std::get(GetParam())), - mInUseEngine(std::get(GetParam())) {} + mCfg(std::get(GetParam())) {} void SetUp() override { SetUpDynamicsProcessingEffect(); } void TearDown() override { TearDownDynamicsProcessingEffect(); } std::vector mCfg; - const bool mInUseEngine; }; TEST_P(DynamicsProcessingTestChannelConfig, SetAndGetPreEqChannelConfig) { - mEngineConfigPreset.preEqStage.inUse = mInUseEngine; EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset)); EXPECT_NO_FATAL_FAILURE(addPreEqChannelConfig(mCfg)); SetAndGetDynamicsProcessingParameters(); } TEST_P(DynamicsProcessingTestChannelConfig, SetAndGetPostEqChannelConfig) { - mEngineConfigPreset.postEqStage.inUse = mInUseEngine; EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset)); EXPECT_NO_FATAL_FAILURE(addPostEqChannelConfig(mCfg)); SetAndGetDynamicsProcessingParameters(); } TEST_P(DynamicsProcessingTestChannelConfig, SetAndGetMbcChannelConfig) { - mEngineConfigPreset.mbcStage.inUse = mInUseEngine; EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset)); EXPECT_NO_FATAL_FAILURE(addMbcChannelConfig(mCfg)); SetAndGetDynamicsProcessingParameters(); @@ -709,19 +694,15 @@ INSTANTIATE_TEST_SUITE_P( testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors( IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())), testing::ValuesIn( - DynamicsProcessingTestHelper::kChannelConfigTestSet), // channel config - testing::Bool()), // Engine inUse + DynamicsProcessingTestHelper::kChannelConfigTestSet)), // channel config [](const auto& info) { auto descriptor = std::get(info.param).second; - std::string engineInUse = - std::to_string(std::get(info.param)); std::string channelConfig = ::android::internal::ToString( std::get(info.param)); std::string name = "Implementor_" + descriptor.common.implementor + "_name_" + descriptor.common.name + "_UUID_" + - toString(descriptor.common.id.uuid) + "_" + channelConfig + - "_engineInUse_" + engineInUse; + toString(descriptor.common.id.uuid) + "_" + channelConfig; std::replace_if( name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_'); return name; @@ -736,11 +717,10 @@ enum EqBandConfigTestParamName { EQ_BAND_CHANNEL, EQ_BAND_ENABLE, EQ_BAND_CUT_OFF_FREQ, - EQ_BAND_GAIN, - EQ_BAND_STAGE_IN_USE + EQ_BAND_GAIN }; using EqBandConfigTestParams = std::tuple, Descriptor>, int32_t, - bool, std::vector>, float, bool>; + bool, std::vector>, float>; void fillEqBandConfig(std::vector& cfgs, const EqBandConfigTestParams& params) { @@ -760,8 +740,7 @@ class DynamicsProcessingTestEqBandConfig : public ::testing::TestWithParam(GetParam())), - mStageInUse(std::get(GetParam())) { + : DynamicsProcessingTestHelper(std::get(GetParam())) { fillEqBandConfig(mCfgs, GetParam()); } @@ -770,11 +749,9 @@ class DynamicsProcessingTestEqBandConfig : public ::testing::TestWithParam mCfgs; - const bool mStageInUse; }; TEST_P(DynamicsProcessingTestEqBandConfig, SetAndGetPreEqBandConfig) { - mEngineConfigPreset.preEqStage.inUse = mStageInUse; mEngineConfigPreset.preEqStage.bandCount = mCfgs.size(); EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset)); std::vector cfgs(mChannelCount); @@ -788,7 +765,6 @@ TEST_P(DynamicsProcessingTestEqBandConfig, SetAndGetPreEqBandConfig) { } TEST_P(DynamicsProcessingTestEqBandConfig, SetAndGetPostEqBandConfig) { - mEngineConfigPreset.postEqStage.inUse = mStageInUse; mEngineConfigPreset.postEqStage.bandCount = mCfgs.size(); EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset)); std::vector cfgs(mChannelCount); @@ -849,21 +825,19 @@ INSTANTIATE_TEST_SUITE_P( DynamicsProcessingTest, DynamicsProcessingTestEqBandConfig, ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors( IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())), - testing::Values(-1, 0, 10), // channel ID - testing::Bool(), // band enable - testing::ValuesIn(kBands), // cut off frequencies - testing::Values(-3.14f, 3.14f), // gain - testing::Values(true)), // stage in use + testing::Values(-1, 0, 10), // channel ID + testing::Bool(), // band enable + testing::ValuesIn(kBands), // cut off frequencies + testing::Values(-3.14f, 3.14f) // gain + ), [](const auto& info) { auto descriptor = std::get(info.param).second; std::vector cfgs; fillEqBandConfig(cfgs, info.param); std::string bands = ::android::internal::ToString(cfgs); - std::string stageInUse = std::to_string(std::get(info.param)); std::string name = "Implementor_" + descriptor.common.implementor + "_name_" + descriptor.common.name + "_UUID_" + - toString(descriptor.common.id.uuid) + "_bands_" + bands + - "_stageInUse_" + stageInUse; + toString(descriptor.common.id.uuid) + "_bands_" + bands; std::replace_if( name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_'); return name; @@ -879,7 +853,6 @@ enum MbcBandConfigParamName { MBC_BAND_CHANNEL, MBC_BAND_ENABLE, MBC_BAND_CUTOFF_FREQ, - MBC_BAND_STAGE_IN_USE, MBC_BAND_ADDITIONAL }; enum MbcBandConfigAdditional { @@ -905,7 +878,7 @@ static constexpr std::array kMbcBandConfig using TestParamsMbcBandConfig = std::tuple, Descriptor>, int32_t, bool, - std::vector>, bool, TestParamsMbcBandConfigAdditional>; + std::vector>, TestParamsMbcBandConfigAdditional>; void fillMbcBandConfig(std::vector& cfgs, const TestParamsMbcBandConfig& params) { @@ -936,8 +909,7 @@ class DynamicsProcessingTestMbcBandConfig public DynamicsProcessingTestHelper { public: DynamicsProcessingTestMbcBandConfig() - : DynamicsProcessingTestHelper(std::get(GetParam())), - mStageInUse(std::get(GetParam())) { + : DynamicsProcessingTestHelper(std::get(GetParam())) { fillMbcBandConfig(mCfgs, GetParam()); } @@ -946,11 +918,9 @@ class DynamicsProcessingTestMbcBandConfig void TearDown() override { TearDownDynamicsProcessingEffect(); } std::vector mCfgs; - const bool mStageInUse; }; TEST_P(DynamicsProcessingTestMbcBandConfig, SetAndGetMbcBandConfig) { - mEngineConfigPreset.mbcStage.inUse = mStageInUse; mEngineConfigPreset.mbcStage.bandCount = mCfgs.size(); EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset)); std::vector cfgs(mChannelCount); @@ -970,18 +940,15 @@ INSTANTIATE_TEST_SUITE_P( testing::Values(-1, 0, 10), // channel count testing::Bool(), // enable testing::ValuesIn(kBands), // cut off frequencies - testing::Bool(), // stage in use testing::ValuesIn(kMbcBandConfigAdditionalParam)), // Additional [](const auto& info) { auto descriptor = std::get(info.param).second; std::vector cfgs; fillMbcBandConfig(cfgs, info.param); std::string mbcBands = ::android::internal::ToString(cfgs); - std::string stageInUse = std::to_string(std::get(info.param)); std::string name = "Implementor_" + descriptor.common.implementor + "_name_" + descriptor.common.name + "_UUID_" + - toString(descriptor.common.id.uuid) + "_bands_" + mbcBands + - "_stageInUse_" + stageInUse; + toString(descriptor.common.id.uuid) + "_bands_" + mbcBands; std::replace_if( name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_'); return name; diff --git a/audio/aidl/vts/VtsHalVolumeTargetTest.cpp b/audio/aidl/vts/VtsHalVolumeTargetTest.cpp index 5930dcf2b8..2c21d2e0a3 100644 --- a/audio/aidl/vts/VtsHalVolumeTargetTest.cpp +++ b/audio/aidl/vts/VtsHalVolumeTargetTest.cpp @@ -140,7 +140,9 @@ using VolumeDataTestParam = std::pair, Descriptor>; class VolumeDataTest : public ::testing::TestWithParam, public VolumeControlHelper { public: - VolumeDataTest() { + VolumeDataTest() + : kVsrApiLevel( + android::base::GetIntProperty("ro.vendor.api_level", __ANDROID_API_FUTURE__)) { std::tie(mFactory, mDescriptor) = GetParam(); mInput.resize(kBufferSize); mInputMag.resize(mTestFrequencies.size()); @@ -165,13 +167,17 @@ class VolumeDataTest : public ::testing::TestWithParam, void SetUp() override { SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags); + // Skips test fixture if api_level <= 34 (__ANDROID_API_U__). + if (kVsrApiLevel <= __ANDROID_API_U__) GTEST_SKIP(); ASSERT_NO_FATAL_FAILURE(SetUpVolumeControl()); } void TearDown() override { SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags); + if (kVsrApiLevel <= __ANDROID_API_U__) GTEST_SKIP(); TearDownVolumeControl(); } + const int kVsrApiLevel; static constexpr int kMaxAudioSample = 1; static constexpr int kTransitionDuration = 300; static constexpr int kNPointFFT = 16384; diff --git a/automotive/audiocontrol/aidl/Android.bp b/automotive/audiocontrol/aidl/Android.bp index 4fc6aac395..edb29c9df5 100644 --- a/automotive/audiocontrol/aidl/Android.bp +++ b/automotive/audiocontrol/aidl/Android.bp @@ -27,6 +27,9 @@ aidl_interface { "com.android.car.framework", ], }, + rust: { + enabled: true, + }, }, versions_with_info: [ { @@ -93,3 +96,17 @@ cc_defaults { latest_android_hardware_automotive_audiocontrol + "-ndk", ], } + +java_defaults { + name: "latest_android_hardware_automotive_audiocontrol_java_static", + static_libs: [ + latest_android_hardware_automotive_audiocontrol + "-java", + ], +} + +rust_defaults { + name: "latest_android_hardware_automotive_audiocontrol_rust", + rustlibs: [ + latest_android_hardware_automotive_audiocontrol + "-rust", + ], +} diff --git a/automotive/audiocontrol/aidl/default/Android.bp b/automotive/audiocontrol/aidl/default/Android.bp index a48d22893e..fd7e167545 100644 --- a/automotive/audiocontrol/aidl/default/Android.bp +++ b/automotive/audiocontrol/aidl/default/Android.bp @@ -30,15 +30,14 @@ cc_binary { defaults: [ "latest_android_hardware_audio_common_ndk_shared", "latest_android_hardware_automotive_audiocontrol_ndk_shared", + "powerpolicyclient_defaults", ], shared_libs: [ "android.hardware.audio.common@7.0-enums", - "android.frameworks.automotive.powerpolicy-V2-ndk", "libbase", "libbinder_ndk", "libcutils", "liblog", - "libpowerpolicyclient", ], srcs: [ "AudioControl.cpp", diff --git a/automotive/audiocontrol/aidl/rust_impl/Android.bp b/automotive/audiocontrol/aidl/rust_impl/Android.bp new file mode 100644 index 0000000000..062d989bab --- /dev/null +++ b/automotive/audiocontrol/aidl/rust_impl/Android.bp @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2024 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. + */ + +rust_binary { + name: "android.hardware.automotive.audiocontrol-V4-rust-service", + relative_install_path: "hw", + vendor: true, + srcs: ["src/*.rs"], + crate_root: "src/main.rs", + defaults: [ + "latest_android_hardware_automotive_audiocontrol_rust", + "latest_android_hardware_audio_common_rust", + ], + vintf_fragments: ["audiocontrol-rust-service.xml"], + init_rc: ["audiocontrol-rust-service.rc"], + rustlibs: [ + "libbinder_rs", + ], +} diff --git a/automotive/audiocontrol/aidl/rust_impl/README.md b/automotive/audiocontrol/aidl/rust_impl/README.md new file mode 100644 index 0000000000..ed22356920 --- /dev/null +++ b/automotive/audiocontrol/aidl/rust_impl/README.md @@ -0,0 +1,13 @@ +# Rust Skeleton Audio Control HAL implementation. + +WARNING: This is not a reference audio control HAl implementation and does +not contain any actual implementation. + +This folder contains a skeleton audio control HAL implementation in Rust to +demonstrate how vendor may implement a Rust audio control HAL. To run this +audio control HAL, include +`android.hardware.automotive.audiocontrol-V4-rust-service` in your image. + +This implementation returns `StatusCode::UNKNOWN_ERROR` for all operations +and does not pass VTS/CTS. Vendor must replace the logic in +`default_audio_control_hal.rs` with the actual implementation. diff --git a/automotive/audiocontrol/aidl/rust_impl/audiocontrol-rust-service.rc b/automotive/audiocontrol/aidl/rust_impl/audiocontrol-rust-service.rc new file mode 100644 index 0000000000..88d180dbd1 --- /dev/null +++ b/automotive/audiocontrol/aidl/rust_impl/audiocontrol-rust-service.rc @@ -0,0 +1,4 @@ +service vendor.audiocontrol-default /vendor/bin/hw/android.hardware.automotive.audiocontrol-service.example + class hal + user audioserver + group system diff --git a/automotive/audiocontrol/aidl/rust_impl/audiocontrol-rust-service.xml b/automotive/audiocontrol/aidl/rust_impl/audiocontrol-rust-service.xml new file mode 100644 index 0000000000..e54c1d332d --- /dev/null +++ b/automotive/audiocontrol/aidl/rust_impl/audiocontrol-rust-service.xml @@ -0,0 +1,23 @@ + + + + + android.hardware.automotive.audiocontrol + 4 + IAudioControl/default + + diff --git a/automotive/audiocontrol/aidl/rust_impl/src/default_audio_control_hal.rs b/automotive/audiocontrol/aidl/rust_impl/src/default_audio_control_hal.rs new file mode 100644 index 0000000000..ba0ca238f4 --- /dev/null +++ b/automotive/audiocontrol/aidl/rust_impl/src/default_audio_control_hal.rs @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2024 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. + */ +use android_hardware_automotive_audiocontrol::aidl::android::hardware::automotive::audiocontrol::{ + AudioFocusChange::AudioFocusChange, + AudioGainConfigInfo::AudioGainConfigInfo, + DuckingInfo::DuckingInfo, + IAudioControl::IAudioControl, + IAudioGainCallback::IAudioGainCallback, + IFocusListener::IFocusListener, + IModuleChangeCallback::IModuleChangeCallback, + MutingInfo::MutingInfo, + Reasons::Reasons, +}; +use android_hardware_audio_common::aidl::android::hardware::audio::common::PlaybackTrackMetadata::PlaybackTrackMetadata; +use binder::{Interface, Result as BinderResult, StatusCode, Strong}; + +/// This struct is defined to implement IAudioControl AIDL interface. +pub struct DefaultAudioControlHal; + +impl Interface for DefaultAudioControlHal {} + +impl IAudioControl for DefaultAudioControlHal { + fn onAudioFocusChange(&self, _usage : &str, _zone_id : i32, _focus_change : AudioFocusChange + ) -> BinderResult<()> { + Err(StatusCode::UNKNOWN_ERROR.into()) + } + + fn onDevicesToDuckChange(&self, _ducking_infos : &[DuckingInfo]) -> BinderResult<()> { + Err(StatusCode::UNKNOWN_ERROR.into()) + } + + fn onDevicesToMuteChange(&self, _muting_infos : &[MutingInfo]) -> BinderResult<()> { + Err(StatusCode::UNKNOWN_ERROR.into()) + } + + fn registerFocusListener(&self, _listener : &Strong) -> BinderResult<()> { + Err(StatusCode::UNKNOWN_ERROR.into()) + } + + fn setBalanceTowardRight(&self, _value : f32) -> BinderResult<()> { + Err(StatusCode::UNKNOWN_ERROR.into()) + } + + fn setFadeTowardFront(&self, _value : f32) -> BinderResult<()> { + Err(StatusCode::UNKNOWN_ERROR.into()) + } + + fn onAudioFocusChangeWithMetaData(&self, _playback_metadata : &PlaybackTrackMetadata, + _zone_id : i32, _focus_change : AudioFocusChange) -> BinderResult<()> { + Err(StatusCode::UNKNOWN_ERROR.into()) + } + + fn setAudioDeviceGainsChanged(&self, _reasons : &[Reasons], _gains : &[AudioGainConfigInfo] + ) -> BinderResult<()> { + Err(StatusCode::UNKNOWN_ERROR.into()) + } + + fn registerGainCallback(&self, _callback : &Strong + ) -> BinderResult<()> { + Err(StatusCode::UNKNOWN_ERROR.into()) + } + + fn setModuleChangeCallback(&self, _callback : &Strong + ) -> BinderResult<()> { + Err(StatusCode::UNKNOWN_ERROR.into()) + } + + fn clearModuleChangeCallback(&self) -> BinderResult<()> { + Err(StatusCode::UNKNOWN_ERROR.into()) + } +} diff --git a/automotive/audiocontrol/aidl/rust_impl/src/main.rs b/automotive/audiocontrol/aidl/rust_impl/src/main.rs new file mode 100644 index 0000000000..2ed4810f9c --- /dev/null +++ b/automotive/audiocontrol/aidl/rust_impl/src/main.rs @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2024 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. + */ +mod default_audio_control_hal; + +use android_hardware_automotive_audiocontrol::aidl::android::hardware::automotive::audiocontrol::IAudioControl::BnAudioControl; +use crate::default_audio_control_hal::DefaultAudioControlHal; + +fn main() { + binder::ProcessState::start_thread_pool(); + let my_service = DefaultAudioControlHal; + let service_name = "android.hardware.automotive.audiocontrol.IAudioControl/default"; + let my_service_binder = BnAudioControl::new_binder( + my_service, + binder::BinderFeatures::default(), + ); + binder::add_service(service_name, my_service_binder.as_binder()) + .expect(format!("Failed to register {}?", service_name).as_str()); + // Does not return. + binder::ProcessState::join_thread_pool() +} diff --git a/automotive/evs/aidl/impl/default/include/EvsVideoEmulatedCamera.h b/automotive/evs/aidl/impl/default/include/EvsVideoEmulatedCamera.h index a850d6598b..9d1610a928 100644 --- a/automotive/evs/aidl/impl/default/include/EvsVideoEmulatedCamera.h +++ b/automotive/evs/aidl/impl/default/include/EvsVideoEmulatedCamera.h @@ -93,6 +93,8 @@ class EvsVideoEmulatedCamera : public EvsCamera { bool initialize(); + bool initializeMediaCodec(); + void generateFrames(); void renderOneFrame(); diff --git a/automotive/evs/aidl/impl/default/resources/evs_mock_configuration.xml b/automotive/evs/aidl/impl/default/resources/evs_mock_configuration.xml index 6cbc18eacf..af5b354bc8 100644 --- a/automotive/evs/aidl/impl/default/resources/evs_mock_configuration.xml +++ b/automotive/evs/aidl/impl/default/resources/evs_mock_configuration.xml @@ -42,6 +42,30 @@ + + + + + + + + + + + + + + + + + + + + + android.hardware.broadcastradio + 2 + IBroadcastRadio/amfm + + diff --git a/broadcastradio/aidl/rust_impl/src/default_broadcastradio_hal.rs b/broadcastradio/aidl/rust_impl/src/default_broadcastradio_hal.rs new file mode 100644 index 0000000000..ea2f9d3b6b --- /dev/null +++ b/broadcastradio/aidl/rust_impl/src/default_broadcastradio_hal.rs @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2024 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. + */ +use android_hardware_broadcastradio::aidl::android::hardware::broadcastradio::{ + AmFmRegionConfig::AmFmRegionConfig, + AnnouncementType::AnnouncementType, + ConfigFlag::ConfigFlag, + DabTableEntry::DabTableEntry, + IAnnouncementListener::IAnnouncementListener, + IBroadcastRadio::IBroadcastRadio, + ICloseHandle::ICloseHandle, + ITunerCallback::ITunerCallback, + ProgramFilter::ProgramFilter, + ProgramSelector::ProgramSelector, + Properties::Properties, + VendorKeyValue::VendorKeyValue, +}; +use binder::{Interface, Result as BinderResult, StatusCode, Strong}; +use std::vec::Vec; + +/// This struct is defined to implement IBroadcastRadio AIDL interface. +pub struct DefaultBroadcastRadioHal; + +impl Interface for DefaultBroadcastRadioHal {} + +impl IBroadcastRadio for DefaultBroadcastRadioHal { + fn getAmFmRegionConfig(&self, _full : bool) -> BinderResult { + Err(StatusCode::UNKNOWN_ERROR.into()) + } + + fn getDabRegionConfig(&self) -> BinderResult> { + Err(StatusCode::UNKNOWN_ERROR.into()) + } + + fn getProperties(&self) -> BinderResult { + Err(StatusCode::UNKNOWN_ERROR.into()) + } + + fn getImage(&self, _id : i32) -> BinderResult> { + Err(StatusCode::UNKNOWN_ERROR.into()) + } + + fn setTunerCallback(&self, _callback : &Strong) -> BinderResult<()> { + Err(StatusCode::UNKNOWN_ERROR.into()) + } + + fn unsetTunerCallback(&self) -> BinderResult<()> { + Err(StatusCode::UNKNOWN_ERROR.into()) + } + + fn tune(&self, _program : &ProgramSelector) -> BinderResult<()> { + Err(StatusCode::UNKNOWN_ERROR.into()) + } + + fn seek(&self, _direction_up : bool, _skip_sub_channel : bool) -> BinderResult<()> { + Err(StatusCode::UNKNOWN_ERROR.into()) + } + + fn step(&self, _direction_up : bool) -> BinderResult<()> { + Err(StatusCode::UNKNOWN_ERROR.into()) + } + + fn cancel(&self) -> BinderResult<()> { + Err(StatusCode::UNKNOWN_ERROR.into()) + } + + fn startProgramListUpdates(&self, _filter : &ProgramFilter) -> BinderResult<()> { + Err(StatusCode::UNKNOWN_ERROR.into()) + } + + fn stopProgramListUpdates(&self) -> BinderResult<()> { + Err(StatusCode::UNKNOWN_ERROR.into()) + } + + fn isConfigFlagSet(&self, _flag : ConfigFlag) -> BinderResult { + Err(StatusCode::UNKNOWN_ERROR.into()) + } + + fn setConfigFlag(&self, _flag : ConfigFlag, _value : bool) -> BinderResult<()> { + Err(StatusCode::UNKNOWN_ERROR.into()) + } + + fn setParameters(&self, _parameters : &[VendorKeyValue]) -> BinderResult> { + Err(StatusCode::UNKNOWN_ERROR.into()) + } + + fn getParameters(&self, _parameters : &[String]) -> BinderResult> { + Err(StatusCode::UNKNOWN_ERROR.into()) + } + + fn registerAnnouncementListener(&self, _listener : &Strong, + _enabled : &[AnnouncementType]) -> BinderResult> { + Err(StatusCode::UNKNOWN_ERROR.into()) + } +} diff --git a/broadcastradio/aidl/rust_impl/src/main.rs b/broadcastradio/aidl/rust_impl/src/main.rs new file mode 100644 index 0000000000..c0bc0559da --- /dev/null +++ b/broadcastradio/aidl/rust_impl/src/main.rs @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2024 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. + */ + mod default_broadcastradio_hal; + +use android_hardware_broadcastradio::aidl::android::hardware::broadcastradio::IBroadcastRadio::BnBroadcastRadio; +use crate::default_broadcastradio_hal::DefaultBroadcastRadioHal; + +fn main() { + binder::ProcessState::start_thread_pool(); + let my_service = DefaultBroadcastRadioHal; + let service_name = "android.hardware.broadcastradio.IBroadcastRadio/amfm"; + let my_service_binder = BnBroadcastRadio::new_binder( + my_service, + binder::BinderFeatures::default(), + ); + binder::add_service(service_name, my_service_binder.as_binder()) + .expect(format!("Failed to register {}?", service_name).as_str()); + // Does not return. + binder::ProcessState::join_thread_pool() +} diff --git a/broadcastradio/aidl/vts/Android.bp b/broadcastradio/aidl/vts/Android.bp index 197ebb57bc..9cfca42310 100644 --- a/broadcastradio/aidl/vts/Android.bp +++ b/broadcastradio/aidl/vts/Android.bp @@ -18,6 +18,7 @@ package { // all of the 'license_kinds' from "hardware_interfaces_license" // to get the below license kinds: // SPDX-license-identifier-Apache-2.0 + default_team: "trendy_team_aaos_framework", default_applicable_licenses: ["hardware_interfaces_license"], } @@ -25,6 +26,7 @@ cc_test { name: "VtsHalBroadcastradioAidlTargetTest", defaults: [ "VtsHalTargetTestDefaults", + "latest_android_hardware_broadcastradio_ndk_static", "use_libaidlvintf_gtest_helper_static", ], tidy_timeout_srcs: ["src/*.cpp"], @@ -35,9 +37,7 @@ cc_test { "libxml2", ], static_libs: [ - "android.hardware.broadcastradio-V2-ndk", - "android.hardware.broadcastradio@common-utils-aidl-lib-V2", - "android.hardware.broadcastradio@vts-utils-lib", + "android.hardware.broadcastradio@common-utils-aidl-lib-latest", "libgmock", ], test_suites: [ diff --git a/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp b/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp index 9633ebb5ae..ee0c63988d 100644 --- a/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp +++ b/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp @@ -193,7 +193,7 @@ class BroadcastRadioHalTest : public testing::TestWithParam { MATCHER_P(InfoHasId, id, std::string(negation ? "does not contain" : "contains") + " " + id.toString()) { - vector ids = bcutils::getAllIds(arg.selector, id.type); + vector ids = bcutils::getAllIds(arg.selector, id.type); return ids.end() != find(ids.begin(), ids.end(), id.value); } @@ -697,7 +697,7 @@ TEST_P(BroadcastRadioHalTest, FmTune) { LOG(DEBUG) << "Current program info: " << infoCb.toString(); // it should tune exactly to what was requested - vector freqs = bcutils::getAllIds(infoCb.selector, IdentifierType::AMFM_FREQUENCY_KHZ); + vector freqs = bcutils::getAllIds(infoCb.selector, IdentifierType::AMFM_FREQUENCY_KHZ); EXPECT_NE(freqs.end(), find(freqs.begin(), freqs.end(), freq)) << "FM freq " << freq << " kHz is not sent back by callback."; } @@ -829,7 +829,7 @@ TEST_P(BroadcastRadioHalTest, DabTune) { LOG(DEBUG) << "Current program info: " << infoCb.toString(); // it should tune exactly to what was requested - vector freqs = bcutils::getAllIds(infoCb.selector, IdentifierType::DAB_FREQUENCY_KHZ); + vector freqs = bcutils::getAllIds(infoCb.selector, IdentifierType::DAB_FREQUENCY_KHZ); EXPECT_NE(freqs.end(), find(freqs.begin(), freqs.end(), freq)) << "DAB freq " << freq << " kHz is not sent back by callback."; } @@ -1152,7 +1152,7 @@ TEST_P(BroadcastRadioHalTest, GetProgramListFromAmFmFilter) { int expectedResultSize = 0; uint64_t expectedFreq = 0; for (const auto& program : *completeList) { - vector amfmIds = + vector amfmIds = bcutils::getAllIds(program.selector, IdentifierType::AMFM_FREQUENCY_KHZ); EXPECT_LE(amfmIds.size(), 1u); if (amfmIds.size() == 0) { @@ -1238,7 +1238,8 @@ TEST_P(BroadcastRadioHalTest, HdRadioStationNameId) { } for (const auto& program : *list) { - vector nameIds = bcutils::getAllIds(program.selector, IdentifierType::HD_STATION_NAME); + vector nameIds = + bcutils::getAllIds(program.selector, IdentifierType::HD_STATION_NAME); EXPECT_LE(nameIds.size(), 1u); if (nameIds.size() == 0) { continue; diff --git a/broadcastradio/common/utilsaidl/Android.bp b/broadcastradio/common/utilsaidl/Android.bp index e3bdfdda22..d88081fae1 100644 --- a/broadcastradio/common/utilsaidl/Android.bp +++ b/broadcastradio/common/utilsaidl/Android.bp @@ -47,17 +47,28 @@ cc_library_static { ], } +cc_library_static { + name: "android.hardware.broadcastradio@common-utils-aidl-lib-latest", + defaults: [ + "BroadcastRadioUtilsDefaults", + "latest_android_hardware_broadcastradio_ndk_static", + ], + srcs: [ + "src/UtilsV2.cpp", + ], +} + cc_test { name: "broadcastradio_utils_aidl_test", defaults: [ "BroadcastRadioUtilsDefaults", + "latest_android_hardware_broadcastradio_ndk_static", ], srcs: [ "test/*.cpp", ], static_libs: [ - "android.hardware.broadcastradio@common-utils-aidl-lib-V2", - "android.hardware.broadcastradio-V2-ndk", + "android.hardware.broadcastradio@common-utils-aidl-lib-latest", ], test_suites: ["general-tests"], } diff --git a/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h b/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h index 25c96d075f..a34ee10507 100644 --- a/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h +++ b/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h @@ -121,7 +121,7 @@ int64_t getId(const ProgramSelector& sel, const IdentifierType& type, int64_t de /** * Returns all IDs of a given type. */ -std::vector getAllIds(const ProgramSelector& sel, const IdentifierType& type); +std::vector getAllIds(const ProgramSelector& sel, const IdentifierType& type); /** * Checks, if a given selector is supported by the radio module. diff --git a/broadcastradio/common/utilsaidl/src/Utils.cpp b/broadcastradio/common/utilsaidl/src/Utils.cpp index ddc5b8db59..3de18660eb 100644 --- a/broadcastradio/common/utilsaidl/src/Utils.cpp +++ b/broadcastradio/common/utilsaidl/src/Utils.cpp @@ -178,8 +178,8 @@ int64_t getId(const ProgramSelector& sel, const IdentifierType& type, int64_t de return getId(sel, type); } -vector getAllIds(const ProgramSelector& sel, const IdentifierType& type) { - vector ret; +vector getAllIds(const ProgramSelector& sel, const IdentifierType& type) { + vector ret; // iterate through primaryId and secondaryIds for (auto it = begin(sel); it != end(sel); it++) { @@ -296,7 +296,12 @@ bool isValid(const ProgramSelector& sel) { sel.primaryId.type > IdentifierType::VENDOR_END)) { return false; } - return isValid(sel.primaryId); + for (auto it = begin(sel); it != end(sel); it++) { + if (!isValid(*it)) { + return false; + } + } + return true; } ProgramIdentifier makeIdentifier(IdentifierType type, int64_t value) { diff --git a/broadcastradio/common/utilsaidl/src/UtilsV2.cpp b/broadcastradio/common/utilsaidl/src/UtilsV2.cpp index 6c75759f07..56365c57fd 100644 --- a/broadcastradio/common/utilsaidl/src/UtilsV2.cpp +++ b/broadcastradio/common/utilsaidl/src/UtilsV2.cpp @@ -102,15 +102,16 @@ bool isValidV2(const ProgramIdentifier& id) { expect(val < 1000u, "SXM channel < 1000"); break; case IdentifierType::HD_STATION_LOCATION: { + val >>= 26; uint64_t latitudeBit = val & 0x1; - expect(latitudeBit == 1u, "Latitude comes first"); - val >>= 27; + expect(latitudeBit == 0u, "Longitude comes first"); + val >>= 1; uint64_t latitudePad = val & 0x1Fu; - expect(latitudePad == 0u, "Latitude padding"); - val >>= 5; + expect(latitudePad == 0u, "Longitude padding"); + val >>= 31; uint64_t longitudeBit = val & 0x1; - expect(longitudeBit == 1u, "Longitude comes next"); - val >>= 27; + expect(longitudeBit == 1u, "Latitude comes next"); + val >>= 1; uint64_t longitudePad = val & 0x1Fu; expect(longitudePad == 0u, "Latitude padding"); break; @@ -135,7 +136,12 @@ bool isValidV2(const ProgramSelector& sel) { sel.primaryId.type > IdentifierType::VENDOR_END)) { return false; } - return isValidV2(sel.primaryId); + for (auto it = begin(sel); it != end(sel); it++) { + if (!isValidV2(*it)) { + return false; + } + } + return true; } bool isValidMetadataV2(const Metadata& metadata) { diff --git a/broadcastradio/common/utilsaidl/test/BroadcastRadioUtilsCommonTest.cpp b/broadcastradio/common/utilsaidl/test/BroadcastRadioUtilsCommonTest.cpp new file mode 100644 index 0000000000..b71bf03d28 --- /dev/null +++ b/broadcastradio/common/utilsaidl/test/BroadcastRadioUtilsCommonTest.cpp @@ -0,0 +1,421 @@ +/* + * Copyright (C) 2024 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 + +namespace aidl::android::hardware::broadcastradio { + +namespace { +constexpr int64_t kFmFrequencyKHz = 97900; +constexpr uint32_t kDabSid = 0x0000C221u; +constexpr int kDabEccCode = 0xE1u; +constexpr int kDabSCIdS = 0x1u; +constexpr uint64_t kDabSidExt = static_cast(kDabSid) | + (static_cast(kDabEccCode) << 32) | + (static_cast(kDabSCIdS) << 40); +constexpr uint32_t kDabEnsemble = 0xCE15u; +constexpr uint64_t kDabFrequencyKhz = 225648u; +constexpr uint64_t kHdStationId = 0xA0000001u; +constexpr uint64_t kHdSubChannel = 1u; +constexpr uint64_t kHdStationLocation = 0x44E647003665CF6u; +constexpr uint64_t kHdStationLocationInvalid = 0x4E647007665CF6u; +constexpr uint64_t kHdFrequency = 97700u; +constexpr int64_t kRdsValue = 0xBEEF; + +struct IsValidIdentifierTestCase { + std::string name; + ProgramIdentifier id; + bool valid; +}; + +std::vector getIsValidIdentifierTestCases() { + return std::vector({ + IsValidIdentifierTestCase{.name = "invalid_id_type", + .id = utils::makeIdentifier(IdentifierType::INVALID, 0), + .valid = false}, + IsValidIdentifierTestCase{ + .name = "invalid_dab_frequency_high", + .id = utils::makeIdentifier(IdentifierType::DAB_FREQUENCY_KHZ, 10000000u), + .valid = false}, + IsValidIdentifierTestCase{ + .name = "invalid_dab_frequency_low", + .id = utils::makeIdentifier(IdentifierType::DAB_FREQUENCY_KHZ, 100000u), + .valid = false}, + IsValidIdentifierTestCase{ + .name = "valid_dab_frequency", + .id = utils::makeIdentifier(IdentifierType::DAB_FREQUENCY_KHZ, 1000000u), + .valid = true}, + IsValidIdentifierTestCase{ + .name = "invalid_am_fm_frequency_high", + .id = utils::makeIdentifier(IdentifierType::AMFM_FREQUENCY_KHZ, 10000000u), + .valid = false}, + IsValidIdentifierTestCase{ + .name = "invalid_am_fm_frequency_low", + .id = utils::makeIdentifier(IdentifierType::AMFM_FREQUENCY_KHZ, 100u), + .valid = false}, + IsValidIdentifierTestCase{.name = "valid_am_fm_frequency", + .id = utils::makeIdentifier( + IdentifierType::AMFM_FREQUENCY_KHZ, kFmFrequencyKHz), + .valid = true}, + IsValidIdentifierTestCase{ + .name = "drmo_frequency_high", + .id = utils::makeIdentifier(IdentifierType::DRMO_FREQUENCY_KHZ, 10000000u), + .valid = false}, + IsValidIdentifierTestCase{ + .name = "drmo_frequency_low", + .id = utils::makeIdentifier(IdentifierType::DRMO_FREQUENCY_KHZ, 100u), + .valid = false}, + IsValidIdentifierTestCase{.name = "valid_drmo_frequency", + .id = utils::makeIdentifier( + IdentifierType::DRMO_FREQUENCY_KHZ, kFmFrequencyKHz), + .valid = true}, + IsValidIdentifierTestCase{.name = "invalid_rds_low", + .id = utils::makeIdentifier(IdentifierType::RDS_PI, 0x0), + .valid = false}, + IsValidIdentifierTestCase{.name = "invalid_rds_high", + .id = utils::makeIdentifier(IdentifierType::RDS_PI, 0x10000), + .valid = false}, + IsValidIdentifierTestCase{.name = "valid_rds", + .id = utils::makeIdentifier(IdentifierType::RDS_PI, 0x1000), + .valid = true}, + IsValidIdentifierTestCase{ + .name = "invalid_hd_id_zero", + .id = utils::makeSelectorHd(/* stationId= */ 0u, kHdSubChannel, kHdFrequency) + .primaryId, + .valid = false}, + IsValidIdentifierTestCase{ + .name = "invalid_hd_suchannel", + .id = utils::makeSelectorHd(kHdStationId, /* subChannel= */ 8u, kHdFrequency) + .primaryId, + .valid = false}, + IsValidIdentifierTestCase{ + .name = "invalid_hd_frequency_low", + .id = utils::makeSelectorHd(kHdStationId, kHdSubChannel, /* frequency= */ 100u) + .primaryId, + .valid = false}, + IsValidIdentifierTestCase{ + .name = "valid_hd_id", + .id = utils::makeSelectorHd(kHdStationId, kHdSubChannel, kHdFrequency) + .primaryId, + .valid = true}, + IsValidIdentifierTestCase{ + .name = "invalid_hd_station_name", + .id = utils::makeIdentifier(IdentifierType::HD_STATION_NAME, 0x41422D464D), + .valid = false}, + IsValidIdentifierTestCase{ + .name = "valid_hd_station_name", + .id = utils::makeIdentifier(IdentifierType::HD_STATION_NAME, 0x414231464D), + .valid = true}, + IsValidIdentifierTestCase{ + .name = "invalid_dab_sid", + .id = utils::makeIdentifier(IdentifierType::DAB_SID_EXT, 0x0E100000000u), + .valid = false}, + IsValidIdentifierTestCase{ + .name = "invalid_dab_ecc_low", + .id = utils::makeIdentifier(IdentifierType::DAB_SID_EXT, 0x0F700000221u), + .valid = false}, + IsValidIdentifierTestCase{ + .name = "invalid_dab_ecc_high", + .id = utils::makeIdentifier(IdentifierType::DAB_SID_EXT, 0x09900000221u), + .valid = false}, + IsValidIdentifierTestCase{ + .name = "valid_dab_sid_ext", + .id = utils::makeIdentifier(IdentifierType::DAB_SID_EXT, kDabSidExt), + .valid = true}, + IsValidIdentifierTestCase{ + .name = "invalid_dab_ensemble_zero", + .id = utils::makeIdentifier(IdentifierType::DAB_ENSEMBLE, 0x0), + .valid = false}, + IsValidIdentifierTestCase{ + .name = "invalid_dab_ensemble_high", + .id = utils::makeIdentifier(IdentifierType::DAB_ENSEMBLE, 0x10000), + .valid = false}, + IsValidIdentifierTestCase{ + .name = "valid_dab_ensemble", + .id = utils::makeIdentifier(IdentifierType::DAB_ENSEMBLE, kDabEnsemble), + .valid = true}, + IsValidIdentifierTestCase{.name = "invalid_dab_scid_low", + .id = utils::makeIdentifier(IdentifierType::DAB_SCID, 0xF), + .valid = false}, + IsValidIdentifierTestCase{.name = "invalid_dab_scid_high", + .id = utils::makeIdentifier(IdentifierType::DAB_SCID, 0x1000), + .valid = false}, + IsValidIdentifierTestCase{.name = "valid_dab_scid", + .id = utils::makeIdentifier(IdentifierType::DAB_SCID, 0x100), + .valid = true}, + IsValidIdentifierTestCase{ + .name = "invalid_drmo_id_zero", + .id = utils::makeIdentifier(IdentifierType::DRMO_SERVICE_ID, 0x0), + .valid = false}, + IsValidIdentifierTestCase{ + .name = "invalid_drmo_id_high", + .id = utils::makeIdentifier(IdentifierType::DRMO_SERVICE_ID, 0x1000000), + .valid = false}, + IsValidIdentifierTestCase{ + .name = "valid_drmo_id", + .id = utils::makeIdentifier(IdentifierType::DRMO_SERVICE_ID, 0x100000), + .valid = true}, + }); +} + +std::vector getIsValidIdentifierV2TestCases() { + std::vector testcases = getIsValidIdentifierTestCases(); + std::vector testcasesNew = std::vector({ + IsValidIdentifierTestCase{ + .name = "invalid_hd_station_location_id", + .id = utils::makeIdentifier(IdentifierType::HD_STATION_LOCATION, + kHdStationLocationInvalid), + .valid = false}, + IsValidIdentifierTestCase{ + .name = "valid_hd_station_location_id", + .id = utils::makeIdentifier(IdentifierType::HD_STATION_LOCATION, + kHdStationLocation), + .valid = true}, + }); + testcases.insert(testcases.end(), testcasesNew.begin(), testcasesNew.end()); + return testcases; +} + +struct IsValidSelectorTestCase { + std::string name; + ProgramSelector sel; + bool valid; +}; + +std::vector getIsValidSelectorTestCases() { + return std::vector({ + IsValidSelectorTestCase{.name = "valid_am_fm_selector", + .sel = utils::makeSelectorAmfm(kFmFrequencyKHz), + .valid = true}, + IsValidSelectorTestCase{ + .name = "valid_hd_selector", + .sel = utils::makeSelectorHd(kHdStationId, kHdSubChannel, kHdFrequency), + .valid = true}, + IsValidSelectorTestCase{ + .name = "valid_dab_selector", + .sel = utils::makeSelectorDab(kDabSidExt, kDabEnsemble, kDabFrequencyKhz), + .valid = true}, + IsValidSelectorTestCase{.name = "valid_rds_selector", + .sel = ProgramSelector{.primaryId = utils::makeIdentifier( + IdentifierType::RDS_PI, 0x1000)}, + .valid = true}, + IsValidSelectorTestCase{.name = "selector_with_invalid_id", + .sel = utils::makeSelectorHd(kHdStationId, kHdSubChannel, + /* frequency= */ 100u), + .valid = false}, + IsValidSelectorTestCase{ + .name = "selector_with_invalid_primary_id_type", + .sel = ProgramSelector{.primaryId = utils::makeIdentifier( + IdentifierType::DAB_ENSEMBLE, kDabEnsemble)}, + .valid = false}, + IsValidSelectorTestCase{ + .name = "selector_with_invalid_secondary_id", + .sel = ProgramSelector{.primaryId = utils::makeIdentifier( + IdentifierType::DAB_SID_EXT, kDabSidExt), + .secondaryIds = {utils::makeIdentifier( + IdentifierType::DAB_ENSEMBLE, 0x0)}}, + .valid = false}, + }); +} + +std::vector getIsValidSelectorV2TestCases() { + ProgramSelector validHdSel = utils::makeSelectorHd(kHdStationId, kHdSubChannel, kHdFrequency); + validHdSel.secondaryIds = { + utils::makeIdentifier(IdentifierType::HD_STATION_LOCATION, kHdStationLocation)}; + ProgramSelector invalidHdSel = utils::makeSelectorHd(kHdStationId, kHdSubChannel, kHdFrequency); + invalidHdSel.secondaryIds = { + utils::makeIdentifier(IdentifierType::HD_STATION_LOCATION, kHdStationLocationInvalid)}; + std::vector testcasesNew = std::vector( + {IsValidSelectorTestCase{.name = "hd_selector_with_valid_station_location", + .sel = validHdSel, + .valid = true}, + IsValidSelectorTestCase{.name = "hd_selector_with_invalid_station_location", + .sel = invalidHdSel, + .valid = false}}); + std::vector testcases = getIsValidSelectorTestCases(); + testcases.insert(testcases.end(), testcasesNew.begin(), testcasesNew.end()); + return testcases; +} + +struct IsValidMetadataTestCase { + std::string name; + Metadata metadata; + bool valid; +}; + +std::vector getIsValidMetadataTestCases() { + return std::vector({ + IsValidMetadataTestCase{.name = "valid_rds_pty", + .metadata = Metadata::make(1), + .valid = true}, + IsValidMetadataTestCase{.name = "negative_rds_pty", + .metadata = Metadata::make(-1), + .valid = false}, + IsValidMetadataTestCase{.name = "large_rds_pty", + .metadata = Metadata::make(256), + .valid = false}, + IsValidMetadataTestCase{.name = "valid_rbds_pty", + .metadata = Metadata::make(1), + .valid = true}, + IsValidMetadataTestCase{.name = "negative_rbds_pty", + .metadata = Metadata::make(-1), + .valid = false}, + IsValidMetadataTestCase{.name = "large_rbds_pty", + .metadata = Metadata::make(256), + .valid = false}, + IsValidMetadataTestCase{ + .name = "valid_dab_ensemble_name_short", + .metadata = Metadata::make("name"), + .valid = true}, + IsValidMetadataTestCase{ + .name = "too_long_dab_ensemble_name_short", + .metadata = Metadata::make("name_long"), + .valid = false}, + IsValidMetadataTestCase{ + .name = "valid_dab_service_name_short", + .metadata = Metadata::make("name"), + .valid = true}, + IsValidMetadataTestCase{ + .name = "too_long_dab_service_name_short", + .metadata = Metadata::make("name_long"), + .valid = false}, + IsValidMetadataTestCase{ + .name = "valid_dab_component_name_short", + .metadata = Metadata::make("name"), + .valid = true}, + IsValidMetadataTestCase{ + .name = "too_long_dab_component_name_short", + .metadata = Metadata::make("name_long"), + .valid = false}, + }); +} + +std::vector getIsValidMetadataV2TestCases() { + std::vector testcases = getIsValidMetadataTestCases(); + std::vector testcasesNew = std::vector({ + IsValidMetadataTestCase{ + .name = "valid_hd_station_name_short", + .metadata = Metadata::make("name_short"), + .valid = true}, + IsValidMetadataTestCase{ + .name = "too_long_hd_station_name_short", + .metadata = Metadata::make("name_too_long"), + .valid = false}, + IsValidMetadataTestCase{.name = "valid_hd_subchannel_available", + .metadata = Metadata::make(1), + .valid = true}, + IsValidMetadataTestCase{ + .name = "negative_subchannel_available", + .metadata = Metadata::make(-1), + .valid = false}, + IsValidMetadataTestCase{ + .name = "large_subchannel_available", + .metadata = Metadata::make(256), + .valid = false}, + }); + testcases.insert(testcases.end(), testcasesNew.begin(), testcasesNew.end()); + return testcases; +} +} // namespace + +class IsValidIdentifierTest : public testing::TestWithParam {}; + +INSTANTIATE_TEST_SUITE_P(IsValidIdentifierTests, IsValidIdentifierTest, + testing::ValuesIn(getIsValidIdentifierTestCases()), + [](const testing::TestParamInfo& info) { + return info.param.name; + }); + +TEST_P(IsValidIdentifierTest, IsValid) { + IsValidIdentifierTestCase testcase = GetParam(); + + ASSERT_EQ(utils::isValid(testcase.id), testcase.valid); +} + +class IsValidIdentifierV2Test : public testing::TestWithParam {}; + +INSTANTIATE_TEST_SUITE_P( + IsValidIdentifierV2Tests, IsValidIdentifierV2Test, + testing::ValuesIn(getIsValidIdentifierV2TestCases()), + [](const testing::TestParamInfo& info) { + return info.param.name; + }); + +TEST_P(IsValidIdentifierV2Test, IsValidV2) { + IsValidIdentifierTestCase testcase = GetParam(); + + ASSERT_EQ(utils::isValidV2(testcase.id), testcase.valid); +} + +class IsValidSelectorTest : public testing::TestWithParam {}; + +INSTANTIATE_TEST_SUITE_P(IsValidSelectorTests, IsValidSelectorTest, + testing::ValuesIn(getIsValidSelectorTestCases()), + [](const testing::TestParamInfo& info) { + return info.param.name; + }); + +TEST_P(IsValidSelectorTest, IsValid) { + IsValidSelectorTestCase testcase = GetParam(); + + ASSERT_EQ(utils::isValid(testcase.sel), testcase.valid); +} + +class IsValidSelectorV2Test : public testing::TestWithParam {}; + +INSTANTIATE_TEST_SUITE_P(IsValidSelectorV2Tests, IsValidSelectorV2Test, + testing::ValuesIn(getIsValidSelectorV2TestCases()), + [](const testing::TestParamInfo& info) { + return info.param.name; + }); + +TEST_P(IsValidSelectorV2Test, IsValidV2) { + IsValidSelectorTestCase testcase = GetParam(); + + ASSERT_EQ(utils::isValidV2(testcase.sel), testcase.valid); +} + +class IsValidMetadataTest : public testing::TestWithParam {}; + +INSTANTIATE_TEST_SUITE_P(IsValidMetadataTests, IsValidMetadataTest, + testing::ValuesIn(getIsValidMetadataTestCases()), + [](const testing::TestParamInfo& info) { + return info.param.name; + }); + +TEST_P(IsValidMetadataTest, IsValidMetadata) { + IsValidMetadataTestCase testParam = GetParam(); + + ASSERT_EQ(utils::isValidMetadata(testParam.metadata), testParam.valid); +} + +class IsValidMetadataV2Test : public testing::TestWithParam {}; + +INSTANTIATE_TEST_SUITE_P(IsValidMetadataV2Tests, IsValidMetadataV2Test, + testing::ValuesIn(getIsValidMetadataV2TestCases()), + [](const testing::TestParamInfo& info) { + return info.param.name; + }); + +TEST_P(IsValidMetadataV2Test, IsValidMetadataV2) { + IsValidMetadataTestCase testParam = GetParam(); + + ASSERT_EQ(utils::isValidMetadataV2(testParam.metadata), testParam.valid); +} + +} // namespace aidl::android::hardware::broadcastradio diff --git a/broadcastradio/common/utilsaidl/test/BroadcastRadioUtilsTest.cpp b/broadcastradio/common/utilsaidl/test/BroadcastRadioUtilsTest.cpp index a5c9073133..81f94706a8 100644 --- a/broadcastradio/common/utilsaidl/test/BroadcastRadioUtilsTest.cpp +++ b/broadcastradio/common/utilsaidl/test/BroadcastRadioUtilsTest.cpp @@ -66,230 +66,6 @@ std::vector getBandTestCases() { .frequency = 110000, .bandResult = utils::FrequencyBand::UNKNOWN}}); } - -struct IsValidIdentifierTestCase { - std::string name; - ProgramIdentifier id; - bool valid; -}; - -std::vector getIsValidIdentifierTestCases() { - return std::vector({ - IsValidIdentifierTestCase{.name = "invalid_id_type", - .id = utils::makeIdentifier(IdentifierType::INVALID, 0), - .valid = false}, - IsValidIdentifierTestCase{ - .name = "invalid_dab_frequency_high", - .id = utils::makeIdentifier(IdentifierType::DAB_FREQUENCY_KHZ, 10000000u), - .valid = false}, - IsValidIdentifierTestCase{ - .name = "invalid_dab_frequency_low", - .id = utils::makeIdentifier(IdentifierType::DAB_FREQUENCY_KHZ, 100000u), - .valid = false}, - IsValidIdentifierTestCase{ - .name = "valid_dab_frequency", - .id = utils::makeIdentifier(IdentifierType::DAB_FREQUENCY_KHZ, 1000000u), - .valid = true}, - IsValidIdentifierTestCase{ - .name = "invalid_am_fm_frequency_high", - .id = utils::makeIdentifier(IdentifierType::AMFM_FREQUENCY_KHZ, 10000000u), - .valid = false}, - IsValidIdentifierTestCase{ - .name = "invalid_am_fm_frequency_low", - .id = utils::makeIdentifier(IdentifierType::AMFM_FREQUENCY_KHZ, 100u), - .valid = false}, - IsValidIdentifierTestCase{.name = "valid_am_fm_frequency", - .id = utils::makeIdentifier( - IdentifierType::AMFM_FREQUENCY_KHZ, kFmFrequencyKHz), - .valid = true}, - IsValidIdentifierTestCase{ - .name = "drmo_frequency_high", - .id = utils::makeIdentifier(IdentifierType::DRMO_FREQUENCY_KHZ, 10000000u), - .valid = false}, - IsValidIdentifierTestCase{ - .name = "drmo_frequency_low", - .id = utils::makeIdentifier(IdentifierType::DRMO_FREQUENCY_KHZ, 100u), - .valid = false}, - IsValidIdentifierTestCase{.name = "valid_drmo_frequency", - .id = utils::makeIdentifier( - IdentifierType::DRMO_FREQUENCY_KHZ, kFmFrequencyKHz), - .valid = true}, - IsValidIdentifierTestCase{.name = "invalid_rds_low", - .id = utils::makeIdentifier(IdentifierType::RDS_PI, 0x0), - .valid = false}, - IsValidIdentifierTestCase{.name = "invalid_rds_high", - .id = utils::makeIdentifier(IdentifierType::RDS_PI, 0x10000), - .valid = false}, - IsValidIdentifierTestCase{.name = "valid_rds", - .id = utils::makeIdentifier(IdentifierType::RDS_PI, 0x1000), - .valid = true}, - IsValidIdentifierTestCase{ - .name = "invalid_hd_id_zero", - .id = utils::makeSelectorHd(/* stationId= */ 0u, kHdSubChannel, kHdFrequency) - .primaryId, - .valid = false}, - IsValidIdentifierTestCase{ - .name = "invalid_hd_suchannel", - .id = utils::makeSelectorHd(kHdStationId, /* subChannel= */ 8u, kHdFrequency) - .primaryId, - .valid = false}, - IsValidIdentifierTestCase{ - .name = "invalid_hd_frequency_low", - .id = utils::makeSelectorHd(kHdStationId, kHdSubChannel, /* frequency= */ 100u) - .primaryId, - .valid = false}, - IsValidIdentifierTestCase{ - .name = "valid_hd_id", - .id = utils::makeSelectorHd(kHdStationId, kHdSubChannel, kHdFrequency) - .primaryId, - .valid = true}, - IsValidIdentifierTestCase{ - .name = "invalid_hd_station_name", - .id = utils::makeIdentifier(IdentifierType::HD_STATION_NAME, 0x41422D464D), - .valid = false}, - IsValidIdentifierTestCase{ - .name = "valid_hd_station_name", - .id = utils::makeIdentifier(IdentifierType::HD_STATION_NAME, 0x414231464D), - .valid = true}, - IsValidIdentifierTestCase{ - .name = "invalid_dab_sid", - .id = utils::makeIdentifier(IdentifierType::DAB_SID_EXT, 0x0E100000000u), - .valid = false}, - IsValidIdentifierTestCase{ - .name = "invalid_dab_ecc_low", - .id = utils::makeIdentifier(IdentifierType::DAB_SID_EXT, 0x0F700000221u), - .valid = false}, - IsValidIdentifierTestCase{ - .name = "invalid_dab_ecc_high", - .id = utils::makeIdentifier(IdentifierType::DAB_SID_EXT, 0x09900000221u), - .valid = false}, - IsValidIdentifierTestCase{ - .name = "valid_dab_sid_ext", - .id = utils::makeIdentifier(IdentifierType::DAB_SID_EXT, kDabSidExt), - .valid = true}, - IsValidIdentifierTestCase{ - .name = "invalid_dab_ensemble_zero", - .id = utils::makeIdentifier(IdentifierType::DAB_ENSEMBLE, 0x0), - .valid = false}, - IsValidIdentifierTestCase{ - .name = "invalid_dab_ensemble_high", - .id = utils::makeIdentifier(IdentifierType::DAB_ENSEMBLE, 0x10000), - .valid = false}, - IsValidIdentifierTestCase{ - .name = "valid_dab_ensemble", - .id = utils::makeIdentifier(IdentifierType::DAB_ENSEMBLE, kDabEnsemble), - .valid = true}, - IsValidIdentifierTestCase{.name = "invalid_dab_scid_low", - .id = utils::makeIdentifier(IdentifierType::DAB_SCID, 0xF), - .valid = false}, - IsValidIdentifierTestCase{.name = "invalid_dab_scid_high", - .id = utils::makeIdentifier(IdentifierType::DAB_SCID, 0x1000), - .valid = false}, - IsValidIdentifierTestCase{.name = "valid_dab_scid", - .id = utils::makeIdentifier(IdentifierType::DAB_SCID, 0x100), - .valid = true}, - IsValidIdentifierTestCase{ - .name = "invalid_drmo_id_zero", - .id = utils::makeIdentifier(IdentifierType::DRMO_SERVICE_ID, 0x0), - .valid = false}, - IsValidIdentifierTestCase{ - .name = "invalid_drmo_id_high", - .id = utils::makeIdentifier(IdentifierType::DRMO_SERVICE_ID, 0x1000000), - .valid = false}, - IsValidIdentifierTestCase{ - .name = "valid_drmo_id", - .id = utils::makeIdentifier(IdentifierType::DRMO_SERVICE_ID, 0x100000), - .valid = true}, - }); -} - -struct IsValidSelectorTestCase { - std::string name; - ProgramSelector sel; - bool valid; -}; - -std::vector getIsValidSelectorTestCases() { - return std::vector({ - IsValidSelectorTestCase{.name = "valid_am_fm_selector", - .sel = utils::makeSelectorAmfm(kFmFrequencyKHz), - .valid = true}, - IsValidSelectorTestCase{ - .name = "valid_hd_selector", - .sel = utils::makeSelectorHd(kHdStationId, kHdSubChannel, kHdFrequency), - .valid = true}, - IsValidSelectorTestCase{ - .name = "valid_dab_selector", - .sel = utils::makeSelectorDab(kDabSidExt, kDabEnsemble, kDabFrequencyKhz), - .valid = true}, - IsValidSelectorTestCase{.name = "valid_rds_selector", - .sel = ProgramSelector{.primaryId = utils::makeIdentifier( - IdentifierType::RDS_PI, 0x1000)}, - .valid = true}, - IsValidSelectorTestCase{.name = "selector_with_invalid_id", - .sel = utils::makeSelectorHd(kHdStationId, kHdSubChannel, - /* frequency= */ 100u), - .valid = false}, - IsValidSelectorTestCase{ - .name = "selector_with_invalid_primary_id_type", - .sel = ProgramSelector{.primaryId = utils::makeIdentifier( - IdentifierType::DAB_ENSEMBLE, kDabEnsemble)}, - .valid = false}, - }); -} - -struct IsValidMetadataTestCase { - std::string name; - Metadata metadata; - bool valid; -}; - -std::vector getIsValidMetadataTestCases() { - return std::vector({ - IsValidMetadataTestCase{.name = "valid_rds_pty", - .metadata = Metadata::make(1), - .valid = true}, - IsValidMetadataTestCase{.name = "negative_rds_pty", - .metadata = Metadata::make(-1), - .valid = false}, - IsValidMetadataTestCase{.name = "large_rds_pty", - .metadata = Metadata::make(256), - .valid = false}, - IsValidMetadataTestCase{.name = "valid_rbds_pty", - .metadata = Metadata::make(1), - .valid = true}, - IsValidMetadataTestCase{.name = "negative_rbds_pty", - .metadata = Metadata::make(-1), - .valid = false}, - IsValidMetadataTestCase{.name = "large_rbds_pty", - .metadata = Metadata::make(256), - .valid = false}, - IsValidMetadataTestCase{ - .name = "valid_dab_ensemble_name_short", - .metadata = Metadata::make("name"), - .valid = true}, - IsValidMetadataTestCase{ - .name = "too_long_dab_ensemble_name_short", - .metadata = Metadata::make("name_long"), - .valid = false}, - IsValidMetadataTestCase{ - .name = "valid_dab_service_name_short", - .metadata = Metadata::make("name"), - .valid = true}, - IsValidMetadataTestCase{ - .name = "too_long_dab_service_name_short", - .metadata = Metadata::make("name_long"), - .valid = false}, - IsValidMetadataTestCase{ - .name = "valid_dab_component_name_short", - .metadata = Metadata::make("name"), - .valid = true}, - IsValidMetadataTestCase{ - .name = "too_long_dab_component_name_short", - .metadata = Metadata::make("name_long"), - .valid = false}, - }); -} } // namespace class GetBandTest : public testing::TestWithParam {}; @@ -305,48 +81,6 @@ TEST_P(GetBandTest, GetBand) { ASSERT_EQ(utils::getBand(testcase.frequency), testcase.bandResult); } -class IsValidMetadataTest : public testing::TestWithParam {}; - -INSTANTIATE_TEST_SUITE_P(IsValidMetadataTests, IsValidMetadataTest, - testing::ValuesIn(getIsValidMetadataTestCases()), - [](const testing::TestParamInfo& info) { - return info.param.name; - }); - -TEST_P(IsValidMetadataTest, IsValidMetadata) { - IsValidMetadataTestCase testParam = GetParam(); - - ASSERT_EQ(utils::isValidMetadata(testParam.metadata), testParam.valid); -} - -class IsValidIdentifierTest : public testing::TestWithParam {}; - -INSTANTIATE_TEST_SUITE_P(IsValidIdentifierTests, IsValidIdentifierTest, - testing::ValuesIn(getIsValidIdentifierTestCases()), - [](const testing::TestParamInfo& info) { - return info.param.name; - }); - -TEST_P(IsValidIdentifierTest, IsValid) { - IsValidIdentifierTestCase testcase = GetParam(); - - ASSERT_EQ(utils::isValid(testcase.id), testcase.valid); -} - -class IsValidSelectorTest : public testing::TestWithParam {}; - -INSTANTIATE_TEST_SUITE_P(IsValidSelectorTests, IsValidSelectorTest, - testing::ValuesIn(getIsValidSelectorTestCases()), - [](const testing::TestParamInfo& info) { - return info.param.name; - }); - -TEST_P(IsValidSelectorTest, IsValid) { - IsValidSelectorTestCase testcase = GetParam(); - - ASSERT_EQ(utils::isValid(testcase.sel), testcase.valid); -} - TEST(BroadcastRadioUtilsTest, IdentifierIteratorBegin) { ProgramSelector sel = { .primaryId = utils::makeIdentifier(IdentifierType::RDS_PI, kRdsValue), @@ -503,13 +237,22 @@ TEST(BroadcastRadioUtilsTest, GetAllIdsWithAvailableIds) { sel.secondaryIds.push_back( utils::makeIdentifier(IdentifierType::AMFM_FREQUENCY_KHZ, secondaryFrequencyKHz)); - std::vector allIds = utils::getAllIds(sel, IdentifierType::AMFM_FREQUENCY_KHZ); + std::vector allIds = utils::getAllIds(sel, IdentifierType::AMFM_FREQUENCY_KHZ); ASSERT_EQ(allIds.size(), 2u); EXPECT_NE(std::find(allIds.begin(), allIds.end(), kFmFrequencyKHz), allIds.end()); EXPECT_NE(std::find(allIds.begin(), allIds.end(), secondaryFrequencyKHz), allIds.end()); } +TEST(BroadcastRadioUtilsTest, GetAllIdsWithIdLongerThan32Bit) { + ProgramSelector sel = utils::makeSelectorDab(kDabSidExt, kDabEnsemble, kDabFrequencyKhz); + + std::vector allIds = utils::getAllIds(sel, IdentifierType::DAB_SID_EXT); + + ASSERT_EQ(allIds.size(), 1u); + EXPECT_NE(std::find(allIds.begin(), allIds.end(), kDabSidExt), allIds.end()); +} + TEST(BroadcastRadioUtilsTest, GetAllIdsWithIdNotFound) { ProgramSelector sel = utils::makeSelectorDab(kDabSidExt, kDabEnsemble, kDabFrequencyKhz); diff --git a/broadcastradio/common/utilsaidl/test/BroadcastRadioUtilsV2Test.cpp b/broadcastradio/common/utilsaidl/test/BroadcastRadioUtilsV2Test.cpp deleted file mode 100644 index cf9f9e965b..0000000000 --- a/broadcastradio/common/utilsaidl/test/BroadcastRadioUtilsV2Test.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2024 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 - -namespace aidl::android::hardware::broadcastradio { - -namespace { -struct IsValidMetadataV2TestCase { - std::string name; - Metadata metadata; - bool valid; -}; - -std::vector getIsValidMetadataV2TestCases() { - return std::vector({ - IsValidMetadataV2TestCase{.name = "valid_rds_pty", - .metadata = Metadata::make(1), - .valid = true}, - IsValidMetadataV2TestCase{.name = "negative_rds_pty", - .metadata = Metadata::make(-1), - .valid = false}, - IsValidMetadataV2TestCase{ - .name = "valid_hd_station_name_short", - .metadata = Metadata::make("name_short"), - .valid = true}, - IsValidMetadataV2TestCase{ - .name = "too_long_hd_station_name_short", - .metadata = Metadata::make("name_too_long"), - .valid = false}, - IsValidMetadataV2TestCase{ - .name = "valid_hd_subchannel_available", - .metadata = Metadata::make(1), - .valid = true}, - IsValidMetadataV2TestCase{ - .name = "negative_subchannel_available", - .metadata = Metadata::make(-1), - .valid = false}, - IsValidMetadataV2TestCase{ - .name = "large_subchannel_available", - .metadata = Metadata::make(256), - .valid = false}, - }); -} -} // namespace - -class IsValidMetadataV2Test : public testing::TestWithParam {}; - -INSTANTIATE_TEST_SUITE_P(IsValidMetadataV2Tests, IsValidMetadataV2Test, - testing::ValuesIn(getIsValidMetadataV2TestCases()), - [](const testing::TestParamInfo& info) { - return info.param.name; - }); - -TEST_P(IsValidMetadataV2Test, IsValidMetadataV2) { - IsValidMetadataV2TestCase testParam = GetParam(); - - ASSERT_EQ(utils::isValidMetadataV2(testParam.metadata), testParam.valid); -} - -} // namespace aidl::android::hardware::broadcastradio diff --git a/camera/device/3.4/default/ExternalCameraUtils.cpp b/camera/device/3.4/default/ExternalCameraUtils.cpp index 8f4626c56d..d9610c2d28 100644 --- a/camera/device/3.4/default/ExternalCameraUtils.cpp +++ b/camera/device/3.4/default/ExternalCameraUtils.cpp @@ -108,9 +108,38 @@ int AllocatedFrame::allocate(YCbCrLayout* out) { return -EINVAL; } - uint32_t dataSize = mWidth * mHeight * 3 / 2; // YUV420 - if (mData.size() != dataSize) { - mData.resize(dataSize); + // This frame might be sent to jpeglib to be encoded. Since AllocatedFrame only contains YUV420, + // jpeglib expects height and width of Y component to be an integral multiple of 2*DCTSIZE, + // and heights and widths of Cb and Cr components to be an integral multiple of DCTSIZE. If the + // image size does not meet this requirement, libjpeg expects its input to be padded to meet the + // constraints. This padding is removed from the final encoded image so the content in the + // padding doesn't matter. What matters is that the memory is accessible to jpeglib at the time + // of encoding. + // For example, if the image size is 1500x844 and DCTSIZE is 8, jpeglib expects a YUV 420 + // frame with components of following sizes: + // Y: 1504x848 because 1504 and 848 are the next smallest multiples of 2*8 + // Cb/Cr: 752x424 which are the next smallest multiples of 8 + + // jpeglib takes an array of row pointers which makes vertical padding trivial when setting up + // the pointers. Padding horizontally is a bit more complicated. AllocatedFrame holds the data + // in a flattened buffer, which means memory accesses past a row will flow into the next logical + // row. For any row of a component, we can consider the first few bytes of the next row as + // padding for the current one. This is true for Y and Cb components and all but last row of the + // Cr component. Reading past the last row of Cr component will lead to undefined behavior as + // libjpeg attempts to read memory past the allocated buffer. To prevent undefined behavior, + // the buffer allocated here is padded such that libjpeg never accesses unallocated memory when + // reading the last row. Effectively, we only need to ensure that the last row of Cr component + // has width that is an integral multiple of DCTSIZE. + + size_t dataSize = mWidth * mHeight * 3 / 2; // YUV420 + + size_t cbWidth = mWidth / 2; + size_t requiredCbWidth = DCTSIZE * ((cbWidth + DCTSIZE - 1) / DCTSIZE); + size_t padding = requiredCbWidth - cbWidth; + size_t finalSize = dataSize + padding; + + if (mData.size() != finalSize) { + mData.resize(finalSize); } if (out != nullptr) { diff --git a/camera/device/aidl/android/hardware/camera/device/ICameraDevice.aidl b/camera/device/aidl/android/hardware/camera/device/ICameraDevice.aidl index 440c2b3728..5da515bb61 100644 --- a/camera/device/aidl/android/hardware/camera/device/ICameraDevice.aidl +++ b/camera/device/aidl/android/hardware/camera/device/ICameraDevice.aidl @@ -372,66 +372,13 @@ interface ICameraDevice { * the particular StreamConfiguration is supported, the camera HAL must take all * the keys in sessionParameters into consideration. * - * 2. For version 3 of this interface, the camera compliance test will verify that + * 2. For version 3 of this interface, the camera compliance tests will verify that * isStreamCombinationWithSettingsSupported behaves properly for all combinations of - * below features. This function must return true for all supported combinations, - * and return false for non-supported feature combinations. The list of features - * required may grow in future versions. The additional metadata entries in - * StreamConfiguration::sessionParameters are {CONTROL_AE_TARGET_FPS_RANGE, - * CONTROL_VIDEO_STABILIZATION_MODE}. - * - * - Stream Combinations (a subset of LEGACY device mandatory stream combinations): - * { - * // 4:3 16:9 - * // S1440P: 1920 x 1440 2560 x 1440 - * // S1080P: 1440 x 1080 1920 x 1080 - * // S720P: 960 x 720 1280 x 720 - * - * // Simple preview, GPU video processing, or no-preview video recording - * {PRIV, MAXIMUM}, - * {PRIV, PREVIEW}, - * {PRIV, S1440P}, - * {PRIV, S1080P}, - * {PRIV, S720P}, - * // In-application video/image processing - * {YUV, MAXIMUM}, - * {YUV, PREVIEW}, - * {YUV, S1440P}, - * {YUV, S1080P}, - * {YUV, S720P}, - * // Standard still imaging. - * {PRIV, PREVIEW, JPEG, MAXIMUM}, - * {PRIV, S1440P, JPEG, MAXIMUM}, - * {PRIV, S1080P, JPEG, MAXIMUM}, - * {PRIV, S720P, JPEG, MAXIMUM}, - * {PRIV, S1440P, JPEG, S1440P}, - * {PRIV, S1080P, JPEG, S1080P}, - * {PRIV, S720P, JPEG, S1080P}, - * // In-app processing plus still capture. - * {YUV, PREVIEW, JPEG, MAXIMUM}, - * {YUV, S1440P, JPEG, MAXIMUM}, - * {YUV, S1080P, JPEG, MAXIMUM}, - * {YUV, S720P, JPEG, MAXIMUM}, - * // Standard recording. - * {PRIV, PREVIEW, PRIV, PREVIEW}, - * {PRIV, S1440P, PRIV, S1440P}, - * {PRIV, S1080P, PRIV, S1080P}, - * {PRIV, S720P, PRIV, S720P}, - * // Preview plus in-app processing. - * {PRIV, PREVIEW, YUV, PREVIEW}, - * {PRIV, S1440P, YUV, S1440P}, - * {PRIV, S1080P, YUV, S1080P}, - * {PRIV, S720P, YUV, S720P}, - * } - * - VIDEO_STABILIZATION_MODES: {OFF, PREVIEW} - * - AE_TARGET_FPS_RANGE: {{*, 30}, {*, 60}} - * - DYNAMIC_RANGE_PROFILE: {STANDARD, HLG10} - * - * Note: If a combination contains a S1440P, S1080P, or S720P stream, - * both 4:3 and 16:9 aspect ratio will be considered. For example, for the - * stream combination of {PRIV, S1440P, JPEG, MAXIMUM}, and if MAXIMUM == - * 4032 x 3024, the camera compliance test will verify both - * {PRIV, 1920 x 1440, JPEG, 4032 x 3024} and {PRIV, 2560 x 1440, JPEG, 4032 x 2268}. + * features described in the android.info.sessionConfigurationQueryVersion section of + * /system/media/camera/docs/docs.html. This function must + * return true for all supported combinations, and return false for non-supported + * feature combinations. The list of feature combinations required may grow in future + * HAL versions. * * @param streams The StreamConfiguration to be tested, with optional CaptureRequest parameters. * diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl index f1333728c2..236bcaf5a3 100644 --- a/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl +++ b/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl @@ -580,25 +580,25 @@ enum CameraMetadataTag { /** * android.flash.singleStrengthMaxLevel [static, int32, public] * - *

Maximum flash brightness level for manual flash control in SINGLE mode.

+ *

Maximum flash brightness level for manual flash control in SINGLE mode.

*/ ANDROID_FLASH_SINGLE_STRENGTH_MAX_LEVEL, /** * android.flash.singleStrengthDefaultLevel [static, int32, public] * - *

Default flash brightness level for manual flash control in SINGLE mode.

+ *

Default flash brightness level for manual flash control in SINGLE mode.

*/ ANDROID_FLASH_SINGLE_STRENGTH_DEFAULT_LEVEL, /** * android.flash.torchStrengthMaxLevel [static, int32, public] * - *

Maximum flash brightness level for manual flash control in TORCH mode

+ *

Maximum flash brightness level for manual flash control in TORCH mode

*/ ANDROID_FLASH_TORCH_STRENGTH_MAX_LEVEL, /** * android.flash.torchStrengthDefaultLevel [static, int32, public] * - *

Default flash brightness level for manual flash control in TORCH mode

+ *

Default flash brightness level for manual flash control in TORCH mode

*/ ANDROID_FLASH_TORCH_STRENGTH_DEFAULT_LEVEL, /** diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp index c8e683c290..82666ae3df 100644 --- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp +++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp @@ -8140,7 +8140,7 @@ void CameraHidlTest::verifyCameraCharacteristics(Status status, const CameraMeta ANDROID_LENS_POSE_REFERENCE, &entry); if (0 == retcode && entry.count > 0) { uint8_t poseReference = entry.data.u8[0]; - ASSERT_TRUE(poseReference <= ANDROID_LENS_POSE_REFERENCE_UNDEFINED && + ASSERT_TRUE(poseReference <= ANDROID_LENS_POSE_REFERENCE_AUTOMOTIVE && poseReference >= ANDROID_LENS_POSE_REFERENCE_PRIMARY_CAMERA); } diff --git a/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp b/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp index 90ec32c43c..ad8d4c877f 100644 --- a/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp +++ b/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp @@ -178,6 +178,9 @@ TEST_P(CameraAidlTest, validateManualFlashStrengthControlKeys) { const camera_metadata_t* staticMeta = reinterpret_cast(meta.metadata.data()); verifyManualFlashStrengthControlCharacteristics(staticMeta); + ret = mSession->close(); + mSession = nullptr; + ASSERT_TRUE(ret.isOk()); } } else { ALOGI("validateManualFlashStrengthControlKeys: Test skipped.\n"); @@ -297,6 +300,15 @@ TEST_P(CameraAidlTest, getSessionCharacteristics) { ASSERT_TRUE(ret.isOk()); ASSERT_NE(device, nullptr); + int32_t interfaceVersion = -1; + ret = device->getInterfaceVersion(&interfaceVersion); + ASSERT_TRUE(ret.isOk()); + bool supportSessionCharacteristics = + (interfaceVersion >= CAMERA_DEVICE_API_MINOR_VERSION_3); + if (!supportSessionCharacteristics) { + continue; + } + CameraMetadata meta; openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/, &device /*out*/); @@ -339,6 +351,10 @@ TEST_P(CameraAidlTest, getSessionCharacteristics) { ret = device->getSessionCharacteristics(config, &session_chars); ASSERT_TRUE(ret.isOk()); verifySessionCharacteristics(session_chars, camera_chars); + + ret = mSession->close(); + mSession = nullptr; + ASSERT_TRUE(ret.isOk()); } } else { ALOGI("getSessionCharacteristics: Test skipped.\n"); diff --git a/camera/provider/aidl/vts/camera_aidl_test.cpp b/camera/provider/aidl/vts/camera_aidl_test.cpp index c38c2f4964..f905011806 100644 --- a/camera/provider/aidl/vts/camera_aidl_test.cpp +++ b/camera/provider/aidl/vts/camera_aidl_test.cpp @@ -711,8 +711,8 @@ void CameraAidlTest::verifyCameraCharacteristics(const CameraMetadata& chars) { retcode = find_camera_metadata_ro_entry(metadata, ANDROID_LENS_POSE_REFERENCE, &entry); if (0 == retcode && entry.count > 0) { uint8_t poseReference = entry.data.u8[0]; - ASSERT_TRUE(poseReference <= ANDROID_LENS_POSE_REFERENCE_UNDEFINED && - poseReference >= ANDROID_LENS_POSE_REFERENCE_PRIMARY_CAMERA); + ASSERT_TRUE(poseReference <= ANDROID_LENS_POSE_REFERENCE_AUTOMOTIVE && + poseReference >= ANDROID_LENS_POSE_REFERENCE_PRIMARY_CAMERA); } retcode = @@ -1221,18 +1221,21 @@ void CameraAidlTest::verifyManualFlashStrengthControlCharacteristics( int torchDefRetCode = find_camera_metadata_ro_entry(staticMeta, ANDROID_FLASH_TORCH_STRENGTH_DEFAULT_LEVEL, &torchDefEntry); if (torch_supported) { + int expectedEntryCount; if(singleMaxRetCode == 0 && singleDefRetCode == 0 && torchMaxRetCode == 0 && torchDefRetCode == 0) { singleMaxLevel = *singleMaxEntry.data.i32; singleDefLevel = *singleDefEntry.data.i32; torchMaxLevel = *torchMaxEntry.data.i32; torchDefLevel = *torchDefEntry.data.i32; - ASSERT_TRUE((singleMaxEntry.count == singleDefEntry.count == torchMaxEntry.count - == torchDefEntry.count == 1)); + expectedEntryCount = 1; } else { - ASSERT_TRUE((singleMaxEntry.count == singleDefEntry.count == torchMaxEntry.count - == torchDefEntry.count == 0)); + expectedEntryCount = 0; } + ASSERT_EQ(singleMaxEntry.count, expectedEntryCount); + ASSERT_EQ(singleDefEntry.count, expectedEntryCount); + ASSERT_EQ(torchMaxEntry.count, expectedEntryCount); + ASSERT_EQ(torchDefEntry.count, expectedEntryCount); // if the device supports this feature default levels should be greater than 0 if (singleMaxLevel > 1) { ASSERT_GT(torchMaxLevel, 1); diff --git a/compatibility_matrices/compatibility_matrix.202504.xml b/compatibility_matrices/compatibility_matrix.202504.xml index 73b41937c5..7e19852dc2 100644 --- a/compatibility_matrices/compatibility_matrix.202504.xml +++ b/compatibility_matrices/compatibility_matrix.202504.xml @@ -76,7 +76,7 @@ android.hardware.automotive.vehicle - 1-3 + 1-4 IVehicle default @@ -108,7 +108,7 @@ android.hardware.biometrics.fingerprint - 3-4 + 3-5 IFingerprint default diff --git a/gnss/aidl/default/Gnss.cpp b/gnss/aidl/default/Gnss.cpp index c31f991b9d..94d4d000ac 100644 --- a/gnss/aidl/default/Gnss.cpp +++ b/gnss/aidl/default/Gnss.cpp @@ -162,12 +162,13 @@ ScopedAStatus Gnss::close() { return ScopedAStatus::ok(); } -void Gnss::reportLocation(const GnssLocation& location) const { +void Gnss::reportLocation(const GnssLocation& location) { std::unique_lock lock(mMutex); if (sGnssCallback == nullptr) { ALOGE("%s: GnssCallback is null.", __func__); return; } + mLastLocation = std::make_shared(location); auto status = sGnssCallback->gnssLocationCb(location); if (!status.isOk()) { ALOGE("%s: Unable to invoke gnssLocationCb", __func__); @@ -359,7 +360,6 @@ ScopedAStatus Gnss::getExtensionGnssNavigationMessage( ndk::ScopedAStatus Gnss::getExtensionGnssDebug(std::shared_ptr* iGnssDebug) { ALOGD("Gnss::getExtensionGnssDebug"); - *iGnssDebug = SharedRefBase::make(); return ndk::ScopedAStatus::ok(); } @@ -398,4 +398,8 @@ void Gnss::setGnssMeasurementInterval(const long intervalMs) { mGnssMeasurementIntervalMs = intervalMs; } +std::shared_ptr Gnss::getLastLocation() const { + return mLastLocation; +} + } // namespace aidl::android::hardware::gnss diff --git a/gnss/aidl/default/Gnss.h b/gnss/aidl/default/Gnss.h index 245d60785f..73085ef591 100644 --- a/gnss/aidl/default/Gnss.h +++ b/gnss/aidl/default/Gnss.h @@ -87,18 +87,19 @@ class Gnss : public BnGnss { void reportSvStatus() const; void setGnssMeasurementEnabled(const bool enabled); void setGnssMeasurementInterval(const long intervalMs); + std::shared_ptr getLastLocation() const; std::shared_ptr mGnssConfiguration; std::shared_ptr mGnssPowerIndication; std::shared_ptr mGnssMeasurementInterface; private: - void reportLocation(const GnssLocation&) const; + void reportLocation(const GnssLocation&); void reportSvStatus(const std::vector& svInfoList) const; + void reportGnssStatusValue(const IGnssCallback::GnssStatusValue gnssStatusValue) const; + void reportNmea() const; std::vector filterBlocklistedSatellites( std::vector gnssSvInfoList) const; - void reportGnssStatusValue(const IGnssCallback::GnssStatusValue gnssStatusValue) const; std::unique_ptr getLocationFromHW(); - void reportNmea() const; static std::shared_ptr sGnssCallback; @@ -109,6 +110,7 @@ class Gnss : public BnGnss { std::atomic mIsNmeaActive; std::atomic mFirstFixReceived; std::atomic mGnssMeasurementEnabled; + std::shared_ptr mLastLocation; std::thread mThread; ::android::hardware::gnss::common::ThreadBlocker mThreadBlocker; diff --git a/gnss/aidl/default/GnssDebug.cpp b/gnss/aidl/default/GnssDebug.cpp index f40c0bcef0..5ae6edd098 100644 --- a/gnss/aidl/default/GnssDebug.cpp +++ b/gnss/aidl/default/GnssDebug.cpp @@ -18,10 +18,15 @@ #include "GnssDebug.h" #include +#include +#include "Constants.h" +#include "Gnss.h" #include "MockLocation.h" namespace aidl::android::hardware::gnss { +using ::android::hardware::gnss::common::kMockTimestamp; + ndk::ScopedAStatus GnssDebug::getDebugData(DebugData* debugData) { ALOGD("GnssDebug::getDebugData"); @@ -36,10 +41,94 @@ ndk::ScopedAStatus GnssDebug::getDebugData(DebugData* debugData) { .speedAccuracyMetersPerSecond = 1, .bearingAccuracyDegrees = 90, .ageSeconds = 0.99}; - TimeDebug timeDebug = {.timeEstimateMs = 1519930775453L, + TimeDebug timeDebug = {.timeEstimateMs = static_cast( + kMockTimestamp + ::android::elapsedRealtimeNano() / 1e6), .timeUncertaintyNs = 1000, - .frequencyUncertaintyNsPerSec = 5.0e4}; - std::vector satelliteDataArrayDebug = {}; + .frequencyUncertaintyNsPerSec = 800}; + SatelliteData satelliteData1 = { + .svid = 3, + .constellation = GnssConstellationType::GPS, + .ephemerisType = SatelliteEphemerisType::EPHEMERIS, + .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, + .ephemerisHealth = SatelliteEphemerisHealth::GOOD, + .ephemerisAgeSeconds = 12, + .serverPredictionIsAvailable = true, + .serverPredictionAgeSeconds = 30}; + SatelliteData satelliteData2 = { + .svid = 5, + .constellation = GnssConstellationType::GPS, + .ephemerisType = SatelliteEphemerisType::EPHEMERIS, + .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, + .ephemerisHealth = SatelliteEphemerisHealth::GOOD, + .ephemerisAgeSeconds = 12, + .serverPredictionIsAvailable = true, + .serverPredictionAgeSeconds = 30}; + SatelliteData satelliteData3 = { + .svid = 17, + .constellation = GnssConstellationType::GPS, + .ephemerisType = SatelliteEphemerisType::EPHEMERIS, + .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, + .ephemerisHealth = SatelliteEphemerisHealth::GOOD, + .ephemerisAgeSeconds = 12, + .serverPredictionIsAvailable = true, + .serverPredictionAgeSeconds = 30}; + SatelliteData satelliteData4 = { + .svid = 26, + .constellation = GnssConstellationType::GPS, + .ephemerisType = SatelliteEphemerisType::EPHEMERIS, + .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, + .ephemerisHealth = SatelliteEphemerisHealth::GOOD, + .ephemerisAgeSeconds = 12, + .serverPredictionIsAvailable = true, + .serverPredictionAgeSeconds = 30}; + SatelliteData satelliteData5 = { + .svid = 5, + .constellation = GnssConstellationType::GLONASS, + .ephemerisType = SatelliteEphemerisType::EPHEMERIS, + .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, + .ephemerisHealth = SatelliteEphemerisHealth::GOOD, + .ephemerisAgeSeconds = 12, + .serverPredictionIsAvailable = true, + .serverPredictionAgeSeconds = 30}; + SatelliteData satelliteData6 = { + .svid = 17, + .constellation = GnssConstellationType::GLONASS, + .ephemerisType = SatelliteEphemerisType::EPHEMERIS, + .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, + .ephemerisHealth = SatelliteEphemerisHealth::GOOD, + .ephemerisAgeSeconds = 12, + .serverPredictionIsAvailable = true, + .serverPredictionAgeSeconds = 30}; + SatelliteData satelliteData7 = { + .svid = 18, + .constellation = GnssConstellationType::GLONASS, + .ephemerisType = SatelliteEphemerisType::EPHEMERIS, + .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, + .ephemerisHealth = SatelliteEphemerisHealth::GOOD, + .ephemerisAgeSeconds = 12, + .serverPredictionIsAvailable = true, + .serverPredictionAgeSeconds = 30}; + SatelliteData satelliteData8 = { + .svid = 10, + .constellation = GnssConstellationType::GLONASS, + .ephemerisType = SatelliteEphemerisType::EPHEMERIS, + .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, + .ephemerisHealth = SatelliteEphemerisHealth::GOOD, + .ephemerisAgeSeconds = 12, + .serverPredictionIsAvailable = true, + .serverPredictionAgeSeconds = 30}; + SatelliteData satelliteData9 = { + .svid = 3, + .constellation = GnssConstellationType::IRNSS, + .ephemerisType = SatelliteEphemerisType::EPHEMERIS, + .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, + .ephemerisHealth = SatelliteEphemerisHealth::GOOD, + .ephemerisAgeSeconds = 12, + .serverPredictionIsAvailable = true, + .serverPredictionAgeSeconds = 30}; + std::vector satelliteDataArrayDebug = { + satelliteData1, satelliteData2, satelliteData3, satelliteData4, satelliteData5, + satelliteData6, satelliteData7, satelliteData8, satelliteData9}; debugData->position = positionDebug; debugData->time = timeDebug; debugData->satelliteDataArray = satelliteDataArrayDebug; diff --git a/gnss/aidl/default/GnssDebug.h b/gnss/aidl/default/GnssDebug.h index 001d47cf5c..b6844b3113 100644 --- a/gnss/aidl/default/GnssDebug.h +++ b/gnss/aidl/default/GnssDebug.h @@ -20,6 +20,8 @@ namespace aidl::android::hardware::gnss { +class Gnss; + struct GnssDebug : public BnGnssDebug { public: ndk::ScopedAStatus getDebugData(DebugData* debugData) override; diff --git a/gnss/aidl/default/GnssMeasurementInterface.cpp b/gnss/aidl/default/GnssMeasurementInterface.cpp index f3242138cb..db1b8c6bc5 100644 --- a/gnss/aidl/default/GnssMeasurementInterface.cpp +++ b/gnss/aidl/default/GnssMeasurementInterface.cpp @@ -146,15 +146,18 @@ void GnssMeasurementInterface::stop() { mIsActive = false; mGnss->setGnssMeasurementEnabled(false); mThreadBlocker.notify(); - for (auto iter = mThreads.begin(); iter != mThreads.end(); ++iter) { + for (auto iter = mThreads.begin(); iter != mThreads.end();) { if (iter->joinable()) { - mFutures.push_back(std::async(std::launch::async, [this, iter] { - iter->join(); - mThreads.erase(iter); - })); - } else { - mThreads.erase(iter); + // Store the thread object by value + std::thread threadToMove = std::move(*iter); + + mFutures.push_back(std::async(std::launch::async, + [threadToMove = std::move(threadToMove)]() mutable { + ALOGD("joining thread"); + threadToMove.join(); + })); } + iter = mThreads.erase(iter); } } diff --git a/gnss/aidl/default/GnssNavigationMessageInterface.cpp b/gnss/aidl/default/GnssNavigationMessageInterface.cpp index c262dc6b88..eb1d6556b6 100644 --- a/gnss/aidl/default/GnssNavigationMessageInterface.cpp +++ b/gnss/aidl/default/GnssNavigationMessageInterface.cpp @@ -90,15 +90,18 @@ void GnssNavigationMessageInterface::stop() { ALOGD("stop"); mIsActive = false; mThreadBlocker.notify(); - for (auto iter = mThreads.begin(); iter != mThreads.end(); ++iter) { + for (auto iter = mThreads.begin(); iter != mThreads.end();) { if (iter->joinable()) { - mFutures.push_back(std::async(std::launch::async, [this, iter] { - iter->join(); - mThreads.erase(iter); - })); - } else { - mThreads.erase(iter); + // Store the thread object by value + std::thread threadToMove = std::move(*iter); + + mFutures.push_back(std::async(std::launch::async, + [threadToMove = std::move(threadToMove)]() mutable { + ALOGD("joining thread"); + threadToMove.join(); + })); } + iter = mThreads.erase(iter); } } diff --git a/gnss/aidl/vts/gnss_hal_test_cases.cpp b/gnss/aidl/vts/gnss_hal_test_cases.cpp index 9381a0a12e..f7408d8dd6 100644 --- a/gnss/aidl/vts/gnss_hal_test_cases.cpp +++ b/gnss/aidl/vts/gnss_hal_test_cases.cpp @@ -1149,40 +1149,139 @@ TEST_P(GnssHalTest, GnssDebugValuesSanityTest) { sp iGnssDebug; auto status = aidl_gnss_hal_->getExtensionGnssDebug(&iGnssDebug); ASSERT_TRUE(status.isOk()); - - if (!IsAutomotiveDevice()) { - ASSERT_TRUE(iGnssDebug != nullptr); - - IGnssDebug::DebugData data; - auto status = iGnssDebug->getDebugData(&data); - ASSERT_TRUE(status.isOk()); - - if (data.position.valid) { - ASSERT_TRUE(data.position.latitudeDegrees >= -90 && - data.position.latitudeDegrees <= 90); - ASSERT_TRUE(data.position.longitudeDegrees >= -180 && - data.position.longitudeDegrees <= 180); - ASSERT_TRUE(data.position.altitudeMeters >= -1000 && // Dead Sea: -414m - data.position.altitudeMeters <= 20000); // Mount Everest: 8850m - ASSERT_TRUE(data.position.speedMetersPerSec >= 0 && - data.position.speedMetersPerSec <= 600); - ASSERT_TRUE(data.position.bearingDegrees >= -360 && - data.position.bearingDegrees <= 360); - ASSERT_TRUE(data.position.horizontalAccuracyMeters > 0 && - data.position.horizontalAccuracyMeters <= 20000000); - ASSERT_TRUE(data.position.verticalAccuracyMeters > 0 && - data.position.verticalAccuracyMeters <= 20000); - ASSERT_TRUE(data.position.speedAccuracyMetersPerSecond > 0 && - data.position.speedAccuracyMetersPerSecond <= 500); - ASSERT_TRUE(data.position.bearingAccuracyDegrees > 0 && - data.position.bearingAccuracyDegrees <= 180); - ASSERT_TRUE(data.position.ageSeconds >= 0); - } - ASSERT_TRUE(data.time.timeEstimateMs >= 1483228800000); // Jan 01 2017 00:00:00 GMT. - ASSERT_TRUE(data.time.timeUncertaintyNs > 0); - ASSERT_TRUE(data.time.frequencyUncertaintyNsPerSec > 0 && - data.time.frequencyUncertaintyNsPerSec <= 2.0e5); // 200 ppm + if (IsAutomotiveDevice()) { + return; } + ASSERT_TRUE(iGnssDebug != nullptr); + + IGnssDebug::DebugData data; + status = iGnssDebug->getDebugData(&data); + ASSERT_TRUE(status.isOk()); + Utils::checkPositionDebug(data); + + // Additional GnssDebug tests for AIDL version >= 4 (launched in Android 15(V)+) + if (aidl_gnss_hal_->getInterfaceVersion() <= 3) { + return; + } + + // Start location and check the consistency between SvStatus and DebugData + aidl_gnss_cb_->location_cbq_.reset(); + aidl_gnss_cb_->sv_info_list_cbq_.reset(); + StartAndCheckLocations(/* count= */ 2); + int location_called_count = aidl_gnss_cb_->location_cbq_.calledCount(); + ALOGD("Observed %d GnssSvStatus, while awaiting 2 locations (%d received)", + aidl_gnss_cb_->sv_info_list_cbq_.size(), location_called_count); + + // Wait for up to kNumSvInfoLists events for kTimeoutSeconds for each event. + int kTimeoutSeconds = 2; + int kNumSvInfoLists = 4; + std::list> sv_info_lists; + std::vector last_sv_info_list; + + do { + EXPECT_GT(aidl_gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_lists, kNumSvInfoLists, + kTimeoutSeconds), + 0); + if (!sv_info_lists.empty()) { + last_sv_info_list = sv_info_lists.back(); + ALOGD("last_sv_info size = %d", (int)last_sv_info_list.size()); + } + } while (!sv_info_lists.empty() && last_sv_info_list.size() == 0); + + StopAndClearLocations(); + + status = iGnssDebug->getDebugData(&data); + Utils::checkPositionDebug(data); + + // Validate SatelliteEphemerisType, SatelliteEphemerisSource, SatelliteEphemerisHealth + for (auto sv_info : last_sv_info_list) { + if ((sv_info.svFlag & static_cast(IGnssCallback::GnssSvFlags::USED_IN_FIX)) == 0) { + continue; + } + ALOGD("Found usedInFix const: %d, svid: %d", static_cast(sv_info.constellation), + sv_info.svid); + bool foundDebugData = false; + for (auto satelliteData : data.satelliteDataArray) { + if (satelliteData.constellation == sv_info.constellation && + satelliteData.svid == sv_info.svid) { + foundDebugData = true; + ALOGD("Found GnssDebug data for this sv."); + EXPECT_TRUE(satelliteData.serverPredictionIsAvailable || + satelliteData.ephemerisType == + IGnssDebug::SatelliteEphemerisType::EPHEMERIS); + // for satellites with ephType=0, they need ephHealth=0 if used-in-fix + if (satelliteData.ephemerisType == IGnssDebug::SatelliteEphemerisType::EPHEMERIS) { + EXPECT_TRUE(satelliteData.ephemerisHealth == + IGnssDebug::SatelliteEphemerisHealth::GOOD); + } + break; + } + } + // Every Satellite where GnssStatus says it is used-in-fix has a valid ephemeris - i.e. it's + // it shows either a serverPredAvail: 1, or a ephType=0 + EXPECT_TRUE(foundDebugData); + } + + bool hasServerPredictionAvailable = false; + bool hasNoneZeroServerPredictionAgeSeconds = false; + bool hasNoneDemodEphSource = false; + for (auto satelliteData : data.satelliteDataArray) { + // for satellites with serverPredAvail: 1, the serverPredAgeSec: is not 0 for all + // satellites (at least not on 2 fixes in a row - it could get lucky once) + if (satelliteData.serverPredictionIsAvailable) { + hasServerPredictionAvailable = true; + if (satelliteData.serverPredictionAgeSeconds != 0) { + hasNoneZeroServerPredictionAgeSeconds = true; + } + } + // for satellites with ephType=0, they need ephSource 0-3 + if (satelliteData.ephemerisType == IGnssDebug::SatelliteEphemerisType::EPHEMERIS) { + EXPECT_TRUE(satelliteData.ephemerisSource >= + SatellitePvt::SatelliteEphemerisSource::DEMODULATED && + satelliteData.ephemerisSource <= + SatellitePvt::SatelliteEphemerisSource::OTHER); + if (satelliteData.ephemerisSource != + SatellitePvt::SatelliteEphemerisSource::DEMODULATED) { + hasNoneDemodEphSource = true; + } + } + } + if (hasNoneDemodEphSource && hasServerPredictionAvailable) { + EXPECT_TRUE(hasNoneZeroServerPredictionAgeSeconds); + } + + /** + - Gnss Location Data:: should show some valid information, ideally reasonably close (+/-1km) to + the Location output - at least after the 2nd valid location output (maybe in general, wait + for 2 good Location outputs before checking this, in case they don't update the assistance + until after they output the Location) + */ + double distanceM = + Utils::distanceMeters(data.position.latitudeDegrees, data.position.longitudeDegrees, + aidl_gnss_cb_->last_location_.latitudeDegrees, + aidl_gnss_cb_->last_location_.longitudeDegrees); + ALOGD("distance between debug position and last position: %.2lf", distanceM); + EXPECT_LT(distanceM, 1000.0); // 1km + + /** + - Gnss Time Data:: timeEstimate should be reasonably close to the current GPS time. + - Gnss Time Data:: timeUncertaintyNs should always be > 0 and < 5e9 (could be large due + to solve-for-time type solutions) + - Gnss Time Data:: frequencyUncertaintyNsPerSec: should always be > 0 and < 1000 (1000 ns/s + corresponds to roughly a 300 m/s speed error, which should be pretty rare) + */ + ALOGD("debug time: %" PRId64 ", position time: %" PRId64, data.time.timeEstimateMs, + aidl_gnss_cb_->last_location_.timestampMillis); + // Allowing 5s between the last location time and the current GPS time + EXPECT_LT(abs(data.time.timeEstimateMs - aidl_gnss_cb_->last_location_.timestampMillis), 5000); + + ALOGD("debug time uncertainty: %f ns", data.time.timeUncertaintyNs); + EXPECT_GT(data.time.timeUncertaintyNs, 0); + EXPECT_LT(data.time.timeUncertaintyNs, 5e9); + + ALOGD("debug freq uncertainty: %f ns/s", data.time.frequencyUncertaintyNsPerSec); + EXPECT_GT(data.time.frequencyUncertaintyNsPerSec, 0); + EXPECT_LT(data.time.frequencyUncertaintyNsPerSec, 1000); } /* @@ -1714,7 +1813,8 @@ TEST_P(GnssHalTest, TestAccumulatedDeltaRange) { * 2. verify the SvStatus are received at expected interval */ TEST_P(GnssHalTest, TestSvStatusIntervals) { - if (aidl_gnss_hal_->getInterfaceVersion() <= 2) { + // Only runs on devices launched in Android 15+ + if (aidl_gnss_hal_->getInterfaceVersion() <= 3) { return; } ALOGD("TestSvStatusIntervals"); diff --git a/gnss/common/utils/vts/Utils.cpp b/gnss/common/utils/vts/Utils.cpp index 69e2b346b0..e3ff0f3d24 100644 --- a/gnss/common/utils/vts/Utils.cpp +++ b/gnss/common/utils/vts/Utils.cpp @@ -20,6 +20,7 @@ #include "gtest/gtest.h" #include +#include #include namespace android { @@ -58,6 +59,31 @@ void Utils::checkLocationElapsedRealtime(const android::hardware::gnss::GnssLoca checkElapsedRealtime(location.elapsedRealtime); } +void Utils::checkPositionDebug(android::hardware::gnss::IGnssDebug::DebugData data) { + if (data.position.valid) { + ASSERT_TRUE(data.position.latitudeDegrees >= -90 && data.position.latitudeDegrees <= 90); + ASSERT_TRUE(data.position.longitudeDegrees >= -180 && + data.position.longitudeDegrees <= 180); + ASSERT_TRUE(data.position.altitudeMeters >= -1000 && // Dead Sea: -414m + data.position.altitudeMeters <= 20000); // Mount Everest: 8850m + ASSERT_TRUE(data.position.speedMetersPerSec >= 0 && data.position.speedMetersPerSec <= 600); + ASSERT_TRUE(data.position.bearingDegrees >= -360 && data.position.bearingDegrees <= 360); + ASSERT_TRUE(data.position.horizontalAccuracyMeters > 0 && + data.position.horizontalAccuracyMeters <= 20000000); + ASSERT_TRUE(data.position.verticalAccuracyMeters > 0 && + data.position.verticalAccuracyMeters <= 20000); + ASSERT_TRUE(data.position.speedAccuracyMetersPerSecond > 0 && + data.position.speedAccuracyMetersPerSecond <= 500); + ASSERT_TRUE(data.position.bearingAccuracyDegrees > 0 && + data.position.bearingAccuracyDegrees <= 180); + ASSERT_TRUE(data.position.ageSeconds >= 0); + } + ASSERT_TRUE(data.time.timeEstimateMs >= 1483228800000); // Jan 01 2017 00:00:00 GMT. + ASSERT_TRUE(data.time.timeUncertaintyNs > 0); + ASSERT_TRUE(data.time.frequencyUncertaintyNsPerSec > 0 && + data.time.frequencyUncertaintyNsPerSec <= 2.0e5); // 200 ppm +} + void Utils::checkElapsedRealtime(const ElapsedRealtime& elapsedRealtime) { ASSERT_TRUE(elapsedRealtime.flags >= 0 && elapsedRealtime.flags <= (ElapsedRealtime::HAS_TIMESTAMP_NS | @@ -282,6 +308,17 @@ bool Utils::isAutomotiveDevice() { return strncmp(buffer, "automotive", PROPERTY_VALUE_MAX) == 0; } +double Utils::distanceMeters(double lat1, double lon1, double lat2, double lon2) { + double R = 6378.137; // Radius of earth in KM + double dLat = lat2 * M_PI / 180 - lat1 * M_PI / 180; + double dLon = lon2 * M_PI / 180 - lon1 * M_PI / 180; + double a = sin(dLat / 2) * sin(dLat / 2) + + cos(lat1 * M_PI / 180) * cos(lat2 * M_PI / 180) * sin(dLon / 2) * sin(dLon / 2); + double c = 2 * atan2(sqrt(a), sqrt(1 - a)); + double d = R * c; + return d * 1000; // meters +} + } // namespace common } // namespace gnss } // namespace hardware diff --git a/gnss/common/utils/vts/include/Utils.h b/gnss/common/utils/vts/include/Utils.h index 7b890781db..62d409ac66 100644 --- a/gnss/common/utils/vts/include/Utils.h +++ b/gnss/common/utils/vts/include/Utils.h @@ -43,6 +43,7 @@ struct Utils { static void checkElapsedRealtime( const android::hardware::gnss::ElapsedRealtime& elapsedRealtime); + static void checkPositionDebug(android::hardware::gnss::IGnssDebug::DebugData data); static const android::hardware::gnss::GnssLocation getMockLocation( double latitudeDegrees, double longitudeDegrees, double horizontalAccuracyMeters); @@ -57,6 +58,7 @@ struct Utils { V2_0::GnssConstellationType constellation); static bool isAutomotiveDevice(); + static double distanceMeters(double lat1, double lon1, double lat2, double lon2); private: template diff --git a/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl b/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl index 2985212ed5..1117504c43 100644 --- a/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl +++ b/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl @@ -161,8 +161,7 @@ enum PixelFormat { * * The allocator should examine the usage bits passed in when allocating a * buffer with this format, and it should derive the pixel format from - * those usage flags. This format must never be used with any of the - * BufferUsage::CPU_* usage flags. + * those usage flags. * * Even when the internally chosen format has an alpha component, the * clients must assume the alpha vlaue to be 1.0. diff --git a/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h b/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h index 336d15dc6c..6a4598727a 100644 --- a/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h +++ b/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -649,7 +650,8 @@ class CommandReaderBase { *outLength = static_cast(val & length_mask); if (mDataRead + *outLength > mDataSize) { - ALOGE("command 0x%x has invalid command length %" PRIu16, *outCommand, *outLength); + ALOGE("command %s has invalid command length %" PRIu16, + toString(*outCommand).c_str(), *outLength); // undo the read() above mDataRead--; return false; diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/CommandResultPayload.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/CommandResultPayload.aidl index 106fd87ebd..99c91aa32e 100644 --- a/graphics/composer/aidl/android/hardware/graphics/composer3/CommandResultPayload.aidl +++ b/graphics/composer/aidl/android/hardware/graphics/composer3/CommandResultPayload.aidl @@ -28,6 +28,10 @@ import android.hardware.graphics.composer3.ReleaseFences; union CommandResultPayload { /** * Indicates an error generated by a command. + * + * If there is an error from a command, the composer should only respond + * with the CommandError, and not with other results + * (e.g. ChangedCompositionTypes). */ CommandError error; diff --git a/graphics/composer/aidl/vts/VtsComposerClient.h b/graphics/composer/aidl/vts/VtsComposerClient.h index fabc82a7a6..da6116f7b1 100644 --- a/graphics/composer/aidl/vts/VtsComposerClient.h +++ b/graphics/composer/aidl/vts/VtsComposerClient.h @@ -258,13 +258,13 @@ class VtsDisplay { struct DisplayConfig { DisplayConfig(int32_t vsyncPeriod_, int32_t configGroup_, - std::optional vrrConfig_ = {}) + std::optional vrrConfigOpt_ = {}) : vsyncPeriod(vsyncPeriod_), configGroup(configGroup_), - vrrConfig(std::move(vrrConfig_)) {} + vrrConfigOpt(std::move(vrrConfigOpt_)) {} int32_t vsyncPeriod; int32_t configGroup; - std::optional vrrConfig; + std::optional vrrConfigOpt; }; void addDisplayConfig(int32_t config, DisplayConfig displayConfig) { @@ -273,6 +273,35 @@ class VtsDisplay { DisplayConfig getDisplayConfig(int32_t config) { return mDisplayConfigs.find(config)->second; } + bool isRateSameBetweenConfigs(int config1, int config2) { + const auto displayConfig1 = getDisplayConfig(config1); + const auto displayConfig2 = getDisplayConfig(config2); + const auto vrrConfigOpt1 = displayConfig1.vrrConfigOpt; + const auto vrrConfigOpt2 = displayConfig2.vrrConfigOpt; + + if (vrrConfigOpt1 && vrrConfigOpt2 && + vrrConfigOpt1->minFrameIntervalNs == vrrConfigOpt2->minFrameIntervalNs) { + return true; + } else if (displayConfig1.vsyncPeriod == displayConfig2.vsyncPeriod) { + return true; + } + return false; + } + + std::string printConfig(int config) { + const auto displayConfig = getDisplayConfig(config); + const auto vrrConfigOpt = displayConfig.vrrConfigOpt; + std::stringstream ss; + if (displayConfig.vrrConfigOpt) { + ss << "{Config " << config << ": vsyncPeriod " << displayConfig.vsyncPeriod + << ", minFrameIntervalNs " << vrrConfigOpt->minFrameIntervalNs << "}"; + } + else { + ss << "{Config " << config << ": vsyncPeriod " << displayConfig.vsyncPeriod << "}"; + } + return ss.str(); + } + std::unordered_map getDisplayConfigs() { return mDisplayConfigs; } private: diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp index d4ce3ba2b6..3d9253f917 100644 --- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp +++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp @@ -59,10 +59,12 @@ class GraphicsCompositionTestBase : public ::testing::Test { EXPECT_TRUE(mComposerClient->setPowerMode(getPrimaryDisplayId(), PowerMode::ON).isOk()); + const auto format = getHasReadbackBuffer() ? mPixelFormat : common::PixelFormat::RGBA_8888; + ASSERT_NO_FATAL_FAILURE( mTestRenderEngine = std::unique_ptr(new TestRenderEngine( ::android::renderengine::RenderEngineCreationArgs::Builder() - .setPixelFormat(static_cast(common::PixelFormat::RGBA_8888)) + .setPixelFormat(static_cast(format)) .setImageCacheSize(TestRenderEngine::sMaxFrameBufferAcquireBuffers) .setEnableProtectedContext(false) .setPrecacheToneMapperShaderOnly(false) diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp index 012aa3f31b..eaf23b5abe 100644 --- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp +++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp @@ -1603,18 +1603,24 @@ class GraphicsComposerAidlCommandTest : public GraphicsComposerAidlTest { EXPECT_TRUE(mComposerClient->setActiveConfig(&display, config1).isOk()); sendRefreshFrame(display, nullptr); - const auto displayConfigGroup1 = display.getDisplayConfig(config1); - int32_t vsyncPeriod1 = displayConfigGroup1.vsyncPeriod; - int32_t configGroup1 = displayConfigGroup1.configGroup; + const auto displayConfig1 = display.getDisplayConfig(config1); + int32_t vsyncPeriod1 = displayConfig1.vsyncPeriod; + int32_t configGroup1 = displayConfig1.configGroup; - const auto displayConfigGroup2 = display.getDisplayConfig(config2); - int32_t vsyncPeriod2 = displayConfigGroup2.vsyncPeriod; - int32_t configGroup2 = displayConfigGroup2.configGroup; + const auto displayConfig2 = display.getDisplayConfig(config2); + int32_t vsyncPeriod2 = displayConfig2.vsyncPeriod; + int32_t configGroup2 = displayConfig2.configGroup; if (vsyncPeriod1 == vsyncPeriod2) { return; // continue } + if ((!displayConfig1.vrrConfigOpt && displayConfig2.vrrConfigOpt) || + (displayConfig1.vrrConfigOpt && !displayConfig2.vrrConfigOpt)) { + // switching between vrr to non-vrr modes + return; // continue + } + // We don't allow delayed change when changing config groups if (params.delayForChange > 0 && configGroup1 != configGroup2) { return; // continue @@ -2197,13 +2203,13 @@ TEST_P(GraphicsComposerAidlCommandTest, SetLayerCompositionType) { TEST_P(GraphicsComposerAidlCommandTest, DisplayDecoration) { for (VtsDisplay& display : mDisplays) { - auto& writer = getWriter(display.getDisplayId()); + const auto displayId = display.getDisplayId(); + auto& writer = getWriter(displayId); const auto [layerStatus, layer] = - mComposerClient->createLayer(display.getDisplayId(), kBufferSlotCount, &writer); - EXPECT_TRUE(layerStatus.isOk()); + mComposerClient->createLayer(displayId, kBufferSlotCount, &writer); + ASSERT_TRUE(layerStatus.isOk()); - const auto [error, support] = - mComposerClient->getDisplayDecorationSupport(display.getDisplayId()); + const auto [error, support] = mComposerClient->getDisplayDecorationSupport(displayId); const auto format = (error.isOk() && support) ? support->format : aidl::android::hardware::graphics::common::PixelFormat::RGBA_8888; @@ -2223,9 +2229,9 @@ TEST_P(GraphicsComposerAidlCommandTest, DisplayDecoration) { configureLayer(display, layer, Composition::DISPLAY_DECORATION, display.getFrameRect(), display.getCrop()); - writer.setLayerBuffer(display.getDisplayId(), layer, /*slot*/ 0, decorBuffer->handle, + writer.setLayerBuffer(displayId, layer, /*slot*/ 0, decorBuffer->handle, /*acquireFence*/ -1); - writer.validateDisplay(display.getDisplayId(), ComposerClientWriter::kNoTimestamp, + writer.validateDisplay(displayId, ComposerClientWriter::kNoTimestamp, VtsComposerClient::kNoFrameIntervalNs); execute(); if (support) { @@ -2235,6 +2241,7 @@ TEST_P(GraphicsComposerAidlCommandTest, DisplayDecoration) { ASSERT_EQ(1, errors.size()); EXPECT_EQ(IComposerClient::EX_UNSUPPORTED, errors[0].errorCode); } + EXPECT_TRUE(mComposerClient->destroyLayer(displayId, layer, &writer).isOk()); } } @@ -2738,7 +2745,7 @@ TEST_P(GraphicsComposerAidlCommandV2Test, SetRefreshRateChangedCallbackDebug_Ena const auto displayFilter = [&](auto refreshRateChangedDebugData) { bool nonVrrRateMatching = true; if (std::optional vrrConfigOpt = - display.getDisplayConfig(configId).vrrConfig; + display.getDisplayConfig(configId).vrrConfigOpt; getInterfaceVersion() >= 3 && !vrrConfigOpt) { nonVrrRateMatching = refreshRateChangedDebugData.refreshPeriodNanos == refreshRateChangedDebugData.vsyncPeriodNanos; @@ -2836,10 +2843,7 @@ TEST_P(GraphicsComposerAidlCommandV2Test, .isOk()); forEachTwoConfigs(displayId, [&](int32_t config1, int32_t config2) { - const int32_t vsyncPeriod1 = display.getDisplayConfig(config1).vsyncPeriod; - const int32_t vsyncPeriod2 = display.getDisplayConfig(config2).vsyncPeriod; - - if (vsyncPeriod1 == vsyncPeriod2) { + if (display.isRateSameBetweenConfigs(config1, config2)) { return; // continue } @@ -2854,6 +2858,7 @@ TEST_P(GraphicsComposerAidlCommandV2Test, sendRefreshFrame(display, &timeline); } + const int32_t vsyncPeriod2 = display.getDisplayConfig(config2).vsyncPeriod; const auto callbackFilter = [displayId, vsyncPeriod2](auto refreshRateChangedDebugData) { constexpr int kVsyncThreshold = 1000; @@ -2872,8 +2877,9 @@ TEST_P(GraphicsComposerAidlCommandV2Test, } while (--retryCount > 0); if (retryCount == 0) { - GTEST_FAIL() << "failed to get a callback for the display " << displayId - << " with config " << config2; + GTEST_FAIL() << "Failed to get a callback for Display " << displayId + << " switching from " << display.printConfig(config1) + << " to " << display.printConfig(config2); } }); @@ -3002,14 +3008,10 @@ TEST_P(GraphicsComposerAidlCommandV3Test, CreateBatchedCommand) { GTEST_SKIP() << "LAYER_LIFECYCLE_BATCH_COMMAND not supported by the implementation"; return; } - auto& writer = getWriter(getPrimaryDisplayId()); - int64_t layer = 5; - writer.setLayerLifecycleBatchCommandType(getPrimaryDisplayId(), layer, - LayerLifecycleBatchCommandType::CREATE); - writer.setNewBufferSlotCount(getPrimaryDisplayId(), layer, 1); - writer.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp, - VtsComposerClient::kNoFrameIntervalNs); + const auto& [status, layer] = + mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer); + EXPECT_TRUE(status.isOk()); execute(); ASSERT_TRUE(mReader.takeErrors().empty()); } @@ -3019,15 +3021,13 @@ TEST_P(GraphicsComposerAidlCommandV3Test, CreateBatchedCommand_BadDisplay) { GTEST_SKIP() << "LAYER_LIFECYCLE_BATCH_COMMAND not supported by the implementation"; return; } - - auto& writer = getWriter(getPrimaryDisplayId()); + auto& writer = getWriter(getInvalidDisplayId()); int64_t layer = 5; writer.setLayerLifecycleBatchCommandType(getInvalidDisplayId(), layer, LayerLifecycleBatchCommandType::CREATE); - writer.setNewBufferSlotCount(getPrimaryDisplayId(), layer, 1); - writer.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp, - VtsComposerClient::kNoFrameIntervalNs); + writer.setNewBufferSlotCount(getInvalidDisplayId(), layer, 1); execute(); + const auto errors = mReader.takeErrors(); ASSERT_TRUE(errors.size() == 1 && errors[0].errorCode == IComposerClient::EX_BAD_DISPLAY); } @@ -3037,26 +3037,15 @@ TEST_P(GraphicsComposerAidlCommandV3Test, DestroyBatchedCommand) { GTEST_SKIP() << "LAYER_LIFECYCLE_BATCH_COMMAND not supported by the implementation"; return; } - auto& writer = getWriter(getPrimaryDisplayId()); - int64_t layer = 5; - writer.setLayerLifecycleBatchCommandType(getPrimaryDisplayId(), layer, - LayerLifecycleBatchCommandType::CREATE); - writer.setNewBufferSlotCount(getPrimaryDisplayId(), layer, 1); - writer.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp, - VtsComposerClient::kNoFrameIntervalNs); + const auto& [status, layer] = + mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer); + EXPECT_TRUE(status.isOk()); execute(); ASSERT_TRUE(mReader.takeErrors().empty()); - writer.setLayerLifecycleBatchCommandType(getPrimaryDisplayId(), layer, - LayerLifecycleBatchCommandType::DESTROY); - layer++; - writer.setLayerLifecycleBatchCommandType(getPrimaryDisplayId(), layer, - LayerLifecycleBatchCommandType::CREATE); - writer.setNewBufferSlotCount(getPrimaryDisplayId(), layer, 1); - + EXPECT_TRUE(mComposerClient->destroyLayer(getPrimaryDisplayId(), layer, &writer).isOk()); execute(); - const auto errors = mReader.takeErrors(); - ASSERT_TRUE(errors.size() == 1 && errors[0].errorCode == IComposerClient::EX_BAD_DISPLAY); + ASSERT_TRUE(mReader.takeErrors().empty()); } TEST_P(GraphicsComposerAidlCommandV3Test, DestroyBatchedCommand_BadDisplay) { @@ -3064,25 +3053,20 @@ TEST_P(GraphicsComposerAidlCommandV3Test, DestroyBatchedCommand_BadDisplay) { GTEST_SKIP() << "LAYER_LIFECYCLE_BATCH_COMMAND not supported by the implementation"; return; } - auto& writer = getWriter(getPrimaryDisplayId()); - int64_t layer = 5; - writer.setLayerLifecycleBatchCommandType(getPrimaryDisplayId(), layer, - LayerLifecycleBatchCommandType::CREATE); - writer.setNewBufferSlotCount(getPrimaryDisplayId(), layer, 1); - writer.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp, - VtsComposerClient::kNoFrameIntervalNs); - execute(); - ASSERT_TRUE(mReader.takeErrors().empty()); - writer.setLayerLifecycleBatchCommandType(getInvalidDisplayId(), layer, - LayerLifecycleBatchCommandType::DESTROY); - layer++; - writer.setLayerLifecycleBatchCommandType(getInvalidDisplayId(), layer, - LayerLifecycleBatchCommandType::CREATE); - writer.setNewBufferSlotCount(getPrimaryDisplayId(), layer, 1); + const auto& [status, layer] = + mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer); + EXPECT_TRUE(status.isOk()); execute(); ASSERT_TRUE(mReader.takeErrors().empty()); + + auto& invalid_writer = getWriter(getInvalidDisplayId()); + invalid_writer.setLayerLifecycleBatchCommandType(getInvalidDisplayId(), layer, + LayerLifecycleBatchCommandType::DESTROY); + execute(); + const auto errors = mReader.takeErrors(); + ASSERT_TRUE(errors.size() == 1 && errors[0].errorCode == IComposerClient::EX_BAD_DISPLAY); } TEST_P(GraphicsComposerAidlCommandV3Test, NoCreateDestroyBatchedCommandIncorrectLayer) { diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/ProtectCallback.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/ProtectCallback.h index 92ed1cda5d..9a7fe5e1c7 100644 --- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/ProtectCallback.h +++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/ProtectCallback.h @@ -56,6 +56,8 @@ class IProtectedCallback { // Thread safe class class DeathMonitor final { public: + explicit DeathMonitor(uintptr_t cookieKey) : kCookieKey(cookieKey) {} + static void serviceDied(void* cookie); void serviceDied(); // Precondition: `killable` must be non-null. @@ -63,9 +65,18 @@ class DeathMonitor final { // Precondition: `killable` must be non-null. void remove(IProtectedCallback* killable) const; + uintptr_t getCookieKey() const { return kCookieKey; } + + ~DeathMonitor(); + DeathMonitor(const DeathMonitor&) = delete; + DeathMonitor(DeathMonitor&&) noexcept = delete; + DeathMonitor& operator=(const DeathMonitor&) = delete; + DeathMonitor& operator=(DeathMonitor&&) noexcept = delete; + private: mutable std::mutex mMutex; mutable std::vector mObjects GUARDED_BY(mMutex); + const uintptr_t kCookieKey; }; class DeathHandler final { diff --git a/neuralnetworks/aidl/utils/src/ProtectCallback.cpp b/neuralnetworks/aidl/utils/src/ProtectCallback.cpp index 54a673caf5..4a7ac08895 100644 --- a/neuralnetworks/aidl/utils/src/ProtectCallback.cpp +++ b/neuralnetworks/aidl/utils/src/ProtectCallback.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -33,6 +34,16 @@ namespace aidl::android::hardware::neuralnetworks::utils { +namespace { + +// Only dereference the cookie if it's valid (if it's in this set) +// Only used with ndk +std::mutex sCookiesMutex; +uintptr_t sCookieKeyCounter GUARDED_BY(sCookiesMutex) = 0; +std::map> sCookies GUARDED_BY(sCookiesMutex); + +} // namespace + void DeathMonitor::serviceDied() { std::lock_guard guard(mMutex); std::for_each(mObjects.begin(), mObjects.end(), @@ -40,8 +51,24 @@ void DeathMonitor::serviceDied() { } void DeathMonitor::serviceDied(void* cookie) { - auto deathMonitor = static_cast(cookie); - deathMonitor->serviceDied(); + std::shared_ptr monitor; + { + std::lock_guard guard(sCookiesMutex); + if (auto it = sCookies.find(reinterpret_cast(cookie)); it != sCookies.end()) { + monitor = it->second.lock(); + sCookies.erase(it); + } else { + LOG(INFO) + << "Service died, but cookie is no longer valid so there is nothing to notify."; + return; + } + } + if (monitor) { + LOG(INFO) << "Notifying DeathMonitor from serviceDied."; + monitor->serviceDied(); + } else { + LOG(INFO) << "Tried to notify DeathMonitor from serviceDied but could not promote."; + } } void DeathMonitor::add(IProtectedCallback* killable) const { @@ -57,12 +84,25 @@ void DeathMonitor::remove(IProtectedCallback* killable) const { mObjects.erase(removedIter); } +DeathMonitor::~DeathMonitor() { + // lock must be taken so object is not used in OnBinderDied" + std::lock_guard guard(sCookiesMutex); + sCookies.erase(kCookieKey); +} + nn::GeneralResult DeathHandler::create(std::shared_ptr object) { if (object == nullptr) { return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "utils::DeathHandler::create must have non-null object"; } - auto deathMonitor = std::make_shared(); + + std::shared_ptr deathMonitor; + { + std::lock_guard guard(sCookiesMutex); + deathMonitor = std::make_shared(sCookieKeyCounter++); + sCookies[deathMonitor->getCookieKey()] = deathMonitor; + } + auto deathRecipient = ndk::ScopedAIBinder_DeathRecipient( AIBinder_DeathRecipient_new(DeathMonitor::serviceDied)); @@ -70,8 +110,9 @@ nn::GeneralResult DeathHandler::create(std::shared_ptrisRemote()) { - const auto ret = ndk::ScopedAStatus::fromStatus(AIBinder_linkToDeath( - object->asBinder().get(), deathRecipient.get(), deathMonitor.get())); + const auto ret = ndk::ScopedAStatus::fromStatus( + AIBinder_linkToDeath(object->asBinder().get(), deathRecipient.get(), + reinterpret_cast(deathMonitor->getCookieKey()))); HANDLE_ASTATUS(ret) << "AIBinder_linkToDeath failed"; } @@ -91,8 +132,9 @@ DeathHandler::DeathHandler(std::shared_ptr object, DeathHandler::~DeathHandler() { if (kObject != nullptr && kDeathRecipient.get() != nullptr && kDeathMonitor != nullptr) { - const auto ret = ndk::ScopedAStatus::fromStatus(AIBinder_unlinkToDeath( - kObject->asBinder().get(), kDeathRecipient.get(), kDeathMonitor.get())); + const auto ret = ndk::ScopedAStatus::fromStatus( + AIBinder_unlinkToDeath(kObject->asBinder().get(), kDeathRecipient.get(), + reinterpret_cast(kDeathMonitor->getCookieKey()))); const auto maybeSuccess = handleTransportError(ret); if (!maybeSuccess.ok()) { LOG(ERROR) << maybeSuccess.error().message; diff --git a/neuralnetworks/aidl/utils/test/DeviceTest.cpp b/neuralnetworks/aidl/utils/test/DeviceTest.cpp index 73727b3974..ffd3b8e5f1 100644 --- a/neuralnetworks/aidl/utils/test/DeviceTest.cpp +++ b/neuralnetworks/aidl/utils/test/DeviceTest.cpp @@ -697,7 +697,8 @@ TEST_P(DeviceTest, prepareModelAsyncCrash) { const auto mockDevice = createMockDevice(); const auto device = Device::create(kName, mockDevice, kVersion).value(); const auto ret = [&device]() { - DeathMonitor::serviceDied(device->getDeathMonitor()); + DeathMonitor::serviceDied( + reinterpret_cast(device->getDeathMonitor()->getCookieKey())); return ndk::ScopedAStatus::ok(); }; EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _)) @@ -846,7 +847,8 @@ TEST_P(DeviceTest, prepareModelWithConfigAsyncCrash) { const auto mockDevice = createMockDevice(); const auto device = Device::create(kName, mockDevice, kVersion).value(); const auto ret = [&device]() { - DeathMonitor::serviceDied(device->getDeathMonitor()); + DeathMonitor::serviceDied( + reinterpret_cast(device->getDeathMonitor()->getCookieKey())); return ndk::ScopedAStatus::ok(); }; EXPECT_CALL(*mockDevice, prepareModelWithConfig(_, _, _)) @@ -970,7 +972,8 @@ TEST_P(DeviceTest, prepareModelFromCacheAsyncCrash) { const auto mockDevice = createMockDevice(); const auto device = Device::create(kName, mockDevice, kVersion).value(); const auto ret = [&device]() { - DeathMonitor::serviceDied(device->getDeathMonitor()); + DeathMonitor::serviceDied( + reinterpret_cast(device->getDeathMonitor()->getCookieKey())); return ndk::ScopedAStatus::ok(); }; EXPECT_CALL(*mockDevice, prepareModelFromCache(_, _, _, _, _)) diff --git a/power/aidl/android/hardware/power/SessionConfig.aidl b/power/aidl/android/hardware/power/SessionConfig.aidl index 93dc9a278e..ca89183e16 100644 --- a/power/aidl/android/hardware/power/SessionConfig.aidl +++ b/power/aidl/android/hardware/power/SessionConfig.aidl @@ -25,6 +25,9 @@ parcelable SessionConfig { /** * The session's unique ID, used to identify the session for debugging and * for multiplexing on the per-process FMQ channel. + * + * Values that fit in the 32-bit int range value must be provided when using + * the FMQ API, as the FMQ messages can only accept 32-bit Session IDs. */ long id; } diff --git a/radio/aidl/android/hardware/radio/network/SecurityAlgorithm.aidl b/radio/aidl/android/hardware/radio/network/SecurityAlgorithm.aidl index 01f732738b..451eaa98d6 100644 --- a/radio/aidl/android/hardware/radio/network/SecurityAlgorithm.aidl +++ b/radio/aidl/android/hardware/radio/network/SecurityAlgorithm.aidl @@ -62,7 +62,7 @@ enum SecurityAlgorithm { // IMS and SIP layer security (See 3GPP TS 33.203) // No IPsec config SIP_NO_IPSEC_CONFIG = 66, - IMS_NULL = 67, + IMS_NULL = 67, // Deprecated. Use SIP_NO_IPSEC_CONFIG and SIP_NULL instead. // Has IPsec config SIP_NULL = 68, diff --git a/radio/aidl/vts/radio_network_test.cpp b/radio/aidl/vts/radio_network_test.cpp index ec2a29c677..914cad0cd2 100644 --- a/radio/aidl/vts/radio_network_test.cpp +++ b/radio/aidl/vts/radio_network_test.cpp @@ -2171,6 +2171,14 @@ TEST_P(RadioNetworkTest, setEmergencyMode) { // exit emergency mode for other tests serial = GetRandomSerialNumber(); radio_network->exitEmergencyMode(serial); + + EXPECT_EQ(std::cv_status::no_timeout, wait()); + EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type); + EXPECT_EQ(serial, radioRsp_network->rspInfo.serial); + + ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error, + {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED, + RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR})); } /* diff --git a/sensors/aidl/default/include/sensors-impl/Sensors.h b/sensors/aidl/default/include/sensors-impl/Sensors.h index e270d9682e..2adbc9dfb4 100644 --- a/sensors/aidl/default/include/sensors-impl/Sensors.h +++ b/sensors/aidl/default/include/sensors-impl/Sensors.h @@ -119,6 +119,8 @@ class Sensors : public BnSensors, public ISensorsEventCallback { // Utility function to delete the Event Flag void deleteEventFlag() { + // Hold the lock to ensure we don't delete the flag while it's being used in postEvents() + std::lock_guard lock(mWriteLock); if (mEventQueueFlag != nullptr) { status_t status = EventFlag::deleteEventFlag(&mEventQueueFlag); if (status != OK) { diff --git a/thermal/aidl/vts/VtsHalThermalTargetTest.cpp b/thermal/aidl/vts/VtsHalThermalTargetTest.cpp index 4208d093f8..7f33e2df66 100644 --- a/thermal/aidl/vts/VtsHalThermalTargetTest.cpp +++ b/thermal/aidl/vts/VtsHalThermalTargetTest.cpp @@ -25,6 +25,7 @@ #define LOG_TAG "thermal_aidl_hal_test" +#include #include #include #include @@ -70,6 +71,16 @@ static const CoolingDevice kCoolingDevice = { .timeWindowMs = 7000, }; +static const std::string FEATURE_WATCH = "android.hardware.type.watch"; +static const std::string FEATURE_TELEVISION = "android.hardware.type.television"; +static const std::string FEATURE_LEANBACK = "android.software.leanback"; +static const std::string FEATURE_AUTOMOTIVE = "android.hardware.type.automotive"; +static const std::string FEATURE_PC = "android.hardware.type.pc"; +static const std::string FEATURE_EMBEDDED = "android.hardware.type.embedded"; +static const std::string kNonHandheldFeatures[] = {FEATURE_AUTOMOTIVE, FEATURE_LEANBACK, + FEATURE_PC, FEATURE_TELEVISION, + FEATURE_WATCH, FEATURE_EMBEDDED}; + // Callback class for receiving thermal event notifications from main class class ThermalCallback : public BnThermalChangedCallback { public: @@ -341,8 +352,13 @@ TEST_P(ThermalAidlTest, TemperatureThresholdTest) { // @VsrTest = VSR-3.2.5-002 TEST_P(ThermalAidlTest, SkinTemperatureThresholdsTest) { auto apiLevel = ::android::base::GetIntProperty("ro.vendor.api_level", 0); - if (apiLevel < 35) { - GTEST_SKIP() << "Skipping test as the vendor level is below 35: " << apiLevel; + if (apiLevel < 202404) { + GTEST_SKIP() << "Skipping test as the vendor level is below 202404: " << apiLevel; + } + for (const auto& feature : kNonHandheldFeatures) { + if (::testing::deviceSupportsFeature(feature.c_str())) { + GTEST_SKIP() << "Skipping test as the device has feature: " << feature; + } } std::vector temperatures; ::ndk::ScopedAStatus status = diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp index 6c6846f636..db474d6920 100644 --- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp +++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp @@ -41,6 +41,8 @@ using android::hardware::vibrator::IVibratorManager; using android::hardware::vibrator::PrimitivePwle; using std::chrono::high_resolution_clock; +using namespace ::std::chrono_literals; + const std::vector kEffects{android::enum_range().begin(), android::enum_range().end()}; const std::vector kEffectStrengths{android::enum_range().begin(), @@ -71,6 +73,9 @@ const std::vector kInvalidPrimitives = { static_cast(static_cast(kCompositePrimitives.back()) + 1), }; +// Timeout to wait for vibration callback completion. +static constexpr auto VIBRATION_CALLBACK_TIMEOUT = 100ms; + class CompletionCallback : public BnVibratorCallback { public: CompletionCallback(const std::function &callback) : mCallback(callback) {} @@ -221,7 +226,7 @@ TEST_P(VibratorAidl, OnWithCallback) { sp callback = new CompletionCallback([&completionPromise] { completionPromise.set_value(); }); uint32_t durationMs = 250; - std::chrono::milliseconds timeout{durationMs * 2}; + auto timeout = std::chrono::milliseconds(durationMs) + VIBRATION_CALLBACK_TIMEOUT; EXPECT_TRUE(vibrator->on(durationMs, callback).isOk()); EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready); EXPECT_TRUE(vibrator->off().isOk()); @@ -288,10 +293,10 @@ TEST_P(VibratorAidl, ValidateEffectWithCallback) { if (!status.isOk()) continue; - //TODO(b/187207798): revert back to conservative timeout values once - //latencies have been fixed - std::chrono::milliseconds timeout{lengthMs * 8}; + auto timeout = std::chrono::milliseconds(lengthMs) + VIBRATION_CALLBACK_TIMEOUT; EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready); + + EXPECT_TRUE(vibrator->off().isOk()); } } } @@ -619,9 +624,7 @@ TEST_P(VibratorAidl, ComposeCallback) { EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, callback).exceptionCode()) << toString(primitive); - // TODO(b/261130361): Investigate why latency from driver and hardware will cause test - // to fail when wait duration is ~40ms or less. - EXPECT_EQ(completionFuture.wait_for(duration + std::chrono::milliseconds(50)), + EXPECT_EQ(completionFuture.wait_for(duration + VIBRATION_CALLBACK_TIMEOUT), std::future_status::ready) << toString(primitive); end = high_resolution_clock::now(); @@ -782,9 +785,7 @@ TEST_P(VibratorAidl, ComposeValidPwleWithCallback) { int32_t segmentDurationMaxMs; vibrator->getPwlePrimitiveDurationMax(&segmentDurationMaxMs); uint32_t durationMs = segmentDurationMaxMs * 2 + 100; // Sum of 2 active and 1 braking below - //TODO(b/187207798): revert back to conservative timeout values once - //latencies have been fixed - std::chrono::milliseconds timeout{durationMs * 4}; + auto timeout = std::chrono::milliseconds(durationMs) + VIBRATION_CALLBACK_TIMEOUT; ActivePwle active = composeValidActivePwle(vibrator, capabilities); diff --git a/vibrator/bench/benchmark.cpp b/vibrator/bench/benchmark.cpp index b96e06da5b..deaa6f2c55 100644 --- a/vibrator/bench/benchmark.cpp +++ b/vibrator/bench/benchmark.cpp @@ -20,6 +20,8 @@ #include #include #include +#include +#include using ::android::enum_range; using ::android::sp; @@ -31,9 +33,8 @@ using ::benchmark::Fixture; using ::benchmark::kMicrosecond; using ::benchmark::State; using ::benchmark::internal::Benchmark; -using ::std::chrono::duration; -using ::std::chrono::duration_cast; -using ::std::chrono::high_resolution_clock; + +using namespace ::std::chrono_literals; namespace Aidl = ::android::hardware::vibrator; namespace V1_0 = ::android::hardware::vibrator::V1_0; @@ -41,14 +42,28 @@ namespace V1_1 = ::android::hardware::vibrator::V1_1; namespace V1_2 = ::android::hardware::vibrator::V1_2; namespace V1_3 = ::android::hardware::vibrator::V1_3; +// Fixed number of iterations for benchmarks that trigger a vibration on the loop. +// They require slow cleanup to ensure a stable state on each run and less noisy metrics. +static constexpr auto VIBRATION_ITERATIONS = 500; + +// Timeout to wait for vibration callback completion. +static constexpr auto VIBRATION_CALLBACK_TIMEOUT = 100ms; + +// Max duration the vibrator can be turned on, in milliseconds. +static constexpr uint32_t MAX_ON_DURATION_MS = UINT16_MAX; + template class BaseBench : public Fixture { public: + void SetUp(State& /*state*/) override { + android::ProcessState::self()->setThreadPoolMaxThreadCount(1); + android::ProcessState::self()->startThreadPool(); + } + void TearDown(State& /*state*/) override { - if (!mVibrator) { - return; + if (mVibrator) { + mVibrator->off(); } - mVibrator->off(); } static void DefaultConfig(Benchmark* b) { b->Unit(kMicrosecond); } @@ -66,7 +81,19 @@ class BaseBench : public Fixture { template class VibratorBench : public BaseBench { public: - void SetUp(State& /*state*/) override { this->mVibrator = I::getService(); } + void SetUp(State& state) override { + BaseBench::SetUp(state); + this->mVibrator = I::getService(); + } + + protected: + bool shouldSkipWithError(State& state, const android::hardware::Return&& ret) { + if (!ret.isOk()) { + state.SkipWithError(ret.description()); + return true; + } + return false; + } }; enum class EmptyEnum : uint32_t; @@ -118,16 +145,25 @@ class VibratorEffectsBench : public VibratorBench { }); if (!supported) { - state->SkipWithMessage("performApi returned UNSUPPORTED_OPERATION"); + state->SkipWithMessage("effect unsupported"); return; } for (auto _ : *state) { - state->ResumeTiming(); - (*this->mVibrator.*performApi)(effect, strength, - [](Status /*status*/, uint32_t /*lengthMs*/) {}); + // Test + auto ret = (*this->mVibrator.*performApi)( + effect, strength, [](Status /*status*/, uint32_t /*lengthMs*/) {}); + + // Cleanup state->PauseTiming(); - this->mVibrator->off(); + if (!ret.isOk()) { + state->SkipWithError(ret.description()); + return; + } + if (this->shouldSkipWithError(*state, this->mVibrator->off())) { + return; + } + state->ResumeTiming(); } } @@ -157,24 +193,38 @@ class VibratorEffectsBench : public VibratorBench { using VibratorBench_V1_0 = VibratorBench; BENCHMARK_WRAPPER(VibratorBench_V1_0, on, { - uint32_t ms = UINT32_MAX; + auto ms = MAX_ON_DURATION_MS; for (auto _ : state) { - state.ResumeTiming(); - mVibrator->on(ms); + // Test + if (shouldSkipWithError(state, mVibrator->on(ms))) { + return; + } + + // Cleanup state.PauseTiming(); - mVibrator->off(); + if (shouldSkipWithError(state, mVibrator->off())) { + return; + } + state.ResumeTiming(); } }); BENCHMARK_WRAPPER(VibratorBench_V1_0, off, { - uint32_t ms = UINT32_MAX; + auto ms = MAX_ON_DURATION_MS; for (auto _ : state) { + // Setup state.PauseTiming(); - mVibrator->on(ms); + if (shouldSkipWithError(state, mVibrator->on(ms))) { + return; + } state.ResumeTiming(); - mVibrator->off(); + + // Test + if (shouldSkipWithError(state, mVibrator->off())) { + return; + } } }); @@ -185,20 +235,23 @@ BENCHMARK_WRAPPER(VibratorBench_V1_0, supportsAmplitudeControl, { }); BENCHMARK_WRAPPER(VibratorBench_V1_0, setAmplitude, { + auto ms = MAX_ON_DURATION_MS; uint8_t amplitude = UINT8_MAX; if (!mVibrator->supportsAmplitudeControl()) { - state.SkipWithMessage("Amplitude control unavailable"); + state.SkipWithMessage("amplitude control unavailable"); return; } - mVibrator->on(UINT32_MAX); - - for (auto _ : state) { - mVibrator->setAmplitude(amplitude); + if (shouldSkipWithError(state, mVibrator->on(ms))) { + return; } - mVibrator->off(); + for (auto _ : state) { + if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) { + return; + } + } }); using VibratorEffectsBench_V1_0 = VibratorEffectsBench; @@ -218,7 +271,15 @@ using VibratorEffectsBench_V1_2 = BENCHMARK_WRAPPER(VibratorEffectsBench_V1_2, perform_1_2, { performBench(&state, &V1_2::IVibrator::perform_1_2); }); -using VibratorBench_V1_3 = VibratorBench; +class VibratorBench_V1_3 : public VibratorBench { + public: + void TearDown(State& state) override { + VibratorBench::TearDown(state); + if (mVibrator) { + mVibrator->setExternalControl(false); + } + } +}; BENCHMARK_WRAPPER(VibratorBench_V1_3, supportsExternalControl, { for (auto _ : state) { @@ -227,18 +288,23 @@ BENCHMARK_WRAPPER(VibratorBench_V1_3, supportsExternalControl, { }); BENCHMARK_WRAPPER(VibratorBench_V1_3, setExternalControl, { - bool enable = true; - if (!mVibrator->supportsExternalControl()) { state.SkipWithMessage("external control unavailable"); return; } for (auto _ : state) { - state.ResumeTiming(); - mVibrator->setExternalControl(enable); + // Test + if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) { + return; + } + + // Cleanup state.PauseTiming(); - mVibrator->setExternalControl(false); + if (shouldSkipWithError(state, mVibrator->setExternalControl(false))) { + return; + } + state.ResumeTiming(); } }); @@ -248,13 +314,13 @@ BENCHMARK_WRAPPER(VibratorBench_V1_3, supportsExternalAmplitudeControl, { return; } - mVibrator->setExternalControl(true); + if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) { + return; + } for (auto _ : state) { mVibrator->supportsAmplitudeControl(); } - - mVibrator->setExternalControl(false); }); BENCHMARK_WRAPPER(VibratorBench_V1_3, setExternalAmplitude, { @@ -265,7 +331,9 @@ BENCHMARK_WRAPPER(VibratorBench_V1_3, setExternalAmplitude, { return; } - mVibrator->setExternalControl(true); + if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) { + return; + } if (!mVibrator->supportsAmplitudeControl()) { state.SkipWithMessage("amplitude control unavailable"); @@ -273,10 +341,10 @@ BENCHMARK_WRAPPER(VibratorBench_V1_3, setExternalAmplitude, { } for (auto _ : state) { - mVibrator->setAmplitude(amplitude); + if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) { + return; + } } - - mVibrator->setExternalControl(false); }); using VibratorEffectsBench_V1_3 = VibratorEffectsBench; @@ -286,9 +354,42 @@ BENCHMARK_WRAPPER(VibratorEffectsBench_V1_3, perform_1_3, class VibratorBench_Aidl : public BaseBench { public: - void SetUp(State& /*state*/) override { + void SetUp(State& state) override { + BaseBench::SetUp(state); this->mVibrator = android::waitForVintfService(); } + + void TearDown(State& state) override { + BaseBench::TearDown(state); + if (mVibrator) { + mVibrator->setExternalControl(false); + } + } + + protected: + int32_t hasCapabilities(int32_t capabilities) { + int32_t deviceCapabilities = 0; + this->mVibrator->getCapabilities(&deviceCapabilities); + return (deviceCapabilities & capabilities) == capabilities; + } + + bool shouldSkipWithError(State& state, const android::binder::Status&& status) { + if (!status.isOk()) { + state.SkipWithError(status.toString8().c_str()); + return true; + } + return false; + } + + static void SlowBenchConfig(Benchmark* b) { b->Iterations(VIBRATION_ITERATIONS); } +}; + +class SlowVibratorBench_Aidl : public VibratorBench_Aidl { + public: + static void DefaultConfig(Benchmark* b) { + VibratorBench_Aidl::DefaultConfig(b); + SlowBenchConfig(b); + } }; class HalCallback : public Aidl::BnVibratorCallback { @@ -296,30 +397,70 @@ class HalCallback : public Aidl::BnVibratorCallback { HalCallback() = default; ~HalCallback() = default; - android::binder::Status onComplete() override { return android::binder::Status::ok(); } + android::binder::Status onComplete() override { + mPromise.set_value(); + return android::binder::Status::ok(); + } + + void waitForComplete() { + // Wait until the HAL has finished processing previous vibration before starting a new one, + // so the HAL state is consistent on each run and metrics are less noisy. Some of the newest + // HAL implementations are waiting on previous vibration cleanup and might be significantly + // slower, so make sure we measure vibrations on a clean slate. + mPromise.get_future().wait_for(VIBRATION_CALLBACK_TIMEOUT); + } + + private: + std::promise mPromise; }; -BENCHMARK_WRAPPER(VibratorBench_Aidl, on, { - int32_t capabilities = 0; - mVibrator->getCapabilities(&capabilities); - - int32_t ms = INT32_MAX; - auto cb = (capabilities & Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr; +BENCHMARK_WRAPPER(SlowVibratorBench_Aidl, on, { + auto ms = MAX_ON_DURATION_MS; for (auto _ : state) { - state.ResumeTiming(); - mVibrator->on(ms, cb); + auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr; + + // Test + if (shouldSkipWithError(state, mVibrator->on(ms, cb))) { + return; + } + + // Cleanup state.PauseTiming(); - mVibrator->off(); + if (shouldSkipWithError(state, mVibrator->off())) { + return; + } + if (cb) { + cb->waitForComplete(); + } + state.ResumeTiming(); } }); -BENCHMARK_WRAPPER(VibratorBench_Aidl, off, { +BENCHMARK_WRAPPER(SlowVibratorBench_Aidl, off, { + auto ms = MAX_ON_DURATION_MS; + for (auto _ : state) { + auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr; + + // Setup state.PauseTiming(); - mVibrator->on(INT32_MAX, nullptr); + if (shouldSkipWithError(state, mVibrator->on(ms, cb))) { + return; + } + state.ResumeTiming(); + + // Test + if (shouldSkipWithError(state, mVibrator->off())) { + return; + } + + // Cleanup + state.PauseTiming(); + if (cb) { + cb->waitForComplete(); + } state.ResumeTiming(); - mVibrator->off(); } }); @@ -327,76 +468,97 @@ BENCHMARK_WRAPPER(VibratorBench_Aidl, getCapabilities, { int32_t capabilities = 0; for (auto _ : state) { - mVibrator->getCapabilities(&capabilities); + if (shouldSkipWithError(state, mVibrator->getCapabilities(&capabilities))) { + return; + } } }); BENCHMARK_WRAPPER(VibratorBench_Aidl, setAmplitude, { - int32_t capabilities = 0; - mVibrator->getCapabilities(&capabilities); - if ((capabilities & Aidl::IVibrator::CAP_AMPLITUDE_CONTROL) == 0) { + auto ms = MAX_ON_DURATION_MS; + float amplitude = 1.0f; + + if (!hasCapabilities(Aidl::IVibrator::CAP_AMPLITUDE_CONTROL)) { state.SkipWithMessage("amplitude control unavailable"); return; } - float amplitude = 1.0f; - mVibrator->on(INT32_MAX, nullptr); - - for (auto _ : state) { - mVibrator->setAmplitude(amplitude); + auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr; + if (shouldSkipWithError(state, mVibrator->on(ms, cb))) { + return; } - mVibrator->off(); + for (auto _ : state) { + if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) { + return; + } + } }); BENCHMARK_WRAPPER(VibratorBench_Aidl, setExternalControl, { - int32_t capabilities = 0; - mVibrator->getCapabilities(&capabilities); - if ((capabilities & Aidl::IVibrator::CAP_EXTERNAL_CONTROL) == 0) { + if (!hasCapabilities(Aidl::IVibrator::CAP_EXTERNAL_CONTROL)) { state.SkipWithMessage("external control unavailable"); return; } for (auto _ : state) { - state.ResumeTiming(); - mVibrator->setExternalControl(true); + // Test + if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) { + return; + } + + // Cleanup state.PauseTiming(); - mVibrator->setExternalControl(false); + if (shouldSkipWithError(state, mVibrator->setExternalControl(false))) { + return; + } + state.ResumeTiming(); } }); BENCHMARK_WRAPPER(VibratorBench_Aidl, setExternalAmplitude, { - int32_t capabilities = 0; - mVibrator->getCapabilities(&capabilities); - if ((capabilities & Aidl::IVibrator::CAP_EXTERNAL_CONTROL) == 0 || - (capabilities & Aidl::IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL) == 0) { + auto externalControl = static_cast(Aidl::IVibrator::CAP_EXTERNAL_CONTROL); + auto externalAmplitudeControl = + static_cast(Aidl::IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL); + if (!hasCapabilities(externalControl | externalAmplitudeControl)) { state.SkipWithMessage("external amplitude control unavailable"); return; } - float amplitude = 1.0f; - mVibrator->setExternalControl(true); - - for (auto _ : state) { - mVibrator->setAmplitude(amplitude); + if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) { + return; } - mVibrator->setExternalControl(false); + float amplitude = 1.0f; + for (auto _ : state) { + if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) { + return; + } + } }); BENCHMARK_WRAPPER(VibratorBench_Aidl, getSupportedEffects, { std::vector supportedEffects; for (auto _ : state) { - mVibrator->getSupportedEffects(&supportedEffects); + if (shouldSkipWithError(state, mVibrator->getSupportedEffects(&supportedEffects))) { + return; + } } }); BENCHMARK_WRAPPER(VibratorBench_Aidl, getSupportedAlwaysOnEffects, { + if (!hasCapabilities(Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL)) { + state.SkipWithMessage("always on control unavailable"); + return; + } + std::vector supportedEffects; for (auto _ : state) { - mVibrator->getSupportedAlwaysOnEffects(&supportedEffects); + if (shouldSkipWithError(state, mVibrator->getSupportedAlwaysOnEffects(&supportedEffects))) { + return; + } } }); @@ -404,7 +566,9 @@ BENCHMARK_WRAPPER(VibratorBench_Aidl, getSupportedPrimitives, { std::vector supportedPrimitives; for (auto _ : state) { - mVibrator->getSupportedPrimitives(&supportedPrimitives); + if (shouldSkipWithError(state, mVibrator->getSupportedPrimitives(&supportedPrimitives))) { + return; + } } }); @@ -427,12 +591,30 @@ class VibratorEffectsBench_Aidl : public VibratorBench_Aidl { auto getStrength(const State& state) const { return static_cast(this->getOtherArg(state, 1)); } + + bool isEffectSupported(const Aidl::Effect& effect) { + std::vector supported; + mVibrator->getSupportedEffects(&supported); + return std::find(supported.begin(), supported.end(), effect) != supported.end(); + } + + bool isAlwaysOnEffectSupported(const Aidl::Effect& effect) { + std::vector supported; + mVibrator->getSupportedAlwaysOnEffects(&supported); + return std::find(supported.begin(), supported.end(), effect) != supported.end(); + } +}; + +class SlowVibratorEffectsBench_Aidl : public VibratorEffectsBench_Aidl { + public: + static void DefaultConfig(Benchmark* b) { + VibratorEffectsBench_Aidl::DefaultConfig(b); + SlowBenchConfig(b); + } }; BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, alwaysOnEnable, { - int32_t capabilities = 0; - mVibrator->getCapabilities(&capabilities); - if ((capabilities & Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL) == 0) { + if (!hasCapabilities(Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL)) { state.SkipWithMessage("always on control unavailable"); return; } @@ -441,25 +623,28 @@ BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, alwaysOnEnable, { auto effect = getEffect(state); auto strength = getStrength(state); - std::vector supported; - mVibrator->getSupportedAlwaysOnEffects(&supported); - if (std::find(supported.begin(), supported.end(), effect) == supported.end()) { - state.SkipWithMessage("always on effects unavailable"); + if (!isAlwaysOnEffectSupported(effect)) { + state.SkipWithMessage("always on effect unsupported"); return; } for (auto _ : state) { - state.ResumeTiming(); - mVibrator->alwaysOnEnable(id, effect, strength); + // Test + if (shouldSkipWithError(state, mVibrator->alwaysOnEnable(id, effect, strength))) { + return; + } + + // Cleanup state.PauseTiming(); - mVibrator->alwaysOnDisable(id); + if (shouldSkipWithError(state, mVibrator->alwaysOnDisable(id))) { + return; + } + state.ResumeTiming(); } }); BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, alwaysOnDisable, { - int32_t capabilities = 0; - mVibrator->getCapabilities(&capabilities); - if ((capabilities & Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL) == 0) { + if (!hasCapabilities(Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL)) { state.SkipWithMessage("always on control unavailable"); return; } @@ -468,42 +653,55 @@ BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, alwaysOnDisable, { auto effect = getEffect(state); auto strength = getStrength(state); - std::vector supported; - mVibrator->getSupportedAlwaysOnEffects(&supported); - if (std::find(supported.begin(), supported.end(), effect) == supported.end()) { - state.SkipWithMessage("always on effects unavailable"); + if (!isAlwaysOnEffectSupported(effect)) { + state.SkipWithMessage("always on effect unsupported"); return; } for (auto _ : state) { + // Setup state.PauseTiming(); - mVibrator->alwaysOnEnable(id, effect, strength); + if (shouldSkipWithError(state, mVibrator->alwaysOnEnable(id, effect, strength))) { + return; + } state.ResumeTiming(); - mVibrator->alwaysOnDisable(id); + + // Test + if (shouldSkipWithError(state, mVibrator->alwaysOnDisable(id))) { + return; + } } }); -BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, perform, { - int32_t capabilities = 0; - mVibrator->getCapabilities(&capabilities); - +BENCHMARK_WRAPPER(SlowVibratorEffectsBench_Aidl, perform, { auto effect = getEffect(state); auto strength = getStrength(state); - auto cb = (capabilities & Aidl::IVibrator::CAP_PERFORM_CALLBACK) ? new HalCallback() : nullptr; - int32_t lengthMs = 0; - std::vector supported; - mVibrator->getSupportedEffects(&supported); - if (std::find(supported.begin(), supported.end(), effect) == supported.end()) { - state.SkipWithMessage("effects unavailable"); + if (!isEffectSupported(effect)) { + state.SkipWithMessage("effect unsupported"); return; } + int32_t lengthMs = 0; + for (auto _ : state) { - state.ResumeTiming(); - mVibrator->perform(effect, strength, cb, &lengthMs); + auto cb = hasCapabilities(Aidl::IVibrator::CAP_PERFORM_CALLBACK) ? new HalCallback() + : nullptr; + + // Test + if (shouldSkipWithError(state, mVibrator->perform(effect, strength, cb, &lengthMs))) { + return; + } + + // Cleanup state.PauseTiming(); - mVibrator->off(); + if (shouldSkipWithError(state, mVibrator->off())) { + return; + } + if (cb) { + cb->waitForComplete(); + } + state.ResumeTiming(); } }); @@ -520,13 +718,29 @@ class VibratorPrimitivesBench_Aidl : public VibratorBench_Aidl { auto getPrimitive(const State& state) const { return static_cast(this->getOtherArg(state, 0)); } + + bool isPrimitiveSupported(const Aidl::CompositePrimitive& primitive) { + std::vector supported; + mVibrator->getSupportedPrimitives(&supported); + return std::find(supported.begin(), supported.end(), primitive) != supported.end(); + } +}; + +class SlowVibratorPrimitivesBench_Aidl : public VibratorPrimitivesBench_Aidl { + public: + static void DefaultConfig(Benchmark* b) { + VibratorPrimitivesBench_Aidl::DefaultConfig(b); + SlowBenchConfig(b); + } }; BENCHMARK_WRAPPER(VibratorBench_Aidl, getCompositionDelayMax, { int32_t ms = 0; for (auto _ : state) { - mVibrator->getCompositionDelayMax(&ms); + if (shouldSkipWithError(state, mVibrator->getCompositionDelayMax(&ms))) { + return; + } } }); @@ -534,14 +748,14 @@ BENCHMARK_WRAPPER(VibratorBench_Aidl, getCompositionSizeMax, { int32_t size = 0; for (auto _ : state) { - mVibrator->getCompositionSizeMax(&size); + if (shouldSkipWithError(state, mVibrator->getCompositionSizeMax(&size))) { + return; + } } }); BENCHMARK_WRAPPER(VibratorPrimitivesBench_Aidl, getPrimitiveDuration, { - int32_t capabilities = 0; - mVibrator->getCapabilities(&capabilities); - if ((capabilities & Aidl::IVibrator::CAP_COMPOSE_EFFECTS) == 0) { + if (!hasCapabilities(Aidl::IVibrator::CAP_COMPOSE_EFFECTS)) { state.SkipWithMessage("compose effects unavailable"); return; } @@ -549,22 +763,20 @@ BENCHMARK_WRAPPER(VibratorPrimitivesBench_Aidl, getPrimitiveDuration, { auto primitive = getPrimitive(state); int32_t ms = 0; - std::vector supported; - mVibrator->getSupportedPrimitives(&supported); - if (std::find(supported.begin(), supported.end(), primitive) == supported.end()) { - state.SkipWithMessage("supported primitives unavailable"); + if (!isPrimitiveSupported(primitive)) { + state.SkipWithMessage("primitive unsupported"); return; } for (auto _ : state) { - mVibrator->getPrimitiveDuration(primitive, &ms); + if (shouldSkipWithError(state, mVibrator->getPrimitiveDuration(primitive, &ms))) { + return; + } } }); -BENCHMARK_WRAPPER(VibratorPrimitivesBench_Aidl, compose, { - int32_t capabilities = 0; - mVibrator->getCapabilities(&capabilities); - if ((capabilities & Aidl::IVibrator::CAP_COMPOSE_EFFECTS) == 0) { +BENCHMARK_WRAPPER(SlowVibratorPrimitivesBench_Aidl, compose, { + if (!hasCapabilities(Aidl::IVibrator::CAP_COMPOSE_EFFECTS)) { state.SkipWithMessage("compose effects unavailable"); return; } @@ -574,22 +786,33 @@ BENCHMARK_WRAPPER(VibratorPrimitivesBench_Aidl, compose, { effect.scale = 1.0f; effect.delayMs = 0; - std::vector supported; - mVibrator->getSupportedPrimitives(&supported); - if (std::find(supported.begin(), supported.end(), effect.primitive) == supported.end()) { - state.SkipWithMessage("supported primitives unavailable"); + if (effect.primitive == Aidl::CompositePrimitive::NOOP) { + state.SkipWithMessage("skipping primitive NOOP"); + return; + } + if (!isPrimitiveSupported(effect.primitive)) { + state.SkipWithMessage("primitive unsupported"); return; } - auto cb = new HalCallback(); std::vector effects; effects.push_back(effect); for (auto _ : state) { - state.ResumeTiming(); - mVibrator->compose(effects, cb); + auto cb = new HalCallback(); + + // Test + if (shouldSkipWithError(state, mVibrator->compose(effects, cb))) { + return; + } + + // Cleanup state.PauseTiming(); - mVibrator->off(); + if (shouldSkipWithError(state, mVibrator->off())) { + return; + } + cb->waitForComplete(); + state.ResumeTiming(); } }); diff --git a/wifi/aidl/default/aidl_struct_util.cpp b/wifi/aidl/default/aidl_struct_util.cpp index d9e023c80e..d82450e348 100644 --- a/wifi/aidl/default/aidl_struct_util.cpp +++ b/wifi/aidl/default/aidl_struct_util.cpp @@ -525,6 +525,7 @@ bool convertLegacyGscanCapabilitiesToAidl(const legacy_hal::wifi_gscan_capabilit return true; } +// Only use to prepare parameters for Gscan. legacy_hal::wifi_band convertAidlWifiBandToLegacy(WifiBand band) { switch (band) { case WifiBand::BAND_UNSPECIFIED: @@ -541,6 +542,15 @@ legacy_hal::wifi_band convertAidlWifiBandToLegacy(WifiBand band) { return legacy_hal::WIFI_BAND_ABG; case WifiBand::BAND_24GHZ_5GHZ_WITH_DFS: return legacy_hal::WIFI_BAND_ABG_WITH_DFS; + case WifiBand::BAND_6GHZ: + case WifiBand::BAND_60GHZ: + case WifiBand::BAND_5GHZ_6GHZ: + case WifiBand::BAND_24GHZ_5GHZ_6GHZ: + case WifiBand::BAND_24GHZ_5GHZ_6GHZ_60GHZ: + case WifiBand::BAND_24GHZ_5GHZ_WITH_DFS_6GHZ: + case WifiBand::BAND_24GHZ_5GHZ_WITH_DFS_6GHZ_60GHZ: + LOG(INFO) << "WifiBand mapping may be incorrect, since 6GHz is not supported by legacy"; + return legacy_hal::WIFI_BAND_UNSPECIFIED; default: CHECK(false); return {}; diff --git a/wifi/aidl/default/wifi_legacy_hal.cpp b/wifi/aidl/default/wifi_legacy_hal.cpp index cf86120032..bd92a20f8d 100644 --- a/wifi/aidl/default/wifi_legacy_hal.cpp +++ b/wifi/aidl/default/wifi_legacy_hal.cpp @@ -2012,7 +2012,7 @@ wifi_error WifiLegacyHal::twtClearStats(const std::string& iface_name, uint8_t c } wifi_error WifiLegacyHal::setScanMode(const std::string& iface_name, bool enable) { - return global_func_table_.wifi_set_scan_mode(iface_name.c_str(), enable); + return global_func_table_.wifi_set_scan_mode(getIfaceHandle(iface_name), enable); } wifi_error WifiLegacyHal::setDtimConfig(const std::string& iface_name, uint32_t multiplier) { diff --git a/wifi/legacy_headers/include/hardware_legacy/wifi_hal.h b/wifi/legacy_headers/include/hardware_legacy/wifi_hal.h index e770777aae..9baa2c7809 100644 --- a/wifi/legacy_headers/include/hardware_legacy/wifi_hal.h +++ b/wifi/legacy_headers/include/hardware_legacy/wifi_hal.h @@ -715,7 +715,7 @@ typedef struct wlan_driver_wake_reason_cnt_t { /* Wi-Fi coex channel avoidance support */ -#define WIFI_COEX_NO_POWER_CAP (int32_t)0x7FFFFFF +#define WIFI_COEX_NO_POWER_CAP (int32_t)0x7FFFFFFF typedef enum { WIFI_AWARE = 1 << 0, @@ -1386,7 +1386,7 @@ typedef struct { * @param enable true if current is scan only mode * @return Synchronous wifi_error */ - wifi_error (*wifi_set_scan_mode)(const char * ifname, bool enable); + wifi_error (*wifi_set_scan_mode)(wifi_interface_handle iface, bool enable); wifi_error (*wifi_nan_pairing_end)(transaction_id id, wifi_interface_handle iface,