diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp index 14082eba1fdc72bfa1712b78e8a46f2e5692ebdd..36fd0d053d4fcbe2821d91faaaa2bdb3925ddede 100644 --- a/audio/aidl/default/Android.bp +++ b/audio/aidl/default/Android.bp @@ -202,6 +202,47 @@ cc_test { test_suites: ["general-tests"], } +cc_test { + name: "audio_alsa_utils_tests", + vendor_available: true, + defaults: [ + "latest_android_media_audio_common_types_ndk_static", + "latest_android_hardware_audio_core_ndk_static", + ], + static_libs: [ + "libalsautilsv2", + "libtinyalsav2", + ], + shared_libs: [ + "libaudio_aidl_conversion_common_ndk", + "libaudioaidlcommon", + "libaudioutils", + "libbase", + "libbinder_ndk", + "libcutils", + "libfmq", + "libmedia_helper", + "libstagefright_foundation", + "libutils", + ], + header_libs: [ + "libaudio_system_headers", + "libaudioaidl_headers", + ], + srcs: [ + "alsa/Utils.cpp", + "tests/AlsaUtilsTest.cpp", + ], + cflags: [ + "-Wall", + "-Wextra", + "-Werror", + "-Wthread-safety", + "-DBACKEND_NDK", + ], + test_suites: ["general-tests"], +} + cc_defaults { name: "aidlaudioeffectservice_defaults", defaults: [ diff --git a/audio/aidl/default/alsa/Utils.cpp b/audio/aidl/default/alsa/Utils.cpp index 10374f23161cb04e39708a6a57500379533759a2..77e4f65d2096ffb71faf51ee4149d348e0f45bd9 100644 --- a/audio/aidl/default/alsa/Utils.cpp +++ b/audio/aidl/default/alsa/Utils.cpp @@ -39,6 +39,8 @@ using aidl::android::media::audio::common::PcmType; namespace aidl::android::hardware::audio::core::alsa { +const float kUnityGainFloat = 1.0f; + DeviceProxy::DeviceProxy() : mProfile(nullptr), mProxy(nullptr, alsaProxyDeleter) {} DeviceProxy::DeviceProxy(const DeviceProfile& deviceProfile) @@ -140,7 +142,6 @@ AudioFormatDescription make_AudioFormatDescription(PcmType pcm) { const AudioFormatDescToPcmFormatMap& getAudioFormatDescriptorToPcmFormatMap() { static const AudioFormatDescToPcmFormatMap formatDescToPcmFormatMap = { - {make_AudioFormatDescription(PcmType::UINT_8_BIT), PCM_FORMAT_S8}, {make_AudioFormatDescription(PcmType::INT_16_BIT), PCM_FORMAT_S16_LE}, {make_AudioFormatDescription(PcmType::FIXED_Q_8_24), PCM_FORMAT_S24_LE}, {make_AudioFormatDescription(PcmType::INT_24_BIT), PCM_FORMAT_S24_3LE}, @@ -165,6 +166,92 @@ const PcmFormatToAudioFormatDescMap& getPcmFormatToAudioFormatDescMap() { return pcmFormatToFormatDescMap; } +void applyGainToInt16Buffer(void* buffer, const size_t bufferSizeBytes, const float gain, + int channelCount) { + const uint16_t unityGainQ4_12 = u4_12_from_float(kUnityGainFloat); + const uint16_t vl = u4_12_from_float(gain); + const uint32_t vrl = (vl << 16) | vl; + int numFrames = 0; + if (channelCount == 2) { + numFrames = bufferSizeBytes / sizeof(uint32_t); + if (numFrames == 0) { + return; + } + uint32_t* intBuffer = (uint32_t*)buffer; + if (CC_UNLIKELY(vl > unityGainQ4_12)) { + do { + int32_t l = mulRL(1, *intBuffer, vrl) >> 12; + int32_t r = mulRL(0, *intBuffer, vrl) >> 12; + l = clamp16(l); + r = clamp16(r); + *intBuffer++ = (r << 16) | (l & 0xFFFF); + } while (--numFrames); + } else { + do { + int32_t l = mulRL(1, *intBuffer, vrl) >> 12; + int32_t r = mulRL(0, *intBuffer, vrl) >> 12; + *intBuffer++ = (r << 16) | (l & 0xFFFF); + } while (--numFrames); + } + } else { + numFrames = bufferSizeBytes / sizeof(uint16_t); + if (numFrames == 0) { + return; + } + int16_t* intBuffer = (int16_t*)buffer; + if (CC_UNLIKELY(vl > unityGainQ4_12)) { + do { + int32_t mono = mul(*intBuffer, static_cast(vl)) >> 12; + *intBuffer++ = clamp16(mono); + } while (--numFrames); + } else { + do { + int32_t mono = mul(*intBuffer, static_cast(vl)) >> 12; + *intBuffer++ = static_cast(mono & 0xFFFF); + } while (--numFrames); + } + } +} + +void applyGainToInt32Buffer(int32_t* typedBuffer, const size_t bufferSizeBytes, const float gain) { + int numSamples = bufferSizeBytes / sizeof(int32_t); + if (numSamples == 0) { + return; + } + if (CC_UNLIKELY(gain > kUnityGainFloat)) { + do { + float multiplied = (*typedBuffer) * gain; + if (multiplied > INT32_MAX) { + *typedBuffer++ = INT32_MAX; + } else if (multiplied < INT32_MIN) { + *typedBuffer++ = INT32_MIN; + } else { + *typedBuffer++ = multiplied; + } + } while (--numSamples); + } else { + do { + *typedBuffer++ = (*typedBuffer) * gain; + } while (--numSamples); + } +} + +void applyGainToFloatBuffer(float* floatBuffer, const size_t bufferSizeBytes, const float gain) { + int numSamples = bufferSizeBytes / sizeof(float); + if (numSamples == 0) { + return; + } + if (CC_UNLIKELY(gain > kUnityGainFloat)) { + do { + *floatBuffer++ = std::clamp((*floatBuffer) * gain, -kUnityGainFloat, kUnityGainFloat); + } while (--numSamples); + } else { + do { + *floatBuffer++ = (*floatBuffer) * gain; + } while (--numSamples); + } +} + } // namespace std::ostream& operator<<(std::ostream& os, const DeviceProfile& device) { @@ -345,7 +432,7 @@ pcm_format aidl2c_AudioFormatDescription_pcm_format(const AudioFormatDescription return findValueOrDefault(getAudioFormatDescriptorToPcmFormatMap(), aidl, PCM_FORMAT_INVALID); } -void applyGain(void* buffer, float gain, size_t bytesToTransfer, enum pcm_format pcmFormat, +void applyGain(void* buffer, float gain, size_t bufferSizeBytes, enum pcm_format pcmFormat, int channelCount) { if (channelCount != 1 && channelCount != 2) { LOG(WARNING) << __func__ << ": unsupported channel count " << channelCount; @@ -355,56 +442,37 @@ void applyGain(void* buffer, float gain, size_t bytesToTransfer, enum pcm_format LOG(WARNING) << __func__ << ": unsupported pcm format " << pcmFormat; return; } - const float unityGainFloat = 1.0f; - if (std::abs(gain - unityGainFloat) < 1e-6) { + if (std::abs(gain - kUnityGainFloat) < 1e-6) { return; } - int numFrames; switch (pcmFormat) { - case PCM_FORMAT_S16_LE: { - const uint16_t unityGainQ4_12 = u4_12_from_float(unityGainFloat); - const uint16_t vl = u4_12_from_float(gain); - const uint32_t vrl = (vl << 16) | vl; - if (channelCount == 2) { - numFrames = bytesToTransfer / sizeof(uint32_t); - uint32_t* intBuffer = (uint32_t*)buffer; - if (CC_UNLIKELY(vl > unityGainQ4_12)) { - // volume is boosted, so we might need to clamp even though - // we process only one track. - do { - int32_t l = mulRL(1, *intBuffer, vrl) >> 12; - int32_t r = mulRL(0, *intBuffer, vrl) >> 12; - l = clamp16(l); - r = clamp16(r); - *intBuffer++ = (r << 16) | (l & 0xFFFF); - } while (--numFrames); - } else { - do { - int32_t l = mulRL(1, *intBuffer, vrl) >> 12; - int32_t r = mulRL(0, *intBuffer, vrl) >> 12; - *intBuffer++ = (r << 16) | (l & 0xFFFF); - } while (--numFrames); - } - } else { - numFrames = bytesToTransfer / sizeof(uint16_t); - int16_t* intBuffer = (int16_t*)buffer; - if (CC_UNLIKELY(vl > unityGainQ4_12)) { - // volume is boosted, so we might need to clamp even though - // we process only one track. - do { - int32_t mono = mulRL(1, *intBuffer, vrl) >> 12; - *intBuffer++ = clamp16(mono); - } while (--numFrames); - } else { - do { - int32_t mono = mulRL(1, *intBuffer, vrl) >> 12; - *intBuffer++ = static_cast(mono & 0xFFFF); - } while (--numFrames); - } + case PCM_FORMAT_S16_LE: + applyGainToInt16Buffer(buffer, bufferSizeBytes, gain, channelCount); + break; + case PCM_FORMAT_FLOAT_LE: { + float* floatBuffer = (float*)buffer; + applyGainToFloatBuffer(floatBuffer, bufferSizeBytes, gain); + } break; + case PCM_FORMAT_S24_LE: + // PCM_FORMAT_S24_LE buffer is composed of signed fixed-point 32-bit Q8.23 data with + // min and max limits of the same bit representation as min and max limits of + // PCM_FORMAT_S32_LE buffer. + case PCM_FORMAT_S32_LE: { + int32_t* typedBuffer = (int32_t*)buffer; + applyGainToInt32Buffer(typedBuffer, bufferSizeBytes, gain); + } break; + case PCM_FORMAT_S24_3LE: { + int numSamples = bufferSizeBytes / (sizeof(uint8_t) * 3); + if (numSamples == 0) { + return; } + std::unique_ptr typedBuffer(new int32_t[numSamples]); + memcpy_to_i32_from_p24(typedBuffer.get(), (uint8_t*)buffer, numSamples); + applyGainToInt32Buffer(typedBuffer.get(), numSamples * sizeof(int32_t), gain); + memcpy_to_p24_from_i32((uint8_t*)buffer, typedBuffer.get(), numSamples); } break; default: - // TODO(336370745): Implement gain for other supported formats + LOG(FATAL) << __func__ << ": unsupported pcm format " << pcmFormat; break; } } diff --git a/audio/aidl/default/config/audioPolicy/api/current.txt b/audio/aidl/default/config/audioPolicy/api/current.txt index 0b4800bfdaed3b88e387593fa3e850bbced890d0..c675820c68f2ce7311d68d3304d1297157c0974f 100644 --- a/audio/aidl/default/config/audioPolicy/api/current.txt +++ b/audio/aidl/default/config/audioPolicy/api/current.txt @@ -223,6 +223,18 @@ package android.audio.policy.configuration { enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_FLAC; enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_HE_AAC_V1; enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_HE_AAC_V2; + enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_IAMF_BASE_AAC; + enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_IAMF_BASE_ENHANCED_AAC; + enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_IAMF_BASE_ENHANCED_FLAC; + enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_IAMF_BASE_ENHANCED_OPUS; + enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_IAMF_BASE_ENHANCED_PCM; + enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_IAMF_BASE_FLAC; + enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_IAMF_BASE_OPUS; + enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_IAMF_BASE_PCM; + enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_IAMF_SIMPLE_AAC; + enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_IAMF_SIMPLE_FLAC; + enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_IAMF_SIMPLE_OPUS; + enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_IAMF_SIMPLE_PCM; enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_IEC60958; enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_IEC61937; enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_LC3; diff --git a/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd b/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd index 30b5044576df7a1872b0453414520aa2b8f51f88..94856a5a5c1fee857de5a0cf88db90d7c1e5f470 100644 --- a/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd +++ b/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd @@ -417,6 +417,18 @@ + + + + + + + + + + + + diff --git a/audio/aidl/default/tests/AlsaUtilsTest.cpp b/audio/aidl/default/tests/AlsaUtilsTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..226eea02889cf8dcbc5c0dce81c1c23d97d9931d --- /dev/null +++ b/audio/aidl/default/tests/AlsaUtilsTest.cpp @@ -0,0 +1,253 @@ +/* + * 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. + */ + +#define LOG_TAG "AlsaUtilsTest" + +#include +#include +#include +#include +#include + +extern "C" { +#include +} + +namespace alsa = ::aidl::android::hardware::audio::core::alsa; + +namespace { + +const static constexpr float kInt16tTolerance = 4; +const static constexpr float kIntTolerance = 1; +const static constexpr float kFloatTolerance = 1e-4; +const static constexpr float kUnityGain = 1; +const static constexpr int32_t kInt24Min = -(1 << 23); +const static constexpr int32_t kInt24Max = (1 << 23) - 1; +const static constexpr float kFloatMin = -1; +const static constexpr float kFloatMax = 1; +const static int32_t kQ8_23Min = 0x80000000; +const static int32_t kQ8_23Max = 0x7FFFFFFF; +const static std::vector kInt16Buffer = {10000, 100, 0, INT16_MAX, + INT16_MIN, -2500, 1000, -5800}; +const static std::vector kFloatBuffer = {0.5, -0.6, kFloatMin, 0.01, kFloatMax, 0.0}; +const static std::vector kInt32Buffer = {100, 0, 8000, INT32_MAX, INT32_MIN, -300}; +const static std::vector kQ8_23Buffer = { + kQ8_23Min, kQ8_23Max, 0x00000000, 0x00000001, 0x00400000, static_cast(0xFFD33333)}; +const static std::vector kInt24Buffer = {200, 10, -100, 0, kInt24Min, kInt24Max}; + +template +void* CopyToBuffer(int& bytesToTransfer, std::vector& destBuffer, + const std::vector& srcBuffer) { + bytesToTransfer = srcBuffer.size() * sizeof(T); + destBuffer = srcBuffer; + return destBuffer.data(); +} + +template +void VerifyTypedBufferResults(const std::vector& bufferWithGain, const std::vector& srcBuffer, + float gain, float tolerance) { + for (size_t i = 0; i < srcBuffer.size(); i++) { + EXPECT_NEAR(srcBuffer[i] * gain, static_cast(bufferWithGain[i]), tolerance); + } +} + +template +void VerifyTypedBufferResultsWithClamp(const std::vector& bufferWithGain, + const std::vector& srcBuffer, float gain, float tolerance, + T minValue, T maxValue) { + for (size_t i = 0; i < srcBuffer.size(); i++) { + float expectedResult = std::clamp(srcBuffer[i] * gain, static_cast(minValue), + static_cast(maxValue)); + EXPECT_NEAR(expectedResult, static_cast(bufferWithGain[i]), tolerance); + } +} + +} // namespace + +using ApplyGainTestParameters = std::tuple; +enum { INDEX_PCM_FORMAT, INDEX_CHANNEL_COUNT, INDEX_GAIN }; + +class ApplyGainTest : public ::testing::TestWithParam { + protected: + void SetUp() override; + void VerifyBufferResult(const pcm_format pcmFormat, const float gain); + void VerifyBufferResultWithClamp(const pcm_format pcmFormat, const float gain); + + pcm_format mPcmFormat; + int mBufferSizeBytes; + void* mBuffer; + + private: + std::vector mInt16BufferToConvert; + std::vector mFloatBufferToConvert; + std::vector mInt32BufferToConvert; + std::vector mQ8_23BufferToConvert; + std::vector mInt24BufferToConvert; +}; + +void ApplyGainTest::SetUp() { + mPcmFormat = std::get(GetParam()); + switch (mPcmFormat) { + case PCM_FORMAT_S16_LE: + mBuffer = CopyToBuffer(mBufferSizeBytes, mInt16BufferToConvert, kInt16Buffer); + break; + case PCM_FORMAT_FLOAT_LE: + mBuffer = CopyToBuffer(mBufferSizeBytes, mFloatBufferToConvert, kFloatBuffer); + break; + case PCM_FORMAT_S32_LE: + mBuffer = CopyToBuffer(mBufferSizeBytes, mInt32BufferToConvert, kInt32Buffer); + break; + case PCM_FORMAT_S24_LE: + mBuffer = CopyToBuffer(mBufferSizeBytes, mQ8_23BufferToConvert, kQ8_23Buffer); + break; + case PCM_FORMAT_S24_3LE: { + std::vector original32BitBuffer(kInt24Buffer.begin(), kInt24Buffer.end()); + for (auto& val : original32BitBuffer) { + val <<= 8; + } + mInt24BufferToConvert = std::vector(kInt24Buffer.size()); + mBufferSizeBytes = kInt24Buffer.size() * 3 * sizeof(uint8_t); + memcpy_to_p24_from_i32(reinterpret_cast(mInt24BufferToConvert.data()), + original32BitBuffer.data(), kInt24Buffer.size()); + mBuffer = mInt24BufferToConvert.data(); + } break; + default: + FAIL() << "Unsupported pcm format: " << mPcmFormat; + return; + } +} + +void ApplyGainTest::VerifyBufferResult(const pcm_format pcmFormat, const float gain) { + switch (pcmFormat) { + case PCM_FORMAT_S16_LE: + VerifyTypedBufferResults(mInt16BufferToConvert, kInt16Buffer, gain, kInt16tTolerance); + break; + case PCM_FORMAT_FLOAT_LE: + VerifyTypedBufferResults(mFloatBufferToConvert, kFloatBuffer, gain, kFloatTolerance); + break; + case PCM_FORMAT_S32_LE: + VerifyTypedBufferResults(mInt32BufferToConvert, kInt32Buffer, gain, kIntTolerance); + break; + case PCM_FORMAT_S24_LE: { + for (size_t i = 0; i < kQ8_23Buffer.size(); i++) { + EXPECT_NEAR(float_from_q8_23(kQ8_23Buffer[i]) * gain, + static_cast(float_from_q8_23(mQ8_23BufferToConvert[i])), + kFloatTolerance); + } + } break; + case PCM_FORMAT_S24_3LE: { + size_t bufferSize = kInt24Buffer.size(); + std::vector result32BitBuffer(bufferSize); + memcpy_to_i32_from_p24(result32BitBuffer.data(), + reinterpret_cast(mInt24BufferToConvert.data()), + bufferSize); + for (size_t i = 0; i < bufferSize; i++) { + EXPECT_NEAR(kInt24Buffer[i] * gain, result32BitBuffer[i] >> 8, kIntTolerance); + } + } break; + default: + return; + } +} + +void ApplyGainTest::VerifyBufferResultWithClamp(const pcm_format pcmFormat, const float gain) { + switch (pcmFormat) { + case PCM_FORMAT_S16_LE: + VerifyTypedBufferResultsWithClamp(mInt16BufferToConvert, kInt16Buffer, gain, + kInt16tTolerance, static_cast(INT16_MIN), + static_cast(INT16_MAX)); + break; + case PCM_FORMAT_FLOAT_LE: + VerifyTypedBufferResultsWithClamp(mFloatBufferToConvert, kFloatBuffer, gain, + kFloatTolerance, kFloatMin, kFloatMax); + break; + case PCM_FORMAT_S32_LE: + VerifyTypedBufferResultsWithClamp(mInt32BufferToConvert, kInt32Buffer, gain, + kIntTolerance, INT32_MIN, INT32_MAX); + break; + case PCM_FORMAT_S24_LE: { + for (size_t i = 0; i < kQ8_23Buffer.size(); i++) { + float expectedResult = + std::clamp(float_from_q8_23(kQ8_23Buffer[i]) * gain, + float_from_q8_23(kQ8_23Min), float_from_q8_23(kQ8_23Max)); + EXPECT_NEAR(expectedResult, + static_cast(float_from_q8_23(mQ8_23BufferToConvert[i])), + kFloatTolerance); + } + } break; + case PCM_FORMAT_S24_3LE: { + size_t bufferSize = kInt24Buffer.size(); + std::vector result32BitBuffer(bufferSize); + memcpy_to_i32_from_p24(result32BitBuffer.data(), + reinterpret_cast(mInt24BufferToConvert.data()), + bufferSize); + for (size_t i = 0; i < bufferSize; i++) { + result32BitBuffer[i] >>= 8; + } + VerifyTypedBufferResultsWithClamp(result32BitBuffer, kInt24Buffer, gain, kIntTolerance, + kInt24Min, kInt24Max); + } break; + default: + return; + } +} + +TEST_P(ApplyGainTest, ApplyGain) { + float gain = std::get(GetParam()); + int channelCount = std::get(GetParam()); + + alsa::applyGain(mBuffer, gain, mBufferSizeBytes, mPcmFormat, channelCount); + + if (gain <= kUnityGain) { + VerifyBufferResult(mPcmFormat, gain); + } else { + VerifyBufferResultWithClamp(mPcmFormat, gain); + } +} + +std::string GetApplyGainTestName(const testing::TestParamInfo& info) { + std::string testNameStr; + switch (std::get(info.param)) { + case PCM_FORMAT_S16_LE: + testNameStr = "S16_LE"; + break; + case PCM_FORMAT_FLOAT_LE: + testNameStr = "Float_LE"; + break; + case PCM_FORMAT_S32_LE: + testNameStr = "S32_LE"; + break; + case PCM_FORMAT_S24_LE: + testNameStr = "S24_LE"; + break; + case PCM_FORMAT_S24_3LE: + testNameStr = "S24_3LE"; + break; + default: + testNameStr = "UnsupportedPcmFormat"; + break; + } + testNameStr += std::get(info.param) == 1 ? "_Mono_" : "_Stereo_"; + testNameStr += std::get(info.param) <= kUnityGain ? "WithoutClamp" : "WithClamp"; + return testNameStr; +} + +INSTANTIATE_TEST_SUITE_P(PerPcmFormat, ApplyGainTest, + testing::Combine(testing::Values(PCM_FORMAT_S16_LE, PCM_FORMAT_FLOAT_LE, + PCM_FORMAT_S32_LE, PCM_FORMAT_S24_LE, + PCM_FORMAT_S24_3LE), + testing::Values(1, 2), testing::Values(0.6f, 1.5f)), + GetApplyGainTestName); diff --git a/automotive/TEST_MAPPING b/automotive/TEST_MAPPING index 483a85fd415fbe2af406eb497956d2b82ce9e9fa..2b2f6b026b991ac1112e7bceb5112a251f2b92ed 100644 --- a/automotive/TEST_MAPPING +++ b/automotive/TEST_MAPPING @@ -64,7 +64,82 @@ "name": "CarServiceTelemetryTest" }, { - "name": "CarServiceUnitTest" + "name": "CarServiceCarUnitTest" + }, + { + "name": "CarServiceWifiUnitTest" + }, + { + "name": "CarServiceWatchdogUnitTest" + }, + { + "name": "CarServiceVmsUnitTest" + }, + { + "name": "CarServiceUtilUnitTest" + }, + { + "name": "CarServiceUserUnitTest" + }, + { + "name": "CarServiceTelemetryUnitTest" + }, + { + "name": "CarServiceSystemUiUnitTest" + }, + { + "name": "CarServiceSystemInterfaceUnitTest" + }, + { + "name": "CarServiceStorageMonitoringUnitTest" + }, + { + "name": "CarServiceStatsUnitTest" + }, + { + "name": "CarServiceRemoteAccessUnitTest" + }, + { + "name": "CarServicePropertyUnitTest" + }, + { + "name": "CarServicePowerUnitTest" + }, + { + "name": "CarServicePmUnitTest" + }, + { + "name": "CarServiceOsUnitTest" + }, + { + "name": "CarServiceOemUnitTest" + }, + { + "name": "CarServiceOccupantConnectionUnitTest" + }, + { + "name": "CarServiceHalUnitTest" + }, + { + "name": "CarServiceGarageModeUnitTest" + }, + { + "name": "CarServiceEvsUnitTest" + }, + { + "name": "CarServiceClusterUnitTest" + }, + { + "name": "CarServiceBluetoothUnitTest" + }, + { + "name": "CarServiceAudioUnitTest" + }, + { + "name": "CarServiceAmUnitTest" + }, + { + "name": "CarServiceAdminUnitTest" }, { "name": "CarServiceVmsTest" diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioDeviceConfiguration.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioDeviceConfiguration.aidl new file mode 100644 index 0000000000000000000000000000000000000000..2685f58485294a1f98b708ba5de0452137600c4d --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioDeviceConfiguration.aidl @@ -0,0 +1,41 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable AudioDeviceConfiguration { + android.hardware.automotive.audiocontrol.RoutingDeviceConfiguration routingConfig; + boolean useCoreAudioVolume; + boolean useHalDuckingSignals; + boolean useCarVolumeGroupMuting; +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioFadeConfiguration.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioFadeConfiguration.aidl new file mode 100644 index 0000000000000000000000000000000000000000..0a3c677036ed63034287f2bf0de5e5f6a410d0fe --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioFadeConfiguration.aidl @@ -0,0 +1,50 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable AudioFadeConfiguration { + String name; + android.hardware.automotive.audiocontrol.FadeState fadeState; + long fadeInDurationMs = DEFAULT_FADE_IN_DURATION_MS /* 1000 */; + long fadeOutDurationMs = DEFAULT_FADE_OUT_DURATION_MS /* 2000 */; + long fadeInDelayedForOffendersMs = DEFAULT_DELAY_FADE_IN_OFFENDERS_MS /* 2000 */; + android.media.audio.common.AudioUsage[] fadeableUsages; + @nullable android.media.audio.common.AudioContentType[] unfadeableContentTypes; + List unfadableAudioAttributes; + List fadeOutConfigurations; + List fadeInConfigurations; + const long DEFAULT_FADE_IN_DURATION_MS = 1000; + const long DEFAULT_FADE_OUT_DURATION_MS = 2000; + const long DEFAULT_DELAY_FADE_IN_OFFENDERS_MS = 2000; +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioFocusChange.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioFocusChange.aidl index 58a36673cdec15b46f0c2234f8f53ee3cc67ad9f..8eab521ce4abd0c356e9dcb6088f86a6f0de17c9 100644 --- a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioFocusChange.aidl +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioFocusChange.aidl @@ -39,7 +39,7 @@ enum AudioFocusChange { GAIN_TRANSIENT = 2, GAIN_TRANSIENT_MAY_DUCK = 3, GAIN_TRANSIENT_EXCLUSIVE = 4, - LOSS = -1, - LOSS_TRANSIENT = -2, - LOSS_TRANSIENT_CAN_DUCK = -3, + LOSS = ((-1) * GAIN) /* -1 */, + LOSS_TRANSIENT = ((-1) * GAIN_TRANSIENT) /* -2 */, + LOSS_TRANSIENT_CAN_DUCK = ((-1) * GAIN_TRANSIENT_MAY_DUCK) /* -3 */, } diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZone.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZone.aidl new file mode 100644 index 0000000000000000000000000000000000000000..57a98124f55053383e4c24ddbae4c0ea677866f3 --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZone.aidl @@ -0,0 +1,44 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable AudioZone { + String name; + int id = android.media.audio.common.AudioHalProductStrategy.ZoneId.DEFAULT /* 0 */; + int occupantZoneId = UNASSIGNED_OCCUPANT /* -1 */; + android.hardware.automotive.audiocontrol.AudioZoneContext audioZoneContext; + List audioZoneConfigs; + List inputAudioDevices; + const int UNASSIGNED_OCCUPANT = (-1) /* -1 */; +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZoneConfig.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZoneConfig.aidl new file mode 100644 index 0000000000000000000000000000000000000000..3fd37bc1cf1e59f28caeb5c85df228a65f35216d --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZoneConfig.aidl @@ -0,0 +1,41 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable AudioZoneConfig { + String name; + boolean isDefault; + List volumeGroups; + @nullable android.hardware.automotive.audiocontrol.AudioZoneFadeConfiguration fadeConfiguration; +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZoneContext.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZoneContext.aidl new file mode 100644 index 0000000000000000000000000000000000000000..0f8b946e3022c93de30b8b53a712208487bdcbbc --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZoneContext.aidl @@ -0,0 +1,38 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable AudioZoneContext { + List audioContextInfos; +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZoneContextInfo.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZoneContextInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..01ab1be64304010ebcfda37211076f7382dcb596 --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZoneContextInfo.aidl @@ -0,0 +1,41 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable AudioZoneContextInfo { + String name; + int id = UNASSIGNED_CONTEXT_ID /* -1 */; + List audioAttributes; + const int UNASSIGNED_CONTEXT_ID = (-1) /* -1 */; +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZoneFadeConfiguration.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZoneFadeConfiguration.aidl new file mode 100644 index 0000000000000000000000000000000000000000..f3f32bf6f32b999607c86f81ae4e983d8cee7122 --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZoneFadeConfiguration.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable AudioZoneFadeConfiguration { + android.hardware.automotive.audiocontrol.AudioFadeConfiguration defaultConfiguration; + List transientConfiguration; +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/DeviceToContextEntry.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/DeviceToContextEntry.aidl new file mode 100644 index 0000000000000000000000000000000000000000..923b0bdc485f529eeccebabfda252aed0bd7f9e3 --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/DeviceToContextEntry.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable DeviceToContextEntry { + List contextNames; + android.media.audio.common.AudioPort device; +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/FadeConfiguration.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/FadeConfiguration.aidl new file mode 100644 index 0000000000000000000000000000000000000000..2c978e75ad36c9d6aa0e5d750a8728599f066d52 --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/FadeConfiguration.aidl @@ -0,0 +1,44 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable FadeConfiguration { + long fadeDurationMillis; + android.hardware.automotive.audiocontrol.FadeConfiguration.AudioAttributesOrUsage audioAttributesOrUsage; + @JavaDerive(equals=true, toString=true) @VintfStability + union AudioAttributesOrUsage { + android.media.audio.common.AudioAttributes fadeAttribute; + android.media.audio.common.AudioUsage usage; + } +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/FadeState.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/FadeState.aidl new file mode 100644 index 0000000000000000000000000000000000000000..9b25dfbdec486af4e9b2f043f9a9c5b316c96550 --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/FadeState.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@Backing(type="int") @JavaDerive(toString=true) @VintfStability +enum FadeState { + FADE_STATE_DISABLED, + FADE_STATE_ENABLED_DEFAULT, +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IAudioControl.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IAudioControl.aidl index ffd575dfa4d87f971d2b72569f4911c606563a30..fe39f92cc05b8438baf8f79e48ca9bf3d66813e8 100644 --- a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IAudioControl.aidl +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IAudioControl.aidl @@ -12,6 +12,34 @@ * 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. + *//** + * Important note on Metadata: + * Metadata qualifies a playback track for an output stream. + * This is highly closed to {@link android.media.AudioAttributes}. + * It allows to identify the audio stream rendered / requesting / abandonning the focus. + * + * AudioControl 1.0 was limited to identification through {@code AttributeUsage} listed as + * {@code audioUsage} in audio_policy_configuration.xsd. + * + * Any new OEM needs would not be possible without extension. + * + * Relying on {@link android.hardware.automotive.audiocontrol.PlaybackTrackMetadata} allows + * to use a combination of {@code AttributeUsage}, {@code AttributeContentType} and + * {@code AttributeTags} to identify the use case / routing thanks to + * {@link android.media.audiopolicy.AudioProductStrategy}. + * The belonging to a strategy is deduced by an AOSP logic (in sync at native and java layer). + * + * IMPORTANT NOTE ON TAGS: + * To limit the possibilies and prevent from confusion, we expect the String to follow + * a given formalism that will be enforced. + * + * 1 / By convention, tags shall be a "key=value" pair. + * Vendor must namespace their tag's key (for example com.google.strategy=VR) to avoid conflicts. + * vendor specific applications and must be prefixed by "VX_". Vendor must + * + * 2 / Tags reported here shall be the same as the tags used to define a given + * {@link android.media.audiopolicy.AudioProductStrategy} and so in + * audio_policy_engine_configuration.xml file. */ /////////////////////////////////////////////////////////////////////////////// // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // @@ -48,4 +76,7 @@ interface IAudioControl { oneway void registerGainCallback(in android.hardware.automotive.audiocontrol.IAudioGainCallback callback); void setModuleChangeCallback(in android.hardware.automotive.audiocontrol.IModuleChangeCallback callback); void clearModuleChangeCallback(); + android.hardware.automotive.audiocontrol.AudioDeviceConfiguration getAudioDeviceConfiguration(); + List getOutputMirroringDevices(); + List getCarAudioZones(); } diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/Reasons.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/Reasons.aidl index c1e22d44a7d5e591dd7af910019440aa95fe8842..8d669850a5ff89b0bb10b1d21153a187e084f237 100644 --- a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/Reasons.aidl +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/Reasons.aidl @@ -34,14 +34,14 @@ package android.hardware.automotive.audiocontrol; @Backing(type="int") @VintfStability enum Reasons { - FORCED_MASTER_MUTE = 1, - REMOTE_MUTE = 2, - TCU_MUTE = 4, - ADAS_DUCKING = 8, - NAV_DUCKING = 16, - PROJECTION_DUCKING = 32, - THERMAL_LIMITATION = 64, - SUSPEND_EXIT_VOL_LIMITATION = 128, - EXTERNAL_AMP_VOL_FEEDBACK = 256, - OTHER = -2147483648, + FORCED_MASTER_MUTE = 0x1, + REMOTE_MUTE = 0x2, + TCU_MUTE = 0x4, + ADAS_DUCKING = 0x8, + NAV_DUCKING = 0x10, + PROJECTION_DUCKING = 0x20, + THERMAL_LIMITATION = 0x40, + SUSPEND_EXIT_VOL_LIMITATION = 0x80, + EXTERNAL_AMP_VOL_FEEDBACK = 0x100, + OTHER = 0x80000000, } diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/RoutingDeviceConfiguration.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/RoutingDeviceConfiguration.aidl new file mode 100644 index 0000000000000000000000000000000000000000..901078c69684a54ef303e06d755757d0aa482ab5 --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/RoutingDeviceConfiguration.aidl @@ -0,0 +1,40 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@JavaDerive(equals=true, toString=true) @VintfStability +enum RoutingDeviceConfiguration { + DEFAULT_AUDIO_ROUTING, + DYNAMIC_AUDIO_ROUTING, + CONFIGURABLE_AUDIO_ENGINE_ROUTING, +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/TransientFadeConfigurationEntry.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/TransientFadeConfigurationEntry.aidl new file mode 100644 index 0000000000000000000000000000000000000000..72b247bb8ece49dff4d73e2e6badc87ceae400f0 --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/TransientFadeConfigurationEntry.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable TransientFadeConfigurationEntry { + android.media.audio.common.AudioUsage[] transientUsages; + android.hardware.automotive.audiocontrol.AudioFadeConfiguration transientFadeConfiguration; +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/VolumeActivationConfiguration.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/VolumeActivationConfiguration.aidl new file mode 100644 index 0000000000000000000000000000000000000000..50b76a163e7661aaba7b29e59a6d6350a64ab2d3 --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/VolumeActivationConfiguration.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable VolumeActivationConfiguration { + @nullable String name; + List volumeActivationEntries; +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/VolumeActivationConfigurationEntry.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/VolumeActivationConfigurationEntry.aidl new file mode 100644 index 0000000000000000000000000000000000000000..d457e57db73a861bd1bef31961976c7785d46ae3 --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/VolumeActivationConfigurationEntry.aidl @@ -0,0 +1,42 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable VolumeActivationConfigurationEntry { + android.hardware.automotive.audiocontrol.VolumeInvocationType type = android.hardware.automotive.audiocontrol.VolumeInvocationType.ON_PLAYBACK_CHANGED; + int maxActivationVolumePercentage = DEFAULT_MAX_ACTIVATION_VALUE /* 100 */; + int minActivationVolumePercentage = DEFAULT_MIN_ACTIVATION_VALUE /* 0 */; + const int DEFAULT_MAX_ACTIVATION_VALUE = 100; + const int DEFAULT_MIN_ACTIVATION_VALUE = 0; +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/VolumeGroupConfig.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/VolumeGroupConfig.aidl new file mode 100644 index 0000000000000000000000000000000000000000..cc90bbe77fb750a296160eb8868c18a03e1a727c --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/VolumeGroupConfig.aidl @@ -0,0 +1,42 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable VolumeGroupConfig { + String name; + int id = UNASSIGNED_ID /* -1 */; + List carAudioRoutes; + @nullable android.hardware.automotive.audiocontrol.VolumeActivationConfiguration activationConfiguration; + const int UNASSIGNED_ID = (-1) /* -1 */; +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/VolumeInvocationType.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/VolumeInvocationType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..8ce84913ca5ff1b3c87f6cae4d5bc125db874b09 --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/VolumeInvocationType.aidl @@ -0,0 +1,40 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@Backing(type="int") @JavaDerive(toString=true) @VintfStability +enum VolumeInvocationType { + ON_PLAYBACK_CHANGED, + ON_SOURCE_CHANGED, + ON_BOOT, +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioDeviceConfiguration.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioDeviceConfiguration.aidl new file mode 100644 index 0000000000000000000000000000000000000000..9b5e72422fbc7e056ad996b3a61ff902b9f71fc3 --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioDeviceConfiguration.aidl @@ -0,0 +1,48 @@ +/* + * 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. + */ + +package android.hardware.automotive.audiocontrol; + +import android.hardware.automotive.audiocontrol.RoutingDeviceConfiguration; + +/** + * Use to configure audio configurations at boot up time. + */ +@JavaDerive(equals=true, toString=true) +@VintfStability +parcelable AudioDeviceConfiguration { + /** + * Use to configure audio device routing mechanism + */ + RoutingDeviceConfiguration routingConfig; + + /** + * Use to configure core audio volume usage in car audio service + */ + boolean useCoreAudioVolume; + + /** + * Use to determine if HAL ducking signal should be sent to audio control HAL from car audio + * service + */ + boolean useHalDuckingSignals; + + /** + * Use to determine if HAL volume signal should be sent to audio control HAL from car audio + * service + */ + boolean useCarVolumeGroupMuting; +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioFadeConfiguration.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioFadeConfiguration.aidl new file mode 100644 index 0000000000000000000000000000000000000000..4190c4651afd08c4397974b917b39fbdd0820251 --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioFadeConfiguration.aidl @@ -0,0 +1,122 @@ +/* + * 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. + */ + +package android.hardware.automotive.audiocontrol; + +import android.hardware.automotive.audiocontrol.FadeConfiguration; +import android.hardware.automotive.audiocontrol.FadeState; +import android.media.audio.common.AudioAttributes; +import android.media.audio.common.AudioContentType; +import android.media.audio.common.AudioUsage; + +/** + * Encapsulates the audio fade configuration info + */ +@JavaDerive(equals=true, toString=true) +@VintfStability +parcelable AudioFadeConfiguration { + /** + * Default fade in duration + */ + const long DEFAULT_FADE_IN_DURATION_MS = 1000; + + /** + * Default fade out duration + */ + const long DEFAULT_FADE_OUT_DURATION_MS = 2000; + + /** + * Default delay for fade in offenders + */ + const long DEFAULT_DELAY_FADE_IN_OFFENDERS_MS = 2000; + + /** + * Audio configuration name, use for debugging purposes + */ + String name; + + /** + * Audio configuration state + */ + FadeState fadeState; + + /** + * Fade in duration in milliseconds + * + *

Use to construct the default fade in configuration. This can be overwritten for different + * attributes/usages by passing a list of fade-in configuration, + * see {@code #fadeInConfigurations} + */ + long fadeInDurationMs = DEFAULT_FADE_IN_DURATION_MS; + + /** + * Fade out duration in milliseconds + * + *

Use to construct the default fade out configuration. This can be overwritten for different + * attributes/usages by passing a list of fade-out configuration, + * see {@code #fadeOutConfigurations} + */ + long fadeOutDurationMs = DEFAULT_FADE_OUT_DURATION_MS; + + /** + * Fade in delayed duration for audio focus offender in milliseconds + * + *

Fade offender are defined as audio players that do not stop playback after audio focus + * lost. This timeout serves to continue to fadeout the offender until audio is stopped or the + * timeout expires. + */ + long fadeInDelayedForOffendersMs = DEFAULT_DELAY_FADE_IN_OFFENDERS_MS; + + /** + * List of audio attribute usage that should be faded using the parameters in + * this configuration. + * + *

If the list is empty car audio service will overwrite the list for the confgiruation with + * default usages, e.g. {AudioUsage#MEDIA, AudioUsage#GAME} + */ + AudioUsage[] fadeableUsages; + + /** + * Optional list of audio attribute content types that should not be faded. + * + **

The list can be empty in cases where there are no unfadeable content types. + * + *

If the list is not set car audio service will overwrite the list for the confgiruation + * with default content type, e.g. {AudioContentType#SPEECH}. + */ + @nullable AudioContentType[] unfadeableContentTypes; + + /** + * List of audio attribute that should not be faded. + * + *

The list can be empty in cases where there are no unfadeable attributes + */ + List unfadableAudioAttributes; + + /** + * List of fade out configutions which should apply to this audio fade configurations + * + *

The list can be empty in cases where there are no fade out configurations. + */ + List fadeOutConfigurations; + + /** + * List of fade in configutions which should apply to this audio fade configurations + * + *

The list can be empty in cases where there are no fade out configurations + */ + List fadeInConfigurations; +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZone.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZone.aidl new file mode 100644 index 0000000000000000000000000000000000000000..d31d6fd8e34595f8efa93ac9367634f1bb94f20b --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZone.aidl @@ -0,0 +1,73 @@ +/* + * 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. + */ + +package android.hardware.automotive.audiocontrol; + +import android.hardware.automotive.audiocontrol.AudioZoneConfig; +import android.hardware.automotive.audiocontrol.AudioZoneContext; +import android.media.audio.common.AudioHalProductStrategy; +import android.media.audio.common.AudioPort; + +/** + * Encapsulates the audio configurations for each audio zone + */ +@JavaDerive(equals=true, toString=true) +@VintfStability +parcelable AudioZone { + /** + * Value indicating the occupant zone is not assigned. + */ + const int UNASSIGNED_OCCUPANT = -1; + + /** + * Audio zone name, only use for debug purposes. + * + *

If present it must be non-empty otherwise car audio service will construct a name + * based on audio zone id. + */ + String name; + + /** + * Audio zone id use to distiguish between the different audio zones for + * volume management, fade, and min/max activation management. + * + *

Value must start at {@link AudioHalProductStrategy#ZoneId#DEFAULT} for the primary zone + * and increase for each different zone. Zone id must also not repeat for different zones. + */ + int id = AudioHalProductStrategy.ZoneId.DEFAULT; + + /** + * Occupant zone id that should be mapped to this audio zone. + * + *

For audio zones not mapped to an occupant zone use UNASSIGNED_OCCUPANT + */ + int occupantZoneId = UNASSIGNED_OCCUPANT; + + /** + * Car audio context which can be used in the audio zone + */ + AudioZoneContext audioZoneContext; + + /** + * List of car audio configurations + */ + List audioZoneConfigs; + + /** + * List of input audio devices used for this zone + */ + List inputAudioDevices; +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZoneConfig.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZoneConfig.aidl new file mode 100644 index 0000000000000000000000000000000000000000..6822da580af7940478dc6338fbdda3818421577a --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZoneConfig.aidl @@ -0,0 +1,51 @@ +/* + * 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. + */ + +package android.hardware.automotive.audiocontrol; + +import android.hardware.automotive.audiocontrol.AudioZoneFadeConfiguration; +import android.hardware.automotive.audiocontrol.VolumeGroupConfig; + +/** + * Encapsulates the audio zone config information + */ +@JavaDerive(equals=true, toString=true) +@VintfStability +parcelable AudioZoneConfig { + /** + * Audio zone config name + * + *

Must be non-empty and unique among the configurations within a zone. + */ + String name; + + /** + * Determines if the audio configuration is the default configuration. + * + *

There can only be a single default configuration per zone. + */ + boolean isDefault; + + /** + * List car volume group that should be managed within this configuration + */ + List volumeGroups; + + /** + * Car audio zone fade configuration + */ + @nullable AudioZoneFadeConfiguration fadeConfiguration; +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZoneContext.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZoneContext.aidl new file mode 100644 index 0000000000000000000000000000000000000000..390cb091602f3bc56d045d4341a7c736723e0682 --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZoneContext.aidl @@ -0,0 +1,34 @@ +/* + * 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. + */ + +package android.hardware.automotive.audiocontrol; + +import android.hardware.automotive.audiocontrol.AudioZoneContextInfo; + +/** + * Encapsulates the list of car audio context info definitions + */ +@JavaDerive(equals=true, toString=true) +@VintfStability +parcelable AudioZoneContext { + /** + * List of car audio context info. + * + *

The list must include all audio attributes usages currently supported so that all audio + * attribute usages can be routed for each car audio configuration. + */ + List audioContextInfos; +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZoneContextInfo.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZoneContextInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..0ca425c044f574a44e579a8137df2f50dfd308c7 --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZoneContextInfo.aidl @@ -0,0 +1,54 @@ +/* + * 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. + */ + +package android.hardware.automotive.audiocontrol; + +import android.media.audio.common.AudioAttributes; + +/** + * Encapsulates groups of audio attributes which should be managed together. + */ +@JavaDerive(equals=true, toString=true) +@VintfStability +parcelable AudioZoneContextInfo { + /** + * Value indicating the context info id is not assigned. + */ + const int UNASSIGNED_CONTEXT_ID = -1; + + /** + * Context name which can be used to map the info to an audio route + * management as described in each audio configuration. + * + *

Name must be non-empty and unique among all audio context info within the same + * {@link android.hardware.automotive.audiocontrol.AudioZoneContext} container. + */ + String name; + + /** + * Used in car audio service to manage the info + * + *

Must be non-negative integer if assigned, or UNASSIGNED_CONTEXT_ID otherwise. If using + * configurable audio policy engine audio routing with multi-zone configurations the value must + * be assigned. + */ + int id = UNASSIGNED_CONTEXT_ID; + + /** + * List of audio attributes that belong to the context + */ + List audioAttributes; +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZoneFadeConfiguration.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZoneFadeConfiguration.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a60421471304bb1198b2462654b360e3a10f582d --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZoneFadeConfiguration.aidl @@ -0,0 +1,40 @@ +/* + * 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. + */ + +package android.hardware.automotive.audiocontrol; + +import android.hardware.automotive.audiocontrol.AudioFadeConfiguration; +import android.hardware.automotive.audiocontrol.TransientFadeConfigurationEntry; + +/** + * Encapsulates the audio zone fade configuration + */ +@JavaDerive(equals=true, toString=true) +@VintfStability +parcelable AudioZoneFadeConfiguration { + /** + * Defines the default fade configuration + */ + AudioFadeConfiguration defaultConfiguration; + + /** + * List of transient fade configurations. + * + *

The list can be empty if the fade configuration for the zone does not have transient fade + * configurations. + */ + List transientConfiguration; +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/DeviceToContextEntry.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/DeviceToContextEntry.aidl new file mode 100644 index 0000000000000000000000000000000000000000..bcb5ee7c7c04d9d46a10ec6c6b748aaee09a1ad3 --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/DeviceToContextEntry.aidl @@ -0,0 +1,47 @@ +/* + * 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. + */ + +package android.hardware.automotive.audiocontrol; + +import android.media.audio.common.AudioPort; + +/** + * Encapsulates the audio context that should be route to particular device + */ +@JavaDerive(equals=true, toString=true) +@VintfStability +parcelable DeviceToContextEntry { + /** + * List of audio context names that should be routed to the audio device. + * + *

The names must match a {@link AudioZoneContextInfo#name} in the corresponding + * {@link AudioZone#audioZoneContext). + * + *

Within a {@link AudioZoneConfig} a context name must not repeat among the different + * {@link VolumeGroupConfig}. The value can repeat among different {@link AudioZoneConfig} + * within a {@link AudioZone}. + */ + List contextNames; + + /** + * Audio port where contexts should be routed. + * + *

For dynamic devices (OUT_HEADSET, OUT_HEADPHONE, etc.) , the audio device address can be + * omitted since the information will be obtained at run time when the device is + * connected/enabled. + */ + AudioPort device; +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/FadeConfiguration.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/FadeConfiguration.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e700d6c1845c24553328eb80c1c51ad90cda2965 --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/FadeConfiguration.aidl @@ -0,0 +1,45 @@ +/* + * 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. + */ + +package android.hardware.automotive.audiocontrol; + +import android.media.audio.common.AudioAttributes; +import android.media.audio.common.AudioUsage; + +/** + * Encapsulates the in/out fade configuration + */ +@JavaDerive(equals=true, toString=true) +@VintfStability +parcelable FadeConfiguration { + /** + * Fade duration in milliseconds + */ + long fadeDurationMillis; + + @JavaDerive(equals=true, toString=true) + @VintfStability + union AudioAttributesOrUsage { + AudioAttributes fadeAttribute; + AudioUsage usage; + } + + /** + * Audio attribute or usage that should be impacted by the fade out duration + * {@code #fadeDurationMillis} + */ + AudioAttributesOrUsage audioAttributesOrUsage; +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/FadeState.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/FadeState.aidl new file mode 100644 index 0000000000000000000000000000000000000000..346caae57ca78b2f6de2a02446ffbffb67166a23 --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/FadeState.aidl @@ -0,0 +1,34 @@ +/* + * 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. + */ + +package android.hardware.automotive.audiocontrol; + +/** + * Encapsulates the audio fade configuration state + */ +@VintfStability +@Backing(type="int") +@JavaDerive(toString=true) +enum FadeState { + /** + * Fade configuration should be disabled + */ + FADE_STATE_DISABLED, + /** + * Fade configuration should be enabled by default + */ + FADE_STATE_ENABLED_DEFAULT, +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioControl.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioControl.aidl index 9564efc85983ac93430da413ed95f1bad477b776..1202b4cd01b3446176e5a031818e7e73190848af 100644 --- a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioControl.aidl +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioControl.aidl @@ -46,14 +46,17 @@ package android.hardware.automotive.audiocontrol; * audio_policy_engine_configuration.xml file. */ import android.hardware.audio.common.PlaybackTrackMetadata; +import android.hardware.automotive.audiocontrol.AudioDeviceConfiguration; import android.hardware.automotive.audiocontrol.AudioFocusChange; import android.hardware.automotive.audiocontrol.AudioGainConfigInfo; +import android.hardware.automotive.audiocontrol.AudioZone; import android.hardware.automotive.audiocontrol.DuckingInfo; import android.hardware.automotive.audiocontrol.IAudioGainCallback; import android.hardware.automotive.audiocontrol.IFocusListener; import android.hardware.automotive.audiocontrol.IModuleChangeCallback; import android.hardware.automotive.audiocontrol.MutingInfo; import android.hardware.automotive.audiocontrol.Reasons; +import android.media.audio.common.AudioPort; /** * Interacts with the car's audio subsystem to manage audio sources and volumes @@ -206,4 +209,41 @@ interface IAudioControl { * @throws EX_UNSUPPORTED_OPERATION if dynamic audio configs are not supported. */ void clearModuleChangeCallback(); + + /** + * Returns the audio device configurations that should be used to configure + * the car audio service audio management. + * + *

If this method is not supported, car audio service will attempt to configure the car audio + * service properties based on previously supported mechanisms. + * + *

If the returned value contains the + * {@link RoutingDeviceConfiguration#DEFAULT_AUDIO_ROUTING} value, the car audio service will + * attempt to configure audio routing based on the mechanism previously supported by car audio + * service (e.g. car audio configuration file). Otherwise, the {@link #getCarAudioZones()} + * API must return valid audio zone(s) configuration(s) for the device. + * + */ + AudioDeviceConfiguration getAudioDeviceConfiguration(); + + /** + * Returns the list of audio devices that can be used for mirroring between different audio + * zones. + * + * @throws EX_UNSUPPORTED_OPERATION if mirroring devices are not supported. + */ + List getOutputMirroringDevices(); + + /** + * List of audio zones used to configure car audio service at bootup. + * + *

If the returned value from {@link #getAudioDeviceConfiguration()} contains + * {@link RoutingDeviceConfiguration#DEFAULT_AUDIO_ROUTING} value, the car audio service will + * attempt to configure the audio routing based on the mechanism previously supported by + * car audio service (e.g. car audio configuration file). Otherwise, this method must return + * valid audio zone(s) configuration(s) for the device. + * + * @throws EX_UNSUPPORTED_OPERATION if audio zone configuration are not supported. + */ + List getCarAudioZones(); } diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/RoutingDeviceConfiguration.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/RoutingDeviceConfiguration.aidl new file mode 100644 index 0000000000000000000000000000000000000000..2d175401c5ae764e1b844f3b6fc4076b4679dd87 --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/RoutingDeviceConfiguration.aidl @@ -0,0 +1,52 @@ +/* + * 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. + */ + +package android.hardware.automotive.audiocontrol; + +/** + * Use to configure audio device routing mechanism + */ +@JavaDerive(equals=true, toString=true) +@VintfStability +enum RoutingDeviceConfiguration { + /** + * Use to indicate that audio should be managed based on previously supportec mechamisms in + * car audio service. + * + *

If this used then the API to setup the audio zones can just throw + * {@code EX_UNSUPPORTED_OPERATION} if called. + */ + DEFAULT_AUDIO_ROUTING, + /** + * Use to indicate that audio should be managed using the dynamic audio + * policy as setup by car audio service using the setup configuration from + * the {@Link android.hardware.automotive.audiocontrol.AudioZone}'s info from audio control HAL. + * + *

If this used then the APIs to setup the audio zones must return a valid audio zone + * configuration for the device. + */ + DYNAMIC_AUDIO_ROUTING, + /** + * Use to indicate that audio should be managed using the core audio + * routing as setup by car audio service using the setup configuration from + * the {@Link android.hardware.automotive.audiocontrol.AudioZone}'s info from audio control HAL + * and the information contained within the configurable audio policy engine. + * + *

If this used then the APIs to setup the audio zone(s) must return valid audio zone + * configuration(s) for the device. + */ + CONFIGURABLE_AUDIO_ENGINE_ROUTING, +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/TransientFadeConfigurationEntry.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/TransientFadeConfigurationEntry.aidl new file mode 100644 index 0000000000000000000000000000000000000000..198423657f8b867a1da3c5ab57af8d060d7cb2d7 --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/TransientFadeConfigurationEntry.aidl @@ -0,0 +1,38 @@ +/* + * 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. + */ + +package android.hardware.automotive.audiocontrol; + +import android.hardware.automotive.audiocontrol.AudioFadeConfiguration; +import android.media.audio.common.AudioUsage; + +/** + * Encapsulates the transient audio fade configuration entry. + */ +@JavaDerive(equals=true, toString=true) +@VintfStability +parcelable TransientFadeConfigurationEntry { + /** + * List of audio usages gainers that should be used for this configuration entry. + */ + AudioUsage[] transientUsages; + + /** + * Defines the transient fade configuration that should be used for the focus interaction with + * the usages defined in {@link #transientUsages} + */ + AudioFadeConfiguration transientFadeConfiguration; +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/VolumeActivationConfiguration.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/VolumeActivationConfiguration.aidl new file mode 100644 index 0000000000000000000000000000000000000000..edc5f6010e7c8bdab7dc1a8ac8ff4bc676ad5cbb --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/VolumeActivationConfiguration.aidl @@ -0,0 +1,42 @@ +/* + * 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. + */ + +package android.hardware.automotive.audiocontrol; + +import android.hardware.automotive.audiocontrol.VolumeActivationConfigurationEntry; + +/** + * Use to configure audio activiations, only used at boot up time. + */ +@JavaDerive(equals=true, toString=true) +@VintfStability +parcelable VolumeActivationConfiguration { + /** + * Configuration name used for debugging purposes to identify config used. + * + *

Is present, it must be non-empty and unique for all volume acvitations, otherwise + * car audio service will construct one based on audio zone, configuration and volume group + * info. + */ + @nullable String name; + + /** + * List of activation configurations. + * + *

Car audio service currently only uses the first activation config on the list. + */ + List volumeActivationEntries; +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/VolumeActivationConfigurationEntry.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/VolumeActivationConfigurationEntry.aidl new file mode 100644 index 0000000000000000000000000000000000000000..7072a2c84c3d98505ff07dadca66a2ae2d6e81de --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/VolumeActivationConfigurationEntry.aidl @@ -0,0 +1,63 @@ +/* + * 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. + */ + +package android.hardware.automotive.audiocontrol; + +import android.hardware.automotive.audiocontrol.VolumeInvocationType; + +/** + * Audio activiation volume configuration entry. + * + *

The entry can defined both the minimum and maximum activation values or only one. The latter + * allows activations to occur only on the minimum value or maximum value as configured. + */ +@JavaDerive(equals=true, toString=true) +@VintfStability +parcelable VolumeActivationConfigurationEntry { + /** + * Default maximum activation value. + */ + const int DEFAULT_MAX_ACTIVATION_VALUE = 100; + + /** + * Default minimum activation value. + */ + const int DEFAULT_MIN_ACTIVATION_VALUE = 0; + + /** + * Activation type, should be one of: + * ON_PLAYBACK_CHANGED, ON_SOURCE_CHANGED, ON_BOOT + */ + VolumeInvocationType type = VolumeInvocationType.ON_PLAYBACK_CHANGED; + + /** + * Max activation percentage between {@code DEFAULT_MIN_ACTIVATION_VALUE} to + * {@code DEFAULT_MAX_ACTIVATION_VALUE} percen. + * + *

The value should be {@code DEFAULT_MAX_ACTIVATION_VALUE} if max activation should not + * apply. + */ + int maxActivationVolumePercentage = DEFAULT_MAX_ACTIVATION_VALUE; + + /** + * Min activation percentage between {@code DEFAULT_MIN_ACTIVATION_VALUE} to + * {@code DEFAULT_MAX_ACTIVATION_VALUE} percent. + * + *

The value should be {@code DEFAULT_MIN_ACTIVATION_VALUE} if min activation should not + * apply. + */ + int minActivationVolumePercentage = DEFAULT_MIN_ACTIVATION_VALUE; +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/VolumeGroupConfig.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/VolumeGroupConfig.aidl new file mode 100644 index 0000000000000000000000000000000000000000..bea80cebc14de239c107fb7f7ef5abebf8138e87 --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/VolumeGroupConfig.aidl @@ -0,0 +1,60 @@ +/* + * 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. + */ + +package android.hardware.automotive.audiocontrol; + +import android.hardware.automotive.audiocontrol.DeviceToContextEntry; +import android.hardware.automotive.audiocontrol.VolumeActivationConfiguration; + +/** + * Encapsulates the audio volume grouping for audio zone config. + */ +@JavaDerive(equals=true, toString=true) +@VintfStability +parcelable VolumeGroupConfig { + /** + * Value indicating the volume group is not assigned an ID. + */ + const int UNASSIGNED_ID = -1; + + /** + * Audio zone group name. + * + *

Must be non-empty if using configurable audio policy engine volume management, + * {@see AudioDeviceConfiguration#useCoreAudioVolume} for details. For non-core volume group + * management this can be left empty or use for debugging purposes. + */ + String name; + + /** + * Audio zone group id. + * + *

Must be set if using configurable audio policy engine volume management, can be + * {@code #UNASSIGNED_ID} otherwise. See {@code AudioDeviceConfiguration#useCoreAudioVolume} + * for details. + */ + int id = UNASSIGNED_ID; + + /** + * Entries of audio device to audio context that are managed similarly for this volume group. + */ + List carAudioRoutes; + + /** + * Optional volume activation configuration that should be used for this volume group. + */ + @nullable VolumeActivationConfiguration activationConfiguration; +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/VolumeInvocationType.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/VolumeInvocationType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..032350504871e7bc1b5efe69d6f2a668357a979a --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/VolumeInvocationType.aidl @@ -0,0 +1,40 @@ +/* + * 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. + */ + +package android.hardware.automotive.audiocontrol; + +/** + * Audio activiation type which can be used to activate the min/max + * volume changes. + */ +@VintfStability +@Backing(type="int") +@JavaDerive(toString=true) +enum VolumeInvocationType { + /** + * Invocation of volume group activation performed at every playback change. + */ + ON_PLAYBACK_CHANGED, + /** + * Invocation of volume group activation performed only once at playback after first playback + * for a client (app/service UID). + */ + ON_SOURCE_CHANGED, + /** + * Invocation of volume group activation in perform only at playback once after boot up. + */ + ON_BOOT, +} diff --git a/automotive/audiocontrol/aidl/default/Android.bp b/automotive/audiocontrol/aidl/default/Android.bp index fd7e1675458701d79b9a7e7572470cf5c3e9f535..1c11c989b787549a3e1da01b4ded84b9689ad1f0 100644 --- a/automotive/audiocontrol/aidl/default/Android.bp +++ b/automotive/audiocontrol/aidl/default/Android.bp @@ -31,13 +31,19 @@ cc_binary { "latest_android_hardware_audio_common_ndk_shared", "latest_android_hardware_automotive_audiocontrol_ndk_shared", "powerpolicyclient_defaults", + "car.audio.configuration.xsd.default", + "car.fade.configuration.xsd.default", ], shared_libs: [ "android.hardware.audio.common@7.0-enums", - "libbase", "libbinder_ndk", "libcutils", "liblog", + "libbase", + "libxml2", + "libutils", + "android.hardware.audiocontrol.internal", + "libaudio_aidl_conversion_common_ndk", ], srcs: [ "AudioControl.cpp", diff --git a/automotive/audiocontrol/aidl/default/AudioControl.cpp b/automotive/audiocontrol/aidl/default/AudioControl.cpp index 7e7e145d374451d571dc73cfef1c6a68b27449fd..9ae422b1cf171a3ccb5b851f735e4bb7b8dc2739 100644 --- a/automotive/audiocontrol/aidl/default/AudioControl.cpp +++ b/automotive/audiocontrol/aidl/default/AudioControl.cpp @@ -19,6 +19,7 @@ #include "AudioControl.h" +#include #include #include #include @@ -27,8 +28,8 @@ #include #include #include - #include + #include #include @@ -41,16 +42,18 @@ using ::android::base::EqualsIgnoreCase; using ::android::base::ParseBool; using ::android::base::ParseBoolResult; using ::android::base::ParseInt; +using ::android::hardware::audiocontrol::internal::CarAudioConfigurationXmlConverter; using ::std::shared_ptr; using ::std::string; -namespace xsd { -using namespace ::android::audio::policy::configuration::V7_0; +namespace converter { +using namespace ::android::hardware::audiocontrol::internal; } +namespace api = aidl::android::hardware::automotive::audiocontrol; +namespace xsd = ::android::audio::policy::configuration::V7_0; + namespace { -const float kLowerBound = -1.0f; -const float kUpperBound = 1.0f; bool checkCallerHasWritePermissions(int fd) { // Double check that's only called by root - it should be be blocked at debug() level, // but it doesn't hurt to make sure... @@ -62,7 +65,7 @@ bool checkCallerHasWritePermissions(int fd) { } bool isValidValue(float value) { - return (value >= kLowerBound) && (value <= kUpperBound); + return (value >= -1.0f) && (value <= 1.0f); } bool safelyParseInt(string s, int* out) { @@ -71,6 +74,53 @@ bool safelyParseInt(string s, int* out) { } return true; } + +std::string formatDump(const std::string& input) { + const char kSpacer = ' '; + std::string output; + int indentLevel = 0; + bool newLine = false; + + for (char c : input) { + switch (c) { + case '{': + if (!newLine) { + output += '\n'; + } + newLine = true; + indentLevel++; + for (int i = 0; i < indentLevel; ++i) { + output += kSpacer; + } + break; + case '}': + if (!newLine) { + output += '\n'; + } + newLine = true; + indentLevel--; + for (int i = 0; i < indentLevel; ++i) { + output += kSpacer; + } + break; + case ',': + if (!newLine) { + output += '\n'; + } + newLine = true; + for (int i = 0; i < indentLevel; ++i) { + output += kSpacer; + } + break; + default: + newLine = false; + output += c; + } + } + + return output; +} + } // namespace namespace { @@ -90,6 +140,9 @@ using ::aidl::android::media::audio::common::AudioPortMixExt; using ::aidl::android::media::audio::common::AudioProfile; using ::aidl::android::media::audio::common::PcmType; +const static std::string kAudioConfigFile = "/vendor/etc/car_audio_configuration.xml"; +const static std::string kFadeConfigFile = "/vendor/etc/car_audio_fade_configuration.xml"; + // reuse common code artifacts void fillProfile(const std::vector& channelLayouts, const std::vector& sampleRates, AudioProfile* profile) { @@ -162,6 +215,12 @@ AudioGain createGain(int32_t mode, AudioChannelLayout channelMask, int32_t minVa } } // namespace +AudioControl::AudioControl() : AudioControl(kAudioConfigFile, kFadeConfigFile) {} + +AudioControl::AudioControl(const std::string& carAudioConfig, const std::string& audioFadeConfig) + : mCarAudioConfigurationConverter(std::make_shared( + carAudioConfig, audioFadeConfig)) {} + ndk::ScopedAStatus AudioControl::registerFocusListener( const shared_ptr& in_listener) { LOG(DEBUG) << "registering focus listener"; @@ -245,14 +304,23 @@ template static inline std::string toString(const std::vector& in_values) { return std::accumulate(std::begin(in_values), std::end(in_values), std::string{}, [](const std::string& ls, const aidl_type& rs) { - return ls + (ls.empty() ? "" : ",") + rs.toString(); + return ls + (ls.empty() ? "" : ", ") + rs.toString(); }); } template static inline std::string toEnumString(const std::vector& in_values) { return std::accumulate(std::begin(in_values), std::end(in_values), std::string{}, [](const std::string& ls, const aidl_enum_type& rs) { - return ls + (ls.empty() ? "" : ",") + toString(rs); + return ls + (ls.empty() ? "" : ", ") + toString(rs); + }); +} + +template +static inline std::string toString(const std::vector>& in_values) { + return std::accumulate(std::begin(in_values), std::end(in_values), std::string{}, + [](const std::string& ls, const std::optional& rs) { + return ls + (ls.empty() ? "" : ", ") + + (rs.has_value() ? rs.value().toString() : "empty"); }); } @@ -309,6 +377,50 @@ ndk::ScopedAStatus AudioControl::clearModuleChangeCallback() { return ndk::ScopedAStatus::ok(); } +ndk::ScopedAStatus AudioControl::getAudioDeviceConfiguration( + AudioDeviceConfiguration* audioDeviceConfig) { + if (!audioDeviceConfig) { + LOG(ERROR) << __func__ << "Audio device configuration must not be null"; + return ndk::ScopedAStatus::fromStatus(STATUS_UNEXPECTED_NULL); + } + if (!mCarAudioConfigurationConverter) { + return ndk::ScopedAStatus::ok(); + } + const auto& innerDeviceConfig = mCarAudioConfigurationConverter->getAudioDeviceConfiguration(); + audioDeviceConfig->routingConfig = innerDeviceConfig.routingConfig; + audioDeviceConfig->useCoreAudioVolume = innerDeviceConfig.useCoreAudioVolume; + audioDeviceConfig->useCarVolumeGroupMuting = innerDeviceConfig.useCarVolumeGroupMuting; + audioDeviceConfig->useHalDuckingSignals = innerDeviceConfig.useHalDuckingSignals; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus AudioControl::getOutputMirroringDevices( + std::vector* mirroringDevices) { + if (!mirroringDevices) { + LOG(ERROR) << __func__ << "Mirroring devices must not be null"; + return ndk::ScopedAStatus::fromStatus(STATUS_UNEXPECTED_NULL); + } + if (!mCarAudioConfigurationConverter || !mCarAudioConfigurationConverter->getErrors().empty()) { + return ndk::ScopedAStatus::ok(); + } + const auto& innerDevice = mCarAudioConfigurationConverter->getOutputMirroringDevices(); + mirroringDevices->insert(mirroringDevices->end(), innerDevice.begin(), innerDevice.end()); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus AudioControl::getCarAudioZones(std::vector* audioZones) { + if (!audioZones) { + LOG(ERROR) << __func__ << "Audio zones must not be null"; + return ndk::ScopedAStatus::fromStatus(STATUS_UNEXPECTED_NULL); + } + if (!mCarAudioConfigurationConverter || !mCarAudioConfigurationConverter->getErrors().empty()) { + return ndk::ScopedAStatus::ok(); + } + const auto& innerZones = mCarAudioConfigurationConverter->getAudioZones(); + audioZones->insert(audioZones->end(), innerZones.begin(), innerZones.end()); + return ndk::ScopedAStatus::ok(); +} + binder_status_t AudioControl::dump(int fd, const char** args, uint32_t numArgs) { if (numArgs == 0) { return dumpsys(fd); @@ -342,6 +454,25 @@ binder_status_t AudioControl::dumpsys(int fd) { dprintf(fd, "Focus listener registered\n"); } dprintf(fd, "AudioGainCallback %sregistered\n", (mAudioGainCallback == nullptr ? "NOT " : "")); + + AudioDeviceConfiguration configuration; + if (getAudioDeviceConfiguration(&configuration).isOk()) { + dprintf(fd, "AudioDeviceConfiguration: %s\n", configuration.toString().c_str()); + } + std::vector audioZones; + if (getCarAudioZones(&audioZones).isOk()) { + dprintf(fd, "Audio zones count: %zu\n", audioZones.size()); + for (const auto& zone : audioZones) { + dprintf(fd, "AudioZone: %s\n", formatDump(zone.toString()).c_str()); + } + } + std::vector mirroringDevices; + if (getOutputMirroringDevices(&mirroringDevices).isOk()) { + dprintf(fd, "Mirroring devices count: %zu\n", mirroringDevices.size()); + for (const auto& device : mirroringDevices) { + dprintf(fd, "Mirroring device: %s\n", formatDump(device.toString()).c_str()); + } + } return STATUS_OK; } diff --git a/automotive/audiocontrol/aidl/default/AudioControl.h b/automotive/audiocontrol/aidl/default/AudioControl.h index 7eca446f126094c6b3dfebc47b901914c8a70766..0425570e2bf0ed181cb4495f2d0533a65412a49c 100644 --- a/automotive/audiocontrol/aidl/default/AudioControl.h +++ b/automotive/audiocontrol/aidl/default/AudioControl.h @@ -35,13 +35,17 @@ #include #include +#include "converter/include/CarAudioConfigurationXmlConverter.h" + namespace aidl::android::hardware::automotive::audiocontrol { -namespace audiohalcommon = ::aidl::android::hardware::audio::common; namespace audiomediacommon = ::aidl::android::media::audio::common; +namespace audiohalcommon = ::aidl::android::hardware::audio::common; class AudioControl : public BnAudioControl { public: + AudioControl(); + AudioControl(const std::string& carAudioConfig, const std::string& audioFadeConfig); ndk::ScopedAStatus onAudioFocusChange(const std::string& in_usage, int32_t in_zoneId, AudioFocusChange in_focusChange) override; ndk::ScopedAStatus onDevicesToDuckChange( @@ -63,6 +67,11 @@ class AudioControl : public BnAudioControl { ndk::ScopedAStatus setModuleChangeCallback( const std::shared_ptr& in_callback) override; ndk::ScopedAStatus clearModuleChangeCallback() override; + ndk::ScopedAStatus getAudioDeviceConfiguration( + AudioDeviceConfiguration* audioDeviceConfig) override; + ndk::ScopedAStatus getOutputMirroringDevices( + std::vector<::aidl::android::media::audio::common::AudioPort>* mirrorDevices) override; + ndk::ScopedAStatus getCarAudioZones(std::vector* audioZones) override; binder_status_t dump(int fd, const char** args, uint32_t numArgs) override; @@ -81,6 +90,9 @@ class AudioControl : public BnAudioControl { std::shared_ptr mModuleChangeCallback = nullptr; + std::shared_ptr<::android::hardware::audiocontrol::internal::CarAudioConfigurationXmlConverter> + mCarAudioConfigurationConverter = nullptr; + binder_status_t cmdHelp(int fd) const; binder_status_t cmdRequestFocus(int fd, const char** args, uint32_t numArgs); binder_status_t cmdAbandonFocus(int fd, const char** args, uint32_t numArgs); diff --git a/automotive/audiocontrol/aidl/default/audiocontrol-default.xml b/automotive/audiocontrol/aidl/default/audiocontrol-default.xml index bcb5669f385713afa986d0e78f386d76cf945388..ffef7fc6dd1b1852bdc853acf499bd0304d33b74 100644 --- a/automotive/audiocontrol/aidl/default/audiocontrol-default.xml +++ b/automotive/audiocontrol/aidl/default/audiocontrol-default.xml @@ -1,7 +1,7 @@ android.hardware.automotive.audiocontrol - 4 + 5 IAudioControl/default diff --git a/automotive/audiocontrol/aidl/default/converter/Android.bp b/automotive/audiocontrol/aidl/default/converter/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..c00afa2dbf758ec2eedb9f1fc1dcee2437642fd7 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/Android.bp @@ -0,0 +1,56 @@ +// 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. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_library { + name: "android.hardware.audiocontrol.internal", + vendor: true, + srcs: [ + "src/CarAudioConfigurationXmlConverter.cpp", + "src/CarAudioConfigurationUtils.cpp", + ], + export_include_dirs: [ + "include", + ], + defaults: [ + "latest_android_hardware_audio_common_ndk_static", + "latest_android_hardware_automotive_audiocontrol_ndk_shared", + "car.audio.configuration.xsd.default", + "car.fade.configuration.xsd.default", + "aidlaudioservice_defaults", + "latest_android_media_audio_common_types_ndk_static", + ], + shared_libs: [ + "libbase", + "libutils", + "libmedia_helper", + "car.audio.configuration.xsd.default", + "car.fade.configuration.xsd.default", + "liblog", + ], + static_libs: [ + "libaudio_aidl_conversion_common_ndk_cpp", + ], + header_libs: [ + "libaudio_system_headers", + ], +} diff --git a/automotive/audiocontrol/aidl/default/converter/include/CarAudioConfigurationUtils.h b/automotive/audiocontrol/aidl/default/converter/include/CarAudioConfigurationUtils.h new file mode 100644 index 0000000000000000000000000000000000000000..29fec0b1f11d1e5e378a67c6c54c529f567ee3cc --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/include/CarAudioConfigurationUtils.h @@ -0,0 +1,37 @@ +/* + * 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. + */ + +#ifndef ANDROID_HARDWARE_AUDIOCONTROL_INTERNAL_CONFIGURATION_UTILS_H +#define ANDROID_HARDWARE_AUDIOCONTROL_INTERNAL_CONFIGURATION_UTILS_H + +#include + +#include +#include + +namespace android { +namespace hardware { +namespace audiocontrol { +namespace internal { + +::aidl::android::hardware::automotive::audiocontrol::AudioZoneContext getDefaultCarAudioContext(); + +} // namespace internal +} // namespace audiocontrol +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_AUDIOCONTROL_INTERNAL_CONFIGURATION_UTILS_H diff --git a/automotive/audiocontrol/aidl/default/converter/include/CarAudioConfigurationXmlConverter.h b/automotive/audiocontrol/aidl/default/converter/include/CarAudioConfigurationXmlConverter.h new file mode 100644 index 0000000000000000000000000000000000000000..ed29172cf563d85e895bc997263ae262c1a4012d --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/include/CarAudioConfigurationXmlConverter.h @@ -0,0 +1,87 @@ +/* + * 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. + */ + +#ifndef MAIN8_CARAUDIOCONFIGURATIONXMLCONVERTER_H +#define MAIN8_CARAUDIOCONFIGURATIONXMLCONVERTER_H + +#include + +#include "../include/CarAudioConfigurationUtils.h" + +#include +#include +#include + +namespace android::hardware::automotive::audiocontrol { +class CarAudioConfigurationType; +} + +namespace android { +namespace hardware { +namespace audiocontrol { +namespace internal { + +class CarAudioConfigurationXmlConverter { + public: + explicit CarAudioConfigurationXmlConverter(const std::string& audioConfigFile, + const std::string& fadeConfigFile) + : mAudioConfigFile(audioConfigFile), mFadeConfigFile(fadeConfigFile) { + init(); + } + + ::aidl::android::hardware::automotive::audiocontrol::AudioDeviceConfiguration + getAudioDeviceConfiguration() const; + + std::vector<::aidl::android::hardware::automotive::audiocontrol::AudioZone> getAudioZones() + const; + std::vector<::aidl::android::media::audio::common::AudioPort> getOutputMirroringDevices() const; + + const std::string getErrors() const { return mParseErrors; } + + private: + void init(); + void initNonDynamicRouting(); + void initFadeConfigurations(); + void initAudioDeviceConfiguration( + const ::android::hardware::automotive::audiocontrol::CarAudioConfigurationType& + carAudioConfigurationType); + void initCarAudioConfigurations( + const ::android::hardware::automotive::audiocontrol::CarAudioConfigurationType& + carAudioConfigurationType); + void parseAudioDeviceConfigurations( + const ::android::hardware::automotive::audiocontrol::CarAudioConfigurationType& + carAudioConfigurationType); + + const std::string mAudioConfigFile; + const std::string mFadeConfigFile; + ::aidl::android::hardware::automotive::audiocontrol::AudioDeviceConfiguration + mAudioDeviceConfiguration; + std::optional<::aidl::android::hardware::automotive::audiocontrol::AudioZoneContext> + mAudioZoneContext; + std::vector<::aidl::android::hardware::automotive::audiocontrol::AudioZone> mAudioZones; + std::vector<::aidl::android::media::audio::common::AudioPort> mOutputMirroringDevices; + std::string mParseErrors; + std::unordered_map + mFadeConfigurations; +}; + +} // namespace internal +} // namespace audiocontrol +} // namespace hardware +} // namespace android + +#endif // MAIN8_CARAUDIOCONFIGURATIONXMLCONVERTER_H diff --git a/automotive/audiocontrol/aidl/default/converter/src/CarAudioConfigurationUtils.cpp b/automotive/audiocontrol/aidl/default/converter/src/CarAudioConfigurationUtils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e2f81915c4e7620da2d58b9baf6e03e874d9c331 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/src/CarAudioConfigurationUtils.cpp @@ -0,0 +1,104 @@ +/* + * 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/CarAudioConfigurationUtils.h" + +#include +#include + +#include +#include + +using ::aidl::android::hardware::automotive::audiocontrol::AudioZoneContext; +using ::aidl::android::hardware::automotive::audiocontrol::AudioZoneContextInfo; + +using aidl::android::media::audio::common::AudioAttributes; +using aidl::android::media::audio::common::AudioUsage; +using aidl::android::media::audio::common::AudioUsage::ALARM; +using aidl::android::media::audio::common::AudioUsage::ANNOUNCEMENT; +using aidl::android::media::audio::common::AudioUsage::ASSISTANCE_ACCESSIBILITY; +using aidl::android::media::audio::common::AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE; +using aidl::android::media::audio::common::AudioUsage::ASSISTANCE_SONIFICATION; +using aidl::android::media::audio::common::AudioUsage::ASSISTANT; +using aidl::android::media::audio::common::AudioUsage::CALL_ASSISTANT; +using aidl::android::media::audio::common::AudioUsage::EMERGENCY; +using aidl::android::media::audio::common::AudioUsage::GAME; +using aidl::android::media::audio::common::AudioUsage::MEDIA; +using aidl::android::media::audio::common::AudioUsage::NOTIFICATION; +using aidl::android::media::audio::common::AudioUsage::NOTIFICATION_EVENT; +using aidl::android::media::audio::common::AudioUsage::NOTIFICATION_TELEPHONY_RINGTONE; +using aidl::android::media::audio::common::AudioUsage::SAFETY; +using aidl::android::media::audio::common::AudioUsage::UNKNOWN; +using aidl::android::media::audio::common::AudioUsage::VEHICLE_STATUS; +using aidl::android::media::audio::common::AudioUsage::VOICE_COMMUNICATION; +using aidl::android::media::audio::common::AudioUsage::VOICE_COMMUNICATION_SIGNALLING; + +namespace android { +namespace hardware { +namespace audiocontrol { +namespace internal { + +std::vector createAudioAttributes(const std::vector& usages) { + std::vector audioAttributes; + for (const auto& usage : usages) { + AudioAttributes attributes; + attributes.usage = usage; + audioAttributes.push_back(attributes); + } + return audioAttributes; +} + +AudioZoneContextInfo createAudioZoneContextInfo(const std::string& name, int id, + const std::vector& usages) { + AudioZoneContextInfo info; + info.name = name; + info.id = id; + info.audioAttributes = createAudioAttributes(usages); + return info; +} + +AudioZoneContext createAudioZoneContextInfo(const std::vector& info) { + AudioZoneContext context; + context.audioContextInfos.insert(context.audioContextInfos.begin(), info.begin(), info.end()); + return context; +} + +AudioZoneContext getDefaultCarAudioContext() { + // For legacy reasons, context names are lower case here. + static const AudioZoneContext kDefaultContext = createAudioZoneContextInfo( + {createAudioZoneContextInfo("music", 1, {UNKNOWN, MEDIA, GAME}), + createAudioZoneContextInfo("navigation", 2, {ASSISTANCE_NAVIGATION_GUIDANCE}), + createAudioZoneContextInfo("voice_command", 3, {ASSISTANCE_ACCESSIBILITY, ASSISTANT}), + createAudioZoneContextInfo("call_ring", 4, {NOTIFICATION_TELEPHONY_RINGTONE}), + createAudioZoneContextInfo( + "call", 5, + {VOICE_COMMUNICATION, CALL_ASSISTANT, VOICE_COMMUNICATION_SIGNALLING}), + createAudioZoneContextInfo("alarm", 6, {ALARM}), + createAudioZoneContextInfo("notification", 7, {NOTIFICATION, NOTIFICATION_EVENT}), + createAudioZoneContextInfo("system_sound", 8, {ASSISTANCE_SONIFICATION}), + createAudioZoneContextInfo("emergency", 9, {EMERGENCY}), + createAudioZoneContextInfo("safety", 10, {SAFETY}), + createAudioZoneContextInfo("vehicle_status", 11, {VEHICLE_STATUS}), + createAudioZoneContextInfo("announcement", 12, {ANNOUNCEMENT})}); + return kDefaultContext; +} + +} // namespace internal +} // namespace audiocontrol +} // namespace hardware +} // namespace android diff --git a/automotive/audiocontrol/aidl/default/converter/src/CarAudioConfigurationXmlConverter.cpp b/automotive/audiocontrol/aidl/default/converter/src/CarAudioConfigurationXmlConverter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f4e8123776719373c61934bf9ff6ee0567ed02e9 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/src/CarAudioConfigurationXmlConverter.cpp @@ -0,0 +1,1134 @@ +/* + * 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. + */ + +#define LOG_TAG "AudioControl::XSD_Converter" + +#define LOG_NDEBUG 0 +#include + +#include "../include/CarAudioConfigurationXmlConverter.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace audiocontrol { +namespace internal { +namespace xsd = ::android::hardware::automotive::audiocontrol; +namespace fade = android::hardware::automotive::audiocontrol::fade; +namespace api = ::aidl::android::hardware::automotive::audiocontrol; + +using aidl::android::media::audio::common::AudioAttributes; +using aidl::android::media::audio::common::AudioContentType; +using aidl::android::media::audio::common::AudioDevice; +using aidl::android::media::audio::common::AudioDeviceAddress; +using aidl::android::media::audio::common::AudioDeviceDescription; +using aidl::android::media::audio::common::AudioDeviceType; +using aidl::android::media::audio::common::AudioHalProductStrategy; +using aidl::android::media::audio::common::AudioPort; +using aidl::android::media::audio::common::AudioPortDeviceExt; +using aidl::android::media::audio::common::AudioPortExt; +using aidl::android::media::audio::common::AudioUsage; + +using namespace ::android::base; + +namespace { + +static const std::string kUseCoreRouting{"useCoreAudioRouting"}; +static const std::string kUseCoreVolume{"useCoreAudioVolume"}; +static const std::string kUseHalDuckingSignals{"useHalDuckingSignals"}; +static const std::string kUseCarVolumeGroupMuting{"useCarVolumeGroupMuting"}; + +static constexpr char kOutBusType[] = "AUDIO_DEVICE_OUT_BUS"; +static constexpr char kInBusType[] = "AUDIO_DEVICE_IN_BUS"; + +using ActivationMap = std::unordered_map; +using FadeConfigurationMap = std::unordered_map< + std::string, ::aidl::android::hardware::automotive::audiocontrol::AudioFadeConfiguration>; + +inline bool isReadableConfigurationFile(const std::string& filePath) { + return !filePath.empty() && filePath.ends_with(".xml") && (access(filePath.c_str(), R_OK) == 0); +} + +inline bool parseBoolOrDefaultIfFailed(const std::string& value, bool defaultValue) { + ParseBoolResult results = ParseBool(value); + return results == ParseBoolResult::kError ? defaultValue : results == ParseBoolResult::kTrue; +} + +void parseCoreRoutingInfo(const std::string& value, api::AudioDeviceConfiguration& config) { + if (!parseBoolOrDefaultIfFailed(value, /* defaultValue= */ false)) { + return; + } + config.routingConfig = api::RoutingDeviceConfiguration::CONFIGURABLE_AUDIO_ENGINE_ROUTING; +} + +void parseCoreVolumeInfo(const std::string& value, api::AudioDeviceConfiguration& config) { + config.useCoreAudioVolume = parseBoolOrDefaultIfFailed(value, config.useCoreAudioVolume); +} + +void parseHalDuckingInfo(const std::string& value, api::AudioDeviceConfiguration& config) { + config.useHalDuckingSignals = parseBoolOrDefaultIfFailed(value, config.useHalDuckingSignals); +} + +void parseHalMutingInfo(const std::string& value, api::AudioDeviceConfiguration& config) { + config.useCarVolumeGroupMuting = + parseBoolOrDefaultIfFailed(value, config.useCarVolumeGroupMuting); +} + +bool parseAudioAttributeUsageString(const std::string& usageString, AudioUsage& usage) { + audio_usage_t legacyUsage; + if (!::android::UsageTypeConverter::fromString(usageString, legacyUsage)) { + LOG(ERROR) << __func__ << " could not parse usage from string " << usageString; + return false; + } + ConversionResult result = + ::aidl::android::legacy2aidl_audio_usage_t_AudioUsage(legacyUsage); + if (!result.ok()) { + LOG(ERROR) << __func__ << " could not parse usage legacy type " << legacyUsage; + return false; + } + usage = result.value(); + return true; +} + +bool parseAudioAttributeUsage(const xsd::UsageType& usageType, AudioAttributes& attributes) { + if (!usageType.hasValue()) { + LOG(ERROR) << __func__ << " usage does not have value"; + return false; + } + if (!parseAudioAttributeUsageString(xsd::toString(usageType.getValue()), attributes.usage)) { + return false; + } + return true; +} + +bool parseAudioAttributesUsages(const std::vector& usages, + std::vector& audioAttributes) { + for (const auto& xsdUsage : usages) { + AudioAttributes attributes; + if (!parseAudioAttributeUsage(xsdUsage, attributes)) { + return false; + } + audioAttributes.push_back(attributes); + } + return true; +} + +bool parseContentTypeString(const std::string& typeString, AudioContentType& type) { + audio_content_type_t legacyContentType; + if (!::android::AudioContentTypeConverter::fromString(typeString, legacyContentType)) { + LOG(ERROR) << __func__ << " could not parse content type from string " << typeString; + return false; + } + ConversionResult result = + ::aidl::android::legacy2aidl_audio_content_type_t_AudioContentType(legacyContentType); + if (!result.ok()) { + LOG(ERROR) << __func__ << " could not convert legacy content type " << legacyContentType; + return false; + } + type = result.value(); + return true; +} + +bool parseAudioAttribute(const xsd::AttributesType& attributesType, AudioAttributes& attributes) { + if (attributesType.hasUsage()) { + if (!parseAudioAttributeUsageString(xsd::toString(attributesType.getUsage()), + attributes.usage)) { + LOG(ERROR) << __func__ << " could not parse audio usage: " + << xsd::toString(attributesType.getUsage()); + return false; + } + } + + if (attributesType.hasContentType()) { + if (!parseContentTypeString(xsd::toString(attributesType.getContentType()), + attributes.contentType)) { + return false; + } + } + + if (attributesType.hasTags()) { + attributes.tags.push_back(attributesType.getTags()); + } + return true; +} + +bool parseAudioAttributes(const std::vector& xsdAttributes, + std::vector& audioAttributes) { + for (const auto& xsdAttribute : xsdAttributes) { + AudioAttributes attribute; + if (!parseAudioAttribute(xsdAttribute, attribute)) { + return false; + } + audioAttributes.push_back(attribute); + } + return true; +} + +bool parseAudioAttributes(const xsd::AudioAttributesUsagesType& xsdAttributeOrUsages, + std::vector& audioAttributes) { + if (xsdAttributeOrUsages.hasUsage_optional()) { + if (!parseAudioAttributesUsages(xsdAttributeOrUsages.getUsage_optional(), + audioAttributes)) { + LOG(ERROR) << __func__ << " could not parse audio usages"; + return false; + } + } + + if (xsdAttributeOrUsages.hasAudioAttribute_optional()) { + if (!parseAudioAttributes(xsdAttributeOrUsages.getAudioAttribute_optional(), + audioAttributes)) { + LOG(ERROR) << __func__ << " could not parse audio attributes"; + return false; + } + } + return true; +} + +bool parseAudioContext(const xsd::OemContextType& xsdContextInfo, + api::AudioZoneContextInfo& contextInfo) { + if (!xsdContextInfo.hasName()) { + LOG(ERROR) << __func__ << " Audio context info missing name"; + return false; + } + + contextInfo.name = xsdContextInfo.getName(); + + if (xsdContextInfo.hasId()) { + ParseInt(xsdContextInfo.getId().c_str(), &contextInfo.id); + } + + if (xsdContextInfo.hasAudioAttributes()) { + if (!parseAudioAttributes(*xsdContextInfo.getFirstAudioAttributes(), + contextInfo.audioAttributes)) { + return false; + } + } + + return true; +} + +bool parseAudioContexts(const xsd::OemContextsType* xsdContexts, api::AudioZoneContext& context) { + if (!xsdContexts->hasOemContext()) { + return false; + } + const auto xsdContextInfos = xsdContexts->getOemContext(); + for (const auto& xsdContextInfo : xsdContextInfos) { + api::AudioZoneContextInfo info; + if (!parseAudioContext(xsdContextInfo, info)) { + continue; + } + context.audioContextInfos.push_back(info); + } + return true; +} + +bool createAudioDevice(const std::string& address, const std::string& type, AudioPort& port) { + audio_devices_t legacyDeviceType = AUDIO_DEVICE_NONE; + ::android::DeviceConverter::fromString(type, legacyDeviceType); + std::string tempString; + ::android::DeviceConverter::toString(legacyDeviceType, tempString); + ConversionResult result = + ::aidl::android::legacy2aidl_audio_devices_t_AudioDeviceDescription(legacyDeviceType); + if (legacyDeviceType == AUDIO_DEVICE_NONE || !result.ok()) { + LOG(ERROR) << __func__ << " could not parse legacy device type"; + return false; + } + AudioDevice device; + if (!address.empty()) { + device.address = AudioDeviceAddress::make(address); + } + device.type = result.value(); + + port.ext = AudioPortExt::make(device); + + return true; +} + +std::string outTypeToOutAudioDevice(const std::string& device) { + const static std::unordered_map typeToOutDevice{ + {"TYPE_BUILTIN_SPEAKER", "AUDIO_DEVICE_OUT_SPEAKER"}, + {"TYPE_WIRED_HEADSET", "AUDIO_DEVICE_OUT_WIRED_HEADSET"}, + {"TYPE_WIRED_HEADPHONES", "AUDIO_DEVICE_OUT_WIRED_HEADPHONE,"}, + {"TYPE_BLUETOOTH_A2DP", "AUDIO_DEVICE_OUT_BLUETOOTH_A2DP"}, + {"TYPE_HDMI", "AUDIO_DEVICE_OUT_HDMI"}, + {"TYPE_USB_ACCESSORY", "AUDIO_DEVICE_OUT_USB_ACCESSORY"}, + {"TYPE_USB_DEVICE", "AUDIO_DEVICE_OUT_USB_DEVICE,"}, + {"TYPE_USB_HEADSET", "AUDIO_DEVICE_OUT_USB_HEADSET"}, + {"TYPE_AUX_LINE", "AUDIO_DEVICE_OUT_AUX_LINE"}, + {"TYPE_BUS", "AUDIO_DEVICE_OUT_BUS"}, + {"TYPE_BLE_HEADSET", "AUDIO_DEVICE_OUT_BLE_HEADSET"}, + {"TYPE_BLE_SPEAKER", "AUDIO_DEVICE_OUT_BLE_SPEAKER"}, + {"TYPE_BLE_BROADCAST", "AUDIO_DEVICE_OUT_BLE_BROADCAST"}, + }; + + if (!device.starts_with("TYPE_")) { + return device; + } + + const auto it = typeToOutDevice.find(device); + return it != typeToOutDevice.end() ? it->second : device; +} + +bool parseAudioDeviceToContexts(const xsd::DeviceRoutesType& deviceRoutesType, + api::DeviceToContextEntry& route) { + std::string address = deviceRoutesType.hasAddress() ? deviceRoutesType.getAddress() : ""; + // Default type is bus for schema + std::string type = outTypeToOutAudioDevice(deviceRoutesType.hasType() + ? xsd::toString(deviceRoutesType.getType()) + : std::string(kOutBusType)); + // Address must be present for audio device bus + if (address.empty() && type == std::string(kOutBusType)) { + LOG(ERROR) << __func__ << " empty device address for bus device type"; + return false; + } + if (!createAudioDevice(address, type, route.device)) { + return false; + } + + if (!deviceRoutesType.hasContext()) { + LOG(ERROR) << __func__ << " empty device context mapping"; + return false; + } + + for (const auto& xsdContext : deviceRoutesType.getContext()) { + if (!xsdContext.hasContext()) { + LOG(ERROR) << __func__ << " audio device route missing context info"; + return false; + } + route.contextNames.push_back(xsdContext.getContext()); + } + + return true; +} + +bool parseAudioDeviceRoutes(const std::vector deviceRoutesTypes, + std::vector& routes) { + for (const auto& deviceRouteType : deviceRoutesTypes) { + api::DeviceToContextEntry entry; + if (!parseAudioDeviceToContexts(deviceRouteType, entry)) { + return false; + } + routes.push_back(entry); + } + return true; +} + +void parseVolumeGroupActivation(const std::string& activationConfigName, + const ActivationMap& activations, + api::VolumeGroupConfig& volumeGroup) { + if (activationConfigName.empty()) { + LOG(ERROR) << __func__ << " Volume group " << volumeGroup.name + << " has empty volume group activation name"; + return; + } + const auto& it = activations.find(activationConfigName); + if (it == activations.end()) { + LOG(ERROR) << __func__ << " Volume group " << volumeGroup.name + << " has non-existing volume group activation name " << activationConfigName; + return; + } + volumeGroup.activationConfiguration = it->second; +} + +bool parseVolumeGroup(const xsd::VolumeGroupType& volumeGroupType, const ActivationMap& activations, + api::VolumeGroupConfig& volumeGroup) { + if (!volumeGroupType.hasDevice()) { + LOG(ERROR) << __func__ << " no device found"; + return false; + } + + if (volumeGroupType.hasName()) { + volumeGroup.name = volumeGroupType.getName(); + } + + if (!parseAudioDeviceRoutes(volumeGroupType.getDevice(), volumeGroup.carAudioRoutes)) { + return false; + } + + if (volumeGroupType.hasActivationConfig()) { + parseVolumeGroupActivation(volumeGroupType.getActivationConfig(), activations, volumeGroup); + } + + return true; +} + +bool parseVolumeGroups(const xsd::VolumeGroupsType* volumeGroupsType, + const ActivationMap& activations, + std::vector& volumeGroups) { + if (!volumeGroupsType->hasGroup()) { + LOG(ERROR) << __func__ << " no volume groups found"; + return false; + } + for (const auto& volumeGroupType : volumeGroupsType->getGroup()) { + api::VolumeGroupConfig volumeGroup; + if (!parseVolumeGroup(volumeGroupType, activations, volumeGroup)) { + return false; + } + volumeGroups.push_back(volumeGroup); + } + return true; +} + +void parseFadeConfigurationUsages(const xsd::ApplyFadeConfigType& fadeConfigType, + std::vector& usages) { + if (!fadeConfigType.hasAudioAttributes()) { + return; + } + const xsd::AudioAttributeUsagesType* attributesOrUsagesType = + fadeConfigType.getFirstAudioAttributes(); + if (!attributesOrUsagesType->hasUsage()) { + return; + } + for (const auto& usageType : attributesOrUsagesType->getUsage()) { + AudioUsage usage; + if (!usageType.hasValue() || + !parseAudioAttributeUsageString(xsd::toString(usageType.getValue()), usage)) { + continue; + } + usages.push_back(usage); + } +} + +void parseZoneFadeConfiguration(const xsd::ApplyFadeConfigType& fadeConfigType, + const FadeConfigurationMap& fadeConfigurations, + api::AudioZoneFadeConfiguration& zoneFadeConfiguration) { + if (!fadeConfigType.hasName()) { + LOG(ERROR) << __func__ << " Found a fade config without a name, skipping assignment"; + return; + } + + const auto it = fadeConfigurations.find(fadeConfigType.getName()); + if (it == fadeConfigurations.end()) { + LOG(ERROR) << __func__ << " Config name " << fadeConfigType.getName() + << " not found, skipping assignment"; + return; + } + // Return for default since default configurations do not have any audio attributes mapping + if (fadeConfigType.hasIsDefault()) { + zoneFadeConfiguration.defaultConfiguration = it->second; + return; + } + + api::TransientFadeConfigurationEntry entry; + entry.transientFadeConfiguration = it->second; + parseFadeConfigurationUsages(fadeConfigType, entry.transientUsages); + zoneFadeConfiguration.transientConfiguration.push_back(entry); +} + +void parseZoneFadeConfigurations(const xsd::ZoneConfigType& zoneConfigType, + const FadeConfigurationMap& fadeConfigurations, + std::optional& zoneFadeConfig) { + if (!zoneConfigType.hasApplyFadeConfigs()) { + return; + } + const xsd::ApplyFadeConfigsType* applyFadeConfigs = zoneConfigType.getFirstApplyFadeConfigs(); + if (!applyFadeConfigs->hasFadeConfig()) { + return; + } + api::AudioZoneFadeConfiguration zoneFadeConfiguration; + for (const auto& fadeConfigType : applyFadeConfigs->getFadeConfig()) { + parseZoneFadeConfiguration(fadeConfigType, fadeConfigurations, zoneFadeConfiguration); + } + zoneFadeConfig = zoneFadeConfiguration; +} + +bool parseAudioZoneConfig(const xsd::ZoneConfigType& zoneConfigType, + const ActivationMap& activations, + const FadeConfigurationMap& fadeConfigurations, + api::AudioZoneConfig& config) { + if (!zoneConfigType.hasVolumeGroups()) { + LOG(ERROR) << __func__ << " no volume groups found"; + return false; + } + + if (zoneConfigType.hasName()) { + config.name = zoneConfigType.getName(); + } + if (!parseVolumeGroups(zoneConfigType.getFirstVolumeGroups(), activations, + config.volumeGroups)) { + return false; + } + + parseZoneFadeConfigurations(zoneConfigType, fadeConfigurations, config.fadeConfiguration); + + config.isDefault = zoneConfigType.hasIsDefault() && zoneConfigType.getIsDefault(); + + return true; +} + +bool parseAudioZoneConfigs(const xsd::ZoneConfigsType* zoneConfigsType, + const ActivationMap& activations, + const FadeConfigurationMap& fadeConfigurations, + std::vector& configs) { + if (!zoneConfigsType->hasZoneConfig()) { + LOG(ERROR) << __func__ << " No zone configs found"; + return false; + } + + if (zoneConfigsType->getZoneConfig().empty()) { + LOG(ERROR) << __func__ << " Empty list of audio configurations"; + return false; + } + + for (const auto& zoneConfigType : zoneConfigsType->getZoneConfig()) { + api::AudioZoneConfig config; + if (!parseAudioZoneConfig(zoneConfigType, activations, fadeConfigurations, config)) { + return false; + } + configs.push_back(config); + } + + return true; +} + +bool parseInputDevice(const xsd::InputDeviceType& xsdInputDevice, AudioPort& inputDevice) { + // Input device must have a non-empty address + if (!xsdInputDevice.hasAddress() || xsdInputDevice.getAddress().empty()) { + LOG(ERROR) << __func__ << " missing device address"; + return false; + } + // By default a device is bus type, unless specified + std::string inputDeviceType = + xsdInputDevice.hasType() ? xsd::toString(xsdInputDevice.getType()) : kInBusType; + if (!createAudioDevice(xsdInputDevice.getAddress(), inputDeviceType, inputDevice)) { + return false; + } + return true; +} + +void parseInputDevices(const xsd::InputDevicesType* xsdInputDevices, + std::vector& inputDevices) { + if (!xsdInputDevices->hasInputDevice()) { + return; + } + for (const auto& xsdInputDevice : xsdInputDevices->getInputDevice()) { + AudioPort inputDevice; + if (!parseInputDevice(xsdInputDevice, inputDevice)) { + continue; + } + inputDevices.push_back(inputDevice); + } +} + +bool parseAudioZone(const xsd::ZoneType& zone, const ActivationMap& activations, + const FadeConfigurationMap& fadeConfigurations, api::AudioZone& audioZone) { + static int kPrimaryZoneId = static_cast(AudioHalProductStrategy::ZoneId::DEFAULT); + if (zone.hasName()) { + audioZone.name = zone.getName(); + } + + if (zone.hasOccupantZoneId()) { + ParseInt(zone.getOccupantZoneId().c_str(), &audioZone.occupantZoneId); + } + + if (zone.hasInputDevices()) { + parseInputDevices(zone.getFirstInputDevices(), audioZone.inputAudioDevices); + } + + // Audio zone id is required + if (!zone.hasAudioZoneId()) { + LOG(ERROR) << __func__ << " Audio zone id required for each zone"; + return false; + } + + bool isPrimary = zone.hasIsPrimary() && zone.getIsPrimary(); + + if (isPrimary) { + audioZone.id = kPrimaryZoneId; + } + + // ID not required in XML for primary zone + if (!ParseInt(zone.getAudioZoneId().c_str(), &audioZone.id) && !isPrimary) { + LOG(ERROR) << __func__ + << " Could not parse audio zone id, must be a non-negative integer or isPrimary " + "must be specify as true for primary zone"; + return false; + } + + if (isPrimary && audioZone.id != kPrimaryZoneId) { + LOG(ERROR) << __func__ << " Audio zone is primary but has zone id " + << std::to_string(audioZone.id) << " instead of primary zone id " + << std::to_string(kPrimaryZoneId); + return false; + } + + if (!zone.hasZoneConfigs()) { + LOG(ERROR) << __func__ << " Missing audio zone configs for audio zone id " << audioZone.id; + return false; + } + if (!parseAudioZoneConfigs(zone.getFirstZoneConfigs(), activations, fadeConfigurations, + audioZone.audioZoneConfigs)) { + LOG(ERROR) << __func__ << " Could not parse zone configs for audio zone id " << audioZone.id + << ", name " << audioZone.name; + return false; + } + + return true; +} + +std::string parseAudioZones(const xsd::ZonesType* zones, const api::AudioZoneContext& context, + const ActivationMap& activations, + const FadeConfigurationMap& fadeConfigurations, + std::vector& audioZones) { + if (!zones->hasZone()) { + return "audio zones are missing"; + } + const auto& xsdZones = zones->getZone(); + for (const auto& xsdZone : xsdZones) { + api::AudioZone audioZone; + audioZone.audioZoneContext = context; + if (!parseAudioZone(xsdZone, activations, fadeConfigurations, audioZone)) { + continue; + } + audioZones.push_back(audioZone); + } + return ""; +} + +std::unordered_map> +getConfigsParsers() { + static const std::unordered_map< + std::string, std::function> + parsers{ + {kUseCoreRouting, parseCoreRoutingInfo}, + {kUseCoreVolume, parseCoreVolumeInfo}, + {kUseHalDuckingSignals, parseHalDuckingInfo}, + {kUseCarVolumeGroupMuting, parseHalMutingInfo}, + }; + + return parsers; +} + +bool parseVolumeActivationType(const xsd::ActivationType& xsdType, + api::VolumeInvocationType& activationType) { + switch (xsdType) { + case xsd::ActivationType::onBoot: + activationType = api::VolumeInvocationType::ON_BOOT; + break; + case xsd::ActivationType::onSourceChanged: + activationType = api::VolumeInvocationType::ON_SOURCE_CHANGED; + break; + case xsd::ActivationType::onPlaybackChanged: + activationType = api::VolumeInvocationType::ON_PLAYBACK_CHANGED; + break; + default: + return false; + } + return true; +} + +bool parseVolumeGroupActivationEntry(const xsd::ActivationVolumeConfigEntryType& xsdEntry, + api::VolumeActivationConfigurationEntry& entry) { + if (!xsdEntry.hasInvocationType()) { + // Legacy file had default invocation type as on playback changed + entry.type = api::VolumeInvocationType::ON_PLAYBACK_CHANGED; + } else if (!parseVolumeActivationType(xsdEntry.getInvocationType(), entry.type)) { + LOG(ERROR) << __func__ << " Could not parse configuration entry type"; + return false; + } + + if (xsdEntry.hasMaxActivationVolumePercentage()) { + // Parse int ranges are not inclusive + ParseInt(xsdEntry.getMaxActivationVolumePercentage().c_str(), + &entry.maxActivationVolumePercentage, + api::VolumeActivationConfigurationEntry::DEFAULT_MIN_ACTIVATION_VALUE - 1, + api::VolumeActivationConfigurationEntry::DEFAULT_MAX_ACTIVATION_VALUE + 1); + } + + if (xsdEntry.hasMinActivationVolumePercentage()) { + // Parse int ranges are not inclusive + ParseInt(xsdEntry.getMinActivationVolumePercentage().c_str(), + &entry.minActivationVolumePercentage, + api::VolumeActivationConfigurationEntry::DEFAULT_MIN_ACTIVATION_VALUE - 1, + api::VolumeActivationConfigurationEntry::DEFAULT_MAX_ACTIVATION_VALUE + 1); + } + + return true; +} + +bool parseVolumeGroupActivationEntries( + const std::vector& xsdEntries, + std::vector& entries) { + for (const auto& xsdEntry : xsdEntries) { + api::VolumeActivationConfigurationEntry entry; + if (!parseVolumeGroupActivationEntry(xsdEntry, entry)) { + LOG(ERROR) << __func__ << " Could not parse volume group activation entries"; + return false; + } + entries.push_back(entry); + } + return true; +} + +bool parseVolumeGroupActivation(const xsd::ActivationVolumeConfigType& xsdActivationConfig, + api::VolumeActivationConfiguration& activation) { + if (!xsdActivationConfig.hasName()) { + LOG(ERROR) << __func__ << " Activation config missing volume activation name"; + return false; + } + if (!xsdActivationConfig.hasActivationVolumeConfigEntry()) { + LOG(ERROR) << __func__ << " Activation config missing volume activation entries"; + return false; + } + if (!parseVolumeGroupActivationEntries(xsdActivationConfig.getActivationVolumeConfigEntry(), + activation.volumeActivationEntries)) { + LOG(ERROR) << __func__ << " Could not parse volume activation name"; + return false; + } + activation.name = xsdActivationConfig.getName(); + return true; +} + +void parseVolumeGroupActivations(const xsd::ActivationVolumeConfigsType* xsdActivationConfigs, + ActivationMap& activations) { + if (!xsdActivationConfigs->hasActivationVolumeConfig()) { + LOG(ERROR) << __func__ << " No volume group activations found"; + return; + } + for (const auto& xsdActivationConfig : xsdActivationConfigs->getActivationVolumeConfig()) { + api::VolumeActivationConfiguration activationConfiguration; + if (!parseVolumeGroupActivation(xsdActivationConfig, activationConfiguration)) { + continue; + } + std::string name = xsdActivationConfig.getName(); + activations.emplace(name, activationConfiguration); + } +} + +void parseOutputMirroringDevices(const xsd::MirroringDevicesType* mirroringDevicesType, + std::vector& mirroringDevices) { + if (!mirroringDevicesType->hasMirroringDevice()) { + LOG(ERROR) << __func__ << " Missing audio mirroring devices"; + return; + } + for (const auto& xsdMirrorDevice : mirroringDevicesType->getMirroringDevice()) { + AudioPort mirrorDevicePort; + if (!xsdMirrorDevice.hasAddress()) { + LOG(ERROR) << __func__ << " Missing audio mirroring device address"; + continue; + } + if (!createAudioDevice(xsdMirrorDevice.getAddress(), kOutBusType, mirrorDevicePort)) { + LOG(ERROR) << __func__ << " Could not create mirror device with address " + << xsdMirrorDevice.getAddress(); + continue; + } + mirroringDevices.push_back(mirrorDevicePort); + } +} + +api::FadeState getFadeState(const fade::FadeStateType& xsdFadeState) { + // Return default value if missing + if (!xsdFadeState.hasValue()) { + return api::FadeState::FADE_STATE_ENABLED_DEFAULT; + } + // For legacy files, "0" and "1 " need to be supported. + switch (xsdFadeState.getValue()) { + case fade::FadeStateEnumType::_0: + // Fallthrough + case fade::FadeStateEnumType::FADE_STATE_DISABLED: + return api::FadeState::FADE_STATE_DISABLED; + case fade::FadeStateEnumType::_1: + // Fallthrough + case fade::FadeStateEnumType::FADE_STATE_ENABLED_DEFAULT: + // Fallthrough + default: + return api::FadeState::FADE_STATE_ENABLED_DEFAULT; + } +} + +void parseFadeableUsages(const fade::FadeableUsagesType& fadeUsages, + std::vector& usages) { + if (!fadeUsages.hasUsage()) { + return; + } + for (const auto& fadeUsage : fadeUsages.getUsage()) { + AudioUsage audioUsage; + if (!fadeUsage.hasValue() || + !parseAudioAttributeUsageString(fade::toString(fadeUsage.getValue()), audioUsage)) { + continue; + } + usages.push_back(audioUsage); + } +} + +void parseFadeAudioAttribute(const fade::AttributesType& fadeAttributes, + AudioAttributes& attributes) { + if (fadeAttributes.hasUsage()) { + parseAudioAttributeUsageString(fade::toString(fadeAttributes.getUsage()), attributes.usage); + } + if (fadeAttributes.hasContentType()) { + parseContentTypeString(fade::toString(fadeAttributes.getContentType()), + attributes.contentType); + } + if (fadeAttributes.hasTags()) { + attributes.tags.push_back(fadeAttributes.getTags()); + } +} + +bool parseFadeAudioAttribute(const fade::AudioAttributesUsagesType& fadeAttributes, + std::vector& audioAttributes) { + if (fadeAttributes.hasUsage_optional()) { + for (const auto& usage : fadeAttributes.getUsage_optional()) { + AudioAttributes attributes; + if (!usage.hasValue() || !parseAudioAttributeUsageString( + fade::toString(usage.getValue()), attributes.usage)) { + continue; + } + audioAttributes.push_back(attributes); + } + } + if (fadeAttributes.hasAudioAttribute_optional()) { + for (const auto& fadeAttribute : fadeAttributes.getAudioAttribute_optional()) { + AudioAttributes attribute; + parseFadeAudioAttribute(fadeAttribute, attribute); + audioAttributes.push_back(attribute); + } + } + return true; +} + +void parseUnfadeableAudioAttributes(const fade::UnfadeableAudioAttributesType& fadeAttributes, + std::vector& audioAttributes) { + if (!fadeAttributes.hasAudioAttributes()) { + return; + } + parseFadeAudioAttribute(*fadeAttributes.getFirstAudioAttributes(), audioAttributes); +} + +void parseUnfadeableContentType(const fade::UnfadeableContentTypesType& fadeTypes, + std::optional>& contentTypes) { + if (!fadeTypes.hasContentType()) { + return; + } + std::vector contents; + for (const auto& fadeContentType : fadeTypes.getContentType()) { + AudioContentType contentType; + if (!fadeContentType.hasValue() || + !parseContentTypeString(fade::toString(fadeContentType.getValue()), contentType)) { + continue; + } + contents.push_back(contentType); + } + contentTypes = contents; +} + +void parseFadeConfigAudioAttributes(const fade::AudioAttributesUsagesType& fadeAudioAttributesType, + const int64_t fadeDurationMillins, + std::vector& fadeInConfigurations) { + if (fadeAudioAttributesType.hasAudioAttribute_optional()) { + for (const auto& fadeAudioAttribute : + fadeAudioAttributesType.getAudioAttribute_optional()) { + api::FadeConfiguration fadeConfiguration; + AudioAttributes attributes; + parseFadeAudioAttribute(fadeAudioAttribute, attributes); + fadeConfiguration.fadeDurationMillis = fadeDurationMillins; + fadeConfiguration.audioAttributesOrUsage + .set(attributes); + fadeInConfigurations.push_back(fadeConfiguration); + } + } + + if (fadeAudioAttributesType.hasUsage_optional()) { + for (const auto& fadeAudioUsage : fadeAudioAttributesType.getUsage_optional()) { + api::FadeConfiguration fadeConfiguration; + AudioUsage usage; + if (!fadeAudioUsage.hasValue() || + !parseAudioAttributeUsageString(fade::toString(fadeAudioUsage.getValue()), usage)) { + continue; + } + fadeConfiguration.fadeDurationMillis = fadeDurationMillins; + fadeConfiguration.audioAttributesOrUsage + .set(usage); + fadeInConfigurations.push_back(fadeConfiguration); + } + } +} +void parseFadeConfiguration(const fade::FadeConfigurationType& fadeConfigurationType, + std::vector& fadeConfigurations) { + if (!fadeConfigurationType.hasFadeDurationMillis() || + !fadeConfigurationType.hasAudioAttributes() || + fadeConfigurationType.getAudioAttributes().empty()) { + return; + } + + int64_t fadeDurationMillis = 0L; + + if (!ParseInt(fadeConfigurationType.getFadeDurationMillis().c_str(), &fadeDurationMillis, + static_cast(0))) { + return; + } + parseFadeConfigAudioAttributes(*fadeConfigurationType.getFirstAudioAttributes(), + fadeDurationMillis, fadeConfigurations); +} + +void parseFadeInConfigurations(const fade::FadeInConfigurationsType& fadeInConfigurationsType, + std::vector& fadeInConfigurations) { + if (!fadeInConfigurationsType.hasFadeConfiguration()) { + return; + } + for (const auto& fadeConfigurationType : fadeInConfigurationsType.getFadeConfiguration()) { + parseFadeConfiguration(fadeConfigurationType, fadeInConfigurations); + } +} + +void parseFadeOutConfigurations(const fade::FadeOutConfigurationsType& fadeOutConfigurationsType, + std::vector& fadeOutConfigurations) { + if (!fadeOutConfigurationsType.hasFadeConfiguration()) { + return; + } + for (const auto& fadeConfigurationType : fadeOutConfigurationsType.getFadeConfiguration()) { + parseFadeConfiguration(fadeConfigurationType, fadeOutConfigurations); + } +} + +bool parseFadeConfig(const fade::FadeConfigurationConfig& fadeConfig, + api::AudioFadeConfiguration& configuration) { + // Fade configuration must have a name for zone association. Fade state is also needed to + // determine accurate usage. + if (!fadeConfig.hasName()) { + LOG(ERROR) << __func__ << " Fade configuration missing name"; + return false; + } + if (!fadeConfig.hasFadeState()) { + LOG(ERROR) << __func__ << " Fade configuration missing fade state"; + return false; + } + configuration.name = fadeConfig.getName(); + configuration.fadeState = getFadeState(*fadeConfig.getFirstFadeState()); + if (fadeConfig.hasDefaultFadeOutDurationInMillis()) { + ParseInt(fadeConfig.getDefaultFadeOutDurationInMillis().c_str(), + &configuration.fadeOutDurationMs, static_cast(0)); + } + if (fadeConfig.hasDefaultFadeInDurationInMillis()) { + ParseInt(fadeConfig.getDefaultFadeInDurationInMillis().c_str(), + &configuration.fadeInDurationMs, static_cast(0)); + } + if (fadeConfig.hasDefaultFadeInDelayForOffenders()) { + ParseInt(fadeConfig.getDefaultFadeInDelayForOffenders().c_str(), + &configuration.fadeInDelayedForOffendersMs, static_cast(0)); + } + + if (fadeConfig.hasFadeableUsages()) { + parseFadeableUsages(*fadeConfig.getFirstFadeableUsages(), configuration.fadeableUsages); + } + + if (fadeConfig.hasUnfadeableContentTypes()) { + parseUnfadeableContentType(*fadeConfig.getFirstUnfadeableContentTypes(), + configuration.unfadeableContentTypes); + } + + if (fadeConfig.hasUnfadeableAudioAttributes()) { + parseUnfadeableAudioAttributes(*fadeConfig.getFirstUnfadeableAudioAttributes(), + configuration.unfadableAudioAttributes); + } + if (fadeConfig.hasFadeInConfigurations()) { + parseFadeInConfigurations(*fadeConfig.getFirstFadeInConfigurations(), + configuration.fadeInConfigurations); + } + if (fadeConfig.hasFadeOutConfigurations()) { + parseFadeOutConfigurations(*fadeConfig.getFirstFadeOutConfigurations(), + configuration.fadeOutConfigurations); + } + + return true; +} + +void parseFadeConfigs(const std::vector& fadeConfigTypes, + std::vector& fadeConfigs) { + for (const auto& fadeConfig : fadeConfigTypes) { + api::AudioFadeConfiguration configuration; + if (!parseFadeConfig(fadeConfig, configuration)) { + continue; + } + fadeConfigs.push_back(configuration); + } +} + +void parseFadeConfigs(const fade::FadeConfigurationConfigs& fadeConfigsType, + std::vector& fadeConfigs) { + if (!fadeConfigsType.hasConfig()) { + LOG(ERROR) << __func__ << " Fade config file does not contains any fade configs"; + return; + } + parseFadeConfigs(fadeConfigsType.getConfig(), fadeConfigs); +} +} // namespace + +void CarAudioConfigurationXmlConverter::init() { + if (!isReadableConfigurationFile(mAudioConfigFile)) { + mParseErrors = "Configuration file " + mAudioConfigFile + " is not readable"; + initNonDynamicRouting(); + return; + } + + // Supports loading legacy fade configurations from a different file + if (isReadableConfigurationFile(mFadeConfigFile)) { + initFadeConfigurations(); + } + + const auto& configOptional = xsd::read(mAudioConfigFile.c_str()); + + if (!configOptional.has_value()) { + mParseErrors = + "Configuration file " + mAudioConfigFile + " , does not have any configurations"; + initNonDynamicRouting(); + return; + } + + const auto& configurations = configOptional.value(); + initAudioDeviceConfiguration(configurations); + initCarAudioConfigurations(configurations); +} + +void CarAudioConfigurationXmlConverter::initFadeConfigurations() { + const auto& fadeConfigOptional = fade::read(mFadeConfigFile.c_str()); + if (!fadeConfigOptional.has_value() || !fadeConfigOptional.value().hasConfigs()) { + LOG(ERROR) << __func__ << " Fade config file " << mFadeConfigFile.c_str() + << " does not contains fade configuration"; + return; + } + + const auto& fadeConfigs = fadeConfigOptional.value().getConfigs(); + + if (fadeConfigs.empty()) { + LOG(ERROR) << __func__ << " Fade config file " << mFadeConfigFile.c_str() + << " does not contains fade configs"; + } + std::vector fadeConfigurations; + parseFadeConfigs(fadeConfigs.front(), fadeConfigurations); + for (const auto& fadeConfiguration : fadeConfigurations) { + mFadeConfigurations.emplace(fadeConfiguration.name, fadeConfiguration); + } +} + +void CarAudioConfigurationXmlConverter::initNonDynamicRouting() { + mAudioDeviceConfiguration.routingConfig = + api::RoutingDeviceConfiguration::DEFAULT_AUDIO_ROUTING; +} + +void CarAudioConfigurationXmlConverter::initAudioDeviceConfiguration( + const xsd::CarAudioConfigurationType& carAudioConfigurationType) { + parseAudioDeviceConfigurations(carAudioConfigurationType); +} + +void CarAudioConfigurationXmlConverter::parseAudioDeviceConfigurations( + const xsd::CarAudioConfigurationType& carAudioConfigurationType) { + if (!carAudioConfigurationType.hasDeviceConfigurations()) { + return; + } + + mAudioDeviceConfiguration.routingConfig = + api::RoutingDeviceConfiguration::DYNAMIC_AUDIO_ROUTING; + + const auto deviceConfigs = carAudioConfigurationType.getFirstDeviceConfigurations(); + if (!deviceConfigs->hasDeviceConfiguration()) { + return; + } + + std::vector<::android::hardware::automotive::audiocontrol::DeviceConfigurationType> configs = + deviceConfigs->getDeviceConfiguration(); + const auto& parsers = getConfigsParsers(); + for (const auto& deviceConfig : configs) { + if (!deviceConfig.hasName() || !deviceConfig.hasValue()) { + continue; + } + const auto& parser = parsers.find(deviceConfig.getName()); + if (parser == parsers.end()) { + continue; + } + const auto& method = parser->second; + method(deviceConfig.getValue(), mAudioDeviceConfiguration); + } +} + +void CarAudioConfigurationXmlConverter::initCarAudioConfigurations( + const automotive::audiocontrol::CarAudioConfigurationType& carAudioConfigurationType) { + if (!carAudioConfigurationType.hasZones()) { + mParseErrors = "Audio zones not found in file " + mAudioConfigFile; + initNonDynamicRouting(); + return; + } + + api::AudioZoneContext context; + if (!carAudioConfigurationType.hasOemContexts() || + !parseAudioContexts(carAudioConfigurationType.getFirstOemContexts(), context)) { + context = getDefaultCarAudioContext(); + } + + ActivationMap activations; + if (carAudioConfigurationType.hasActivationVolumeConfigs()) { + parseVolumeGroupActivations(carAudioConfigurationType.getFirstActivationVolumeConfigs(), + activations); + } + + if (carAudioConfigurationType.hasMirroringDevices()) { + parseOutputMirroringDevices(carAudioConfigurationType.getFirstMirroringDevices(), + mOutputMirroringDevices); + } + + const auto audioZones = carAudioConfigurationType.getFirstZones(); + + std::string message = + parseAudioZones(audioZones, context, activations, mFadeConfigurations, mAudioZones); + + // Assign dynamic configuration if not assigned + if (!mAudioZones.empty() && mAudioDeviceConfiguration.routingConfig == + api::RoutingDeviceConfiguration::DEFAULT_AUDIO_ROUTING) { + mAudioDeviceConfiguration.routingConfig = + api::RoutingDeviceConfiguration::DYNAMIC_AUDIO_ROUTING; + } + + if (message.empty()) { + return; + } + mParseErrors = + "Error parsing audio zone(s) in file " + mAudioConfigFile + ", message: " + message; + LOG(ERROR) << __func__ << " Error parsing zones: " << message; + initNonDynamicRouting(); +} + +api::AudioDeviceConfiguration CarAudioConfigurationXmlConverter::getAudioDeviceConfiguration() + const { + return mAudioDeviceConfiguration; +} + +std::vector CarAudioConfigurationXmlConverter::getAudioZones() const { + return mAudioZones; +} + +std::vector<::aidl::android::media::audio::common::AudioPort> +CarAudioConfigurationXmlConverter::getOutputMirroringDevices() const { + return mOutputMirroringDevices; +} + +} // namespace internal +} // namespace audiocontrol +} // namespace hardware +} // namespace android \ No newline at end of file diff --git a/automotive/audiocontrol/aidl/default/converter/test/Android.bp b/automotive/audiocontrol/aidl/default/converter/test/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..70d4a20456c60ef99b11e98ab653dce2d569b660 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/test/Android.bp @@ -0,0 +1,63 @@ +// 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. + +package { + default_team: "trendy_team_aaos_framework", + default_applicable_licenses: ["Android-Apache-2.0"], +} + +filegroup { + name: "simple_car_audio_configuration_xml", + srcs: [ + "simple_car_audio_configuration.xml", + "simple_car_audio_configuration_with_device_type.xml", + "multi_zone_car_audio_configuration.xml", + "car_audio_configuration_without_configuration.xml", + "car_audio_configuration_with_default_context.xml", + "car_audio_configuration_with_missing_zones.xml", + "car_audio_configuration_without_audio_zone.xml", + "car_audio_fade_configuration.xml", + ], +} + +cc_test { + name: "AudioControlConverterUnitTest", + vendor: true, + require_root: true, + srcs: ["*.cpp"], + stl: "libc++_static", + static_libs: [ + "libbase", + "android.hardware.audiocontrol.internal", + "libgtest", + "libgmock", + "libutils", + "libaudio_aidl_conversion_common_ndk", + ], + shared_libs: ["liblog"], + defaults: [ + "latest_android_hardware_audio_common_ndk_static", + "car.audio.configuration.xsd.default", + "car.fade.configuration.xsd.default", + "latest_android_hardware_automotive_audiocontrol_ndk_static", + "latest_android_media_audio_common_types_ndk_static", + ], + data: [ + ":simple_car_audio_configuration_xml", + ], + test_suites: ["device-tests"], + exclude_shared_libs: [ + "android.hardware.automotive.audiocontrol-V5-ndk", + ], +} diff --git a/automotive/audiocontrol/aidl/default/converter/test/AudioControlConverterUnitTest.cpp b/automotive/audiocontrol/aidl/default/converter/test/AudioControlConverterUnitTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d11a59a6ca00f6a1c7d20ee98c817d0f7101fe68 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/test/AudioControlConverterUnitTest.cpp @@ -0,0 +1,835 @@ +/* + * 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 +#include +#include +#include + +#include +#include + +namespace converter = ::android::hardware::audiocontrol::internal; +namespace api = ::aidl::android::hardware::automotive::audiocontrol; + +using ::testing::ContainsRegex; +using ::testing::UnorderedElementsAreArray; + +namespace { + +using ::aidl::android::media::audio::common::AudioAttributes; +using ::aidl::android::media::audio::common::AudioContentType; +using ::aidl::android::media::audio::common::AudioDevice; +using ::aidl::android::media::audio::common::AudioDeviceAddress; +using ::aidl::android::media::audio::common::AudioDeviceDescription; +using ::aidl::android::media::audio::common::AudioDeviceType; +using ::aidl::android::media::audio::common::AudioHalProductStrategy; +using ::aidl::android::media::audio::common::AudioPort; +using ::aidl::android::media::audio::common::AudioPortDeviceExt; +using ::aidl::android::media::audio::common::AudioPortExt; +using ::aidl::android::media::audio::common::AudioUsage; + +std::string getTestFilePath(const std::string& filename) { + static std::string baseDir = android::base::GetExecutableDirectory(); + return baseDir + "/" + filename; +} + +AudioAttributes createAudioAttributes(const AudioUsage& usage, + const AudioContentType& type = AudioContentType::UNKNOWN, + const std::string tags = "") { + AudioAttributes attributes; + attributes.usage = usage; + attributes.contentType = type; + if (!tags.empty()) { + attributes.tags.push_back(tags); + } + return attributes; +} + +api::AudioZoneContextInfo createContextInfo(const std::string& name, + const std::vector& attributes, + const int id = -1) { + api::AudioZoneContextInfo info; + info.name = name; + if (id != -1) { + info.id = id; + } + for (const auto& attribute : attributes) { + info.audioAttributes.push_back(attribute); + } + return info; +} + +api::AudioZoneContextInfo createContextInfo(const std::string& name, + const std::vector& usages, + const int id = -1) { + std::vector attributes; + attributes.reserve(usages.size()); + for (const auto& usage : usages) { + attributes.push_back(createAudioAttributes(usage)); + } + return createContextInfo(name, attributes, id); +} + +AudioPort createAudioPort(const std::string& address, const AudioDeviceType& type, + const std::string& connection = "") { + AudioPort port; + AudioDevice device; + device.address = AudioDeviceAddress::make(address); + + AudioDeviceDescription description; + description.type = type; + description.connection = connection; + device.type = description; + + port.ext = AudioPortExt::make(device); + + return port; +} + +api::DeviceToContextEntry createRoutes(const AudioPort& port, + const std::vector& contexts) { + api::DeviceToContextEntry entry; + entry.device = port; + entry.contextNames = contexts; + return entry; +} + +api::VolumeGroupConfig createVolumeGroup(const std::string& name, + const api::VolumeActivationConfiguration& activation, + const std::vector& routes) { + api::VolumeGroupConfig config; + config.name = name; + config.activationConfiguration = activation; + config.carAudioRoutes = routes; + return config; +} + +api::AudioZoneConfig createAudioZoneConfig(const std::string& name, + const api::AudioZoneFadeConfiguration& fadeConfiguration, + const std::vector& groups, + bool isDefault = false) { + api::AudioZoneConfig config; + config.name = name; + config.isDefault = isDefault; + config.volumeGroups = groups; + config.fadeConfiguration = fadeConfiguration; + return config; +} + +api::VolumeActivationConfiguration createVolumeActivation(const std::string& name, + const api::VolumeInvocationType& type, + int minVolume, int maxVolume) { + api::VolumeActivationConfiguration activation; + activation.name = name; + api::VolumeActivationConfigurationEntry entry; + entry.maxActivationVolumePercentage = maxVolume; + entry.minActivationVolumePercentage = minVolume; + entry.type = type; + activation.volumeActivationEntries.push_back(entry); + + return activation; +} + +api::FadeConfiguration createFadeConfiguration(const long& fadeDurationsMillis, + const AudioAttributes& audioAttributes) { + api::FadeConfiguration configuration; + configuration.fadeDurationMillis = fadeDurationsMillis; + configuration.audioAttributesOrUsage + .set( + audioAttributes); + return configuration; +} + +api::FadeConfiguration createFadeConfiguration(const long& fadeDurationsMillis, + const AudioUsage& audioUsage) { + api::FadeConfiguration configuration; + configuration.fadeDurationMillis = fadeDurationsMillis; + configuration.audioAttributesOrUsage + .set(audioUsage); + return configuration; +} + +api::AudioFadeConfiguration createAudioFadeConfiguration( + const std::string& name, const api::FadeState& state, + const std::vector& fadeableUsages = std::vector(), + const std::optional>& unfadeableContentTypes = std::nullopt, + const std::vector unfadeableAudioAttributes = + std::vector(), + const std::vector fadeOutConfigurations = + std::vector(), + const std::vector fadeInConfigurations = + std::vector(), + const long& fadeOutDurationMs = api::AudioFadeConfiguration::DEFAULT_FADE_OUT_DURATION_MS, + const long& fadeInDurationMs = api::AudioFadeConfiguration::DEFAULT_FADE_IN_DURATION_MS, + const long& fadeInDelayedForOffendersMs = + api::AudioFadeConfiguration::DEFAULT_DELAY_FADE_IN_OFFENDERS_MS) { + api::AudioFadeConfiguration audioZoneFadeConfiguration; + audioZoneFadeConfiguration.name = name; + audioZoneFadeConfiguration.fadeInDurationMs = fadeInDurationMs; + audioZoneFadeConfiguration.fadeOutDurationMs = fadeOutDurationMs; + audioZoneFadeConfiguration.fadeInDelayedForOffendersMs = fadeInDelayedForOffendersMs; + audioZoneFadeConfiguration.fadeState = state; + audioZoneFadeConfiguration.fadeableUsages = fadeableUsages; + audioZoneFadeConfiguration.unfadeableContentTypes = unfadeableContentTypes; + audioZoneFadeConfiguration.unfadableAudioAttributes = unfadeableAudioAttributes; + audioZoneFadeConfiguration.fadeOutConfigurations = fadeOutConfigurations; + audioZoneFadeConfiguration.fadeInConfigurations = fadeInConfigurations; + + return audioZoneFadeConfiguration; +} + +api::TransientFadeConfigurationEntry createTransientFadeConfiguration( + const api::AudioFadeConfiguration& fadeConfig, const std::vector& usages) { + api::TransientFadeConfigurationEntry entry; + entry.transientFadeConfiguration = fadeConfig; + entry.transientUsages = usages; + return entry; +} + +api::AudioZoneFadeConfiguration createAudioZoneFadeConfiguration( + const api::AudioFadeConfiguration& defaultConfig, + const std::vector& transientConfigs) { + api::AudioZoneFadeConfiguration zoneFadeConfiguration; + zoneFadeConfiguration.defaultConfiguration = defaultConfig; + zoneFadeConfiguration.transientConfiguration = transientConfigs; + return zoneFadeConfiguration; +} + +api::AudioZone createAudioZone(const std::string& name, const int zoneId, + const std::vector& contexts, + const std::vector& configs) { + api::AudioZone zone; + zone.name = name; + zone.id = zoneId; + zone.occupantZoneId = zoneId; + zone.audioZoneContext.audioContextInfos = contexts; + zone.audioZoneConfigs = configs; + return zone; +} + +const std::vector kFadeableUsages = {AudioUsage::MEDIA, + AudioUsage::GAME, + AudioUsage::ASSISTANCE_SONIFICATION, + AudioUsage::ASSISTANCE_ACCESSIBILITY, + AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE, + AudioUsage::ASSISTANT, + AudioUsage::NOTIFICATION, + AudioUsage::ANNOUNCEMENT}; + +const std::vector kUnfadeableAudioAttributes = { + createAudioAttributes(AudioUsage::MEDIA, AudioContentType::UNKNOWN, "oem_specific_tag1")}; + +const std::vector kFadeOutConfigurations = { + createFadeConfiguration( + 500, createAudioAttributes(AudioUsage::ASSISTANT, AudioContentType::UNKNOWN, + "oem_specific_tag2")), + createFadeConfiguration(500, AudioUsage::MEDIA), + createFadeConfiguration(500, AudioUsage::GAME), + createFadeConfiguration(800, AudioUsage::ASSISTANCE_SONIFICATION), + createFadeConfiguration(800, AudioUsage::ASSISTANCE_ACCESSIBILITY), + createFadeConfiguration(800, AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE), + createFadeConfiguration(800, AudioUsage::ASSISTANT), + createFadeConfiguration(800, AudioUsage::ANNOUNCEMENT), +}; + +const std::vector kFadeInConfigurations = { + createFadeConfiguration( + 1000, createAudioAttributes(AudioUsage::ASSISTANT, AudioContentType::UNKNOWN, + "oem_specific_tag2")), + createFadeConfiguration(1000, AudioUsage::MEDIA), + createFadeConfiguration(1000, AudioUsage::GAME), + createFadeConfiguration(800, AudioUsage::ASSISTANCE_SONIFICATION), + createFadeConfiguration(800, AudioUsage::ASSISTANCE_ACCESSIBILITY), + createFadeConfiguration(800, AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE), + createFadeConfiguration(800, AudioUsage::ASSISTANT), + createFadeConfiguration(800, AudioUsage::ANNOUNCEMENT), +}; + +const api::AudioFadeConfiguration kRelaxedFading = createAudioFadeConfiguration( + "relaxed fading", api::FadeState::FADE_STATE_ENABLED_DEFAULT, kFadeableUsages, + std::optional>( + {AudioContentType::SPEECH, AudioContentType::SONIFICATION}), + kUnfadeableAudioAttributes, kFadeOutConfigurations, kFadeInConfigurations, 800, 500, 10000); + +const std::vector kAggressiveUnfadeableAudioAttributes = { + createAudioAttributes(AudioUsage::MEDIA, AudioContentType::UNKNOWN, "oem_specific_tag1"), + createAudioAttributes(AudioUsage::ASSISTANT, AudioContentType::UNKNOWN, + "oem_projection_service"), +}; + +const std::vector kAggressiveFadeOutConfigurations = { + createFadeConfiguration(150, AudioUsage::MEDIA), + createFadeConfiguration(150, AudioUsage::GAME), + createFadeConfiguration(400, AudioUsage::ASSISTANCE_SONIFICATION), + createFadeConfiguration(400, AudioUsage::ASSISTANCE_ACCESSIBILITY), + createFadeConfiguration(400, AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE), + createFadeConfiguration(400, AudioUsage::ASSISTANT), + createFadeConfiguration(400, AudioUsage::ANNOUNCEMENT), +}; + +const std::vector kAggressiveFadeInConfigurations = { + createFadeConfiguration(300, AudioUsage::MEDIA), + createFadeConfiguration(300, AudioUsage::GAME), + createFadeConfiguration(550, AudioUsage::ASSISTANCE_SONIFICATION), + createFadeConfiguration(550, AudioUsage::ASSISTANCE_ACCESSIBILITY), + createFadeConfiguration(550, AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE), + createFadeConfiguration(550, AudioUsage::ASSISTANT), + createFadeConfiguration(550, AudioUsage::ANNOUNCEMENT), +}; + +const api::AudioFadeConfiguration kAggressiveFading = createAudioFadeConfiguration( + "aggressive fading", api::FadeState::FADE_STATE_ENABLED_DEFAULT, kFadeableUsages, + std::optional>( + {AudioContentType::SPEECH, AudioContentType::MUSIC}), + kAggressiveUnfadeableAudioAttributes, kAggressiveFadeOutConfigurations, + kAggressiveFadeInConfigurations); + +const api::AudioFadeConfiguration kDisabledFading = + createAudioFadeConfiguration("disabled fading", api::FadeState::FADE_STATE_DISABLED); + +const std::vector kDynamicFadeOutConfigurations = { + createFadeConfiguration( + 500, createAudioAttributes(AudioUsage::ASSISTANT, AudioContentType::UNKNOWN, + "oem_specific_tag2")), + createFadeConfiguration(800, AudioUsage::ASSISTANCE_SONIFICATION), + createFadeConfiguration(800, AudioUsage::ASSISTANCE_ACCESSIBILITY), + createFadeConfiguration(800, AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE), + createFadeConfiguration(800, AudioUsage::ASSISTANT), + createFadeConfiguration(800, AudioUsage::ANNOUNCEMENT), +}; + +const std::vector kDynamicFadeInConfigurations = { + createFadeConfiguration( + 1000, createAudioAttributes(AudioUsage::ASSISTANT, AudioContentType::UNKNOWN, + "oem_specific_tag2")), + createFadeConfiguration(800, AudioUsage::ASSISTANCE_SONIFICATION), + createFadeConfiguration(800, AudioUsage::ASSISTANCE_ACCESSIBILITY), + createFadeConfiguration(800, AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE), + createFadeConfiguration(800, AudioUsage::ASSISTANT), + createFadeConfiguration(800, AudioUsage::ANNOUNCEMENT), +}; + +const api::AudioFadeConfiguration kDynamicFading = createAudioFadeConfiguration( + "dynamic fading", api::FadeState::FADE_STATE_ENABLED_DEFAULT, kFadeableUsages, + std::optional>( + {AudioContentType::SPEECH, AudioContentType::MOVIE}), + kUnfadeableAudioAttributes, kDynamicFadeOutConfigurations, kDynamicFadeInConfigurations, + 800, 500); + +const api::AudioZoneFadeConfiguration kDefaultAudioConfigFading = createAudioZoneFadeConfiguration( + kRelaxedFading, + {createTransientFadeConfiguration( + kAggressiveFading, {AudioUsage::VOICE_COMMUNICATION, AudioUsage::ANNOUNCEMENT, + AudioUsage::VEHICLE_STATUS, AudioUsage::SAFETY}), + createTransientFadeConfiguration(kDisabledFading, {AudioUsage::EMERGENCY})}); + +const api::AudioZoneFadeConfiguration kDynamicDeviceAudioConfigFading = + createAudioZoneFadeConfiguration( + kDynamicFading, + {createTransientFadeConfiguration( + kAggressiveFading, + {AudioUsage::VOICE_COMMUNICATION, AudioUsage::ANNOUNCEMENT, + AudioUsage::VEHICLE_STATUS, AudioUsage::SAFETY}), + createTransientFadeConfiguration(kDisabledFading, {AudioUsage::EMERGENCY})}); + +const api::AudioZoneContextInfo kMusicContextInfo = + createContextInfo("oem_music", {AudioUsage::MEDIA, AudioUsage::GAME, AudioUsage::UNKNOWN}); +const api::AudioZoneContextInfo kNotificationContextInfo = createContextInfo( + "oem_notification", {AudioUsage::NOTIFICATION, AudioUsage::NOTIFICATION_EVENT}); +const api::AudioZoneContextInfo kVoiceContextInfo = createContextInfo( + "oem_voice_command", {AudioUsage::ASSISTANT, AudioUsage::ASSISTANCE_ACCESSIBILITY, + AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE}); +const api::AudioZoneContextInfo kCallContextInfo = + createContextInfo("oem_call", {AudioUsage::VOICE_COMMUNICATION, AudioUsage::CALL_ASSISTANT, + AudioUsage::VOICE_COMMUNICATION_SIGNALLING}); +const api::AudioZoneContextInfo kRingContextInfo = + createContextInfo("oem_call_ring", {AudioUsage::NOTIFICATION_TELEPHONY_RINGTONE}); +const api::AudioZoneContextInfo kAlarmContextInfo = + createContextInfo("oem_alarm", {AudioUsage::ALARM}); +const api::AudioZoneContextInfo kSystemContextInfo = createContextInfo( + "oem_system_sound", + {AudioUsage::ASSISTANCE_SONIFICATION, AudioUsage::EMERGENCY, AudioUsage::SAFETY, + AudioUsage::VEHICLE_STATUS, AudioUsage::ANNOUNCEMENT}); +const api::AudioZoneContextInfo kOemContextInfo = createContextInfo( + "oem_context", {createAudioAttributes(AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE, + AudioContentType::SPEECH, "oem=extension_8675309")}); + +const std::vector kSimpleCarAudioConfigurationContext = { + kOemContextInfo, kMusicContextInfo, kNotificationContextInfo, kVoiceContextInfo, + kCallContextInfo, kRingContextInfo, kAlarmContextInfo, kSystemContextInfo}; + +const api::AudioZoneContextInfo kDefaultMusicContextInfo = + createContextInfo("music", {AudioUsage::UNKNOWN, AudioUsage::MEDIA, AudioUsage::GAME}, 1); +const api::AudioZoneContextInfo kDefaultNavContextInfo = + createContextInfo("navigation", {AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE}, 2); +const api::AudioZoneContextInfo kDefaultVoiceContextInfo = createContextInfo( + "voice_command", {AudioUsage::ASSISTANCE_ACCESSIBILITY, AudioUsage::ASSISTANT}, 3); +const api::AudioZoneContextInfo kDefaultRingContextInfo = + createContextInfo("call_ring", {AudioUsage::NOTIFICATION_TELEPHONY_RINGTONE}, 4); +const api::AudioZoneContextInfo kDefaultCallContextInfo = + createContextInfo("call", + {AudioUsage::VOICE_COMMUNICATION, AudioUsage::CALL_ASSISTANT, + AudioUsage::VOICE_COMMUNICATION_SIGNALLING}, + 5); +const api::AudioZoneContextInfo kDefaultAlarmContextInfo = + createContextInfo("alarm", {AudioUsage::ALARM}, 6); +const api::AudioZoneContextInfo kDefaultNotificationContextInfo = createContextInfo( + "notification", {AudioUsage::NOTIFICATION, AudioUsage::NOTIFICATION_EVENT}, 7); +const api::AudioZoneContextInfo kDefaultSystemContextInfo = + createContextInfo("system_sound", {AudioUsage::ASSISTANCE_SONIFICATION}, 8); +const api::AudioZoneContextInfo kDefaultEmergencyContextInfo = + createContextInfo("emergency", {AudioUsage::EMERGENCY}, 9); +const api::AudioZoneContextInfo kDefaultSafetyContextInfo = + createContextInfo("safety", {AudioUsage::SAFETY}, 10); +const api::AudioZoneContextInfo kDefaultVehicleStatusContextInfo = + createContextInfo("vehicle_status", {AudioUsage::VEHICLE_STATUS}, 11); +const api::AudioZoneContextInfo kDefaultAnnouncementContextInfo = + createContextInfo("announcement", {AudioUsage::ANNOUNCEMENT}, 12); + +const std::vector kDefaultCarAudioConfigurationContext = { + kDefaultMusicContextInfo, kDefaultNavContextInfo, + kDefaultVoiceContextInfo, kDefaultRingContextInfo, + kDefaultCallContextInfo, kDefaultAlarmContextInfo, + kDefaultNotificationContextInfo, kDefaultSystemContextInfo, + kDefaultEmergencyContextInfo, kDefaultSafetyContextInfo, + kDefaultVehicleStatusContextInfo, kDefaultAnnouncementContextInfo}; + +const api::VolumeActivationConfiguration kOnBootVolumeActivation = + createVolumeActivation("on_boot_config", api::VolumeInvocationType::ON_BOOT, 0, 80); +const api::VolumeActivationConfiguration kOnSourceVolumeActivation = createVolumeActivation( + "on_source_changed_config", api::VolumeInvocationType::ON_SOURCE_CHANGED, 20, 80); +const api::VolumeActivationConfiguration kOnPlayVolumeActivation = createVolumeActivation( + "on_playback_changed_config", api::VolumeInvocationType::ON_PLAYBACK_CHANGED, 10, 90); + +const AudioPort kBusMediaDevice = createAudioPort("BUS00_MEDIA", AudioDeviceType::OUT_BUS); +const AudioPort kBTMediaDevice = createAudioPort("temp", AudioDeviceType::OUT_DEVICE, "bt-a2dp"); +const AudioPort kUSBMediaDevice = createAudioPort("", AudioDeviceType::OUT_HEADSET, "usb"); + +const AudioPort kBusNavDevice = createAudioPort("BUS02_NAV_GUIDANCE", AudioDeviceType::OUT_BUS); +const AudioPort kBusPhoneDevice = createAudioPort("BUS03_PHONE", AudioDeviceType::OUT_BUS); +const AudioPort kBusSysDevice = createAudioPort("BUS01_SYS_NOTIFICATION", AudioDeviceType::OUT_BUS); + +const AudioPort kMirrorDevice1 = createAudioPort("mirror_bus_device_1", AudioDeviceType::OUT_BUS); +const AudioPort kMirrorDevice2 = createAudioPort("mirror_bus_device_2", AudioDeviceType::OUT_BUS); +const std::vector kMirroringDevices = {kMirrorDevice1, kMirrorDevice2}; + +const AudioPort kMirrorDeviceThree = + createAudioPort("mirror_bus_device_three", AudioDeviceType::OUT_BUS); +const AudioPort kMirrorDeviceFour = + createAudioPort("mirror_bus_device_four", AudioDeviceType::OUT_BUS); +const std::vector kMultiZoneMirroringDevices = {kMirrorDeviceThree, kMirrorDeviceFour}; + +const AudioPort kInFMTunerDevice = createAudioPort("fm_tuner", AudioDeviceType::IN_FM_TUNER); +const AudioPort kInMicDevice = createAudioPort("built_in_mic", AudioDeviceType::IN_MICROPHONE); +const AudioPort kInBusDevice = createAudioPort("in_bus_device", AudioDeviceType::IN_BUS); +const std::vector kInputDevices{kInFMTunerDevice, kInMicDevice, kInBusDevice}; + +const api::VolumeGroupConfig kBusMediaVolumeGroup = createVolumeGroup( + "entertainment", kOnBootVolumeActivation, {createRoutes(kBusMediaDevice, {"oem_music"})}); +const api::VolumeGroupConfig kUSBMediaVolumeGroup = createVolumeGroup( + "entertainment", kOnBootVolumeActivation, {createRoutes(kUSBMediaDevice, {"oem_music"})}); +const api::VolumeGroupConfig kBTMediaVolumeGroup = createVolumeGroup( + "entertainment", kOnBootVolumeActivation, {createRoutes(kBTMediaDevice, {"oem_music"})}); +const api::VolumeGroupConfig kBusNavVolumeGroup = + createVolumeGroup("navvoicecommand", kOnSourceVolumeActivation, + {createRoutes(kBusNavDevice, {"oem_voice_command"})}); +const api::VolumeGroupConfig kBusCallVolumeGroup = + createVolumeGroup("telringvol", kOnPlayVolumeActivation, + {createRoutes(kBusPhoneDevice, {"oem_call", "oem_call_ring"})}); +const api::VolumeGroupConfig kBusSysVolumeGroup = createVolumeGroup( + "systemalarm", kOnSourceVolumeActivation, + {createRoutes(kBusSysDevice, {"oem_alarm", "oem_system_sound", "oem_notification"})}); + +const api::AudioZoneConfig kAllBusZoneConfig = createAudioZoneConfig( + "primary zone config 0", kDefaultAudioConfigFading, + {kBusMediaVolumeGroup, kBusNavVolumeGroup, kBusCallVolumeGroup, kBusSysVolumeGroup}, true); +const api::AudioZoneConfig kBTMediaZoneConfig = createAudioZoneConfig( + "primary zone BT media", kDynamicDeviceAudioConfigFading, + {kBTMediaVolumeGroup, kBusNavVolumeGroup, kBusCallVolumeGroup, kBusSysVolumeGroup}); +const api::AudioZoneConfig kUsBMediaZoneConfig = createAudioZoneConfig( + "primary zone USB media", kDynamicDeviceAudioConfigFading, + {kUSBMediaVolumeGroup, kBusNavVolumeGroup, kBusCallVolumeGroup, kBusSysVolumeGroup}); + +const std::unordered_map kConfigNameToZoneConfig = { + {kAllBusZoneConfig.name, kAllBusZoneConfig}, + {kBTMediaZoneConfig.name, kBTMediaZoneConfig}, + {kUsBMediaZoneConfig.name, kUsBMediaZoneConfig}, +}; + +const api::AudioZoneConfig kDriverZoneConfig = createAudioZoneConfig( + "driver zone config 0", kDefaultAudioConfigFading, + {kBusMediaVolumeGroup, kBusNavVolumeGroup, kBusCallVolumeGroup, kBusSysVolumeGroup}, true); + +const api::AudioZone kDriverZone = + createAudioZone("driver zone", static_cast(AudioHalProductStrategy::ZoneId::DEFAULT), + kSimpleCarAudioConfigurationContext, {kDriverZoneConfig}); + +const api::AudioZoneFadeConfiguration kZoneAudioConfigFading = createAudioZoneFadeConfiguration( + kRelaxedFading, + {createTransientFadeConfiguration(kDisabledFading, {AudioUsage::EMERGENCY})}); + +const AudioPort kBusFrontDevice = createAudioPort("BUS_FRONT", AudioDeviceType::OUT_BUS); +const api::VolumeGroupConfig kFrontVolumeGroup = createVolumeGroup( + "entertainment", kOnBootVolumeActivation, + {createRoutes(kBusFrontDevice, + {"oem_music", "oem_voice_command", "oem_call", "oem_call_ring", "oem_alarm", + "oem_system_sound", "oem_notification"})}); +const api::AudioZoneConfig kFrontZoneConfig = createAudioZoneConfig( + "front passenger config 0", kZoneAudioConfigFading, {kFrontVolumeGroup}, true); +const api::AudioZone kFrontZone = createAudioZone( + "front passenger zone", static_cast(AudioHalProductStrategy::ZoneId::DEFAULT) + 1, + kSimpleCarAudioConfigurationContext, {kFrontZoneConfig}); + +const AudioPort kBusRearDevice = createAudioPort("BUS_REAR", AudioDeviceType::OUT_BUS); +const api::VolumeGroupConfig kRearVolumeGroup = + createVolumeGroup("entertainment", kOnBootVolumeActivation, + {createRoutes(kBusRearDevice, {"oem_music", "oem_voice_command", + "oem_call", "oem_call_ring", "oem_alarm", + "oem_system_sound", "oem_notification"})}); +const api::AudioZoneConfig kRearZoneConfig = createAudioZoneConfig( + "rear seat config 0", kZoneAudioConfigFading, {kRearVolumeGroup}, true); +const api::AudioZone kRearZone = createAudioZone( + "rear seat zone", static_cast(AudioHalProductStrategy::ZoneId::DEFAULT) + 2, + kSimpleCarAudioConfigurationContext, {kRearZoneConfig}); + +std::vector kMultiZones = {kDriverZone, kFrontZone, kRearZone}; + +void expectSameFadeConfiguration(const api::AudioFadeConfiguration& actual, + const api::AudioFadeConfiguration& expected, + const std::string& configName) { + EXPECT_EQ(actual.name, expected.name) << "Audio fade configuration for config " << configName; + const std::string fadeConfigInfo = + "fade config " + actual.name + " in config name " + configName; + EXPECT_EQ(actual.fadeState, expected.fadeState) + << "Audio fade config state for " << fadeConfigInfo; + EXPECT_EQ(actual.fadeInDurationMs, expected.fadeInDurationMs) + << "Audio fade in duration for " << fadeConfigInfo; + EXPECT_EQ(actual.fadeOutDurationMs, expected.fadeOutDurationMs) + << "Audio fade out duration for " << fadeConfigInfo; + EXPECT_EQ(actual.fadeInDelayedForOffendersMs, expected.fadeInDelayedForOffendersMs) + << "Audio fade in delayed for offenders duration for " << fadeConfigInfo; + EXPECT_THAT(actual.fadeableUsages, UnorderedElementsAreArray(expected.fadeableUsages)) + << "Fadeable usages for " << fadeConfigInfo; + EXPECT_TRUE(actual.unfadeableContentTypes.has_value() == + expected.unfadeableContentTypes.has_value()) + << "Optional unfadeable for " << fadeConfigInfo; + if (actual.unfadeableContentTypes.has_value() && expected.unfadeableContentTypes.has_value()) { + EXPECT_THAT(actual.unfadeableContentTypes.value(), + UnorderedElementsAreArray(expected.unfadeableContentTypes.value())) + << "Unfadeable content type for " << fadeConfigInfo; + } + EXPECT_THAT(actual.unfadableAudioAttributes, + UnorderedElementsAreArray(expected.unfadableAudioAttributes)) + << "Unfadeable audio attributes type for " << fadeConfigInfo; + EXPECT_THAT(actual.fadeOutConfigurations, + UnorderedElementsAreArray(expected.fadeOutConfigurations)) + << "Fade-out configurations for " << fadeConfigInfo; + EXPECT_THAT(actual.fadeInConfigurations, + UnorderedElementsAreArray(expected.fadeInConfigurations)) + << "Fade-in configurations for " << fadeConfigInfo; +} + +void expectSameAudioZoneFadeConfiguration( + const std::optional& actual, + const std::optional& expected, + const std::string& configName) { + if (!actual.has_value() || !expected.has_value()) { + EXPECT_EQ(actual.has_value(), expected.has_value()) + << "Audio zone config " << configName << " fade configuration missing"; + return; + } + const api::AudioZoneFadeConfiguration& actualConfig = actual.value(); + const api::AudioZoneFadeConfiguration& expectedConfig = expected.value(); + expectSameFadeConfiguration(actualConfig.defaultConfiguration, + expectedConfig.defaultConfiguration, configName); + EXPECT_THAT(actualConfig.transientConfiguration, + UnorderedElementsAreArray(expectedConfig.transientConfiguration)) + << "Transient fade configuration for config " << configName; +} + +void expectSameAudioZoneConfiguration(const api::AudioZoneConfig& actual, + const api::AudioZoneConfig& expected) { + EXPECT_EQ(actual.isDefault, expected.isDefault) + << "Zone default's status do not match for config " << actual.name; + EXPECT_THAT(actual.volumeGroups, UnorderedElementsAreArray(expected.volumeGroups)) + << "Volume groups for config " << actual.name; + expectSameAudioZoneFadeConfiguration(actual.fadeConfiguration, expected.fadeConfiguration, + actual.name); +} + +class CarAudioConfigurationTest : public testing::Test { + protected: + void SetUp() override; + void TearDown() override; + + std::unique_ptr converter; + + protected: + virtual std::string getCarAudioConfiguration() = 0; + virtual std::string getCarFadeConfiguration() = 0; +}; + +void CarAudioConfigurationTest::SetUp() { + converter = std::make_unique( + getTestFilePath(getCarAudioConfiguration()), + getTestFilePath(getCarFadeConfiguration())); +} + +void CarAudioConfigurationTest::TearDown() { + converter.reset(); +} + +class SimpleCarAudioConfigurationTest : public CarAudioConfigurationTest { + virtual std::string getCarAudioConfiguration() { return "simple_car_audio_configuration.xml"; } + + virtual std::string getCarFadeConfiguration() { return "car_audio_fade_configuration.xml"; } +}; + +TEST_F(SimpleCarAudioConfigurationTest, TestLoadSimpleConfiguration) { + EXPECT_EQ(converter->getErrors(), ""); + + const auto audioDeviceConfigs = converter->getAudioDeviceConfiguration(); + EXPECT_EQ(audioDeviceConfigs.routingConfig, + api::RoutingDeviceConfiguration::DYNAMIC_AUDIO_ROUTING); + EXPECT_FALSE(audioDeviceConfigs.useCoreAudioVolume); + EXPECT_TRUE(audioDeviceConfigs.useHalDuckingSignals); + EXPECT_TRUE(audioDeviceConfigs.useCarVolumeGroupMuting); + + const auto& mirroringDevices = converter->getOutputMirroringDevices(); + + EXPECT_EQ(mirroringDevices.size(), 2) << "Mirroring device size"; + for (const auto& mirroringDevice : mirroringDevices) { + const auto& it = + std::find(kMirroringDevices.begin(), kMirroringDevices.end(), mirroringDevice); + EXPECT_TRUE(it != kMirroringDevices.end()) + << "Mirroring device not found " << mirroringDevice.toString(); + } + + const auto zones = converter->getAudioZones(); + EXPECT_EQ(zones.size(), 1); + + const auto& zone = zones.front(); + EXPECT_EQ(zone.id, static_cast(AudioHalProductStrategy::ZoneId::DEFAULT)); + EXPECT_EQ(zone.occupantZoneId, 0); + EXPECT_EQ(zone.name, "primary zone"); + + EXPECT_EQ(zone.audioZoneContext.audioContextInfos.size(), + kSimpleCarAudioConfigurationContext.size()); + for (const auto& info : zone.audioZoneContext.audioContextInfos) { + const auto iterator = std::find(kSimpleCarAudioConfigurationContext.begin(), + kSimpleCarAudioConfigurationContext.end(), info); + EXPECT_TRUE(iterator != kSimpleCarAudioConfigurationContext.end()) + << "Context name " << info.toString() << kMusicContextInfo.toString(); + } + + for (const auto& config : zone.audioZoneConfigs) { + const auto& iterator = kConfigNameToZoneConfig.find(config.name); + EXPECT_TRUE(iterator != kConfigNameToZoneConfig.end()) + << "Zone config not found " << config.name; + expectSameAudioZoneConfiguration(config, iterator->second); + } + + const auto& inputDevices = zone.inputAudioDevices; + EXPECT_EQ(inputDevices.size(), 3) << "Input devices"; + for (const auto& inputDevice : inputDevices) { + const auto& it = std::find(kInputDevices.begin(), kInputDevices.end(), inputDevice); + EXPECT_TRUE(it != kInputDevices.end()) + << "Input device " << inputDevice.toString() << " not found"; + } +} + +class TypeDeviceCarAudioConfigurationTest : public CarAudioConfigurationTest { + virtual std::string getCarAudioConfiguration() { + return "simple_car_audio_configuration_with_device_type.xml"; + } + + virtual std::string getCarFadeConfiguration() { return "car_audio_fade_configuration.xml"; } +}; + +TEST_F(TypeDeviceCarAudioConfigurationTest, TestLoadConfigurationWithDeviceType) { + EXPECT_EQ(converter->getErrors(), ""); + + const auto audioDeviceConfigs = converter->getAudioDeviceConfiguration(); + EXPECT_EQ(audioDeviceConfigs.routingConfig, + api::RoutingDeviceConfiguration::DYNAMIC_AUDIO_ROUTING); + EXPECT_FALSE(audioDeviceConfigs.useCoreAudioVolume); + EXPECT_TRUE(audioDeviceConfigs.useHalDuckingSignals); + EXPECT_TRUE(audioDeviceConfigs.useCarVolumeGroupMuting); + + const auto& mirroringDevices = converter->getOutputMirroringDevices(); + + EXPECT_EQ(mirroringDevices.size(), 2) << "Mirroring device size"; + for (const auto& mirroringDevice : mirroringDevices) { + const auto& it = + std::find(kMirroringDevices.begin(), kMirroringDevices.end(), mirroringDevice); + EXPECT_TRUE(it != kMirroringDevices.end()) + << "Mirroring device not found " << mirroringDevice.toString(); + } + + const auto zones = converter->getAudioZones(); + EXPECT_EQ(zones.size(), 1); + + const auto& zone = zones.front(); + EXPECT_EQ(zone.id, static_cast(AudioHalProductStrategy::ZoneId::DEFAULT)); + EXPECT_EQ(zone.occupantZoneId, 0); + EXPECT_EQ(zone.name, "primary zone"); + + EXPECT_EQ(zone.audioZoneContext.audioContextInfos.size(), + kSimpleCarAudioConfigurationContext.size()); + for (const auto& info : zone.audioZoneContext.audioContextInfos) { + const auto iterator = std::find(kSimpleCarAudioConfigurationContext.begin(), + kSimpleCarAudioConfigurationContext.end(), info); + EXPECT_TRUE(iterator != kSimpleCarAudioConfigurationContext.end()) + << "Context name " << info.toString() << kMusicContextInfo.toString(); + } + + for (const auto& config : zone.audioZoneConfigs) { + const auto& iterator = kConfigNameToZoneConfig.find(config.name); + EXPECT_TRUE(iterator != kConfigNameToZoneConfig.end()) + << "Zone config not found " << config.name; + expectSameAudioZoneConfiguration(config, iterator->second); + } + + const auto& inputDevices = zone.inputAudioDevices; + EXPECT_EQ(inputDevices.size(), 3) << "Input devices"; + for (const auto& inputDevice : inputDevices) { + const auto& it = std::find(kInputDevices.begin(), kInputDevices.end(), inputDevice); + EXPECT_TRUE(it != kInputDevices.end()) + << "Input device " << inputDevice.toString() << " not found"; + } +} + +class CarAudioConfigurationWithDefaultContextTest : public CarAudioConfigurationTest { + virtual std::string getCarAudioConfiguration() { + return "car_audio_configuration_with_default_context.xml"; + } + + virtual std::string getCarFadeConfiguration() { return ""; } +}; + +TEST_F(CarAudioConfigurationWithDefaultContextTest, TestLoadConfiguration) { + EXPECT_EQ(converter->getErrors(), ""); + const auto& zones = converter->getAudioZones(); + EXPECT_EQ(zones.size(), 1) << "Default audio context zones"; + const auto& zone = zones.front(); + const auto& context = zone.audioZoneContext; + EXPECT_THAT(context.audioContextInfos, + UnorderedElementsAreArray(kDefaultCarAudioConfigurationContext)) + << "Default audio contexts"; +} + +class MultiZoneCarAudioConfigurationTest : public CarAudioConfigurationTest { + std::string getCarAudioConfiguration() override { + return "multi_zone_car_audio_configuration.xml"; + } + + std::string getCarFadeConfiguration() override { return "car_audio_fade_configuration.xml"; } +}; + +TEST_F(MultiZoneCarAudioConfigurationTest, TestLoadMultiZoneConfiguration) { + EXPECT_EQ(converter->getErrors(), ""); + + const auto audioDeviceConfigs = converter->getAudioDeviceConfiguration(); + EXPECT_EQ(audioDeviceConfigs.routingConfig, + api::RoutingDeviceConfiguration::CONFIGURABLE_AUDIO_ENGINE_ROUTING); + EXPECT_TRUE(audioDeviceConfigs.useCoreAudioVolume); + EXPECT_FALSE(audioDeviceConfigs.useHalDuckingSignals); + EXPECT_FALSE(audioDeviceConfigs.useCarVolumeGroupMuting); + + const auto& mirroringDevices = converter->getOutputMirroringDevices(); + + EXPECT_THAT(mirroringDevices, UnorderedElementsAreArray(kMultiZoneMirroringDevices)); + + const auto zones = converter->getAudioZones(); + EXPECT_THAT(zones, UnorderedElementsAreArray(kMultiZones)); +} + +class MalformedCarAudioConfigurationTest : public testing::Test { + protected: + void TearDown() override; + + std::unique_ptr converter; +}; + +void MalformedCarAudioConfigurationTest::TearDown() { + converter.reset(); +} + +TEST_F(MalformedCarAudioConfigurationTest, TestLoadEmptyConfiguration) { + converter = + std::make_unique(getTestFilePath(""), ""); + EXPECT_THAT(converter->getErrors(), ContainsRegex("Configuration file .+ is not readable")) + << "Empty configuration file"; + + const auto audioDeviceConfigs = converter->getAudioDeviceConfiguration(); + EXPECT_EQ(audioDeviceConfigs.routingConfig, + api::RoutingDeviceConfiguration::DEFAULT_AUDIO_ROUTING) + << "Default configuration for empty file"; +} + +TEST_F(MalformedCarAudioConfigurationTest, TestLoadNonExistingConfiguration) { + converter = std::make_unique( + getTestFilePath("non_existing_file.xml"), ""); + EXPECT_THAT(converter->getErrors(), ContainsRegex("Configuration file .+ is not readable")) + << "Empty configuration file"; + + const auto audioDeviceConfigs = converter->getAudioDeviceConfiguration(); + EXPECT_EQ(audioDeviceConfigs.routingConfig, + api::RoutingDeviceConfiguration::DEFAULT_AUDIO_ROUTING) + << "Default configuration for empty file"; +} + +TEST_F(MalformedCarAudioConfigurationTest, TestLoadMalforedConfiguration) { + converter = std::make_unique( + getTestFilePath("car_audio_configuration_without_configuration.xml"), ""); + EXPECT_THAT(converter->getErrors(), + ContainsRegex("Configuration file .+ does not have any configurations")) + << "Configuration file without configurations"; + + const auto audioDeviceConfigs = converter->getAudioDeviceConfiguration(); + EXPECT_EQ(audioDeviceConfigs.routingConfig, + api::RoutingDeviceConfiguration::DEFAULT_AUDIO_ROUTING) + << "Default configuration for malformed file"; +} + +TEST_F(MalformedCarAudioConfigurationTest, TestLoadConfigurationWithoutZones) { + converter = std::make_unique( + getTestFilePath("car_audio_configuration_without_audio_zone.xml"), ""); + EXPECT_THAT(converter->getErrors(), ContainsRegex("Audio zones not found in file")) + << "Configuration file without zones"; + + const auto audioDeviceConfigs = converter->getAudioDeviceConfiguration(); + EXPECT_EQ(audioDeviceConfigs.routingConfig, + api::RoutingDeviceConfiguration::DEFAULT_AUDIO_ROUTING) + << "Default configuration for file without zones"; +} + +TEST_F(MalformedCarAudioConfigurationTest, TestLoadConfigurationWithMissingZones) { + converter = std::make_unique( + getTestFilePath("car_audio_configuration_with_missing_zones.xml"), ""); + EXPECT_THAT(converter->getErrors(), ContainsRegex("Error parsing audio zone")) + << "Configuration file with missing zones"; + + const auto audioDeviceConfigs = converter->getAudioDeviceConfiguration(); + EXPECT_EQ(audioDeviceConfigs.routingConfig, + api::RoutingDeviceConfiguration::DEFAULT_AUDIO_ROUTING) + << "Default configuration for file with missing zones"; +} + +} // namespace diff --git a/automotive/audiocontrol/aidl/default/converter/test/car_audio_configuration_with_default_context.xml b/automotive/audiocontrol/aidl/default/converter/test/car_audio_configuration_with_default_context.xml new file mode 100644 index 0000000000000000000000000000000000000000..80cb5cdfc1fe83bee3023602efdf7ebb5e4a1028 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/test/car_audio_configuration_with_default_context.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/automotive/audiocontrol/aidl/default/converter/test/car_audio_configuration_with_missing_zones.xml b/automotive/audiocontrol/aidl/default/converter/test/car_audio_configuration_with_missing_zones.xml new file mode 100644 index 0000000000000000000000000000000000000000..a5880b33f4e27aed1f827841c54a0c1065e02e78 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/test/car_audio_configuration_with_missing_zones.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/automotive/audiocontrol/aidl/default/converter/test/car_audio_configuration_without_audio_zone.xml b/automotive/audiocontrol/aidl/default/converter/test/car_audio_configuration_without_audio_zone.xml new file mode 100644 index 0000000000000000000000000000000000000000..1e50e6e2d2ab681ef2d563ad138fe724769da408 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/test/car_audio_configuration_without_audio_zone.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/automotive/audiocontrol/aidl/default/converter/test/car_audio_configuration_without_configuration.xml b/automotive/audiocontrol/aidl/default/converter/test/car_audio_configuration_without_configuration.xml new file mode 100644 index 0000000000000000000000000000000000000000..4f50ca260cd0735fcf2d1f0394e5078f39fccf3d --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/test/car_audio_configuration_without_configuration.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/automotive/audiocontrol/aidl/default/converter/test/car_audio_fade_configuration.xml b/automotive/audiocontrol/aidl/default/converter/test/car_audio_fade_configuration.xml new file mode 100644 index 0000000000000000000000000000000000000000..249f9158154bdd6946e0821810f3c52603eabdfd --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/test/car_audio_fade_configuration.xml @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/automotive/audiocontrol/aidl/default/converter/test/multi_zone_car_audio_configuration.xml b/automotive/audiocontrol/aidl/default/converter/test/multi_zone_car_audio_configuration.xml new file mode 100644 index 0000000000000000000000000000000000000000..f0c9081f5993d2d0a4e7559a1c1bc60c17fd849a --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/test/multi_zone_car_audio_configuration.xml @@ -0,0 +1,196 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/automotive/audiocontrol/aidl/default/converter/test/simple_car_audio_configuration.xml b/automotive/audiocontrol/aidl/default/converter/test/simple_car_audio_configuration.xml new file mode 100644 index 0000000000000000000000000000000000000000..a6f5317a41d504f9dfa0e9babe320b34522b88f0 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/test/simple_car_audio_configuration.xml @@ -0,0 +1,233 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/automotive/audiocontrol/aidl/default/converter/test/simple_car_audio_configuration_with_device_type.xml b/automotive/audiocontrol/aidl/default/converter/test/simple_car_audio_configuration_with_device_type.xml new file mode 100644 index 0000000000000000000000000000000000000000..eec9db9c71e09cd05039af320c37a2a54f656245 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/test/simple_car_audio_configuration_with_device_type.xml @@ -0,0 +1,233 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/automotive/audiocontrol/aidl/default/loaders/config/Android.bp b/automotive/audiocontrol/aidl/default/loaders/config/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..0d5eb8139cf9d2770780e07301cecaed9ba2f5fe --- /dev/null +++ b/automotive/audiocontrol/aidl/default/loaders/config/Android.bp @@ -0,0 +1,45 @@ +// 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. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +xsd_config { + name: "car_audio_configuration_xsd", + srcs: ["car_audio_configuration.xsd"], + package_name: "android.hardware.automotive.audiocontrol", + nullability: true, +} + +cc_defaults { + name: "car.audio.configuration.xsd.default", + static_libs: [ + "libxml2", + ], + generated_sources: [ + "car_audio_configuration_xsd", + ], + generated_headers: [ + "car_audio_configuration_xsd", + ], + header_libs: [ + "libxsdc-utils", + ], +} diff --git a/automotive/audiocontrol/aidl/default/loaders/config/api/current.txt b/automotive/audiocontrol/aidl/default/loaders/config/api/current.txt new file mode 100644 index 0000000000000000000000000000000000000000..c87b8c6adbf69edd25d014d2381e925db31d8783 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/loaders/config/api/current.txt @@ -0,0 +1,331 @@ +// Signature format: 2.0 +package android.hardware.automotive.audiocontrol { + + public enum ActivationType { + method @NonNull public String getRawName(); + enum_constant public static final android.hardware.automotive.audiocontrol.ActivationType onBoot; + enum_constant public static final android.hardware.automotive.audiocontrol.ActivationType onPlaybackChanged; + enum_constant public static final android.hardware.automotive.audiocontrol.ActivationType onSourceChanged; + } + + public class ActivationVolumeConfigEntryType { + ctor public ActivationVolumeConfigEntryType(); + method @Nullable public android.hardware.automotive.audiocontrol.ActivationType getInvocationType(); + method @Nullable public String getMaxActivationVolumePercentage(); + method @Nullable public String getMinActivationVolumePercentage(); + method public void setInvocationType(@Nullable android.hardware.automotive.audiocontrol.ActivationType); + method public void setMaxActivationVolumePercentage(@Nullable String); + method public void setMinActivationVolumePercentage(@Nullable String); + } + + public class ActivationVolumeConfigType { + ctor public ActivationVolumeConfigType(); + method @Nullable public java.util.List getActivationVolumeConfigEntry(); + method @Nullable public String getName(); + method public void setName(@Nullable String); + } + + public class ActivationVolumeConfigsType { + ctor public ActivationVolumeConfigsType(); + method @Nullable public java.util.List getActivationVolumeConfig(); + } + + public class ApplyFadeConfigType { + ctor public ApplyFadeConfigType(); + method @Nullable public java.util.List getAudioAttributes(); + method @Nullable public boolean getIsDefault(); + method @Nullable public String getName(); + method public void setIsDefault(@Nullable boolean); + method public void setName(@Nullable String); + } + + public class ApplyFadeConfigsType { + ctor public ApplyFadeConfigsType(); + method @Nullable public java.util.List getFadeConfig(); + } + + public class AttributesType { + ctor public AttributesType(); + method @Nullable public android.hardware.automotive.audiocontrol.ContentTypeEnum getContentType(); + method @Nullable public String getTags(); + method @Nullable public android.hardware.automotive.audiocontrol.UsageEnumType getUsage(); + method public void setContentType(@Nullable android.hardware.automotive.audiocontrol.ContentTypeEnum); + method public void setTags(@Nullable String); + method public void setUsage(@Nullable android.hardware.automotive.audiocontrol.UsageEnumType); + } + + public class AudioAttributeUsagesType { + ctor public AudioAttributeUsagesType(); + method @Nullable public java.util.List getUsage(); + } + + public class AudioAttributesUsagesType { + ctor public AudioAttributesUsagesType(); + method @Nullable public java.util.List getAudioAttribute_optional(); + method @Nullable public java.util.List getUsage_optional(); + } + + public class CarAudioConfigurationType { + ctor public CarAudioConfigurationType(); + method @Nullable public android.hardware.automotive.audiocontrol.ActivationVolumeConfigsType getActivationVolumeConfigs(); + method @Nullable public android.hardware.automotive.audiocontrol.DeviceConfigurationsType getDeviceConfigurations(); + method @Nullable public android.hardware.automotive.audiocontrol.MirroringDevicesType getMirroringDevices(); + method @Nullable public android.hardware.automotive.audiocontrol.OemContextsType getOemContexts(); + method @Nullable public String getVersion(); + method @Nullable public android.hardware.automotive.audiocontrol.ZonesType getZones(); + method public void setActivationVolumeConfigs(@Nullable android.hardware.automotive.audiocontrol.ActivationVolumeConfigsType); + method public void setDeviceConfigurations(@Nullable android.hardware.automotive.audiocontrol.DeviceConfigurationsType); + method public void setMirroringDevices(@Nullable android.hardware.automotive.audiocontrol.MirroringDevicesType); + method public void setOemContexts(@Nullable android.hardware.automotive.audiocontrol.OemContextsType); + method public void setVersion(@Nullable String); + method public void setZones(@Nullable android.hardware.automotive.audiocontrol.ZonesType); + } + + public class ContentType { + ctor public ContentType(); + method @Nullable public android.hardware.automotive.audiocontrol.ContentTypeEnum getValue(); + method public void setValue(@Nullable android.hardware.automotive.audiocontrol.ContentTypeEnum); + } + + public enum ContentTypeEnum { + method @NonNull public String getRawName(); + enum_constant public static final android.hardware.automotive.audiocontrol.ContentTypeEnum AUDIO_CONTENT_TYPE_MOVIE; + enum_constant public static final android.hardware.automotive.audiocontrol.ContentTypeEnum AUDIO_CONTENT_TYPE_MUSIC; + enum_constant public static final android.hardware.automotive.audiocontrol.ContentTypeEnum AUDIO_CONTENT_TYPE_SONIFICATION; + enum_constant public static final android.hardware.automotive.audiocontrol.ContentTypeEnum AUDIO_CONTENT_TYPE_SPEECH; + enum_constant public static final android.hardware.automotive.audiocontrol.ContentTypeEnum AUDIO_CONTENT_TYPE_UNKNOWN; + } + + public class ContextNameType { + ctor public ContextNameType(); + method @Nullable public String getContext(); + method public void setContext(@Nullable String); + } + + public class DeviceConfigurationType { + ctor public DeviceConfigurationType(); + method @Nullable public String getName(); + method @Nullable public String getValue(); + method public void setName(@Nullable String); + method public void setValue(@Nullable String); + } + + public class DeviceConfigurationsType { + ctor public DeviceConfigurationsType(); + method @Nullable public java.util.List getDeviceConfiguration(); + } + + public class DeviceRoutesType { + ctor public DeviceRoutesType(); + method @Nullable public String getAddress(); + method @Nullable public java.util.List getContext(); + method @Nullable public android.hardware.automotive.audiocontrol.OutDeviceType getType(); + method public void setAddress(@Nullable String); + method public void setType(@Nullable android.hardware.automotive.audiocontrol.OutDeviceType); + } + + public enum InDeviceType { + method @NonNull public String getRawName(); + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_AMBIENT; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_AUX_DIGITAL; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_BACK_MIC; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_BLUETOOTH_A2DP; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_BLUETOOTH_BLE; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_BUILTIN_MIC; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_BUS; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_COMMUNICATION; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_DEFAULT; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_ECHO_REFERENCE; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_FM_TUNER; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_HDMI; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_HDMI_ARC; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_IP; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_LINE; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_LOOPBACK; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_PROXY; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_REMOTE_SUBMIX; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_SPDIF; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_STUB; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_TELEPHONY_RX; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_TV_TUNER; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_USB_ACCESSORY; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_USB_DEVICE; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_USB_HEADSET; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_VOICE_CALL; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_WIRED_HEADSET; + } + + public class InputDeviceType { + ctor public InputDeviceType(); + method @Nullable public String getAddress(); + method @Nullable public android.hardware.automotive.audiocontrol.InDeviceType getType(); + method public void setAddress(@Nullable String); + method public void setType(@Nullable android.hardware.automotive.audiocontrol.InDeviceType); + } + + public class InputDevicesType { + ctor public InputDevicesType(); + method @Nullable public java.util.List getInputDevice(); + } + + public class MirroringDevice { + ctor public MirroringDevice(); + method @Nullable public String getAddress(); + method public void setAddress(@Nullable String); + } + + public class MirroringDevicesType { + ctor public MirroringDevicesType(); + method @Nullable public java.util.List getMirroringDevice(); + } + + public class OemContextType { + ctor public OemContextType(); + method @Nullable public android.hardware.automotive.audiocontrol.AudioAttributesUsagesType getAudioAttributes(); + method @Nullable public String getId(); + method @Nullable public String getName(); + method public void setAudioAttributes(@Nullable android.hardware.automotive.audiocontrol.AudioAttributesUsagesType); + method public void setId(@Nullable String); + method public void setName(@Nullable String); + } + + public class OemContextsType { + ctor public OemContextsType(); + method @Nullable public java.util.List getOemContext(); + } + + public enum OutDeviceType { + method @NonNull public String getRawName(); + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_AUX_DIGITAL; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_AUX_LINE; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_BLE_BROADCAST; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_BLE_HEADSET; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_BLE_SPEAKER; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_BLUETOOTH_A2DP; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_BUS; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_DEFAULT; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_HDMI; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_HDMI_ARC; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_HDMI_EARC; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_LINE; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_SPEAKER; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_SPEAKER_SAFE; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_USB_ACCESSORY; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_USB_DEVICE; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_USB_HEADSET; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_WIRED_HEADPHONE; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_WIRED_HEADSET; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType TYPE_AUX_LINE; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType TYPE_BLE_BROADCAST; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType TYPE_BLE_HEADSET; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType TYPE_BLE_SPEAKER; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType TYPE_BLUETOOTH_A2DP; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType TYPE_BUILTIN_SPEAKER; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType TYPE_BUS; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType TYPE_HDMI; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType TYPE_USB_ACCESSORY; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType TYPE_USB_DEVICE; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType TYPE_USB_HEADSET; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType TYPE_WIRED_HEADPHONES; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType TYPE_WIRED_HEADSET; + } + + public enum UsageEnumType { + method @NonNull public String getRawName(); + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_ALARM; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_ANNOUNCEMENT; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_ASSISTANCE_SONIFICATION; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_ASSISTANT; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_CALL_ASSISTANT; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_EMERGENCY; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_GAME; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_MEDIA; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_NOTIFICATION; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_NOTIFICATION_EVENT; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_SAFETY; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_UNKNOWN; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_VEHICLE_STATUS; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_VIRTUAL_SOURCE; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_VOICE_COMMUNICATION; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING; + } + + public class UsageType { + ctor public UsageType(); + method @Nullable public android.hardware.automotive.audiocontrol.UsageEnumType getValue(); + method public void setValue(@Nullable android.hardware.automotive.audiocontrol.UsageEnumType); + } + + public class VolumeGroupType { + ctor public VolumeGroupType(); + method @Nullable public String getActivationConfig(); + method @Nullable public java.util.List getDevice(); + method @Nullable public String getName(); + method public void setActivationConfig(@Nullable String); + method public void setName(@Nullable String); + } + + public class VolumeGroupsType { + ctor public VolumeGroupsType(); + method @Nullable public java.util.List getGroup(); + } + + public class XmlParser { + ctor public XmlParser(); + method @Nullable public static android.hardware.automotive.audiocontrol.CarAudioConfigurationType read(@NonNull java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException; + method @Nullable public static String readText(@NonNull org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; + method public static void skip(@NonNull org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; + } + + public class ZoneConfigType { + ctor public ZoneConfigType(); + method @Nullable public android.hardware.automotive.audiocontrol.ApplyFadeConfigsType getApplyFadeConfigs(); + method @Nullable public boolean getIsDefault(); + method @Nullable public String getName(); + method @Nullable public android.hardware.automotive.audiocontrol.VolumeGroupsType getVolumeGroups(); + method public void setApplyFadeConfigs(@Nullable android.hardware.automotive.audiocontrol.ApplyFadeConfigsType); + method public void setIsDefault(@Nullable boolean); + method public void setName(@Nullable String); + method public void setVolumeGroups(@Nullable android.hardware.automotive.audiocontrol.VolumeGroupsType); + } + + public class ZoneConfigsType { + ctor public ZoneConfigsType(); + method @Nullable public android.hardware.automotive.audiocontrol.ZoneConfigType getZoneConfig(); + method public void setZoneConfig(@Nullable android.hardware.automotive.audiocontrol.ZoneConfigType); + } + + public class ZoneType { + ctor public ZoneType(); + method @Nullable public String getAudioZoneId(); + method @Nullable public android.hardware.automotive.audiocontrol.InputDevicesType getInputDevices(); + method @Nullable public boolean getIsPrimary(); + method @Nullable public String getName(); + method @Nullable public String getOccupantZoneId(); + method @Nullable public android.hardware.automotive.audiocontrol.ZoneConfigsType getZoneConfigs(); + method public void setAudioZoneId(@Nullable String); + method public void setInputDevices(@Nullable android.hardware.automotive.audiocontrol.InputDevicesType); + method public void setIsPrimary(@Nullable boolean); + method public void setName(@Nullable String); + method public void setOccupantZoneId(@Nullable String); + method public void setZoneConfigs(@Nullable android.hardware.automotive.audiocontrol.ZoneConfigsType); + } + + public class ZonesType { + ctor public ZonesType(); + method @Nullable public java.util.List getZone(); + } + +} + diff --git a/automotive/audiocontrol/aidl/default/loaders/config/api/last_current.txt b/automotive/audiocontrol/aidl/default/loaders/config/api/last_current.txt new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/automotive/audiocontrol/aidl/default/loaders/config/api/last_removed.txt b/automotive/audiocontrol/aidl/default/loaders/config/api/last_removed.txt new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/automotive/audiocontrol/aidl/default/loaders/config/api/removed.txt b/automotive/audiocontrol/aidl/default/loaders/config/api/removed.txt new file mode 100644 index 0000000000000000000000000000000000000000..d802177e249b3f97128699222e65c35e57ba7540 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/loaders/config/api/removed.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/automotive/audiocontrol/aidl/default/loaders/config/car_audio_configuration.xsd b/automotive/audiocontrol/aidl/default/loaders/config/car_audio_configuration.xsd new file mode 100644 index 0000000000000000000000000000000000000000..634aedab66bdbb9ef5894f1d2ff6092219551019 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/loaders/config/car_audio_configuration.xsd @@ -0,0 +1,248 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/automotive/audiocontrol/aidl/default/loaders/fade/Android.bp b/automotive/audiocontrol/aidl/default/loaders/fade/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..3dbc2f1ce022254c1a28209c5fbf3e3e787be857 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/loaders/fade/Android.bp @@ -0,0 +1,45 @@ +// 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. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +xsd_config { + name: "car_fade_audio_configuration_xsd", + srcs: ["car_fade_audio_configuration.xsd"], + package_name: "android.hardware.automotive.audiocontrol.fade", + nullability: true, +} + +cc_defaults { + name: "car.fade.configuration.xsd.default", + static_libs: [ + "libxml2", + ], + generated_sources: [ + "car_fade_audio_configuration_xsd", + ], + generated_headers: [ + "car_fade_audio_configuration_xsd", + ], + header_libs: [ + "libxsdc-utils", + ], +} diff --git a/automotive/audiocontrol/aidl/default/loaders/fade/api/current.txt b/automotive/audiocontrol/aidl/default/loaders/fade/api/current.txt new file mode 100644 index 0000000000000000000000000000000000000000..f40f1bef4fcc72ffef13ce58c5aeb9d274ecb2ff --- /dev/null +++ b/automotive/audiocontrol/aidl/default/loaders/fade/api/current.txt @@ -0,0 +1,160 @@ +// Signature format: 2.0 +package android.hardware.automotive.audiocontrol.fade { + + public class AttributesType { + ctor public AttributesType(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.ContentTypeEnum getContentType(); + method @Nullable public String getTags(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.UsageEnumType getUsage(); + method public void setContentType(@Nullable android.hardware.automotive.audiocontrol.fade.ContentTypeEnum); + method public void setTags(@Nullable String); + method public void setUsage(@Nullable android.hardware.automotive.audiocontrol.fade.UsageEnumType); + } + + public class AudioAttributesUsagesType { + ctor public AudioAttributesUsagesType(); + method @Nullable public java.util.List getAudioAttribute_optional(); + method @Nullable public java.util.List getUsage_optional(); + } + + public class CarAudioFadeConfigurationType { + ctor public CarAudioFadeConfigurationType(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.FadeConfigurationConfigs getConfigs(); + method public void setConfigs(@Nullable android.hardware.automotive.audiocontrol.fade.FadeConfigurationConfigs); + } + + public class ContentType { + ctor public ContentType(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.ContentTypeEnum getValue(); + method public void setValue(@Nullable android.hardware.automotive.audiocontrol.fade.ContentTypeEnum); + } + + public enum ContentTypeEnum { + method @NonNull public String getRawName(); + enum_constant public static final android.hardware.automotive.audiocontrol.fade.ContentTypeEnum AUDIO_CONTENT_TYPE_MOVIE; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.ContentTypeEnum AUDIO_CONTENT_TYPE_MUSIC; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.ContentTypeEnum AUDIO_CONTENT_TYPE_SONIFICATION; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.ContentTypeEnum AUDIO_CONTENT_TYPE_SPEECH; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.ContentTypeEnum AUDIO_CONTENT_TYPE_UNKNOWN; + } + + public class FadeConfigurationConfig { + ctor public FadeConfigurationConfig(); + method @Nullable public String getDefaultFadeInDelayForOffenders(); + method @Nullable public String getDefaultFadeInDurationInMillis(); + method @Nullable public String getDefaultFadeOutDurationInMillis(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.FadeInConfigurationsType getFadeInConfigurations(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.FadeOutConfigurationsType getFadeOutConfigurations(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.FadeStateType getFadeState(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.FadeableUsagesType getFadeableUsages(); + method @Nullable public String getName(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.UnfadeableAudioAttributesType getUnfadeableAudioAttributes(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.UnfadeableContentTypesType getUnfadeableContentTypes(); + method public void setDefaultFadeInDelayForOffenders(@Nullable String); + method public void setDefaultFadeInDurationInMillis(@Nullable String); + method public void setDefaultFadeOutDurationInMillis(@Nullable String); + method public void setFadeInConfigurations(@Nullable android.hardware.automotive.audiocontrol.fade.FadeInConfigurationsType); + method public void setFadeOutConfigurations(@Nullable android.hardware.automotive.audiocontrol.fade.FadeOutConfigurationsType); + method public void setFadeState(@Nullable android.hardware.automotive.audiocontrol.fade.FadeStateType); + method public void setFadeableUsages(@Nullable android.hardware.automotive.audiocontrol.fade.FadeableUsagesType); + method public void setName(@Nullable String); + method public void setUnfadeableAudioAttributes(@Nullable android.hardware.automotive.audiocontrol.fade.UnfadeableAudioAttributesType); + method public void setUnfadeableContentTypes(@Nullable android.hardware.automotive.audiocontrol.fade.UnfadeableContentTypesType); + } + + public class FadeConfigurationConfigs { + ctor public FadeConfigurationConfigs(); + method @Nullable public java.util.List getConfig(); + } + + public class FadeConfigurationType { + ctor public FadeConfigurationType(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.AudioAttributesUsagesType getAudioAttributes(); + method @Nullable public String getFadeDurationMillis(); + method public void setAudioAttributes(@Nullable android.hardware.automotive.audiocontrol.fade.AudioAttributesUsagesType); + method public void setFadeDurationMillis(@Nullable String); + } + + public class FadeInConfigurationsType { + ctor public FadeInConfigurationsType(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.FadeConfigurationType getFadeConfiguration(); + method public void setFadeConfiguration(@Nullable android.hardware.automotive.audiocontrol.fade.FadeConfigurationType); + } + + public class FadeOutConfigurationsType { + ctor public FadeOutConfigurationsType(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.FadeConfigurationType getFadeConfiguration(); + method public void setFadeConfiguration(@Nullable android.hardware.automotive.audiocontrol.fade.FadeConfigurationType); + } + + public enum FadeStateEnumType { + method @NonNull public String getRawName(); + enum_constant public static final android.hardware.automotive.audiocontrol.fade.FadeStateEnumType FADE_STATE_DISABLED; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.FadeStateEnumType FADE_STATE_ENABLED_DEFAULT; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.FadeStateEnumType _0; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.FadeStateEnumType _1; + } + + public class FadeStateType { + ctor public FadeStateType(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.FadeStateEnumType getValue(); + method public void setValue(@Nullable android.hardware.automotive.audiocontrol.fade.FadeStateEnumType); + } + + public class FadeableUsagesType { + ctor public FadeableUsagesType(); + method @Nullable public java.util.List getUsage(); + } + + public class UnfadeableAudioAttributesType { + ctor public UnfadeableAudioAttributesType(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.AudioAttributesUsagesType getAudioAttributes(); + method public void setAudioAttributes(@Nullable android.hardware.automotive.audiocontrol.fade.AudioAttributesUsagesType); + } + + public class UnfadeableContentTypesType { + ctor public UnfadeableContentTypesType(); + method @Nullable public java.util.List getContentType(); + } + + public enum UsageEnumType { + method @NonNull public String getRawName(); + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_ALARM; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_ANNOUNCEMENT; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_ASSISTANCE_SONIFICATION; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_ASSISTANT; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_CALL_ASSISTANT; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_EMERGENCY; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_GAME; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_MEDIA; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_NOTIFICATION; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_NOTIFICATION_EVENT; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_SAFETY; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_UNKNOWN; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_VEHICLE_STATUS; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_VIRTUAL_SOURCE; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_VOICE_COMMUNICATION; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING; + } + + public class UsageType { + ctor public UsageType(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.UsageEnumType getValue(); + method public void setValue(@Nullable android.hardware.automotive.audiocontrol.fade.UsageEnumType); + } + + public class XmlParser { + ctor public XmlParser(); + method @Nullable public static android.hardware.automotive.audiocontrol.fade.CarAudioFadeConfigurationType read(@NonNull java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException; + method @Nullable public static String readText(@NonNull org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; + method public static void skip(@NonNull org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; + } + +} + diff --git a/automotive/audiocontrol/aidl/default/loaders/fade/api/last_current.txt b/automotive/audiocontrol/aidl/default/loaders/fade/api/last_current.txt new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/automotive/audiocontrol/aidl/default/loaders/fade/api/last_removed.txt b/automotive/audiocontrol/aidl/default/loaders/fade/api/last_removed.txt new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/automotive/audiocontrol/aidl/default/loaders/fade/api/removed.txt b/automotive/audiocontrol/aidl/default/loaders/fade/api/removed.txt new file mode 100644 index 0000000000000000000000000000000000000000..d802177e249b3f97128699222e65c35e57ba7540 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/loaders/fade/api/removed.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/automotive/audiocontrol/aidl/default/loaders/fade/car_fade_audio_configuration.xsd b/automotive/audiocontrol/aidl/default/loaders/fade/car_fade_audio_configuration.xsd new file mode 100644 index 0000000000000000000000000000000000000000..051be7e286d965a0205a2825a6e422c41f170c6e --- /dev/null +++ b/automotive/audiocontrol/aidl/default/loaders/fade/car_fade_audio_configuration.xsd @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/automotive/audiocontrol/aidl/rust_impl/Android.bp b/automotive/audiocontrol/aidl/rust_impl/Android.bp index 062d989bab5d3e8d71912f197f82cba8abee1b0c..f9d07b22cea4283b910c9eb379eb1c6ab84a2a72 100644 --- a/automotive/audiocontrol/aidl/rust_impl/Android.bp +++ b/automotive/audiocontrol/aidl/rust_impl/Android.bp @@ -15,7 +15,7 @@ */ rust_binary { - name: "android.hardware.automotive.audiocontrol-V4-rust-service", + name: "android.hardware.automotive.audiocontrol-rust-service", relative_install_path: "hw", vendor: true, srcs: ["src/*.rs"], @@ -23,6 +23,7 @@ rust_binary { defaults: [ "latest_android_hardware_automotive_audiocontrol_rust", "latest_android_hardware_audio_common_rust", + "latest_android_media_audio_common_types_rust", ], vintf_fragments: ["audiocontrol-rust-service.xml"], init_rc: ["audiocontrol-rust-service.rc"], diff --git a/automotive/audiocontrol/aidl/rust_impl/README.md b/automotive/audiocontrol/aidl/rust_impl/README.md index ed22356920cd501766d03f3b9e7a933689aa5f6f..b68daf3f8750ce00359980582c9624ea2e8d621c 100644 --- a/automotive/audiocontrol/aidl/rust_impl/README.md +++ b/automotive/audiocontrol/aidl/rust_impl/README.md @@ -6,7 +6,7 @@ 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. +`android.hardware.automotive.audiocontrol-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 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 index ba0ca238f454fdf167bfdfd905998e224be3034a..8184c436fc1b11acc0dd1c1057cd44f267c87fdb 100644 --- a/automotive/audiocontrol/aidl/rust_impl/src/default_audio_control_hal.rs +++ b/automotive/audiocontrol/aidl/rust_impl/src/default_audio_control_hal.rs @@ -23,8 +23,15 @@ use android_hardware_automotive_audiocontrol::aidl::android::hardware::automotiv IModuleChangeCallback::IModuleChangeCallback, MutingInfo::MutingInfo, Reasons::Reasons, + AudioDeviceConfiguration::AudioDeviceConfiguration, + AudioZone::AudioZone +}; +use android_hardware_audio_common::aidl::android::hardware::audio::common::{ + PlaybackTrackMetadata::PlaybackTrackMetadata, +}; +use android_media_audio_common_types::aidl::android::media::audio::common::{ + AudioPort::AudioPort, }; -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. @@ -81,4 +88,16 @@ impl IAudioControl for DefaultAudioControlHal { fn clearModuleChangeCallback(&self) -> BinderResult<()> { Err(StatusCode::UNKNOWN_ERROR.into()) } + + fn getAudioDeviceConfiguration(&self) -> std::result::Result { + Err(binder::StatusCode::UNKNOWN_ERROR.into()) + } + + fn getOutputMirroringDevices(&self) -> std::result::Result, binder::Status> { + Err(binder::StatusCode::UNKNOWN_ERROR.into()) + } + + fn getCarAudioZones(&self) -> std::result::Result, binder::Status> { + Err(binder::StatusCode::UNKNOWN_ERROR.into()) + } } diff --git a/automotive/audiocontrol/aidl/vts/Android.bp b/automotive/audiocontrol/aidl/vts/Android.bp index d94ad556dcb604f3dd6f4072798025cb47fca4be..57c6ae47ff7a53cbf7335c557affff113ff675d2 100644 --- a/automotive/audiocontrol/aidl/vts/Android.bp +++ b/automotive/audiocontrol/aidl/vts/Android.bp @@ -22,6 +22,25 @@ package { default_applicable_licenses: ["hardware_interfaces_license"], } +cc_library { + name: "AudioControlHalTestUtils", + srcs: [ + "src/AudioControlTestUtils.cpp", + ], + export_include_dirs: [ + "include", + ], + defaults: [ + "latest_android_hardware_audio_common_cpp_static", + "latest_android_hardware_automotive_audiocontrol_cpp_static", + "latest_android_media_audio_common_types_cpp_static", + ], + shared_libs: [ + "libbase", + "libutils", + ], +} + cc_test { name: "VtsAidlHalAudioControlTest", defaults: [ @@ -39,9 +58,11 @@ cc_test { "libbinder", "libbase", "libxml2", + "libutils", ], static_libs: [ "libgmock", + "AudioControlHalTestUtils", ], test_suites: [ "general-tests", diff --git a/automotive/audiocontrol/aidl/vts/VtsHalAudioControlTargetTest.cpp b/automotive/audiocontrol/aidl/vts/VtsHalAudioControlTargetTest.cpp index 4e7e963981432aa89c767d486f729dd0ce4fbfdc..f01f04d1e5cd7a37aae4c2bdaa61e912e4759f5c 100644 --- a/automotive/audiocontrol/aidl/vts/VtsHalAudioControlTargetTest.cpp +++ b/automotive/audiocontrol/aidl/vts/VtsHalAudioControlTargetTest.cpp @@ -18,32 +18,62 @@ #include #include #include +#include +#include #include #include #include #include #include +#include #include #include +#include using android::ProcessState; using android::sp; using android::String16; using android::binder::Status; +using android::hardware::automotive::audiocontrol::AudioDeviceConfiguration; +using android::hardware::automotive::audiocontrol::AudioFadeConfiguration; using android::hardware::automotive::audiocontrol::AudioFocusChange; using android::hardware::automotive::audiocontrol::AudioGainConfigInfo; +using android::hardware::automotive::audiocontrol::AudioZone; +using android::hardware::automotive::audiocontrol::AudioZoneConfig; +using android::hardware::automotive::audiocontrol::AudioZoneContextInfo; +using android::hardware::automotive::audiocontrol::AudioZoneFadeConfiguration; using android::hardware::automotive::audiocontrol::BnAudioGainCallback; using android::hardware::automotive::audiocontrol::BnFocusListener; using android::hardware::automotive::audiocontrol::BnModuleChangeCallback; +using android::hardware::automotive::audiocontrol::DeviceToContextEntry; using android::hardware::automotive::audiocontrol::DuckingInfo; +using android::hardware::automotive::audiocontrol::FadeConfiguration; using android::hardware::automotive::audiocontrol::IAudioControl; using android::hardware::automotive::audiocontrol::IModuleChangeCallback; using android::hardware::automotive::audiocontrol::MutingInfo; using android::hardware::automotive::audiocontrol::Reasons; +using android::hardware::automotive::audiocontrol::VolumeActivationConfiguration; +using android::hardware::automotive::audiocontrol::VolumeActivationConfigurationEntry; +using android::hardware::automotive::audiocontrol::VolumeGroupConfig; +using android::hardware::automotive::audiocontrol::RoutingDeviceConfiguration:: + CONFIGURABLE_AUDIO_ENGINE_ROUTING; +using android::hardware::automotive::audiocontrol::RoutingDeviceConfiguration:: + DEFAULT_AUDIO_ROUTING; +using android::hardware::automotive::audiocontrol::VolumeActivationConfigurationEntry:: + DEFAULT_MAX_ACTIVATION_VALUE; +using android::hardware::automotive::audiocontrol::VolumeActivationConfigurationEntry:: + DEFAULT_MIN_ACTIVATION_VALUE; +using android::media::audio::common::AudioHalProductStrategy; + using ::testing::AnyOf; using ::testing::Eq; +using ::testing::Not; +using ::testing::UnorderedElementsAreArray; + +using android::internal::ToString; + #include "android_audio_policy_configuration_V7_0.h" namespace xsd { @@ -52,11 +82,231 @@ using namespace android::audio::policy::configuration::V7_0; namespace audiohalcommon = android::hardware::audio::common; namespace audiomediacommon = android::media::audio::common; +namespace testutils = android::hardware::audiocontrol::testutils; namespace { constexpr int32_t kAidlVersionThree = 3; +constexpr int32_t kAidlVersionFive = 5; + +bool hasValidVolumeGroupActivation(const VolumeActivationConfiguration& activation, + std::string& message) { + if (activation.volumeActivationEntries.empty()) { + message = "Volume group activation must have at least one volume activation entry"; + return false; + } + for (const auto& entry : activation.volumeActivationEntries) { + int32_t max = entry.maxActivationVolumePercentage; + int32_t min = entry.minActivationVolumePercentage; + if (min > DEFAULT_MAX_ACTIVATION_VALUE || min < DEFAULT_MIN_ACTIVATION_VALUE) { + message = "Invalid minActivationVolumePercentage, must be between " + + std::to_string(DEFAULT_MIN_ACTIVATION_VALUE) + " and " + + std::to_string(DEFAULT_MAX_ACTIVATION_VALUE); + return false; + } + if (max > DEFAULT_MAX_ACTIVATION_VALUE || max < DEFAULT_MIN_ACTIVATION_VALUE) { + message = "Invalid maxActivationVolumePercentage, must be between " + + std::to_string(DEFAULT_MIN_ACTIVATION_VALUE) + " and " + + std::to_string(DEFAULT_MAX_ACTIVATION_VALUE); + return false; + } + if (min >= max) { + message = + "Invalid maxActivationVolumePercentage and minActivationVolumePercentage " + "combination, minActivationVolumePercentage must be less than " + "maxActivationVolumePercentage"; + return false; + } + } + return true; +} + +bool hasValidAudioRoute(const DeviceToContextEntry& entry, std::string& message, + std::set& groupDevices) { + if (entry.contextNames.empty()) { + message = " Contexts can not be empty for DeviceToContextEntry"; + return false; + } + std::set contextInRoute; + for (const auto& context : entry.contextNames) { + std::string contextString = ToString(context); + if (contextInRoute.contains(contextString)) { + message = " Context " + contextString + " repeats for DeviceToContextEntry"; + return false; + } + groupDevices.insert(contextString); + } + audiomediacommon::AudioDeviceDescription description; + if (!testutils::getAudioPortDeviceDescriptor(entry.device, description)) { + message = " DeviceToContextEntry must have a valid device port"; + return false; + } + // BUS type also has empty connection + // Note: OUT_BUS is also mapped to OUT_DEVICE + if (description.type != audiomediacommon::AudioDeviceType::OUT_BUS && + !description.connection.empty()) { + return true; + } + std::string address; + if (!testutils::getAddressForAudioPort(entry.device, address) || address.empty()) { + message = " Address can not be empty for BUS devices"; + return false; + } + if (groupDevices.contains(address)) { + message = + " Audio device address can not repeat in the same volume group or within audio" + " zone configuration if not using configurable audio policy engine"; + return false; + } + groupDevices.insert(address); + return true; +} + +inline bool hasValidTimeout(int64_t timeout) { + return timeout > 0; +} +bool hasValidFadeConfiguration(const FadeConfiguration& fadeConfiguration, + const std::string& prefix, std::string& message) { + if (!hasValidTimeout(fadeConfiguration.fadeDurationMillis)) { + message = prefix + " duration must be greater than 0"; + return false; + } + return true; +} +bool hadValidAudioFadeConfiguration(const AudioFadeConfiguration& fadeConfiguration, + std::string& message) { + if (!hasValidTimeout(fadeConfiguration.fadeInDurationMs)) { + message = "Fade-in duration must be greater than 0"; + return false; + } + if (!hasValidTimeout(fadeConfiguration.fadeOutDurationMs)) { + message = "Fade-out duration must be greater than 0"; + return false; + } + if (!hasValidTimeout(fadeConfiguration.fadeInDelayedForOffendersMs)) { + message = "Fade-in delayed for offenders duration must be greater than 0"; + return false; + } + for (const auto& fadeOutConfig : fadeConfiguration.fadeOutConfigurations) { + if (!hasValidFadeConfiguration(fadeOutConfig, "Fade-out", message)) { + return false; + } + } + for (const auto& fadeOutConfig : fadeConfiguration.fadeInConfigurations) { + if (!hasValidFadeConfiguration(fadeOutConfig, "Fade-in", message)) { + return false; + } + } + return true; } +void validateVolumeGroupInfo(const AudioZoneConfig& audioZoneConfig, + const VolumeGroupConfig& volumeGroupConfig, + const AudioDeviceConfiguration& deviceConfig, + std::set& groupDevices, std::set& groupIds) { + std::string zoneConfigName = testutils::toAlphaNumeric(ToString(audioZoneConfig.name)); + std::string volumeGroupName = testutils::toAlphaNumeric(ToString(volumeGroupConfig.name)); + std::string volumeGroupInfo = + "Audio zone config " + zoneConfigName + " volume group " + volumeGroupName; + ALOGI("%s test", volumeGroupInfo.c_str()); + + EXPECT_FALSE(volumeGroupConfig.carAudioRoutes.empty()) + << volumeGroupInfo << " must have at least one audio route"; + if (deviceConfig.routingConfig == CONFIGURABLE_AUDIO_ENGINE_ROUTING) { + EXPECT_FALSE(volumeGroupConfig.name.empty()) + << volumeGroupInfo << " must have a non-empty volume name"; + } + if (volumeGroupConfig.id != VolumeGroupConfig::UNASSIGNED_ID) { + EXPECT_TRUE(groupIds.insert(volumeGroupConfig.id).second) + << volumeGroupInfo << " repeats volume group id " << volumeGroupConfig.id; + } + for (const auto& audioRoute : volumeGroupConfig.carAudioRoutes) { + std::string routeMessage; + EXPECT_TRUE(hasValidAudioRoute(audioRoute, routeMessage, groupDevices)) + << volumeGroupInfo << " Volume route message: " << routeMessage; + } + if (volumeGroupConfig.activationConfiguration.has_value()) { + std::string activationMessage; + EXPECT_TRUE(hasValidVolumeGroupActivation(volumeGroupConfig.activationConfiguration.value(), + activationMessage)) + << volumeGroupInfo << " Activation message: " << activationMessage; + } +} + +void validateAudioZoneFadeConfiguration(const AudioZoneFadeConfiguration& fadeConfiguration) { + ALOGI("Fade configuration test"); + std::set usages; + std::string defaultValidationMessage; + EXPECT_TRUE(hadValidAudioFadeConfiguration(fadeConfiguration.defaultConfiguration, + defaultValidationMessage)) + << "Default configuration validation failed: " << defaultValidationMessage; + for (const auto& entry : fadeConfiguration.transientConfiguration) { + ALOGI("Transient fade configuration test"); + std::string transientFadeConfigurationMessage; + EXPECT_TRUE(hadValidAudioFadeConfiguration(entry.transientFadeConfiguration, + transientFadeConfigurationMessage)) + << "Transient fade configuration validation failed: " + << transientFadeConfigurationMessage; + EXPECT_FALSE(entry.transientUsages.empty()) + << "Transient fade configuration must have at least one audio usage"; + for (const auto& usage : entry.transientUsages) { + EXPECT_FALSE(usages.contains(usage)) << "Audio usages " << ToString(usage) + << " repeat in transient fade configuration"; + } + } +} + +void validateAudioZoneConfiguration(const AudioZone& carAudioZone, + const AudioZoneConfig& audioZoneConfig, + const AudioDeviceConfiguration& deviceConfig) { + std::string zoneConfigName = testutils::toAlphaNumeric(ToString(audioZoneConfig.name)); + ALOGI("Zone config name %s test", zoneConfigName.c_str()); + std::set contextInfoNames; + EXPECT_FALSE(audioZoneConfig.volumeGroups.empty()) + << "Volume groups for zone config " << zoneConfigName.c_str(); + std::set groupDevices; + std::set groupIds; + for (const auto& volumeGroup : audioZoneConfig.volumeGroups) { + ALOGI("Zone config name %s volume group test %s", zoneConfigName.c_str(), + ToString(volumeGroup.name).c_str()); + std::vector groupContexts = + testutils::getContextInfoNamesForVolumeGroup(volumeGroup); + for (const auto& context : groupContexts) { + EXPECT_FALSE(contextInfoNames.contains(context)) + << "Context " << context << " repeats in zone config " << zoneConfigName; + contextInfoNames.insert(context); + } + // Configurable audio policy engine can share devices among volume groups + if (deviceConfig.routingConfig == CONFIGURABLE_AUDIO_ENGINE_ROUTING) { + groupDevices.clear(); + } + validateVolumeGroupInfo(audioZoneConfig, volumeGroup, deviceConfig, groupDevices, groupIds); + } + const auto& audioZoneContexts = carAudioZone.audioZoneContext.audioContextInfos; + std::map infoNameToInfo; + std::transform(audioZoneContexts.begin(), audioZoneContexts.end(), + std::inserter(infoNameToInfo, infoNameToInfo.end()), + [&](const AudioZoneContextInfo& context) { + return std::make_pair(ToString(context.name), context); + }); + std::vector configContextInfos; + for (const auto& contextName : contextInfoNames) { + const auto& pair = infoNameToInfo.find(contextName); + if (pair == infoNameToInfo.end()) { + continue; + } + configContextInfos.push_back(pair->second); + } + std::string message; + EXPECT_TRUE(testutils::contextInfosContainAllAudioAttributeUsages(configContextInfos, message)) + << "Config " << zoneConfigName << " message: " << message; + + if (audioZoneConfig.fadeConfiguration.has_value()) { + validateAudioZoneFadeConfiguration(audioZoneConfig.fadeConfiguration.value()); + } +} + +} // namespace + class AudioControlAidl : public testing::TestWithParam { public: virtual void SetUp() override { @@ -292,12 +542,193 @@ TEST_P(AudioControlAidl, RegisterModuleChangeNullCallbackThrowsException) { AnyOf(Eq(Status::EX_ILLEGAL_ARGUMENT), Eq(Status::EX_UNSUPPORTED_OPERATION))); } +class AudioControlVersionFiveAndAbove : public AudioControlAidl { + public: + virtual void SetUp() override { + AudioControlAidl::SetUp(); + if (isAidlVersionAtleast(kAidlVersionFive)) { + return; + } + GTEST_SKIP() << " Version is lower than " << std::to_string(kAidlVersionFive); + } +}; + +class AudioControlWithAudioConfiguration : public AudioControlVersionFiveAndAbove { + public: + virtual void SetUp() override { + AudioControlVersionFiveAndAbove::SetUp(); + + if (IsSkipped()) { + return; + } + + const auto& configStatus = + audioControl->getAudioDeviceConfiguration(&audioDeviceConfiguration); + + EXPECT_THAT(configStatus.exceptionCode(), + AnyOf(Eq(Status::EX_NONE), Eq(Status::EX_UNSUPPORTED_OPERATION))); + if (!configStatus.isOk()) { + GTEST_SKIP() << "Device does not support audio configurations APIs"; + } + ALOGD("Audio device info: %s", audioDeviceConfiguration.toString().c_str()); + } + + AudioDeviceConfiguration audioDeviceConfiguration; +}; + +TEST_P(AudioControlWithAudioConfiguration, DefaultAudioRoutingConfiguration) { + if (audioDeviceConfiguration.routingConfig != DEFAULT_AUDIO_ROUTING) { + GTEST_SKIP() << "Default audio routing not supported"; + } + std::vector zones; + + const auto& zoneStatus = audioControl->getCarAudioZones(&zones); + + EXPECT_THAT(zoneStatus.exceptionCode(), + AnyOf(Eq(Status::EX_NONE), Eq(Status::EX_UNSUPPORTED_OPERATION))) + << "Default routing can be implemented or unsupported"; + if (!zoneStatus.isOk()) return; + EXPECT_TRUE(zones.empty()) << "Zones must be empty for default routing"; +} + +class AudioControlWithDynamicConfiguration : public AudioControlWithAudioConfiguration { + public: + virtual void SetUp() override { + AudioControlWithAudioConfiguration::SetUp(); + if (IsSkipped()) { + return; + } + if (audioDeviceConfiguration.routingConfig == DEFAULT_AUDIO_ROUTING) { + GTEST_SKIP() << "Dynamic/core audio routing not supported"; + } + const auto& zoneStatus = audioControl->getCarAudioZones(&audioZones); + EXPECT_EQ(zoneStatus.exceptionCode(), Status::EX_NONE) + << "Zones API must be supported for core/dynamic routing"; + } + + std::vector audioZones; +}; + +TEST_P(AudioControlWithDynamicConfiguration, DynamicAudioRoutingConfiguration) { + EXPECT_FALSE(audioZones.empty()) << "Zones must not be empty for core/dynamic routing"; +} + +class AudioControlWithAudioZoneInfo : public AudioControlWithDynamicConfiguration { + public: + virtual void SetUp() override { + AudioControlWithDynamicConfiguration::SetUp(); + if (IsSkipped()) { + return; + } + EXPECT_TRUE(!audioZones.empty()) << "Zones must exist for core/dynamic routing"; + } +}; + +TEST_P(AudioControlWithAudioZoneInfo, AudioZonesRequirements) { + bool primaryZoneFound = false; + std::set zoneIds; + std::set occupantIds; + std::set zoneNames; + std::set deviceAddresses; + for (const auto& zone : audioZones) { + if (zone.id == static_cast(AudioHalProductStrategy::ZoneId::DEFAULT)) { + EXPECT_FALSE(primaryZoneFound) << "There can only be one primary zone"; + primaryZoneFound = true; + } + EXPECT_FALSE(zoneIds.contains(zone.id)) << "Zone " << std::to_string(zone.id) << " repeats"; + zoneIds.insert(zone.id); + if (!zone.name.empty()) { + EXPECT_FALSE(zoneNames.contains(zone.name)) << "Zone " << zone.name << " repeats"; + zoneNames.insert(zone.name); + } + if (zone.occupantZoneId != AudioZone::UNASSIGNED_OCCUPANT) { + EXPECT_FALSE(occupantIds.contains(zone.occupantZoneId)) + << "Occupant zone id " << zone.occupantZoneId << " repeats"; + occupantIds.insert(zone.occupantZoneId); + } + const auto& zoneAddresses = testutils::getDeviceAddressesForZone(zone); + for (const auto& address : zoneAddresses) { + EXPECT_FALSE(deviceAddresses.contains(address)) + << "Device address " << address << " in zone " << zone.name << " repeats"; + } + // Add after zone comparison is done since devices may repeat within a zone for different + // configurations + deviceAddresses.insert(zoneAddresses.begin(), zoneAddresses.end()); + } + EXPECT_TRUE(primaryZoneFound) << "Primary zone must exist"; +} + +TEST_P(AudioControlWithAudioZoneInfo, AudioZoneInfoRequirements) { + for (const auto& carAudioZone : audioZones) { + ALOGI("Zone id %d test", carAudioZone.id); + std::string missingContextMessage; + EXPECT_TRUE(testutils::contextContainsAllAudioAttributeUsages(carAudioZone.audioZoneContext, + missingContextMessage)) + << "Audio zone context for zone id " << std::to_string(carAudioZone.id) + << missingContextMessage; + EXPECT_FALSE(carAudioZone.audioZoneConfigs.empty()) + << "Audio zone zone id " << std::to_string(carAudioZone.id) + << " missing zone configs"; + std::set configNames; + bool defaultConfigFound = false; + for (const auto& config : carAudioZone.audioZoneConfigs) { + ALOGI("Zone id %d config name %s test", carAudioZone.id, ToString(config.name).c_str()); + if (config.isDefault) { + EXPECT_FALSE(defaultConfigFound) + << "Config name " << config.name + << " repeats default config value in zone id " << carAudioZone.id; + defaultConfigFound = true; + } + EXPECT_FALSE(configNames.contains(config.name)) + << "Config name " << config.name << " repeats in " << carAudioZone.id; + } + EXPECT_TRUE(defaultConfigFound) + << "Audio zone " << carAudioZone.id << " must contain default config"; + std::set inputPorts; + ALOGI("Zone id %d input devices test", carAudioZone.id); + for (const auto& audioPort : carAudioZone.inputAudioDevices) { + std::string address; + const auto hasAddress = testutils::getAddressForAudioPort(audioPort, address); + EXPECT_FALSE(inputPorts.contains(audioPort)) + << "Repeating input device for " << carAudioZone.id << ", device address " + << (hasAddress ? address : "empty address"); + inputPorts.insert(audioPort); + } + } +} + +TEST_P(AudioControlWithAudioZoneInfo, AudioZoneConfigInfoRequirements) { + for (const auto& carAudioZone : audioZones) { + for (const auto& audioZoneConfig : carAudioZone.audioZoneConfigs) { + validateAudioZoneConfiguration(carAudioZone, audioZoneConfig, audioDeviceConfiguration); + } + } +} + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioControlAidl); INSTANTIATE_TEST_SUITE_P( Audiocontrol, AudioControlAidl, testing::ValuesIn(android::getAidlHalInstanceNames(IAudioControl::descriptor)), android::PrintInstanceNameToString); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioControlWithAudioConfiguration); +INSTANTIATE_TEST_SUITE_P( + Audiocontrol, AudioControlWithAudioConfiguration, + testing::ValuesIn(android::getAidlHalInstanceNames(IAudioControl::descriptor)), + android::PrintInstanceNameToString); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioControlWithDynamicConfiguration); +INSTANTIATE_TEST_SUITE_P( + Audiocontrol, AudioControlWithDynamicConfiguration, + testing::ValuesIn(android::getAidlHalInstanceNames(IAudioControl::descriptor)), + android::PrintInstanceNameToString); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioControlWithAudioZoneInfo); +INSTANTIATE_TEST_SUITE_P( + Audiocontrol, AudioControlWithAudioZoneInfo, + testing::ValuesIn(android::getAidlHalInstanceNames(IAudioControl::descriptor)), + android::PrintInstanceNameToString); + int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); ProcessState::self()->setThreadPoolMaxThreadCount(1); diff --git a/automotive/audiocontrol/aidl/vts/include/AudioControlTestUtils.h b/automotive/audiocontrol/aidl/vts/include/AudioControlTestUtils.h new file mode 100644 index 0000000000000000000000000000000000000000..46fdce21117894308378345e20242c57f08cd193 --- /dev/null +++ b/automotive/audiocontrol/aidl/vts/include/AudioControlTestUtils.h @@ -0,0 +1,67 @@ +/* + * 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. + */ + +#ifndef MAIN8_AUDIOCONTROLTESTUTILS_H +#define MAIN8_AUDIOCONTROLTESTUTILS_H + +#include +#include +#include + +namespace android { +namespace hardware { +namespace audiocontrol { +namespace testutils { + +std::string toAlphaNumeric(const std::string& info); + +bool getAudioPortDeviceDescriptor( + const android::media::audio::common::AudioPort& audioPort, + android::media::audio::common::AudioDeviceDescription& description); + +bool getAddressForAudioPort(const android::media::audio::common::AudioPort& audioPort, + std::string& address); + +bool getAddressForAudioDevice( + const android::hardware::automotive::audiocontrol::DeviceToContextEntry& device, + std::string& address); + +std::vector getDeviceAddressesForVolumeGroup( + const android::hardware::automotive::audiocontrol::VolumeGroupConfig& config); + +std::vector getDeviceAddressesForZoneConfig( + const android::hardware::automotive::audiocontrol::AudioZoneConfig& config); + +std::vector getDeviceAddressesForZone( + const android::hardware::automotive::audiocontrol::AudioZone& config); + +bool contextInfosContainAllAudioAttributeUsages( + const std::vector& infos, + std::string& message); + +bool contextContainsAllAudioAttributeUsages( + const android::hardware::automotive::audiocontrol::AudioZoneContext& context, + std::string& message); + +std::vector getContextInfoNamesForVolumeGroup( + const android::hardware::automotive::audiocontrol::VolumeGroupConfig& group); + +} // namespace testutils +} // namespace audiocontrol +} // namespace hardware +} // namespace android + +#endif // MAIN8_AUDIOCONTROLTESTUTILS_H diff --git a/automotive/audiocontrol/aidl/vts/src/AudioControlTestUtils.cpp b/automotive/audiocontrol/aidl/vts/src/AudioControlTestUtils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7b7c896fc694607ed3fd70edb9a3579d2ae5f8b3 --- /dev/null +++ b/automotive/audiocontrol/aidl/vts/src/AudioControlTestUtils.cpp @@ -0,0 +1,203 @@ +/* + * 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/AudioControlTestUtils.h" + +#include + +using android::hardware::automotive::audiocontrol::AudioZone; +using android::hardware::automotive::audiocontrol::AudioZoneConfig; +using android::hardware::automotive::audiocontrol::AudioZoneContext; +using android::hardware::automotive::audiocontrol::AudioZoneContextInfo; +using android::hardware::automotive::audiocontrol::DeviceToContextEntry; +using android::hardware::automotive::audiocontrol::VolumeGroupConfig; + +namespace audiomediacommon = android::media::audio::common; + +namespace android { +namespace hardware { +namespace audiocontrol { +namespace testutils { + +std::string toAlphaNumeric(const std::string& info) { + std::string name = info; + for (size_t i = 0; i < name.size(); i++) { + // gtest test names must only contain alphanumeric characters + if (!std::isalnum(name[i])) name[i] = '_'; + } + + return name; +} + +bool getAudioPortDeviceDescriptor(const audiomediacommon::AudioPort& audioPort, + audiomediacommon::AudioDeviceDescription& description) { + if (audioPort.ext.getTag() != audiomediacommon::AudioPortExt::Tag::device) { + return false; + } + const auto& audioDevice = + audioPort.ext.get().device; + description = audioDevice.type; + return true; +} + +bool getAddressForAudioPort(const android::media::audio::common::AudioPort& audioPort, + std::string& address) { + if (audioPort.ext.getTag() != audiomediacommon::AudioPortExt::Tag::device) { + return false; + } + const auto& audioDevice = + audioPort.ext.get().device; + + switch (audioDevice.address.getTag()) { + case audiomediacommon::AudioDeviceAddress::Tag::id: + address = audioDevice.address.get(); + return true; + case audiomediacommon::AudioDeviceAddress::Tag::alsa: + address = android::internal::ToString( + audioDevice.address.get()); + return true; + case audiomediacommon::AudioDeviceAddress::Tag::mac: + address = android::internal::ToString( + audioDevice.address.get()); + return true; + case audiomediacommon::AudioDeviceAddress::Tag::ipv4: + address = android::internal::ToString( + audioDevice.address.get()); + return true; + case audiomediacommon::AudioDeviceAddress::Tag::ipv6: + address = android::internal::ToString( + audioDevice.address.get()); + return true; + default: + address = audioDevice.address.toString(); + return true; + } +} + +bool getAddressForAudioDevice(const DeviceToContextEntry& device, std::string& address) { + if (device.device.flags.getTag() == audiomediacommon::AudioIoFlags::input || + device.device.ext.getTag() != audiomediacommon::AudioPortExt::Tag::device) { + return false; + } + return getAddressForAudioPort(device.device, address); +} + +std::vector getDeviceAddressesForVolumeGroup(const VolumeGroupConfig& config) { + std::vector addresses; + for (const auto& route : config.carAudioRoutes) { + std::string address; + if (!getAddressForAudioDevice(route, address)) { + continue; + } + addresses.push_back(address); + } + return addresses; +} + +std::vector getDeviceAddressesForZoneConfig(const AudioZoneConfig& config) { + std::vector addresses; + for (const auto& volumeGroup : config.volumeGroups) { + const auto groupAddresses = getDeviceAddressesForVolumeGroup(volumeGroup); + addresses.insert(addresses.begin(), groupAddresses.begin(), groupAddresses.end()); + } + return addresses; +} + +std::vector getDeviceAddressesForZone(const AudioZone& config) { + std::vector addresses; + for (const auto& zoneConfig : config.audioZoneConfigs) { + const auto groupAddresses = getDeviceAddressesForZoneConfig(zoneConfig); + addresses.insert(addresses.begin(), groupAddresses.begin(), groupAddresses.end()); + } + return addresses; +} + +static void addContextUsages(const AudioZoneContextInfo& info, + std::set& contextUsages) { + for (const auto& audioAttribute : info.audioAttributes) { + contextUsages.insert(audioAttribute.usage); + } +} + +bool contextInfosContainAllAudioAttributeUsages(const std::vector& infos, + std::string& message) { + static const std::vector audioUsages{ + audiomediacommon::AudioUsage::UNKNOWN, + audiomediacommon::AudioUsage::MEDIA, + audiomediacommon::AudioUsage::VOICE_COMMUNICATION, + audiomediacommon::AudioUsage::VOICE_COMMUNICATION_SIGNALLING, + audiomediacommon::AudioUsage::ALARM, + audiomediacommon::AudioUsage::NOTIFICATION, + audiomediacommon::AudioUsage::NOTIFICATION_TELEPHONY_RINGTONE, + audiomediacommon::AudioUsage::NOTIFICATION_EVENT, + audiomediacommon::AudioUsage::ASSISTANCE_ACCESSIBILITY, + audiomediacommon::AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE, + audiomediacommon::AudioUsage::ASSISTANCE_SONIFICATION, + audiomediacommon::AudioUsage::GAME, + audiomediacommon::AudioUsage::ASSISTANT, + audiomediacommon::AudioUsage::CALL_ASSISTANT, + audiomediacommon::AudioUsage::EMERGENCY, + audiomediacommon::AudioUsage::SAFETY, + audiomediacommon::AudioUsage::VEHICLE_STATUS, + audiomediacommon::AudioUsage::ANNOUNCEMENT, + }; + + std::set contextUsages; + for (const auto& contextInfo : infos) { + addContextUsages(contextInfo, contextUsages); + } + + bool allUsagesPresent = true; + for (const auto& usage : audioUsages) { + if (contextUsages.contains(usage)) { + continue; + } + if (message.empty()) { + message = " Missing usage(s): "; + } + message += audiomediacommon::toString(usage) + ", "; + allUsagesPresent = false; + } + return allUsagesPresent; +} + +bool contextContainsAllAudioAttributeUsages(const AudioZoneContext& context, std::string& message) { + return contextInfosContainAllAudioAttributeUsages(context.audioContextInfos, message); +} + +std::vector getContextInfoNamesForAudioRoute(const DeviceToContextEntry& route) { + std::vector contextInfoNames; + contextInfoNames.reserve(route.contextNames.size()); + for (const auto& contextName : route.contextNames) { + contextInfoNames.push_back(android::internal::ToString(contextName)); + } + return contextInfoNames; +} + +std::vector getContextInfoNamesForVolumeGroup(const VolumeGroupConfig& group) { + std::vector contextInfoNames; + for (const auto& route : group.carAudioRoutes) { + std::vector routeContexts = getContextInfoNamesForAudioRoute(route); + contextInfoNames.insert(contextInfoNames.begin(), routeContexts.begin(), + routeContexts.end()); + } + return contextInfoNames; +} + +} // namespace testutils +} // namespace audiocontrol +} // namespace hardware +} // namespace android \ No newline at end of file diff --git a/automotive/can/1.0/default/libnetdevice/Android.bp b/automotive/can/1.0/default/libnetdevice/Android.bp index b42893edfbf73b2cf8acba74032af8c59afdb5a5..4131a658e4437f38b12118b96d64dc85b781792c 100644 --- a/automotive/can/1.0/default/libnetdevice/Android.bp +++ b/automotive/can/1.0/default/libnetdevice/Android.bp @@ -25,6 +25,7 @@ package { cc_defaults { name: "libnetdevice-common", + host_supported: true, vendor_available: true, cflags: [ "-Wall", diff --git a/automotive/can/1.0/default/libnetdevice/can.cpp b/automotive/can/1.0/default/libnetdevice/can.cpp index 2a0545ac8fd26746ca728df1a9ac2e370fc8cda8..9cf0253ee2e3d228af8efad6dba33e427fc9c891 100644 --- a/automotive/can/1.0/default/libnetdevice/can.cpp +++ b/automotive/can/1.0/default/libnetdevice/can.cpp @@ -33,7 +33,7 @@ namespace android::netdevice::can { static constexpr can_err_mask_t kErrMask = CAN_ERR_MASK; -base::unique_fd socket(const std::string& ifname) { +base::unique_fd socket(std::string_view ifname) { sockaddr_can addr = {}; addr.can_family = AF_CAN; addr.can_ifindex = nametoindex(ifname); @@ -66,11 +66,11 @@ base::unique_fd socket(const std::string& ifname) { return sock; } -bool setBitrate(std::string ifname, uint32_t bitrate) { +bool setBitrate(std::string_view ifname, uint32_t bitrate) { can_bittiming bt = {}; bt.bitrate = bitrate; - nl::MessageFactory req(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_ACK); + nl::MessageFactory req(RTM_NEWLINK); req->ifi_index = nametoindex(ifname); if (req->ifi_index == 0) { diff --git a/automotive/can/1.0/default/libnetdevice/common.cpp b/automotive/can/1.0/default/libnetdevice/common.cpp index 28e50af60ab504819e5be3e30c0137304b0332e5..22add6574648bf6df996d813c51a05da5c630f9e 100644 --- a/automotive/can/1.0/default/libnetdevice/common.cpp +++ b/automotive/can/1.0/default/libnetdevice/common.cpp @@ -22,8 +22,8 @@ namespace android::netdevice { -unsigned int nametoindex(const std::string& ifname) { - const auto ifidx = if_nametoindex(ifname.c_str()); +unsigned int nametoindex(std::string_view ifname) { + const auto ifidx = if_nametoindex(std::string(ifname).c_str()); if (ifidx != 0) return ifidx; if (errno != ENODEV) { diff --git a/automotive/can/1.0/default/libnetdevice/common.h b/automotive/can/1.0/default/libnetdevice/common.h index 661e3f80f2d33aac9e188c9e320d861f1990e9b5..e73c5811567e489055ebd1383dd5165b54087be5 100644 --- a/automotive/can/1.0/default/libnetdevice/common.h +++ b/automotive/can/1.0/default/libnetdevice/common.h @@ -32,6 +32,6 @@ namespace android::netdevice { * \param ifname Interface to check * \return Interface index, or 0 if the interface doesn't exist */ -unsigned int nametoindex(const std::string& ifname); +unsigned int nametoindex(std::string_view ifname); } // namespace android::netdevice diff --git a/automotive/can/1.0/default/libnetdevice/ethtool.cpp b/automotive/can/1.0/default/libnetdevice/ethtool.cpp index 762ef5cc884f09867134ce3055175da136bf41a4..b0f88c7779e8406d42d3168d7eab31eb439faa05 100644 --- a/automotive/can/1.0/default/libnetdevice/ethtool.cpp +++ b/automotive/can/1.0/default/libnetdevice/ethtool.cpp @@ -19,27 +19,28 @@ #include "ifreqs.h" #include +#include namespace android::netdevice::ethtool { -std::optional getValue(const std::string& ifname, uint32_t command) { +std::optional getValue(std::string_view ifname, uint32_t command) { struct ethtool_value valueop = {}; valueop.cmd = command; auto ifr = ifreqs::fromName(ifname); - ifr.ifr_data = &valueop; + ifr.ifr_data = reinterpret_cast(&valueop); if (!ifreqs::send(SIOCETHTOOL, ifr)) return std::nullopt; return valueop.data; } -bool setValue(const std::string& ifname, uint32_t command, uint32_t value) { +bool setValue(std::string_view ifname, uint32_t command, uint32_t value) { struct ethtool_value valueop = {}; valueop.cmd = command; valueop.data = value; auto ifr = ifreqs::fromName(ifname); - ifr.ifr_data = &valueop; + ifr.ifr_data = reinterpret_cast(&valueop); return ifreqs::send(SIOCETHTOOL, ifr); } diff --git a/automotive/can/1.0/default/libnetdevice/ifreqs.cpp b/automotive/can/1.0/default/libnetdevice/ifreqs.cpp index 8471173d245c0b78db2f4f8cd474c2ce7bbd8f72..2e6ad41684283b41fc9945f950c7cf1c41b3824a 100644 --- a/automotive/can/1.0/default/libnetdevice/ifreqs.cpp +++ b/automotive/can/1.0/default/libnetdevice/ifreqs.cpp @@ -21,6 +21,8 @@ #include #include +#include + #include namespace android::netdevice::ifreqs { @@ -68,9 +70,11 @@ bool send(unsigned long request, struct ifreq& ifr) { return true; } -struct ifreq fromName(const std::string& ifname) { +struct ifreq fromName(std::string_view ifname) { struct ifreq ifr = {}; - strlcpy(ifr.ifr_name, ifname.c_str(), IF_NAMESIZE); + // memcpy: last \0 initialized with ifreq above + memcpy(ifr.ifr_name, ifname.data(), + std::min(ifname.size(), static_cast(IF_NAMESIZE - 1))); return ifr; } diff --git a/automotive/can/1.0/default/libnetdevice/ifreqs.h b/automotive/can/1.0/default/libnetdevice/ifreqs.h index aa7030bccd2039eba3b22d48ea206590421129a1..f9d8d3b71ed26e924d78841d4929215ebc3fbffa 100644 --- a/automotive/can/1.0/default/libnetdevice/ifreqs.h +++ b/automotive/can/1.0/default/libnetdevice/ifreqs.h @@ -52,6 +52,6 @@ bool send(unsigned long request, struct ifreq& ifr); * \param ifname Interface to initialize request with * \return Interface request with ifr_name field set to ifname */ -struct ifreq fromName(const std::string& ifname); +struct ifreq fromName(std::string_view ifname); } // namespace android::netdevice::ifreqs diff --git a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/can.h b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/can.h index 3886acf1cdede2c8fdf7b1411cbb04776fd93d41..604573309811a6d6567d7a487d847b05de7e573e 100644 --- a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/can.h +++ b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/can.h @@ -28,7 +28,7 @@ namespace android::netdevice::can { * \param ifname Interface to open a socket against * \return Socket's FD or -1 in case of failure */ -base::unique_fd socket(const std::string& ifname); +base::unique_fd socket(std::string_view ifname); /** * Sets CAN interface bitrate. @@ -36,6 +36,6 @@ base::unique_fd socket(const std::string& ifname); * \param ifname Interface for which the bitrate is to be set * \return true on success, false on failure */ -bool setBitrate(std::string ifname, uint32_t bitrate); +bool setBitrate(std::string_view ifname, uint32_t bitrate); } // namespace android::netdevice::can diff --git a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/ethtool.h b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/ethtool.h index 26bfdce00caf1e619897cee73d89a7f63a979e73..416108f026bb348549cdf98ac22e9b9354fa0b34 100644 --- a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/ethtool.h +++ b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/ethtool.h @@ -29,7 +29,7 @@ namespace android::netdevice::ethtool { * \param command Fetch command (ETHTOOL_G*) * \return value, or nullopt if fetch failed */ -std::optional getValue(const std::string& ifname, uint32_t command); +std::optional getValue(std::string_view ifname, uint32_t command); /** * Set a single value with ethtool_value. @@ -40,6 +40,6 @@ std::optional getValue(const std::string& ifname, uint32_t command); * \param value New value * \return true if succeeded, false otherwise */ -bool setValue(const std::string& ifname, uint32_t command, uint32_t value); +bool setValue(std::string_view ifname, uint32_t command, uint32_t value); } // namespace android::netdevice::ethtool diff --git a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/libnetdevice.h b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/libnetdevice.h index 657f9b2cc6243daaab535e681c8c1a464aee2d1d..15ff491dd952e658a5567fcfba0d479f36ceecd0 100644 --- a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/libnetdevice.h +++ b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/libnetdevice.h @@ -43,7 +43,7 @@ void useSocketDomain(int domain); * \param ifname Interface to check * \return true if it exists, false otherwise */ -bool exists(std::string ifname); +bool exists(std::string_view ifname); /** * Checks if network interface is up. @@ -51,7 +51,7 @@ bool exists(std::string ifname); * \param ifname Interface to check * \return true/false if the check succeeded, nullopt otherwise */ -std::optional isUp(std::string ifname); +std::optional isUp(std::string_view ifname); /** * Interface condition to wait for. @@ -101,7 +101,7 @@ std::optional waitFor(std::set ifnames, WaitCondition * \param ifname Interface to bring up * \return true in case of success, false otherwise */ -bool up(std::string ifname); +bool up(std::string_view ifname); /** * Brings network interface down. @@ -109,7 +109,39 @@ bool up(std::string ifname); * \param ifname Interface to bring down * \return true in case of success, false otherwise */ -bool down(std::string ifname); +bool down(std::string_view ifname); + +/** + * Retrieves all IPv4 addresses of a given interface. + * + * \param ifname Interface to query + * \return list of IPv4 addresses of this interface + */ +std::set getAllAddr4(std::string_view ifname); + +/** + * Set IPv4 address on a given interface. + * + * This function will overwrite any other existing IPv4 addresses. + * + * \param ifname Interface to modify + * \param addr IPv4 address to set + * \return true in case of success, false otherwise + */ +bool setAddr4(std::string_view ifname, std::string_view addr, + std::optional prefixlen = std::nullopt); + +/** + * Add new IPv4 address to a given interface. + * + * Please note this doesn't remove existing IPv4 addresses. + * + * \param ifname Interface to modify + * \param addr IPv4 address to add + * \param prefixlen IPv4 netmask length + * \return true in case of success, false otherwise + */ +bool addAddr4(std::string_view ifname, std::string_view addr, uint8_t prefixlen = 24); /** * Adds virtual link. @@ -118,7 +150,7 @@ bool down(std::string ifname); * \param type the type of the new device * \return true in case of success, false otherwise */ -bool add(std::string dev, std::string type); +bool add(std::string_view dev, std::string_view type); /** * Deletes virtual link. @@ -126,7 +158,7 @@ bool add(std::string dev, std::string type); * \param dev the name of the device to remove * \return true in case of success, false otherwise */ -bool del(std::string dev); +bool del(std::string_view dev); /** * Fetches interface's hardware address. @@ -134,7 +166,7 @@ bool del(std::string dev); * \param ifname Interface name * \return Hardware address (MAC address) or nullopt if the lookup failed */ -std::optional getHwAddr(const std::string& ifname); +std::optional getHwAddr(std::string_view ifname); /** * Changes interface's hardware address. @@ -142,7 +174,7 @@ std::optional getHwAddr(const std::string& ifname); * \param ifname Interface name * \param hwaddr New hardware address to set */ -bool setHwAddr(const std::string& ifname, hwaddr_t hwaddr); +bool setHwAddr(std::string_view ifname, hwaddr_t hwaddr); } // namespace android::netdevice diff --git a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/vlan.h b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/vlan.h index 3e1b736ebd2c1e9f9a6143e36f7e44de9b2db033..884b704c68748a6de20b50e083cd362efe4f203c 100644 --- a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/vlan.h +++ b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/vlan.h @@ -20,6 +20,6 @@ namespace android::netdevice::vlan { -bool add(const std::string& eth, const std::string& vlan, uint16_t id); +bool add(std::string_view eth, std::string_view vlan, uint16_t id); } // namespace android::netdevice::vlan diff --git a/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp b/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp index 413b4b1c54ada7f66f7227931468ad7f7f2a8698..9bb1a571eb4e7ebca2d03603e6ebbeebcf4eadd9 100644 --- a/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp +++ b/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp @@ -23,9 +23,13 @@ #include #include +#include +#include #include #include #include +#include +#include #include #include @@ -37,27 +41,102 @@ void useSocketDomain(int domain) { ifreqs::socketDomain = domain; } -bool exists(std::string ifname) { +bool exists(std::string_view ifname) { return nametoindex(ifname) != 0; } -bool up(std::string ifname) { +bool up(std::string_view ifname) { auto ifr = ifreqs::fromName(ifname); if (!ifreqs::send(SIOCGIFFLAGS, ifr)) return false; + if (ifr.ifr_flags & IFF_UP) return true; ifr.ifr_flags |= IFF_UP; return ifreqs::send(SIOCSIFFLAGS, ifr); } -bool down(std::string ifname) { +bool down(std::string_view ifname) { auto ifr = ifreqs::fromName(ifname); if (!ifreqs::send(SIOCGIFFLAGS, ifr)) return false; + if (!(ifr.ifr_flags & IFF_UP)) return true; ifr.ifr_flags &= ~IFF_UP; return ifreqs::send(SIOCSIFFLAGS, ifr); } -bool add(std::string dev, std::string type) { - nl::MessageFactory req(RTM_NEWLINK, - NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK); +static std::string toString(const sockaddr* addr) { + char host[NI_MAXHOST]; + socklen_t addrlen = (addr->sa_family == AF_INET) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6); + auto res = getnameinfo(addr, addrlen, host, sizeof(host), nullptr, 0, NI_NUMERICHOST); + CHECK(res == 0) << "getnameinfo failed: " << gai_strerror(res); + return host; +} + +static std::unique_ptr getifaddrs() { + ifaddrs* addrs = nullptr; + CHECK(getifaddrs(&addrs) == 0) << "getifaddrs failed: " << strerror(errno); + return {addrs, freeifaddrs}; +} + +std::set getAllAddr4(std::string_view ifname) { + std::set addresses; + auto addrs = getifaddrs(); + for (ifaddrs* addr = addrs.get(); addr != nullptr; addr = addr->ifa_next) { + if (ifname != addr->ifa_name) continue; + if (addr->ifa_addr == nullptr) continue; + if (addr->ifa_addr->sa_family != AF_INET) continue; + addresses.insert(toString(addr->ifa_addr)); + } + return addresses; +} + +static in_addr_t inetAddr(std::string_view addr) { + auto addrn = inet_addr(std::string(addr).c_str()); + CHECK(addrn != INADDR_NONE) << "Invalid address " << addr; + return addrn; +} + +static in_addr_t prefixLengthToIpv4Netmask(uint8_t prefixlen) { + in_addr_t zero = 0; + return htonl(~zero << (32 - prefixlen)); +} + +bool setAddr4(std::string_view ifname, std::string_view addr, std::optional prefixlen) { + auto ifr = ifreqs::fromName(ifname); + auto ifrAddr = reinterpret_cast(&ifr.ifr_addr); + ifrAddr->sin_family = AF_INET; + ifrAddr->sin_addr.s_addr = inetAddr(addr); + if (!ifreqs::send(SIOCSIFADDR, ifr)) return false; + + if (prefixlen.has_value()) { + if (*prefixlen < 0 || *prefixlen > 32) { + LOG(ERROR) << "Invalid prefix length: " << *prefixlen; + return false; + } + ifr = ifreqs::fromName(ifname); + auto ifrNetmask = reinterpret_cast(&ifr.ifr_netmask); + ifrNetmask->sin_family = AF_INET; + ifrNetmask->sin_addr.s_addr = prefixLengthToIpv4Netmask(*prefixlen); + if (!ifreqs::send(SIOCSIFNETMASK, ifr)) return false; + } + + return true; +} + +bool addAddr4(std::string_view ifname, std::string_view addr, uint8_t prefixlen) { + nl::MessageFactory req(RTM_NEWADDR, nl::kCreateFlags); + req->ifa_family = AF_INET; + req->ifa_prefixlen = prefixlen; + req->ifa_flags = IFA_F_SECONDARY; + req->ifa_index = nametoindex(ifname); + + auto addrn = inetAddr(addr); + req.add(IFLA_ADDRESS, addrn); + req.add(IFLA_BROADCAST, addrn); + + nl::Socket sock(NETLINK_ROUTE); + return sock.send(req) && sock.receiveAck(req); +} + +bool add(std::string_view dev, std::string_view type) { + nl::MessageFactory req(RTM_NEWLINK, nl::kCreateFlags); req.add(IFLA_IFNAME, dev); { @@ -69,15 +148,15 @@ bool add(std::string dev, std::string type) { return sock.send(req) && sock.receiveAck(req); } -bool del(std::string dev) { - nl::MessageFactory req(RTM_DELLINK, NLM_F_REQUEST | NLM_F_ACK); +bool del(std::string_view dev) { + nl::MessageFactory req(RTM_DELLINK); req.add(IFLA_IFNAME, dev); nl::Socket sock(NETLINK_ROUTE); return sock.send(req) && sock.receiveAck(req); } -std::optional getHwAddr(const std::string& ifname) { +std::optional getHwAddr(std::string_view ifname) { auto ifr = ifreqs::fromName(ifname); if (!ifreqs::send(SIOCGIFHWADDR, ifr)) return std::nullopt; @@ -86,7 +165,7 @@ std::optional getHwAddr(const std::string& ifname) { return hwaddr; } -bool setHwAddr(const std::string& ifname, hwaddr_t hwaddr) { +bool setHwAddr(std::string_view ifname, hwaddr_t hwaddr) { auto ifr = ifreqs::fromName(ifname); // fetch sa_family @@ -96,13 +175,13 @@ bool setHwAddr(const std::string& ifname, hwaddr_t hwaddr) { return ifreqs::send(SIOCSIFHWADDR, ifr); } -std::optional isUp(std::string ifname) { +std::optional isUp(std::string_view ifname) { auto ifr = ifreqs::fromName(ifname); if (!ifreqs::send(SIOCGIFFLAGS, ifr)) return std::nullopt; return ifr.ifr_flags & IFF_UP; } -static bool hasIpv4(std::string ifname) { +static bool hasIpv4(std::string_view ifname) { auto ifr = ifreqs::fromName(ifname); switch (ifreqs::trySend(SIOCGIFADDR, ifr)) { case 0: diff --git a/automotive/can/1.0/default/libnetdevice/vlan.cpp b/automotive/can/1.0/default/libnetdevice/vlan.cpp index 35b21b83467d71aa9e8a9df68cea7ecb27b2765f..e5b5a61e1d6624e0fd6b6ee0d1b7c51d441839de 100644 --- a/automotive/can/1.0/default/libnetdevice/vlan.cpp +++ b/automotive/can/1.0/default/libnetdevice/vlan.cpp @@ -26,15 +26,14 @@ namespace android::netdevice::vlan { -bool add(const std::string& eth, const std::string& vlan, uint16_t id) { +bool add(std::string_view eth, std::string_view vlan, uint16_t id) { const auto ethidx = nametoindex(eth); if (ethidx == 0) { LOG(ERROR) << "Ethernet interface " << eth << " doesn't exist"; return false; } - nl::MessageFactory req(RTM_NEWLINK, - NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK); + nl::MessageFactory req(RTM_NEWLINK, nl::kCreateFlags); req.add(IFLA_IFNAME, vlan); req.add(IFLA_LINK, ethidx); diff --git a/automotive/can/1.0/default/libnl++/Android.bp b/automotive/can/1.0/default/libnl++/Android.bp index d929d846d03943e09f4bc8ab8b11fadab58b5dba..ade4ae09ca7e4b9a809f5ba75061ac22b4fc8583 100644 --- a/automotive/can/1.0/default/libnl++/Android.bp +++ b/automotive/can/1.0/default/libnl++/Android.bp @@ -25,6 +25,7 @@ package { cc_library_static { name: "libnl++", + host_supported: true, vendor_available: true, cflags: [ "-Wall", diff --git a/automotive/can/1.0/default/libnl++/Socket.cpp b/automotive/can/1.0/default/libnl++/Socket.cpp index 221063d344ec31d46ccc1270ea68f6607fd0ac1d..a5a782c1b7f07d6a3e888557fda416f132d95bec 100644 --- a/automotive/can/1.0/default/libnl++/Socket.cpp +++ b/automotive/can/1.0/default/libnl++/Socket.cpp @@ -20,6 +20,9 @@ #include +// Should be in sys/socket.h or linux/socket.h +#define SOL_NETLINK 270 + namespace android::nl { /** diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/MessageFactory.h b/automotive/can/1.0/default/libnl++/include/libnl++/MessageFactory.h index a5a425e0b2165f24b9e30f3454571912fbbc1369..f65f055d3d0a3393de89825b215b782582d25c91 100644 --- a/automotive/can/1.0/default/libnl++/include/libnl++/MessageFactory.h +++ b/automotive/can/1.0/default/libnl++/include/libnl++/MessageFactory.h @@ -26,6 +26,9 @@ namespace android::nl { +static constexpr uint16_t kDefaultFlags = NLM_F_REQUEST | NLM_F_ACK; +static constexpr uint16_t kCreateFlags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK; + class MessageFactoryBase { protected: static nlattr* add(nlmsghdr* msg, size_t maxLen, nlattrtype_t type, const void* data, @@ -54,7 +57,7 @@ class MessageFactory : private MessageFactoryBase { * \param type Message type (such as RTM_NEWLINK). * \param flags Message flags (such as NLM_F_REQUEST). */ - MessageFactory(nlmsgtype_t type, uint16_t flags) + MessageFactory(nlmsgtype_t type, uint16_t flags = kDefaultFlags) : header(mMessage.header), data(mMessage.data) { mMessage.header.nlmsg_len = offsetof(Message, attributesBuffer); mMessage.header.nlmsg_type = type; diff --git a/automotive/can/1.0/default/libnl++/printer.cpp b/automotive/can/1.0/default/libnl++/printer.cpp index d5404825b8aa022fa7c0811e59d3bc2b693a6b10..8c7c4764144be1902ef5c74e0dd3814ad2001bf2 100644 --- a/automotive/can/1.0/default/libnl++/printer.cpp +++ b/automotive/can/1.0/default/libnl++/printer.cpp @@ -26,6 +26,12 @@ #include #include +// should be in linux/netlink.h +#define NLM_F_DUMP_FILTERED 0x20 +#define NLM_F_NONREC 0x100 +#define NLM_F_CAPPED 0x100 +#define NLM_F_ACK_TLVS 0x200 + namespace android::nl { static void flagsToStream(std::stringstream& ss, __u16 nlmsg_flags, protocols::MessageGenre genre) { diff --git a/automotive/can/1.0/default/libnl++/protocols/common/Error.cpp b/automotive/can/1.0/default/libnl++/protocols/common/Error.cpp index 77451edbeb8d44a9fafff6d47e2b32e7e637a025..277f19d36dc60192659c6a85c68b20d0a4c5162e 100644 --- a/automotive/can/1.0/default/libnl++/protocols/common/Error.cpp +++ b/automotive/can/1.0/default/libnl++/protocols/common/Error.cpp @@ -22,6 +22,17 @@ #include +#include +#ifndef _UAPI__LINUX_NETLINK_H +// linux_glibc (host) includes source headers instead of uapi headers +enum nlmsgerr_attrs { + NLMSGERR_ATTR_UNUSED, + NLMSGERR_ATTR_MSG, + NLMSGERR_ATTR_OFFS, + NLMSGERR_ATTR_COOKIE, +}; +#endif + namespace android::nl::protocols::base { using DataType = AttributeDefinition::DataType; diff --git a/automotive/can/1.0/default/libnl++/protocols/generic/FamilyTracker.cpp b/automotive/can/1.0/default/libnl++/protocols/generic/FamilyTracker.cpp index 3ad101e19d2ce51206668b52f9b249fcf6421da6..eebd1f164f2c9f30b0859fabb57fb51318efb8d5 100644 --- a/automotive/can/1.0/default/libnl++/protocols/generic/FamilyTracker.cpp +++ b/automotive/can/1.0/default/libnl++/protocols/generic/FamilyTracker.cpp @@ -18,6 +18,9 @@ #include +// should be in linux/genetlink.h +#define GENL_START_ALLOC (NLMSG_MIN_TYPE + 3) + namespace android::nl::generic { bool FamilyTracker::track(const Buffer& buffer) { diff --git a/automotive/can/1.0/default/libnl++/protocols/route/Addr.cpp b/automotive/can/1.0/default/libnl++/protocols/route/Addr.cpp index 024d3891b657e220d40f4a74a3b45a260eed7fe4..5bd6262f71e974ac4cc39e20496b1b3c9821da07 100644 --- a/automotive/can/1.0/default/libnl++/protocols/route/Addr.cpp +++ b/automotive/can/1.0/default/libnl++/protocols/route/Addr.cpp @@ -20,6 +20,12 @@ #include "attributes.h" #include "structs.h" +// should be in linux/if_addr.h +#define IFA_F_MANAGETEMPADDR 0x100 +#define IFA_F_NOPREFIXROUTE 0x200 +#define IFA_F_MCAUTOJOIN 0x400 +#define IFA_F_STABLE_PRIVACY 0x800 + namespace android::nl::protocols::route { using DataType = AttributeDefinition::DataType; diff --git a/automotive/can/1.0/default/libnl++/protocols/route/attributes.cpp b/automotive/can/1.0/default/libnl++/protocols/route/attributes.cpp index 69d9b811a9681aea4569de0555fb093443409954..c81ee2791965698eeaf6833dc2181468210c42ae 100644 --- a/automotive/can/1.0/default/libnl++/protocols/route/attributes.cpp +++ b/automotive/can/1.0/default/libnl++/protocols/route/attributes.cpp @@ -22,6 +22,54 @@ #include #include +#include +#ifndef _UAPI_LINUX_IF_LINK_H +enum { + IFLA_INFO_SLAVE_KIND = IFLA_INFO_XSTATS + 1, + IFLA_INFO_SLAVE_DATA, +}; +enum { + IFLA_INET6_TOKEN = IFLA_INET6_ICMP6STATS + 1, + IFLA_INET6_ADDR_GEN_MODE, + IFLA_INET6_RA_MTU, +}; +enum { + IFLA_CARRIER = IFLA_NUM_RX_QUEUES + 1, + IFLA_PHYS_PORT_ID, + IFLA_CARRIER_CHANGES, + IFLA_PHYS_SWITCH_ID, + IFLA_LINK_NETNSID, + IFLA_PHYS_PORT_NAME, + IFLA_PROTO_DOWN, + IFLA_GSO_MAX_SEGS, + IFLA_GSO_MAX_SIZE, + IFLA_PAD, + IFLA_XDP, + IFLA_EVENT, + IFLA_NEW_NETNSID, + IFLA_TARGET_NETNSID, + IFLA_CARRIER_UP_COUNT, + IFLA_CARRIER_DOWN_COUNT, + IFLA_NEW_IFINDEX, + IFLA_MIN_MTU, + IFLA_MAX_MTU, + IFLA_PROP_LIST, + IFLA_ALT_IFNAME, + IFLA_PERM_ADDRESS, + IFLA_PROTO_DOWN_REASON, + IFLA_PARENT_DEV_NAME, + IFLA_PARENT_DEV_BUS_NAME, + IFLA_GRO_MAX_SIZE, + IFLA_TSO_MAX_SIZE, + IFLA_TSO_MAX_SEGS, + IFLA_ALLMULTI, + IFLA_DEVLINK_PORT, + IFLA_GSO_IPV4_MAX_SIZE, + IFLA_GRO_IPV4_MAX_SIZE, + IFLA_DPLL_PIN, +}; +#endif + namespace android::nl::protocols::route { using DataType = AttributeDefinition::DataType; diff --git a/automotive/can/1.0/default/libnl++/protocols/route/structs.h b/automotive/can/1.0/default/libnl++/protocols/route/structs.h index c969a6c8cb4e3f38bdf79f33ba7333fe98061dcf..410c42e90716c435b8088e4073ed85e689fef580 100644 --- a/automotive/can/1.0/default/libnl++/protocols/route/structs.h +++ b/automotive/can/1.0/default/libnl++/protocols/route/structs.h @@ -64,8 +64,8 @@ void statsToStream(std::stringstream& ss, const Buffer attr) { << data.tx_heartbeat_errors << ',' // << data.tx_window_errors << ',' // << data.rx_compressed << ',' // - << data.tx_compressed << ',' // - << data.rx_nohandler << '}'; + << data.tx_compressed << '}'; + // Not printed (due to portability): rx_nohandler, rx_otherhost_dropped } } // namespace android::nl::protocols::route diff --git a/automotive/evs/aidl/impl/default/include/ConfigManager.h b/automotive/evs/aidl/impl/default/include/ConfigManager.h index 37a17dc230e1100232720bd4a0c4fb59ef485fef..f6ba2f2a00757feecd52d1cc0405a7129df408dc 100644 --- a/automotive/evs/aidl/impl/default/include/ConfigManager.h +++ b/automotive/evs/aidl/impl/default/include/ConfigManager.h @@ -50,6 +50,7 @@ typedef struct { class ConfigManager final { public: static std::unique_ptr Create(); + static std::unique_ptr Create(const std::string path); ConfigManager(const ConfigManager&) = delete; ConfigManager& operator=(const ConfigManager&) = delete; @@ -65,6 +66,15 @@ class ConfigManager final { UNKNOWN = std::numeric_limits>::max(), }; + enum class PixelFormat : std::int32_t { + NV12 = 0, + NV21 = 1, + YV12 = 2, + I420 = 3, + + UNKNOWN = std::numeric_limits>::max(), + }; + CameraInfo() : characteristics(nullptr) {} virtual ~CameraInfo(); @@ -82,6 +92,8 @@ class ConfigManager final { static DeviceType deviceTypeFromSV(const std::string_view sv); + static PixelFormat pixelFormatFromSV(const std::string_view sv); + DeviceType deviceType{DeviceType::NONE}; /* @@ -105,6 +117,11 @@ class ConfigManager final { /* Camera module characteristics */ camera_metadata_t* characteristics; + + /* Format of media in a given media container. This field is effective + * only for DeviceType::VIDEO. + */ + PixelFormat format; }; class CameraGroupInfo : public CameraInfo { @@ -272,7 +289,7 @@ class ConfigManager final { * @return bool * True if it completes parsing a file successfully. */ - bool readConfigDataFromXML() noexcept; + bool readConfigDataFromXML(const std::string path) noexcept; /* * read the information of the vehicle diff --git a/automotive/evs/aidl/impl/default/include/EvsCameraBase.h b/automotive/evs/aidl/impl/default/include/EvsCameraBase.h index c3e9dfc47d7f55e5d46f2881d1bd8eba52a8ebb4..d9180e85d4ae26c7fe51b9ac325b783727f416a8 100644 --- a/automotive/evs/aidl/impl/default/include/EvsCameraBase.h +++ b/automotive/evs/aidl/impl/default/include/EvsCameraBase.h @@ -30,6 +30,7 @@ class EvsCameraBase : public evs::BnEvsCamera { ~EvsCameraBase() override = default; + virtual std::string getId() = 0; virtual void shutdown() = 0; protected: diff --git a/automotive/evs/aidl/impl/default/include/EvsMockCamera.h b/automotive/evs/aidl/impl/default/include/EvsMockCamera.h index cd685324be33b59b7f386bdd823cbb504408a91c..67de8dce8000f0fba9edebee3dc0f97302a869e7 100644 --- a/automotive/evs/aidl/impl/default/include/EvsMockCamera.h +++ b/automotive/evs/aidl/impl/default/include/EvsMockCamera.h @@ -65,7 +65,9 @@ class EvsMockCamera : public EvsCamera { ndk::ScopedAStatus setPrimaryClient() override; ndk::ScopedAStatus unsetPrimaryClient() override; - const evs::CameraDesc& getDesc() { return mDescription; } + std::string getId() override { return mDescription.id; } + + const CameraDesc& getDesc() { return mDescription; } static std::shared_ptr Create(const char* deviceName); static std::shared_ptr Create( diff --git a/automotive/evs/aidl/impl/default/include/EvsVideoEmulatedCamera.h b/automotive/evs/aidl/impl/default/include/EvsVideoEmulatedCamera.h index 9d1610a928d66bdf519ff64f7c92799e69a93e06..dc70a43da335221b64e50129791ac48e6b2aa5f3 100644 --- a/automotive/evs/aidl/impl/default/include/EvsVideoEmulatedCamera.h +++ b/automotive/evs/aidl/impl/default/include/EvsVideoEmulatedCamera.h @@ -27,7 +27,6 @@ #include #include #include - #include #include @@ -70,6 +69,8 @@ class EvsVideoEmulatedCamera : public EvsCamera { // Methods from EvsCameraBase follow. void shutdown() override; + std::string getId() override { return mDescription.id; } + const evs::CameraDesc& getDesc() { return mDescription; } static std::shared_ptr Create(const char* deviceName); @@ -117,6 +118,10 @@ class EvsVideoEmulatedCamera : public EvsCamera { bool postVideoStreamStop_locked(ndk::ScopedAStatus& status, std::unique_lock& lck) override; + int (*mFillBuffer)(const uint8_t* src_y, int src_stride_y, const uint8_t* src_u, + int src_stride_u, const uint8_t* src_v, int src_stride_v, uint8_t* dst_argb, + int dst_stride_argb, int width, int height); + // The properties of this camera. CameraDesc mDescription = {}; @@ -149,6 +154,10 @@ class EvsVideoEmulatedCamera : public EvsCamera { uint64_t mUsage = 0; // Bytes per line in the buffers uint32_t mStride = 0; + // Bytes per line in the output buffer + uint32_t mDstStride = 0; + // Bytes per line of U/V plane + uint32_t mUvStride = 0; // Camera parameters. std::unordered_map> mParams; diff --git a/automotive/evs/aidl/impl/default/src/ConfigManager.cpp b/automotive/evs/aidl/impl/default/src/ConfigManager.cpp index d8961d02413cb82d98123adc065c8ec4de1ad1ee..eea80f4d9234458424c3f8f793e4d9c7af9c4913 100644 --- a/automotive/evs/aidl/impl/default/src/ConfigManager.cpp +++ b/automotive/evs/aidl/impl/default/src/ConfigManager.cpp @@ -52,6 +52,25 @@ ConfigManager::CameraInfo::DeviceType ConfigManager::CameraInfo::deviceTypeFromS return search == nameToType.end() ? DeviceType::UNKNOWN : search->second; } +ConfigManager::CameraInfo::PixelFormat ConfigManager::CameraInfo::pixelFormatFromSV( + const std::string_view sv) { + using namespace std::string_view_literals; + static const std::unordered_map nameToFormat = { + // Full resolution Y plane followed by 2x2 subsampled U/V + // interleaved plane. + {"NV12"sv, PixelFormat::NV12}, + // Full resolution Y plane followed by 2x2 subsampled V/U + // interleaved plane. + {"NV21"sv, PixelFormat::NV21}, + // Full resolution Y plane followed by 2x2 subsampled V plane and then U plane. + {"YV12"sv, PixelFormat::YV12}, + // Full resolution Y plane followed by 2x2 subsampled U plane and then V plane. + {"I420"sv, PixelFormat::I420}, + }; + const auto search = nameToFormat.find(sv); + return search == nameToFormat.end() ? PixelFormat::UNKNOWN : search->second; +} + void ConfigManager::printElementNames(const XMLElement* rootElem, const std::string& prefix) const { const XMLElement* curElem = rootElem; @@ -144,6 +163,10 @@ bool ConfigManager::readCameraDeviceInfo(CameraInfo* aCamera, const XMLElement* aCamera->deviceType = CameraInfo::deviceTypeFromSV(typeAttr->Value()); } + if (const auto formatAttr = aDeviceElem->FindAttribute("format")) { + aCamera->format = CameraInfo::pixelFormatFromSV(formatAttr->Value()); + } + /* size information to allocate camera_metadata_t */ size_t totalEntries = 0; size_t totalDataSize = 0; @@ -474,19 +497,16 @@ void ConfigManager::readDisplayInfo(const XMLElement* const aDisplayElem) { return; } -bool ConfigManager::readConfigDataFromXML() noexcept { +bool ConfigManager::readConfigDataFromXML(const std::string path) noexcept { XMLDocument xmlDoc; const int64_t parsingStart = android::elapsedRealtimeNano(); /* load and parse a configuration file */ - xmlDoc.LoadFile(sConfigOverridePath.data()); + xmlDoc.LoadFile(path.c_str()); if (xmlDoc.ErrorID() != tinyxml2::XML_SUCCESS) { - xmlDoc.LoadFile(sConfigDefaultPath.data()); - if (xmlDoc.ErrorID() != tinyxml2::XML_SUCCESS) { - LOG(ERROR) << "Failed to load and/or parse a configuration file, " << xmlDoc.ErrorStr(); - return false; - } + LOG(ERROR) << "Failed to load and/or parse a configuration file, " << xmlDoc.ErrorStr(); + return false; } /* retrieve the root element */ @@ -644,8 +664,7 @@ bool ConfigManager::readConfigDataFromBinary() { p += count * sizeof(camera_metadata_rational_t); break; default: - LOG(WARNING) << "Type " << type << " is unknown; " - << "data may be corrupted."; + LOG(WARNING) << "Type " << type << " is unknown; " << "data may be corrupted."; break; } } @@ -746,8 +765,7 @@ bool ConfigManager::readConfigDataFromBinary() { p += count * sizeof(camera_metadata_rational_t); break; default: - LOG(WARNING) << "Type " << type << " is unknown; " - << "data may be corrupted."; + LOG(WARNING) << "Type " << type << " is unknown; " << "data may be corrupted."; break; } } @@ -958,6 +976,16 @@ bool ConfigManager::writeConfigDataToBinary() { } std::unique_ptr ConfigManager::Create() { + std::unique_ptr mgr = Create(std::string(sConfigOverridePath)); + if (!mgr) { + LOG(DEBUG) << "A configuration override file does not exist. Use a default file instead."; + mgr = Create(std::string((sConfigDefaultPath))); + } + + return mgr; +} + +std::unique_ptr ConfigManager::Create(const std::string path) { std::unique_ptr cfgMgr(new ConfigManager()); /* @@ -968,7 +996,7 @@ std::unique_ptr ConfigManager::Create() { * to the filesystem and construct CameraInfo instead; this was * evaluated as 10x faster. */ - if (!cfgMgr->readConfigDataFromXML()) { + if (!cfgMgr->readConfigDataFromXML(path)) { return nullptr; } else { return cfgMgr; diff --git a/automotive/evs/aidl/impl/default/src/EvsCamera.cpp b/automotive/evs/aidl/impl/default/src/EvsCamera.cpp index 005c71f9e5620d76726ec5108d90f8d9541c0894..c28f86f6998c499cc5bbe1278de9e5b127cb03d8 100644 --- a/automotive/evs/aidl/impl/default/src/EvsCamera.cpp +++ b/automotive/evs/aidl/impl/default/src/EvsCamera.cpp @@ -205,7 +205,8 @@ ndk::ScopedAStatus EvsCamera::stopVideoStream() { } if ((!preVideoStreamStop_locked(status, lck) || !stopVideoStreamImpl_locked(status, lck) || - !postVideoStreamStop_locked(status, lck)) && !status.isOk()) { + !postVideoStreamStop_locked(status, lck)) && + !status.isOk()) { needShutdown = true; } } diff --git a/automotive/evs/aidl/impl/default/src/EvsVideoEmulatedCamera.cpp b/automotive/evs/aidl/impl/default/src/EvsVideoEmulatedCamera.cpp index 480c28d6a8537e900ba8a77f4b66ce81eb55b065..7574a346c6dbb306f8d861f10731d3b3ce724703 100644 --- a/automotive/evs/aidl/impl/default/src/EvsVideoEmulatedCamera.cpp +++ b/automotive/evs/aidl/impl/default/src/EvsVideoEmulatedCamera.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -35,12 +36,45 @@ #include #include +// Uncomment below line to dump decoded frames. +// #define DUMP_FRAMES (1) + namespace aidl::android::hardware::automotive::evs::implementation { namespace { + struct FormatDeleter { void operator()(AMediaFormat* format) const { AMediaFormat_delete(format); } }; + +int fillRGBAFromNv12(const uint8_t* src_y, int src_stride_y, const uint8_t* src_uv, + int src_stride_uv, const uint8_t*, int, uint8_t* dst_abgr, int dst_stride_abgr, + int width, int height) { + return libyuv::NV12ToABGR(src_y, src_stride_y, src_uv, src_stride_uv, dst_abgr, dst_stride_abgr, + width, height); +} + +int fillRGBAFromNv21(const uint8_t* src_y, int src_stride_y, const uint8_t* src_vu, + int src_stride_vu, const uint8_t*, int, uint8_t* dst_abgr, int dst_stride_abgr, + int width, int height) { + return libyuv::NV21ToABGR(src_y, src_stride_y, src_vu, src_stride_vu, dst_abgr, dst_stride_abgr, + width, height); +} + +int fillRGBAFromYv12(const uint8_t* src_y, int src_stride_y, const uint8_t* src_u, int src_stride_u, + const uint8_t* src_v, int src_stride_v, uint8_t* dst_abgr, int dst_stride_abgr, + int width, int height) { + return libyuv::I420ToABGR(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, + dst_abgr, dst_stride_abgr, width, height); +} + +int fillRGBAFromI420(const uint8_t* src_y, int src_stride_y, const uint8_t* src_u, int src_stride_u, + const uint8_t* src_v, int src_stride_v, uint8_t* dst_abgr, int dst_stride_abgr, + int width, int height) { + return libyuv::I420ToABGR(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, + dst_abgr, dst_stride_abgr, width, height); +} + } // namespace EvsVideoEmulatedCamera::EvsVideoEmulatedCamera(Sigil, const char* deviceName, @@ -123,7 +157,7 @@ bool EvsVideoEmulatedCamera::initializeMediaCodec() { mDescription.vendorFlags = 0xFFFFFFFF; // Arbitrary test value mUsage = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_CAMERA_WRITE | GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_RARELY; - mFormat = HAL_PIXEL_FORMAT_YCBCR_420_888; + mFormat = HAL_PIXEL_FORMAT_RGBA_8888; AMediaFormat_setInt32(format.get(), AMEDIAFORMAT_KEY_COLOR_FORMAT, COLOR_FormatYUV420Flexible); { const media_status_t status = @@ -137,6 +171,30 @@ bool EvsVideoEmulatedCamera::initializeMediaCodec() { format.reset(AMediaCodec_getOutputFormat(mVideoCodec.get())); AMediaFormat_getInt32(format.get(), AMEDIAFORMAT_KEY_WIDTH, &mWidth); AMediaFormat_getInt32(format.get(), AMEDIAFORMAT_KEY_HEIGHT, &mHeight); + + switch (mCameraInfo->format) { + default: + case ConfigManager::CameraInfo::PixelFormat::NV12: + mFillBuffer = fillRGBAFromNv12; + mUvStride = mWidth; + mDstStride = mWidth * 4; + break; + case ConfigManager::CameraInfo::PixelFormat::NV21: + mFillBuffer = fillRGBAFromNv21; + mUvStride = mWidth; + mDstStride = mWidth * 4; + break; + case ConfigManager::CameraInfo::PixelFormat::YV12: + mFillBuffer = fillRGBAFromYv12; + mUvStride = mWidth / 2; + mDstStride = mWidth * 4; + break; + case ConfigManager::CameraInfo::PixelFormat::I420: + mFillBuffer = fillRGBAFromI420; + mUvStride = mWidth / 2; + mDstStride = mWidth * 4; + break; + } return true; } @@ -190,6 +248,28 @@ void EvsVideoEmulatedCamera::onCodecOutputAvailable(const int32_t index, uint8_t* const codecOutputBuffer = AMediaCodec_getOutputBuffer(mVideoCodec.get(), index, &decodedOutSize) + info.offset; + int color_format = 0; + const auto outFormat = AMediaCodec_getOutputFormat(mVideoCodec.get()); + if (!AMediaFormat_getInt32(outFormat, AMEDIAFORMAT_KEY_COLOR_FORMAT, &color_format)) { + LOG(ERROR) << "Failed to get the color format."; + return; + } + + int stride = 0; + if (!AMediaFormat_getInt32(outFormat, AMEDIAFORMAT_KEY_STRIDE, &stride)) { + LOG(WARNING) << "Cannot find stride in format. Set as frame width."; + stride = mWidth; + } + + int slice_height = 0; + if (!AMediaFormat_getInt32(outFormat, AMEDIAFORMAT_KEY_SLICE_HEIGHT, &slice_height)) { + LOG(WARNING) << "Cannot find slice-height in format. Set as frame height."; + slice_height = mHeight; + } + + LOG(DEBUG) << "COLOR FORMAT: " << color_format << " stride: " << stride + << " height: " << slice_height; + std::size_t renderBufferId = static_cast(-1); buffer_handle_t renderBufferHandle = nullptr; { @@ -200,7 +280,7 @@ void EvsVideoEmulatedCamera::onCodecOutputAvailable(const int32_t index, std::tie(renderBufferId, renderBufferHandle) = useBuffer_unsafe(); } if (!renderBufferHandle) { - LOG(ERROR) << __func__ << ": Camera failed to get an available render buffer."; + LOG(DEBUG) << __func__ << ": Camera failed to get an available render buffer."; return; } std::vector renderBufferDescs; @@ -236,19 +316,51 @@ void EvsVideoEmulatedCamera::onCodecOutputAvailable(const int32_t index, return; } - std::size_t ySize = mHeight * mStride; + // Decoded output is in YUV4:2:0. + std::size_t ySize = mHeight * mWidth; std::size_t uvSize = ySize / 4; - std::memcpy(pixels, codecOutputBuffer, ySize); - pixels += ySize; - uint8_t* u_head = codecOutputBuffer + ySize; uint8_t* v_head = u_head + uvSize; - for (size_t i = 0; i < uvSize; ++i) { - *(pixels++) = *(u_head++); - *(pixels++) = *(v_head++); +#if DUMP_FRAMES + // TODO: We may want to keep this "dump" option. + static int dumpCount = 0; + static bool dumpData = ++dumpCount < 10; + if (dumpData) { + std::string path = "/data/vendor/dump/"; + path += "dump_" + std::to_string(dumpCount) + ".bin"; + + ::android::base::unique_fd fd( + open(path.data(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP)); + if (fd < 0) { + LOG(ERROR) << "Failed to open " << path; + } else { + auto len = write(fd.get(), codecOutputBuffer, info.size); + LOG(ERROR) << "Write " << len << " to " << path; + } + } +#endif + if (auto result = mFillBuffer(codecOutputBuffer, mWidth, u_head, mUvStride, v_head, mUvStride, + pixels, mDstStride, mWidth, mHeight); + result != 0) { + LOG(ERROR) << "Failed to convert I420 to BGRA"; + } +#if DUMP_FRAMES + else if (dumpData) { + std::string path = "/data/vendor/dump/"; + path += "dump_" + std::to_string(dumpCount) + "_rgba.bin"; + + ::android::base::unique_fd fd( + open(path.data(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP)); + if (fd < 0) { + LOG(ERROR) << "Failed to open " << path; + } else { + auto len = write(fd.get(), pixels, mStride * mHeight * 4); + LOG(ERROR) << "Write " << len << " to " << path; + } } +#endif // Release our output buffer mapper.unlock(renderBufferHandle); @@ -332,8 +444,8 @@ void EvsVideoEmulatedCamera::initializeParameters() { ::android::status_t EvsVideoEmulatedCamera::allocateOneFrame(buffer_handle_t* handle) { static auto& alloc = ::android::GraphicBufferAllocator::get(); unsigned pixelsPerLine = 0; - const auto result = alloc.allocate(mWidth, mHeight, mFormat, 1, mUsage, handle, &pixelsPerLine, - 0, "EvsVideoEmulatedCamera"); + const auto result = alloc.allocate(mWidth, mHeight, HAL_PIXEL_FORMAT_RGBA_8888, 1, mUsage, + handle, &pixelsPerLine, 0, "EvsVideoEmulatedCamera"); if (mStride == 0) { // Gralloc defines stride in terms of pixels per line mStride = pixelsPerLine; @@ -350,7 +462,7 @@ bool EvsVideoEmulatedCamera::startVideoStreamImpl_locked( if (auto status = AMediaCodec_start(mVideoCodec.get()); status != AMEDIA_OK) { LOG(INFO) << __func__ << ": Received error in starting decoder. " - << "Trying again after resetting this emulated device."; + << "Trying again after resetting this emulated device."; if (!initializeMediaCodec()) { LOG(ERROR) << __func__ << ": Failed to re-configure the media codec."; @@ -361,7 +473,7 @@ bool EvsVideoEmulatedCamera::startVideoStreamImpl_locked( AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC); AMediaCodec_flush(mVideoCodec.get()); - if(auto status = AMediaCodec_start(mVideoCodec.get()); status != AMEDIA_OK) { + if (auto status = AMediaCodec_start(mVideoCodec.get()); status != AMEDIA_OK) { LOG(ERROR) << __func__ << ": Received error again in starting decoder. " << "Error code: " << status; return false; @@ -389,7 +501,9 @@ bool EvsVideoEmulatedCamera::postVideoStreamStop_locked(ndk::ScopedAStatus& stat return false; } - EvsEventDesc event = { .aType = EvsEventType::STREAM_STOPPED, }; + EvsEventDesc event = { + .aType = EvsEventType::STREAM_STOPPED, + }; if (auto result = mStream->notify(event); !result.isOk()) { LOG(WARNING) << "Failed to notify the end of the stream."; } diff --git a/automotive/evs/aidl/impl/default/tests/EvsCameraBufferTest.cpp b/automotive/evs/aidl/impl/default/tests/EvsCameraBufferTest.cpp index 8b4676ea8a3743096bb969de66194dda2434ea45..ce0e776cf3798ef524914c2f4c92594f1a6a3019 100644 --- a/automotive/evs/aidl/impl/default/tests/EvsCameraBufferTest.cpp +++ b/automotive/evs/aidl/impl/default/tests/EvsCameraBufferTest.cpp @@ -92,6 +92,7 @@ class EvsCameraForTest : public EvsCamera { (override)); MOCK_METHOD(bool, stopVideoStreamImpl_locked, (ndk::ScopedAStatus & status, std::unique_lock& lck), (override)); + MOCK_METHOD(std::string, getId, (), (override)); }; TEST(EvsCameraBufferTest, ChangeBufferPoolSize) { diff --git a/automotive/evs/aidl/impl/default/tests/EvsCameraStateTest.cpp b/automotive/evs/aidl/impl/default/tests/EvsCameraStateTest.cpp index 1925c793f7837648e36bbc81e66f9e10e0d982fb..c517e3477a7fbf610956db8accbf15b2d1e1c50b 100644 --- a/automotive/evs/aidl/impl/default/tests/EvsCameraStateTest.cpp +++ b/automotive/evs/aidl/impl/default/tests/EvsCameraStateTest.cpp @@ -141,6 +141,7 @@ class EvsCameraForTest : public EvsCamera { (override)); MOCK_METHOD(::ndk::ScopedAStatus, setPrimaryClient, (), (override)); MOCK_METHOD(::ndk::ScopedAStatus, unsetPrimaryClient, (), (override)); + MOCK_METHOD(std::string, getId, (), (override)); bool mStreamStarted = false; bool mStreamStopped = false; @@ -160,7 +161,7 @@ class MockEvsCameraStream : public evs::IEvsCameraStream { MOCK_METHOD(::ndk::ScopedAStatus, notify, (const ::aidl::android::hardware::automotive::evs::EvsEventDesc& in_event), (override)); - MOCK_METHOD(::ndk::ScopedAStatus, getInterfaceVersion, (int32_t * _aidl_return), (override)); + MOCK_METHOD(::ndk::ScopedAStatus, getInterfaceVersion, (int32_t* _aidl_return), (override)); MOCK_METHOD(::ndk::ScopedAStatus, getInterfaceHash, (std::string * _aidl_return), (override)); }; diff --git a/automotive/vehicle/Android.bp b/automotive/vehicle/Android.bp index 606e10800485002091752f91eca4ea29bca790e2..d549a824da77a1200a6186ae7a010a388f838874 100644 --- a/automotive/vehicle/Android.bp +++ b/automotive/vehicle/Android.bp @@ -19,13 +19,21 @@ package { } cc_defaults { - name: "VehicleHalInterfaceDefaults", + name: "VehicleHalInterfaceDefaults-V3", static_libs: [ "android.hardware.automotive.vehicle-V3-ndk", "android.hardware.automotive.vehicle.property-V4-ndk", ], } +cc_defaults { + name: "VehicleHalInterfaceDefaults", + static_libs: [ + "android.hardware.automotive.vehicle-V4-ndk", + "android.hardware.automotive.vehicle.property-V4-ndk", + ], +} + rust_defaults { name: "VehicleHalInterfaceRustDefaults", rustlibs: [ @@ -37,7 +45,7 @@ rust_defaults { aidl_interface_defaults { name: "android.hardware.automotive.vehicle-latest-defaults", imports: [ - "android.hardware.automotive.vehicle-V3", + "android.hardware.automotive.vehicle-V4", "android.hardware.automotive.vehicle.property-V4", ], } diff --git a/automotive/vehicle/TEST_MAPPING b/automotive/vehicle/TEST_MAPPING index d848774a9ab448159781b3b0b1749688fab5f8c2..56bc047acd5f85759fa2b3aacc99365378e1b15f 100644 --- a/automotive/vehicle/TEST_MAPPING +++ b/automotive/vehicle/TEST_MAPPING @@ -48,12 +48,7 @@ "name": "GRPCVehicleHardwareUnitTest" }, { - "name": "CarServiceUnitTest", - "options" : [ - { - "include-filter": "com.android.car.hal.fakevhal.FakeVehicleStubUnitTest" - } - ] + "name": "CarServiceHalUnitTest" }, { "name": "VehicleHalProtoMessageConverterTest" diff --git a/automotive/vehicle/aidl/Android.bp b/automotive/vehicle/aidl/Android.bp index ce9e7a1b352949ec102255c367e7fb50b07d5185..4b2d2b816c0acab1591325ecb4142c3e04539baa 100644 --- a/automotive/vehicle/aidl/Android.bp +++ b/automotive/vehicle/aidl/Android.bp @@ -27,7 +27,7 @@ aidl_interface { srcs: [ "android/hardware/automotive/vehicle/*.aidl", ], - frozen: true, + frozen: false, stability: "vintf", backend: { cpp: { diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/HasSupportedValueInfo.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/HasSupportedValueInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e9633cc90b29678a20b4f2fdb7b33042310b8383 --- /dev/null +++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/HasSupportedValueInfo.aidl @@ -0,0 +1,40 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.vehicle; +@JavaDerive(equals=true, toString=true) @RustDerive(Clone=true) @VintfStability +parcelable HasSupportedValueInfo { + boolean hasMinSupportedValue; + boolean hasMaxSupportedValue; + boolean hasSupportedValuesList; +} diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/IVehicle.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/IVehicle.aidl index b5f62aa3bf5c7630fd755441a35bcbb0efca6a62..ee584163cb902e0390d20b9db87a6a409f472251 100644 --- a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/IVehicle.aidl +++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/IVehicle.aidl @@ -41,6 +41,10 @@ interface IVehicle { void subscribe(in android.hardware.automotive.vehicle.IVehicleCallback callback, in android.hardware.automotive.vehicle.SubscribeOptions[] options, int maxSharedMemoryFileCount); void unsubscribe(in android.hardware.automotive.vehicle.IVehicleCallback callback, in int[] propIds); void returnSharedMemory(in android.hardware.automotive.vehicle.IVehicleCallback callback, long sharedMemoryId); + android.hardware.automotive.vehicle.SupportedValuesListResults getSupportedValuesLists(in List propIdAreaIds); + android.hardware.automotive.vehicle.MinMaxSupportedValueResults getMinMaxSupportedValue(in List propIdAreaIds); + void registerSupportedValueChangeCallback(in android.hardware.automotive.vehicle.IVehicleCallback callback, in List propIdAreaIds); + void unregisterSupportedValueChangeCallback(in android.hardware.automotive.vehicle.IVehicleCallback callback, in List propIdAreaIds); const long INVALID_MEMORY_ID = 0; const int MAX_SHARED_MEMORY_FILES_PER_CLIENT = 3; } diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/IVehicleCallback.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/IVehicleCallback.aidl index 2c5a333ddefd39ed3bf03892da986d12dba53eec..50a8e7636b9fca14c71420de979f447a51cd45d1 100644 --- a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/IVehicleCallback.aidl +++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/IVehicleCallback.aidl @@ -38,4 +38,5 @@ interface IVehicleCallback { oneway void onSetValues(in android.hardware.automotive.vehicle.SetValueResults responses); oneway void onPropertyEvent(in android.hardware.automotive.vehicle.VehiclePropValues propValues, int sharedMemoryFileCount); oneway void onPropertySetError(in android.hardware.automotive.vehicle.VehiclePropErrors errors); + oneway void onSupportedValueChange(in List propIdAreaIds); } diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/MinMaxSupportedValueResult.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/MinMaxSupportedValueResult.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a004b790852559ce72b23a71446821c75f32a7a8 --- /dev/null +++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/MinMaxSupportedValueResult.aidl @@ -0,0 +1,40 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.vehicle; +@JavaDerive(equals=true, toString=true) @RustDerive(Clone=true) @VintfStability +parcelable MinMaxSupportedValueResult { + android.hardware.automotive.vehicle.StatusCode status = android.hardware.automotive.vehicle.StatusCode.OK; + @nullable android.hardware.automotive.vehicle.RawPropValues minSupportedValue; + @nullable android.hardware.automotive.vehicle.RawPropValues maxSupportedValue; +} diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/MinMaxSupportedValueResults.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/MinMaxSupportedValueResults.aidl new file mode 100644 index 0000000000000000000000000000000000000000..914d9c6e1471ce259b96646f8f6a60a3391d24c0 --- /dev/null +++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/MinMaxSupportedValueResults.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.vehicle; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable MinMaxSupportedValueResults { + android.hardware.automotive.vehicle.MinMaxSupportedValueResult[] payloads; + @nullable ParcelFileDescriptor sharedMemoryFd; +} diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/PropIdAreaId.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/PropIdAreaId.aidl new file mode 100644 index 0000000000000000000000000000000000000000..83e9c15d32166b39604593582b708484a3de3915 --- /dev/null +++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/PropIdAreaId.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.vehicle; +@JavaDerive(equals=true, toString=true) @RustDerive(Clone=true) @VintfStability +parcelable PropIdAreaId { + int propId; + int areaId; +} diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/StatusCode.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/StatusCode.aidl index f7e8c5abf750a44c41b240fbd1e2a48bf39d7e16..8651c30f48ca05014a969ca6a599ddb47e334b41 100644 --- a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/StatusCode.aidl +++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/StatusCode.aidl @@ -45,4 +45,5 @@ enum StatusCode { NOT_AVAILABLE_SPEED_HIGH = 8, NOT_AVAILABLE_POOR_VISIBILITY = 9, NOT_AVAILABLE_SAFETY = 10, + NOT_AVAILABLE_SUBSYSTEM_NOT_CONNECTED = 11, } diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SupportedValuesListResult.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SupportedValuesListResult.aidl new file mode 100644 index 0000000000000000000000000000000000000000..f348dcbdae8ef6e09531a5c4deba215cd76ac24e --- /dev/null +++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SupportedValuesListResult.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.vehicle; +@JavaDerive(equals=true, toString=true) @RustDerive(Clone=true) @VintfStability +parcelable SupportedValuesListResult { + android.hardware.automotive.vehicle.StatusCode status = android.hardware.automotive.vehicle.StatusCode.OK; + @nullable List supportedValuesList; +} diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SupportedValuesListResults.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SupportedValuesListResults.aidl new file mode 100644 index 0000000000000000000000000000000000000000..08af47c23959c00947346818b06988b7eccf9dac --- /dev/null +++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SupportedValuesListResults.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.vehicle; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable SupportedValuesListResults { + android.hardware.automotive.vehicle.SupportedValuesListResult[] payloads; + @nullable ParcelFileDescriptor sharedMemoryFd; +} diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl index eb3028e23e44505a3a5c81b7124eba81cb6559dd..e3f8605aad7ce48e17fb1c3c6ee8d65d1f02ba3f 100644 --- a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl +++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl @@ -35,13 +35,35 @@ package android.hardware.automotive.vehicle; @JavaDerive(equals=true, toString=true) @RustDerive(Clone=true) @VintfStability parcelable VehicleAreaConfig { int areaId; + /** + * @deprecated client should use {@code getMinMaxSupportedValue} instead. Only applicable for {@code INT32} type property. Ignored for other types. The optional minimum value at boot time. For backward compatibility, if {@code HasSupportedValueInfo.hasMinSupportedValue} is {@code true}, and {@code HasSupportedValueInfo.hasMaxSupportedValue} is {@code true}, this must be equal to the min supported value ({@code MinMaxSupportedValueResult.minSupportedValue}) at boot time. If no minimum or maximum value is available at boot time, both {@code minInt32Value} and {@code maxInt32Value} must be set to 0. If either one is not 0, then we assume min and max both take effect. + */ int minInt32Value; + /** + * @deprecated client should use {@code getMinMaxSupportedValue} instead. Only applicable for {@code INT32} type property. Ignored for other types. The optional maximum value at boot time. For backward compatibility, if {@code HasSupportedValueInfo.hasMinSupportedValue} is {@code true}, and {@code HasSupportedValueInfo.hasMaxSupportedValue} is {@code true}, this must be equal to the max supported value ({@code MinMaxSupportedValueResult.maxSupportedValue}) at boot time. If no minimum or maximum value is available at boot time, both {@code minInt32Value} and {@code maxInt32Value} must be set to 0. If either one is not 0, then we assume min and max both take effect. + */ int maxInt32Value; + /** + * @deprecated client should use {@code getMinMaxSupportedValue} instead. Only applicable for {@code INT64} type property. Ignored for other types. The optional minimum value at boot time. For backward compatibility, if {@code HasSupportedValueInfo.hasMinSupportedValue} is {@code true}, and {@code HasSupportedValueInfo.hasMaxSupportedValue} is {@code true}, this must be equal to the min supported value ({@code MinMaxSupportedValueResult.minSupportedValue}) at boot time. If no minimum or maximum value is available at boot time, both {@code minInt64Value} and {@code maxInt64Value} must be set to 0. If either one is not 0, then we assume min and max both take effect. + */ long minInt64Value; + /** + * @deprecated client should use {@code getMinMaxSupportedValue} instead. Only applicable for {@code INT64} type property. Ignored for other types. The optional maximum value at boot time. For backward compatibility, if {@code HasSupportedValueInfo.hasMinSupportedValue} is {@code true}, and {@code HasSupportedValueInfo.hasMaxSupportedValue} is {@code true}, this must be equal to the max supported value ({@code MinMaxSupportedValueResult.maxSupportedValue}) at boot time. If no minimum or maximum value is available at boot time, both {@code minInt64Value} and {@code maxInt64Value} must be set to 0. If either one is not 0, then we assume min and max both take effect. + */ long maxInt64Value; + /** + * @deprecated client should use {@code getMinMaxSupportedValue} instead. Only applicable for {@code FLOAT} type property. Ignored for other types. The optional minimum value at boot time. For backward compatibility, if {@code HasSupportedValueInfo.hasMinSupportedValue} is {@code true}, and {@code HasSupportedValueInfo.hasMaxSupportedValue} is {@code true}, this must be equal to the min supported value ({@code MinMaxSupportedValueResult.minSupportedValue}) at boot time. If no minimum or maximum value is available at boot time, both {@code minFloatValue} and {@code maxFloatValue} must be set to 0. If either one is not 0, then we assume min and max both take effect. + */ float minFloatValue; + /** + * @deprecated client should use {@code getMinMaxSupportedValue} instead. Only applicable for {@code FLOAT} type property. Ignored for other types. The optional maximum value at boot time. For backward compatibility, if {@code HasSupportedValueInfo.hasMinSupportedValue} is {@code true}, and {@code HasSupportedValueInfo.hasMaxSupportedValue} is {@code true}, this must be equal to the max supported value ({@code MinMaxSupportedValueResult.maxSupportedValue}) at boot time. If no minimum or maximum value is available at boot time, both {@code minFloatValue} and {@code maxFloatValue} must be set to 0. If either one is not 0, then we assume min and max both take effect. + */ float maxFloatValue; + /** + * @deprecated client should use {@code getMinMaxSupportedValue} instead. Only applicable for property with {@code @data_enum} annotation. Ignored for other properties. Optional supported subset of supported values at boot time. If the property has a @data_enum and supportedEnumValues is {@code null}, then it is assumed all @data_enum values are supported unless specified through another mechanism. For backward compatibility, if {@code HasSupportedValueInfo.hasSupportedValuesList} is {@code true} and this property has {@code data_enum} annotation, this must be set to the same as {@code SupportedValuesListResult.supportedValuesList} at boot time. + */ @nullable long[] supportedEnumValues; android.hardware.automotive.vehicle.VehiclePropertyAccess access = android.hardware.automotive.vehicle.VehiclePropertyAccess.NONE; boolean supportVariableUpdateRate; + @nullable android.hardware.automotive.vehicle.HasSupportedValueInfo hasSupportedValueInfo; } diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropertyStatus.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropertyStatus.aidl index 642ce83f214a01a8f656740e8018fedb0a5a694d..cc88e70f06355c32a056335f0729606cd943c757 100644 --- a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropertyStatus.aidl +++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropertyStatus.aidl @@ -36,5 +36,12 @@ package android.hardware.automotive.vehicle; enum VehiclePropertyStatus { AVAILABLE = 0x00, UNAVAILABLE = 0x01, + NOT_AVAILABLE_GENERAL = 0x01, ERROR = 0x02, + NOT_AVAILABLE_DISABLED = (0x1000 | 0x01) /* 4097 */, + NOT_AVAILABLE_SPEED_LOW = (0x1000 | 0x02) /* 4098 */, + NOT_AVAILABLE_SPEED_HIGH = (0x1000 | 0x03) /* 4099 */, + NOT_AVAILABLE_POOR_VISIBILITY = (0x1000 | 0x04) /* 4100 */, + NOT_AVAILABLE_SAFETY = (0x1000 | 0x05) /* 4101 */, + NOT_AVAILABLE_SUBSYSTEM_NOT_CONNECTED = (0x1000 | 0x06) /* 4102 */, } diff --git a/automotive/vehicle/aidl/aidl_test/Android.bp b/automotive/vehicle/aidl/aidl_test/Android.bp index 1e43070d0ba6a92b2c3e03af0768cae6c0044144..8edd636a83c0094f73de7fb14cd5ae39f7ab472a 100644 --- a/automotive/vehicle/aidl/aidl_test/Android.bp +++ b/automotive/vehicle/aidl/aidl_test/Android.bp @@ -52,7 +52,7 @@ android_test { ":IVehicleGeneratedJavaFiles-V4", ], static_libs: [ - "android.hardware.automotive.vehicle-V3-java", + "android.hardware.automotive.vehicle-V4-java", "android.hardware.automotive.vehicle.property-V4-java", "androidx.test.runner", "truth", diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/HasSupportedValueInfo.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/HasSupportedValueInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..991631b0378825783bcb85e71aa0a04a3d19aaeb --- /dev/null +++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/HasSupportedValueInfo.aidl @@ -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. + */ + +package android.hardware.automotive.vehicle; + +/** + * Whether the [propId, areaId] has min/max supported value or supported values + * list specified. + */ +@VintfStability +@JavaDerive(equals=true, toString=true) +@RustDerive(Clone=true) +parcelable HasSupportedValueInfo { + /** + * Whether [propId, areaId] has min supported value specified. + * + * If this is {@code true}, the hardware specifies a min supported value. + * If {@code MinMaxSupportedValueResult}'s {@code status} is + * {@code StatusCode.OK}, its {@code minSupportedValue} must not be + * {@code null}. + * + * If this is {@code false}, {@code minSupportedValue} must be {@code null}. + * + * Unless otherwise specified, this field is set to {@code false} for any + * properties whose type is not int32, int64 or float. + * + * For certain properties, e.g. {@code EV_BRAKE_REGENERATION_LEVEL}, this + * must always be {@code true}. Check {@code VehicleProperty} + * documentation. + */ + boolean hasMinSupportedValue; + + /** + * Whether [propId, areaId] has max supported value specified. + * + * If this is {@code true}, the hardware specifies a max supported value. + * If {@code MinMaxSupportedValueResult}'s {@code status} is + * {@code StatusCode.OK}, its {@code maxSupportedValue} must not be + * {@code null}. + * + * If this is {@code false}, {@code maxSupportedValue} must be {@code null}. + * + * Unless otherwise specified, this field is set to {@code false} for any + * properties whose type is not int32, int64 or float. + * + * For certain properties, e.g. {@code EV_BRAKE_REGENERATION_LEVEL}, this + * must always be {@code true}. Check {@code VehicleProperty} + * documentation. + */ + boolean hasMaxSupportedValue; + + /** + * Whether [propId, areaId] has supported values list specified. + * + * If this is {@code true}, it means the hardware specifies supported + * values for this property. + * If {@code SupportedValueListResult}'s {@code status} is + * {@code StatusCode.OK}, its {@code supportedValuesList} must not be + * {@code null}. + * + * If this is {@code false}, {@code supportedValuesList} must always be + * {@code null}. + * + * The supported value is the superset for both the input value for writable + * property and the output value for readable property. + * + * For certain properties, e.g. {@code GEAR_SELECTION}, this must always be + * {@code true}. Check {@code VehicleProperty} documentation. + */ + boolean hasSupportedValuesList; +} diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicle.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicle.aidl index c896d143a7a0c6e923491b27b50cea81a0478e7f..220b1dacceff71f5fc29af11b1552d86589f20fc 100644 --- a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicle.aidl +++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicle.aidl @@ -18,8 +18,11 @@ package android.hardware.automotive.vehicle; import android.hardware.automotive.vehicle.GetValueRequests; import android.hardware.automotive.vehicle.IVehicleCallback; +import android.hardware.automotive.vehicle.MinMaxSupportedValueResults; +import android.hardware.automotive.vehicle.PropIdAreaId; import android.hardware.automotive.vehicle.SetValueRequests; import android.hardware.automotive.vehicle.SubscribeOptions; +import android.hardware.automotive.vehicle.SupportedValuesListResults; import android.hardware.automotive.vehicle.VehiclePropConfigs; // Vehicle HAL interface. @@ -260,4 +263,106 @@ interface IVehicle { * the used shared memory file to return. */ void returnSharedMemory(in IVehicleCallback callback, long sharedMemoryId); + + /** + * Gets the supported values lists for [propId, areaId]s. + * + * For a specific [propId, areaId], if the hardware currently specifies + * a list of supported values for it, then it is returned through the + * {@code supportedValuesList} field inside + * {@code SupportedValuesListResult}. If the hardware does not specify + * a list of supported values for it (indicated by + * {@code HasSupportedValueInfo.hasSupportedValuesList} being + * {@code false}), then {@code supportedValuesList} field will be + * {@code null}. + * + * The supported value list applies for both read/write operations. if + * it differs for read/write, this is the super-set. + * + * Must return a list of results, one for each requested [propId, areaId]. + * + * The returned supported values list represents the currently supported + * values and may change dynamically. Caller should use + * {@code registerSupportedValueChangeCallback} to register for supported + * value range change. + * + * If unable to determine the supported values for some [propId, areaId] due + * to error cases, for example, unable to determine EV_CHARGE_PERCENT_LIMIT + * supported values due to battery in an error state, + * {@code SupportedValuesListResult.status} for that should be set to + * a non-okay {@code StatusCode}. + * + * If one of the [propId, areaId] is not supported, + * {@code SupportedValuesListResult.status} for that should be set to + * {@code StatusCode.INVALID_ARG}. + * + * This function should only return non-okay {@code StatusCode} if the whole + * operation failed and unable to get any results. + */ + SupportedValuesListResults getSupportedValuesLists(in List propIdAreaIds); + + /** + * Gets the min/max supported values for [propId, areaId]s. + * + * For a specific [propId, areaId], if the hardware currently specifies + * min/max supported value for it, then it is returned through the + * {@code minSupportedValue} or {@code maxSupportedValue} field inside + * {@code MinMaxSupportedValueResult}. If the hardware does not specify + * min/max supported value for it (indicated by + * {@code HasSupportedValueInfo.hasMinSupportedValue} or + * {@code HasSupportedValueInfo.hasMaxSupportedValue} being + * {@code false}), then {@code minSupportedValue} or + * {@code maxSupportedValue} is {@code null}. + * + * The min/max supported values apply for both read/write operations. if + * they differs for read/write, they are from the super-set. + * + * Must return a list of results, one for each requested [propId, areaId]. + * + * The returned min/max supported values represent the currently supported + * values and may change dynamically. Caller should use + * {@code registerSupportedValueChangeCallback} to register for supported + * value range change. + * + * If unable to determine the supported values for some [propId, areaId] due + * to error cases, for example, unable to determine HVAC_FAN_SPEED + * max supported value due to HVAC in an error state, + * {@code MinMaxSupportedValueResult.status} for that should be set to + * a non-okay {@code StatusCode}. + * + * If one of the [propId, areaId] is not supported, + * {@code MinMaxSupportedValueResult.status} for that should be set to + * {@code StatusCode.INVALID_ARG}. + * + * This function should only return non-okay {@code StatusCode} if the whole + * operation failed and unable to get any results. + */ + MinMaxSupportedValueResults getMinMaxSupportedValue(in List propIdAreaIds); + + /** + * Registers the supported value change callback. + * + * For the specified [propId, areaId]s, + * {@code callback.onSupportedValueChange} must be invoked if change + * happens. + * + * This always registers a new callback for the specified [propId, areaId]s + * if the same callback was not previously registered for them. + * + * The list of [propId, areaId]s to register must not be empty. + * + * @param callback The callback for supported value change. + * @param propIdAreaIds A list of [propId, areaId]s to register. + */ + void registerSupportedValueChangeCallback( + in IVehicleCallback callback, in List propIdAreaIds); + + /** + * Unregisters the supported value change callback. + * + * @param callback The callback to unregister. + * @param propIdAreaIds A list of [propId, areaId]s to unregister. + */ + void unregisterSupportedValueChangeCallback( + in IVehicleCallback callback, in List propIdAreaIds); } diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicleCallback.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicleCallback.aidl index 2b50321b42f2dd00f8471e8a008dbe755cfe5273..7230d09028675c9b1c2cb87767c85a2f226ec763 100644 --- a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicleCallback.aidl +++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicleCallback.aidl @@ -17,6 +17,7 @@ package android.hardware.automotive.vehicle; import android.hardware.automotive.vehicle.GetValueResults; +import android.hardware.automotive.vehicle.PropIdAreaId; import android.hardware.automotive.vehicle.SetValueResults; import android.hardware.automotive.vehicle.StatusCode; import android.hardware.automotive.vehicle.VehiclePropErrors; @@ -96,4 +97,16 @@ interface IVehicleCallback { * does not batch the errors, this may only contain one error. */ oneway void onPropertySetError(in VehiclePropErrors errors); + + /** + * Called when the min/max supported value or supported value list for + * the registered [propId, areaId]s changes. + * + * The caller is supposed to call {@code getMinMaxSupportedValue} or + * {@code getSupportedValuesLists} to get the new supported value range. + * + * @param propIdAreaIds The list of [propId, areaId]s whose supported + * value range changes. + */ + oneway void onSupportedValueChange(in List propIdAreaIds); } diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/MinMaxSupportedValueResult.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/MinMaxSupportedValueResult.aidl new file mode 100644 index 0000000000000000000000000000000000000000..f85ad3aa3d8c8cd88950caeffe920689246d2f3a --- /dev/null +++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/MinMaxSupportedValueResult.aidl @@ -0,0 +1,48 @@ +/* + * 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. + */ + +package android.hardware.automotive.vehicle; + +import android.hardware.automotive.vehicle.RawPropValues; +import android.hardware.automotive.vehicle.StatusCode; + +/** + * One result returned from {@code getMinMaxSupportedValue} for one request. + */ +@VintfStability +@JavaDerive(equals=true, toString=true) +@RustDerive(Clone=true) +parcelable MinMaxSupportedValueResult { + /** + * The status for result. If this is not OK, the operation failed for this + * [propId, areaId]. + */ + StatusCode status = StatusCode.OK; + /** + * The min supported value. + * + * If the [propId, areaId] does not specify a min supported value, this + * is {@code null}. + */ + @nullable RawPropValues minSupportedValue; + /** + * The max supported value. + * + * If the [propId, areaId] does not specify a max supported value, this + * is {@code null}. + */ + @nullable RawPropValues maxSupportedValue; +} diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/MinMaxSupportedValueResults.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/MinMaxSupportedValueResults.aidl new file mode 100644 index 0000000000000000000000000000000000000000..3579979b3a08824832422ab68ec60b9c7ba79625 --- /dev/null +++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/MinMaxSupportedValueResults.aidl @@ -0,0 +1,55 @@ +/* + * 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. + */ + +package android.hardware.automotive.vehicle; + +import android.hardware.automotive.vehicle.MinMaxSupportedValueResult; +import android.os.ParcelFileDescriptor; + +/** + * The result structure for {@code getMinMaxSupportedValue}. + * + * Contains a list of results, one for each [propId, areaId] request. The + * list must contain the same number of result as the {@code propIdAreaIds}. + * The result must be in the same order, e.g. the first result is for the first + * [propId, areaId]. + * + * Java Client should use + * {@link LargeParcelable.reconstructStableAIDLParcelable} to convert this back + * to a regular parcelable and then use the converted parcelable's + * {@code payloads} field. + * + * Native client should use + * {@link LargeParcelable::stableLargeParcelableToParcelable}. + * + * VHAL implementation must store the results into {@link payloads} field and + * use {@link LargeParcelable::parcelableToStableLargeParcelable} before + * sending the converted large parcelable through binder. + */ +@VintfStability +@JavaDerive(equals=true, toString=true) +parcelable MinMaxSupportedValueResults { + /** + * The list of responses if they fit the binder memory limitation. + */ + MinMaxSupportedValueResult[] payloads; + /** + * Shared memory file to store responses if they exceed binder memory + * limitation. Created by VHAL, readable only for the client. + * The client must close it after reading. + */ + @nullable ParcelFileDescriptor sharedMemoryFd; +} diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/PropIdAreaId.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/PropIdAreaId.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ea47350bea60ec9e2db0eac91e4a826fa6ba404f --- /dev/null +++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/PropIdAreaId.aidl @@ -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. + */ + +package android.hardware.automotive.vehicle; + +import android.hardware.automotive.vehicle.RawPropValues; + +/** + * A structure containing one propertyId and one areaId. + */ +@VintfStability +@JavaDerive(equals=true, toString=true) +@RustDerive(Clone=true) +parcelable PropIdAreaId { + /** The property Id. */ + int propId; + /** The area Id. */ + int areaId; +} diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/StatusCode.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/StatusCode.aidl index fd4b199bdb6894df32e2474800bca9a46b5928e3..3fb4532f28ea0c6a0a646e4b0e341ee588f58bf7 100644 --- a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/StatusCode.aidl +++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/StatusCode.aidl @@ -96,4 +96,11 @@ enum StatusCode { * operation such as closing a trunk door, etc. */ NOT_AVAILABLE_SAFETY = 10, + /** + * The feature cannot be accessed because the sub-system for the feature is + * not connected. + * + * E.g. trailer light state is not available when the trailer is detached. + */ + NOT_AVAILABLE_SUBSYSTEM_NOT_CONNECTED = 11, } diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SupportedValuesListResult.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SupportedValuesListResult.aidl new file mode 100644 index 0000000000000000000000000000000000000000..4524f4f0c4eb19c705565b225e844e2a330b1b59 --- /dev/null +++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SupportedValuesListResult.aidl @@ -0,0 +1,41 @@ +/* + * 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. + */ + +package android.hardware.automotive.vehicle; + +import android.hardware.automotive.vehicle.RawPropValues; +import android.hardware.automotive.vehicle.StatusCode; + +/** + * One result returned from {@code getSupportedValuesLists} for one request. + */ +@VintfStability +@JavaDerive(equals=true, toString=true) +@RustDerive(Clone=true) +parcelable SupportedValuesListResult { + /** + * The status for result. If this is not OK, the operation failed for this + * [propId, areaId]. + */ + StatusCode status = StatusCode.OK; + /** + * The supported values list. + * + * If the [propId, areaId] does not specify a supported values list, this + * is {@code null}. + */ + @nullable List supportedValuesList; +} diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SupportedValuesListResults.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SupportedValuesListResults.aidl new file mode 100644 index 0000000000000000000000000000000000000000..da848717e9ba5f4da4ad6a83c1815b0e754bd8b4 --- /dev/null +++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SupportedValuesListResults.aidl @@ -0,0 +1,55 @@ +/* + * 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. + */ + +package android.hardware.automotive.vehicle; + +import android.hardware.automotive.vehicle.SupportedValuesListResult; +import android.os.ParcelFileDescriptor; + +/** + * The result structure for {@code getSupportedValuesLists}. + * + * Contains a list of results, one for each [propId, areaId] request. The + * list must contain the same number of result as the {@code propIdAreaIds}. + * The result must be in the same order, e.g. the first result is for the first + * [propId, areaId]. + * + * Java Client should use + * {@link LargeParcelable.reconstructStableAIDLParcelable} to convert this back + * to a regular parcelable and then use the converted parcelable's + * {@code payloads} field. + * + * Native client should use + * {@link LargeParcelable::stableLargeParcelableToParcelable}. + * + * VHAL implementation must store the results into {@link payloads} field and + * use {@link LargeParcelable::parcelableToStableLargeParcelable} before + * sending the converted large parcelable through binder. + */ +@VintfStability +@JavaDerive(equals=true, toString=true) +parcelable SupportedValuesListResults { + /** + * The list of responses if they fit the binder memory limitation. + */ + SupportedValuesListResult[] payloads; + /** + * Shared memory file to store responses if they exceed binder memory + * limitation. Created by VHAL, readable only for the client. + * The client must close it after reading. + */ + @nullable ParcelFileDescriptor sharedMemoryFd; +} diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl index 9387965df32bf9b9b6649d73e4dbb393d554d7b1..62d7e21d12e253965f03669dbf1bf0260ce129d0 100644 --- a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl +++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl @@ -16,6 +16,7 @@ package android.hardware.automotive.vehicle; +import android.hardware.automotive.vehicle.HasSupportedValueInfo; import android.hardware.automotive.vehicle.VehiclePropertyAccess; @VintfStability @@ -28,26 +29,142 @@ parcelable VehicleAreaConfig { int areaId; /** - * If the property has @data_enum, leave the range to zero. + * @deprecated client should use {@code getMinMaxSupportedValue} instead. * - * Range will be ignored in the following cases: - * - The VehiclePropertyType is not INT32, INT64 or FLOAT. - * - Both of min value and max value are zero. + * Only applicable for {@code INT32} type property. Ignored for other types. + * + * The optional minimum value at boot time. + * + * For backward compatibility, + * if {@code HasSupportedValueInfo.hasMinSupportedValue} is {@code true}, + * and {@code HasSupportedValueInfo.hasMaxSupportedValue} is {@code true}, + * this must be equal to the min supported value + * ({@code MinMaxSupportedValueResult.minSupportedValue}) at boot time. + * + * If no minimum or maximum value is available at boot time, both + * {@code minInt32Value} and {@code maxInt32Value} must be set to 0. + * + * If either one is not 0, then we assume min and max both take effect. */ - int minInt32Value; + + /** + * @deprecated client should use {@code getMinMaxSupportedValue} instead. + * + * Only applicable for {@code INT32} type property. Ignored for other types. + * + * The optional maximum value at boot time. + * + * For backward compatibility, + * if {@code HasSupportedValueInfo.hasMinSupportedValue} is {@code true}, + * and {@code HasSupportedValueInfo.hasMaxSupportedValue} is {@code true}, + * this must be equal to the max supported value + * ({@code MinMaxSupportedValueResult.maxSupportedValue}) at boot time. + * + * If no minimum or maximum value is available at boot time, both + * {@code minInt32Value} and {@code maxInt32Value} must be set to 0. + * + * If either one is not 0, then we assume min and max both take effect. + */ int maxInt32Value; + /** + * @deprecated client should use {@code getMinMaxSupportedValue} instead. + * + * Only applicable for {@code INT64} type property. Ignored for other types. + * + * The optional minimum value at boot time. + * + * For backward compatibility, + * if {@code HasSupportedValueInfo.hasMinSupportedValue} is {@code true}, + * and {@code HasSupportedValueInfo.hasMaxSupportedValue} is {@code true}, + * this must be equal to the min supported value + * ({@code MinMaxSupportedValueResult.minSupportedValue}) at boot time. + * + * If no minimum or maximum value is available at boot time, both + * {@code minInt64Value} and {@code maxInt64Value} must be set to 0. + * + * If either one is not 0, then we assume min and max both take effect. + */ long minInt64Value; + + /** + * @deprecated client should use {@code getMinMaxSupportedValue} instead. + * + * Only applicable for {@code INT64} type property. Ignored for other types. + * + * The optional maximum value at boot time. + * + * For backward compatibility, + * if {@code HasSupportedValueInfo.hasMinSupportedValue} is {@code true}, + * and {@code HasSupportedValueInfo.hasMaxSupportedValue} is {@code true}, + * this must be equal to the max supported value + * ({@code MinMaxSupportedValueResult.maxSupportedValue}) at boot time. + * + * If no minimum or maximum value is available at boot time, both + * {@code minInt64Value} and {@code maxInt64Value} must be set to 0. + * + * If either one is not 0, then we assume min and max both take effect. + */ long maxInt64Value; + /** + * @deprecated client should use {@code getMinMaxSupportedValue} instead. + * + * Only applicable for {@code FLOAT} type property. Ignored for other types. + * + * The optional minimum value at boot time. + * + * For backward compatibility, + * if {@code HasSupportedValueInfo.hasMinSupportedValue} is {@code true}, + * and {@code HasSupportedValueInfo.hasMaxSupportedValue} is {@code true}, + * this must be equal to the min supported value + * ({@code MinMaxSupportedValueResult.minSupportedValue}) at boot time. + * + * If no minimum or maximum value is available at boot time, both + * {@code minFloatValue} and {@code maxFloatValue} must be set to 0. + * + * If either one is not 0, then we assume min and max both take effect. + */ float minFloatValue; + + /** + * @deprecated client should use {@code getMinMaxSupportedValue} instead. + * + * Only applicable for {@code FLOAT} type property. Ignored for other types. + * + * The optional maximum value at boot time. + * + * For backward compatibility, + * if {@code HasSupportedValueInfo.hasMinSupportedValue} is {@code true}, + * and {@code HasSupportedValueInfo.hasMaxSupportedValue} is {@code true}, + * this must be equal to the max supported value + * ({@code MinMaxSupportedValueResult.maxSupportedValue}) at boot time. + * + * If no minimum or maximum value is available at boot time, both + * {@code minFloatValue} and {@code maxFloatValue} must be set to 0. + * + * If either one is not 0, then we assume min and max both take effect. + */ float maxFloatValue; /** - * If the property has a @data_enum, then it is possible to specify a supported subset of the - * @data_enum. If the property has a @data_enum and supportedEnumValues is null, then it is - * assumed all @data_enum values are supported unless specified through another mechanism. + * @deprecated client should use {@code getMinMaxSupportedValue} instead. + * + * Only applicable for property with {@code @data_enum} annotation. Ignored + * for other properties. + * + * Optional supported subset of supported values at boot time. + * + * If the property has a @data_enum and supportedEnumValues is {@code null}, + * then it is assumed all @data_enum values are supported unless specified + * through another mechanism. + * + * For backward compatibility, if + * {@code HasSupportedValueInfo.hasSupportedValuesList} is {@code true} + * and this property has {@code data_enum} annotation, + * this must be set to the same as + * {@code SupportedValuesListResult.supportedValuesList} at boot time. */ @nullable long[] supportedEnumValues; @@ -83,6 +200,8 @@ parcelable VehicleAreaConfig { /** * Whether variable update rate is supported. * + * This is always {@code false} for VHAL implementation < V3. + * * This applies for continuous property only. * * It is HIGHLY RECOMMENDED to support variable update rate for all non-heartbeat continuous @@ -109,4 +228,12 @@ parcelable VehicleAreaConfig { * so this should be false if the property is large (e.g. a byte array of 1k in size). */ boolean supportVariableUpdateRate; + + /** + * For VHAL implementation >= V4, this must not be {@code null}. This specifies whether + * this property may have min/max supported value or supported values list. + * + * For VHAL implementation < V4, this is always {@code null} and is not accessed. + */ + @nullable HasSupportedValueInfo hasSupportedValueInfo; } diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyStatus.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyStatus.aidl index 400e256697c8578c279ddf17c304c4dca4c45e14..4b1dcdb6affe23c14b2161be10b324cdba48c59f 100644 --- a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyStatus.aidl +++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyStatus.aidl @@ -22,8 +22,14 @@ package android.hardware.automotive.vehicle; @VintfStability @Backing(type="int") enum VehiclePropertyStatus { - /** Property is available and behaving normally */ + /** + * Property is available and behaving normally + */ AVAILABLE = 0x00, + /** + * Same as {@link #NOT_AVAILABLE_GENERAL}. + */ + UNAVAILABLE = 0x01, /** * A property in this state is not available for reading and writing. This * is a transient state that depends on the availability of the underlying @@ -34,8 +40,45 @@ enum VehiclePropertyStatus { * this state MAY return NOT_AVAILABLE. The HAL implementation MUST ignore * the value of the status field when writing a property value coming from * Android. + * + * This represents a general not-available status. If more detailed info is + * known, a more specific not-available status should be used instead. + */ + NOT_AVAILABLE_GENERAL = 0x01, + /** + * There is an error with this property. */ - UNAVAILABLE = 0x01, - /** There is an error with this property. */ ERROR = 0x02, + // All NOT_AVAILABLE_XXX status starts with 0x1000. + /** + * The property is not available because the underlying feature is disabled. + */ + NOT_AVAILABLE_DISABLED = 0x1000 | 0x01, + /** + * The property is not available because the vehicle speed is too low. + */ + NOT_AVAILABLE_SPEED_LOW = 0x1000 | 0x02, + /** + * The property is not available because the vehicle speed is too high. + */ + NOT_AVAILABLE_SPEED_HIGH = 0x1000 | 0x03, + /** + * The property is not available because of bad camera or sensor visibility. Examples + * might be bird poop blocking the camera or a bumper cover blocking an ultrasonic sensor. + */ + NOT_AVAILABLE_POOR_VISIBILITY = 0x1000 | 0x04, + /** + * The property cannot be accessed due to safety reasons. Eg. System could be + * in a faulty state, an object or person could be blocking the requested + * operation such as closing a trunk door, etc. + */ + NOT_AVAILABLE_SAFETY = 0x1000 | 0x05, + /** + * The property is not available because the sub-system for the feature is + * not connected. + * + * E.g. the trailer light property is in this state if the trailer is not + * attached. + */ + NOT_AVAILABLE_SUBSYSTEM_NOT_CONNECTED = 0x1000 | 0x06, } diff --git a/automotive/vehicle/aidl/emu_metadata/android.hardware.automotive.vehicle-types-meta.json b/automotive/vehicle/aidl/emu_metadata/android.hardware.automotive.vehicle-types-meta.json index 8ef440d4d75e174ad3507bbad6eee1ca936c8658..272f7c57ade57fbbe016e19428e22370bc8ca47f 100644 --- a/automotive/vehicle/aidl/emu_metadata/android.hardware.automotive.vehicle-types-meta.json +++ b/automotive/vehicle/aidl/emu_metadata/android.hardware.automotive.vehicle-types-meta.json @@ -92,6 +92,20 @@ "data_enum": "PortLocationType", "description": "Multiple EV port locations\nImplement this property if the vehicle has multiple EV ports. Port locations are defined in PortLocationType. For example, a car has one port in front left and one port in rear left: int32Values[0] = PortLocationType::FRONT_LEFT int32Values[1] = PortLocationType::REAR_LEFT\nIf only one port exists on the vehicle, this property's value should list just one element. See INFO_EV_PORT_LOCATION for describing just one port location." }, + { + "name": "INFO_MODEL_TRIM", + "value": 286261517, + "description": "Public trim name of the vehicle.\nThis property must communicate the vehicle's public trim name.\nFor example, say an OEM manufactures two different versions of a vehicle model: \"makeName modelName\" and \"makeName modelName Sport\" This property must be empty for the first vehicle (i.e. base model), and set to \"Sport\" for the second vehicle." + }, + { + "name": "Vehicle Size Class.", + "value": 289472782, + "data_enums": [ + "VehicleSizeClass" + ], + "data_enum": "VehicleSizeClass", + "description": "Vehicle Size Class.\nThis property must communicate an integer array that contains the size classifications followed by the vehicle as enumerated in VehicleSizeClass.aidl. If the vehicle follows a single standard, then the array size of the property's value should be 1. If the vehicle follows multiple standards that the OEM wants to communicate, this may be communicated as additional values in the array.\nFor example, suppose a vehicle model follows the VehicleSizeClass.EU_A_SEGMENT standard in the EU and the VehicleSizeClass.JPN_KEI standard in Japan. In this scenario this property must return an intArray = [VehicleSizeClass.EU_A_SEGMENT, VehicleSizeClass.JPN_KEI]. If this vehicle only followed the VehicleSizeClass.EU_A_SEGMENT standard, then we expect intArray = [VehicleSizeClass.EU_A_SEGMENT]." + }, { "name": "PERF_ODOMETER", "value": 291504644, @@ -117,6 +131,16 @@ "value": 291504656, "description": "Rear bicycle model steering angle for vehicle\nAngle is in degrees. Left is negative.\nThis property is independent of the angle of the steering wheel. This property must communicate the angle of the rear wheels with respect to the vehicle, not the angle of the steering wheel." }, + { + "name": "INSTANTANEOUS_FUEL_ECONOMY", + "value": 291504657, + "description": "Instantaneous Fuel Economy in L\/100km.\nThis property must communicate the instantaneous fuel economy of the vehicle in units of L\/100km. The property's value is independent of DISTANCE_DISPLAY_UNITS, FUEL_VOLUME_DISPLAY_UNITS, and FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME property i.e. this property must always communicate the value in L\/100km.\nFor the EV version of this property, see INSTANTANEOUS_EV_EFFICIENCY." + }, + { + "name": "INSTANTANEOUS_EV_EFFICIENCY", + "value": 291504658, + "description": "Instantaneous EV efficiency in km\/kWh.\nThis property must communicate the instantaneous EV battery efficiency of the vehicle in units of km\/kWh. The property's value is independent of the DISTANCE_DISPLAY_UNITS and EV_BATTERY_DISPLAY_UNITS properties i.e. this property must always communicate the value in km\/kWh.\nFor the fuel version of this property, see INSTANTANEOUS_FUEL_ECONOMY." + }, { "name": "Temperature of engine coolant", "value": 291504897, @@ -194,13 +218,38 @@ { "name": "Tire pressure", "value": 392168201, - "description": "Tire pressure\nEach tires is identified by its areaConfig.areaId config and their minFloatValue\/maxFloatValue are used to store OEM recommended pressure range. The minFloatValue and maxFloatValue in VehicleAreaConfig must be defined. The minFloatValue in the areaConfig data represents the lower bound of the recommended tire pressure. The maxFloatValue in the areaConfig data represents the upper bound of the recommended tire pressure. For example: The following areaConfig indicates the recommended tire pressure of left_front tire is from 200.0 KILOPASCAL to 240.0 KILOPASCAL. .areaConfigs = { VehicleAreaConfig { .areaId = VehicleAreaWheel::LEFT_FRONT, .minFloatValue = 200.0, .maxFloatValue = 240.0, } }," + "description": "Tire pressure\n{@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for all areas.\n{@code MinMaxSupportedValueResult.minSupportedValue} represents the lower bound of the recommended tire pressure for the tire at the specified area ID.\n{@code MinMaxSupportedValueResult.maxSupportedValue} represents the upper bound of the recommended tire pressure for the tire at the specified area ID.\nFor example, if the recommended tire pressure of left_front tire is from 200.0 KILOPASCAL to 240.0 KILOPASCAL, {@code getMinMaxSupportedValue} for [propId=TIRE_PRESSURE, areaId=VehicleAreaWheel::LEFT_FRONT] must return a {@code MinMaxSupportedValueResult} with OK status, 200.0 as minSupportedValue, 240.0 as maxSupportedValue.\nFor backward compatibility, minFloatValue and maxFloatValue in {@code VehicleAreaConfig} must be set to the same as minSupportedValue and maxSupportedValue at boot time.\nEach tire is identified by its areaConfig.areaId config.\nFor example: .areaConfigs = { VehicleAreaConfig { .areaId = VehicleAreaWheel::LEFT_FRONT, .minFloatValue = 200.0, .maxFloatValue = 240.0, } }," }, { "name": "Critically low tire pressure", "value": 392168202, "description": "Critically low tire pressure\nThis property indicates the critically low pressure threshold for each tire. It indicates when it is time for tires to be replaced or fixed. The value must be less than or equal to minFloatValue in TIRE_PRESSURE. Minimum and maximum property values (that is, minFloatValue, maxFloatValue) are not applicable to this property." }, + { + "name": "ACCELERATOR_PEDAL_COMPRESSION_PERCENTAGE", + "value": 291504911, + "description": "Accelerator pedal compression percentage.\nThis property must communicate the percentage that the physical accelerator pedal in the vehicle is compressed. This property must return a float value from 0 to 100.\n0 indicates the pedal is not compressed. 100 indicates the pedal is maximally compressed." + }, + { + "name": "BRAKE_PEDAL_COMPRESSION_PERCENTAGE", + "value": 291504912, + "description": "Brake pedal compression percentage.\nThis property must communicate the percentage that the physical brake pedal in the vehicle is compressed. This property must return a float value from 0 to 100.\n0 indicates the pedal is not compressed. 100 indicates the pedal is maximally compressed." + }, + { + "name": "Brake pad wear percentage.", + "value": 392168209, + "description": "Brake pad wear percentage.\nThis property must communicate the amount of brake pad wear accumulated by the vehicle as a percentage. This property return a float value from 0 to 100.\n0 indicates the brake pad has no wear. 100 indicates the brake pad is maximally worn." + }, + { + "name": "Brake fluid low.", + "value": 287310610, + "description": "Brake fluid low.\nThis property must communicate that the brake fluid level in the vehicle is low according to the OEM. This property must match the vehicle's brake fluid level status as displayed on the instrument cluster. If the brake fluid level is low, this property must be set to true. If not, it must be set to false." + }, + { + "name": "VEHICLE_PASSIVE_SUSPENSION_HEIGHT", + "value": 390071059, + "description": "Vehicle Passive Suspension Height in mm.\nThis property must communicate the real-time suspension displacement of the vehicle relative to its neutral position, given in mm. In other words, the displacement of the suspension at any given point in time relative to the suspension's position when the vehicle is on a flat surface with no passengers or cargo. When the suspension is compressed in comparison to the neutral position, the value should be negative. When the suspension is decompressed in comparison to the neutral position, the value should be positive.\nExamples for further clarity: 1) Suppose the user is driving on a smooth flat surface, and all wheels are currently compressed by 2 cm in comparison to the default suspension height. In this scenario, this property must be set to -20 for all wheels. 2) Suppose the user drives over a pothole. While the front left wheel is over the pothole, it's decompressed by 3 cm in comparison to the rest of the wheels, or 1 cm in comparison to the default suspension height. All the others are still compressed by 2 cm. In this scenario, this property must be set to -20 for all wheels except for the front left, which must be set to 10.\nHasSupportedValueInfo.hasMinSupportedValue and HasSupportedValueInfo.hasMaxSupportedValue must be true for all areas.\nMinMaxSupportedValueResult.minSupportedValue represents the lower bound of the suspension height for the wheel at the specified area ID.\nMinMaxSupportedValueResult.maxSupportedValue represents the upper bound of the suspension height for the wheel at the specified area ID." + }, { "name": "ENGINE_IDLE_AUTO_STOP_ENABLED", "value": 287310624, @@ -213,7 +262,12 @@ "ImpactSensorLocation" ], "data_enum": "ImpactSensorLocation", - "description": "Impact detected.\nBit flag property to relay information on whether an impact has occurred on a particular side of the vehicle as described through the ImpactSensorLocation enum. As a bit flag property, this property can be set to multiple ORed together values of the enum when necessary.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all bit flags of ImpactSensorLocation are supported." + "description": "Impact detected.\nBit flag property to relay information on whether an impact has occurred on a particular side of the vehicle as described through the ImpactSensorLocation enum. As a bit flag property, this property can be set to multiple ORed together values of the enum when necessary.\nFor the global area ID (0), {@code getSupportedValuesList} must return a {@code SupportedValuesListResult} that contains supported values unless all bit flags of ImpactSensorLocation are supported.\nFor backward compatibility, if {@code SupportedValuesListResult} is defined, {@code VehicleAreaConfig#supportedEnumValues} must be set to the same values." + }, + { + "name": "Vehicle horn engaged.", + "value": 287310656, + "description": "Vehicle horn engaged.\nThis property must communicate if the vehicle's horn is currently engaged or not. If true, the horn is engaged. If false, the horn is disengaged." }, { "name": "Currently selected gear", @@ -222,7 +276,7 @@ "VehicleGear" ], "data_enum": "VehicleGear", - "description": "Currently selected gear\nThis is the gear selected by the user.\nValues in the config data must represent the list of supported gears for this vehicle. For example, config data for an automatic transmission must contain {GEAR_NEUTRAL, GEAR_REVERSE, GEAR_PARK, GEAR_DRIVE, GEAR_1, GEAR_2,...} and for manual transmission the list must be {GEAR_NEUTRAL, GEAR_REVERSE, GEAR_1, GEAR_2,...}\nIn the case of an automatic transmission vehicle that allows the driver to select specific gears on demand (i.e. \"manual mode\"), GEAR_SELECTION's value must be set to the specific gear selected by the driver instead of simply GEAR_DRIVE." + "description": "Currently selected gear\nThis is the gear selected by the user.\n{@code VehicleAreaConfig.HasSupportedValueInfo.hasSupportedValuesList} for the global area ID (0) must be {@code true}.\n{@code getSupportedValuesList} for [GEAR_SELECTION, areaId=0] must return a {@code SupportedValuesListResult} that contains non-null {@code supportedValuesList}.\nThe supportedValues must represent the list of supported gears for this vehicle. For example, for an automatic transmission, the list can be {GEAR_NEUTRAL, GEAR_REVERSE, GEAR_PARK, GEAR_DRIVE, GEAR_1, GEAR_2,...} and for manual transmission it can be {GEAR_NEUTRAL, GEAR_REVERSE, GEAR_1, GEAR_2,...}.\nIn the case of an automatic transmission vehicle that allows the driver to select specific gears on demand (i.e. \"manual mode\"), GEAR_SELECTION's value must be set to the specific gear selected by the driver instead of simply GEAR_DRIVE.\nFor backward compatibility, config array for this property must be a list of values same as the supported values at boot-time." }, { "name": "CURRENT_GEAR", @@ -231,7 +285,7 @@ "VehicleGear" ], "data_enum": "VehicleGear", - "description": "Current gear. In non-manual case, selected gear may not match the current gear. For example, if the selected gear is GEAR_DRIVE, the current gear will be one of GEAR_1, GEAR_2 etc, which reflects the actual gear the transmission is currently running in.\nValues in the config data must represent the list of supported gears for this vehicle. For example, config data for an automatic transmission must contain {GEAR_NEUTRAL, GEAR_REVERSE, GEAR_PARK, GEAR_1, GEAR_2,...} and for manual transmission the list must be {GEAR_NEUTRAL, GEAR_REVERSE, GEAR_1, GEAR_2,...}. This list need not be the same as that of the supported gears reported in GEAR_SELECTION." + "description": "Current gear. In non-manual case, selected gear may not match the current gear. For example, if the selected gear is GEAR_DRIVE, the current gear will be one of GEAR_1, GEAR_2 etc, which reflects the actual gear the transmission is currently running in.\n{@code VehicleAreaConfig.HasSupportedValueInfo.hasSupportedValuesList} for the global area ID (0) must be {@code true}.\n{@code getSupportedValuesList} for [GEAR_SELECTION, areaId=0] must return a {@code SupportedValuesListResult} that contains non-null {@code supportedValuesList}.\nThe supported values list must represent the list of supported gears for this vehicle. For example, for an automatic transmission, this list can be {GEAR_NEUTRAL, GEAR_REVERSE, GEAR_PARK, GEAR_1, GEAR_2,...} and for manual transmission the list can be {GEAR_NEUTRAL, GEAR_REVERSE, GEAR_1, GEAR_2,...}. This list need not be the same as that of the supported gears reported in GEAR_SELECTION.\nFor backward compatibility, config array for this property must be a list of values same as the supported values at boot-time." }, { "name": "Parking brake state.", @@ -246,7 +300,7 @@ { "name": "EV_BRAKE_REGENERATION_LEVEL", "value": 289408012, - "description": "Regenerative braking level of a electronic vehicle\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All values between minInt32Value and maxInt32Value must be supported. The minInt32Value must be 0.\nThe maxInt32Value indicates the setting for the maximum amount of energy regenerated from braking. The minInt32Value indicates the setting for no regenerative braking.\nThis property is a more granular form of EV_REGENERATIVE_BRAKING_STATE. It allows the user to set a more specific level of regenerative braking if the states in EvRegenerativeBrakingState are not granular enough for the OEM.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only." + "description": "Regenerative braking level of a electronic vehicle\n{@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for global area ID(0)\n{@code MinMaxSupportedValueResult.minSupportedValue} must be 0.\n{@code MinMaxSupportedValueResult.maxSupportedValue} indicates the setting for the maximum amount of energy regenerated from braking. The minSupportedValue indicates the setting for no regenerative braking.\nAll values between min and max supported value must be supported.\nFor backward compatibility, minInt32Value and maxInt32Value in {@code VehicleAreaConfig} must be set to the same as minSupportedValue and maxSupportedValue at boot time.\nThis property is a more granular form of EV_REGENERATIVE_BRAKING_STATE. It allows the user to set a more specific level of regenerative braking if the states in EvRegenerativeBrakingState are not granular enough for the OEM.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only." }, { "name": "Warning for fuel low level.", @@ -265,7 +319,7 @@ "VehicleTurnSignal" ], "data_enum": "VehicleTurnSignal", - "description": "State of the vehicles turn signals" + "description": "(Deprecated) State of the vehicles turn signals\nThis property has been deprecated as it ambiguously defines the state of the vehicle turn signals without making clear if it means the state of the turn signal lights or the state of the turn signal switch. The introduction of TURN_SIGNAL_LIGHT_STATE and TURN_SIGNAL_SWITCH rectifies this problem." }, { "name": "Represents ignition state", @@ -293,7 +347,7 @@ "EvStoppingMode" ], "data_enum": "EvStoppingMode", - "description": "Represents property for the current stopping mode of the vehicle.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues must be defined unless all enum values of EvStoppingMode are supported.\nThe EvStoppingMode enum may be extended to include more states in the future.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only." + "description": "Represents property for the current stopping mode of the vehicle.\nFor the global area ID (0), {@code getSupportedValuesList} must return a {@code SupportedValuesListResult} that contains supported values unless all enum values of EvStoppingMode are supported.\nFor backward compatibility, if {@code SupportedValuesListResult} is defined, {@code VehicleAreaConfig#supportedEnumValues} must be set to the same values.\nThe EvStoppingMode enum may be extended to include more states in the future.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only." }, { "name": "ELECTRONIC_STABILITY_CONTROL_ENABLED", @@ -308,7 +362,25 @@ "ErrorState" ], "data_enum": "ElectronicStabilityControlState", - "description": "Electronic Stability Control (ESC) state.\nReturns the current state of ESC. This property must always return a valid state defined in ElectronicStabilityControlState or ErrorState. It must not surface errors through StatusCode and must use the supported error states instead.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of both ElectronicStabilityControlState (including OTHER, which is not recommended) and ErrorState are supported." + "description": "Electronic Stability Control (ESC) state.\nReturns the current state of ESC. This property must always return a valid state defined in ElectronicStabilityControlState or ErrorState. It must not surface errors through StatusCode and must use the supported error states instead.\nFor the global area ID (0), {@code getSupportedValuesList} must return a {@code SupportedValuesListResult} that contains supported values unless all states of both ElectronicStabilityControlState (including OTHER, which is not recommended) and ErrorState are supported.\nFor backward compatibility, if {@code SupportedValuesListResult} is defined, {@code VehicleAreaConfig#supportedEnumValues} must be set to the same values." + }, + { + "name": "Turn signal light state.", + "value": 289408016, + "data_enums": [ + "VehicleTurnSignal" + ], + "data_enum": "VehicleTurnSignal", + "description": "Turn signal light state.\nThis property must communicate the actual state of the turn signal lights.\nExamples: 1) Left turn signal light is currently pulsing, right turn signal light is currently off. This property must return VehicleTurnSignal.LEFT while the light is on during the pulse, and VehicleTurnSignal.NONE when it is off during the pulse. 2) Right turn signal light is currently pulsing, left turn signal light is currently off. This property must return VehicleTurnSignal.RIGHT while the light is on during the pulse, and VehicleTurnSignal.NONE when it is off during the pulse. 3) Both turn signal lights are currently pulsing (e.g. when hazard lights switch is on). This property must return VehicleTurnSignal.LEFT | VehicleTurnSignal.RIGHT while the lights are on during the pulse, and VehicleTurnSignal.NONE when they are off during the pulse.\nNote that this property uses VehicleTurnSignal as a bit flag, unlike TURN_SIGNAL_SWITCH, which uses it like a regular enum. This means this property can support ORed together values in VehicleTurnSignal.\nThis is different from the function of TURN_SIGNAL_SWITCH, which must communicate the state of the turn signal lever\/switch.\nThis property is a replacement to the TURN_SIGNAL_STATE property, which is now deprecated." + }, + { + "name": "Turn signal switch.", + "value": 289408017, + "data_enums": [ + "VehicleTurnSignal" + ], + "data_enum": "VehicleTurnSignal", + "description": "Turn signal switch.\nThis property must communicate the state of the turn signal lever\/switch. This is different from the function of TURN_SIGNAL_LIGHT_STATE, which must communicate the actual state of the turn signal lights.\nNote that this property uses VehicleTurnSignal as a regular enum, unlike TURN_SIGNAL_LIGHT_STATE, which uses it like a bit flag. This means this property cannot support ORed together values in VehicleTurnSignal.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only." }, { "name": "Fan speed setting", @@ -322,7 +394,7 @@ "VehicleHvacFanDirection" ], "data_enum": "VehicleHvacFanDirection", - "description": "Fan direction setting\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only." + "description": "Fan direction setting\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only.\nThe supported hvac fan direction is exposed through {@code HVAC_FAN_DIRECTION_AVAILABLE} property. Caller should not call {@code getSupportedValuesList}, or use {@code VehicleAreaConfig#supportedEnumValues}." }, { "name": "HVAC current temperature.", @@ -476,7 +548,11 @@ { "name": "Speed units for display", "value": 289408517, - "description": "Speed units for display\nIndicates type of units the car is using to display speed to user. Eg. m\/s, km\/h, or mph.\nVehiclePropConfig.configArray is used to indicate the supported speed display units. Pressure units are defined in VehicleUnit. For example: configArray[0] = METER_PER_SEC configArray[1] = MILES_PER_HOUR configArray[2] = KILOMETERS_PER_HOUR\nIf updating VEHICLE_SPEED_DISPLAY_UNITS affects the values of other *_DISPLAY_UNITS properties, then their values must be updated and communicated to the AAOS framework as well.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only." + "data_enums": [ + "VehicleUnit" + ], + "data_enum": "VehicleUnit", + "description": "Speed units for display\nIndicates type of units the car is using to display speed to user. Eg. m\/s, km\/h, or mph.\n{@code VehicleAreaConfig.HasSupportedValueInfo.hasSupportedValuesList} for the global area ID (0) must be {@code true}.\n{@code getSupportedValuesLists} for [VEHICLE_SPEED_DISPLAY_UNITS, areaId=0] must return a {@code SupportedValuesListResult} that contains non-null {@code supportedValuesList}, e.g. [METER_PER_SEC, MILES_PER_HOUR, KILOMETERS_PER_HOUR].\nFor backward compatibility, config array for this property must contain the same values as supported values at boot time. For example: configArray[0] = METER_PER_SEC configArray[1] = MILES_PER_HOUR configArray[2] = KILOMETERS_PER_HOUR\nIf updating VEHICLE_SPEED_DISPLAY_UNITS affects the values of other *_DISPLAY_UNITS properties, then their values must be updated and communicated to the AAOS framework as well.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only." }, { "name": "EXTERNAL_CAR_TIME", @@ -1352,7 +1428,16 @@ "VehicleAutonomousState" ], "data_enum": "VehicleAutonomousState", - "description": "Current state of vehicle autonomy.\nDefines the level of autonomy currently engaged in the vehicle from the J3016_202104 revision of the SAE standard levels 0-5, with 0 representing no autonomy and 5 representing full driving automation. These levels should be used in accordance with the standards defined in https:\/\/www.sae.org\/standards\/content\/j3016_202104\/ and https:\/\/www.sae.org\/blog\/sae-j3016-update\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of VehicleAutonomousState are supported." + "description": "Current state of vehicle autonomy.\nDefines the level of autonomy currently engaged in the vehicle from the J3016_202104 revision of the SAE standard levels 0-5, with 0 representing no autonomy and 5 representing full driving automation.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of VehicleAutonomousState are supported." + }, + { + "name": "VEHICLE_DRIVING_AUTOMATION_TARGET_LEVEL", + "value": 289410895, + "data_enums": [ + "VehicleAutonomousState" + ], + "data_enum": "VehicleAutonomousState", + "description": "Target state of vehicle autonomy.\nDefines the level of autonomy being targeted by the vehicle from the J3016_202104 revision of the SAE standard levels 0-5, with 0 representing no autonomy and 5 representing full driving automation.\nFor example, suppose the vehicle is currently in a Level 3 state of automation and wants to give the driver full manual control (i.e. Level 0) as soon as it's safe to do so. In this scenario, this property must be set to VehicleAutonomousState.LEVEL_0. Similarly, if the vehicle is currently in Level 1 state of automation and wants to go up to Level 2, this property must be set to VehicleAutonomousState.LEVEL_2. If the vehicle has already reached and is currently in the target level of autonomy, this property must be equal to the value of VEHICLE_DRIVING_AUTOMATION_CURRENT_LEVEL.\nFor the global area ID (0), the SupportedValuesListResult#supportedValuesList array must be defined unless all states of VehicleAutonomousState are supported. These values must match the values in supportedValuesList of VEHICLE_DRIVING_AUTOMATION_CURRENT_LEVEL.\nFor the property that communicates the current state of autonomy, see VEHICLE_DRIVING_AUTOMATION_CURRENT_LEVEL." }, { "name": "CAMERA_SERVICE_CURRENT_STATE", @@ -2191,6 +2276,14 @@ "name": "GBT_DC", "value": 11 }, + { + "name": "SAE_J3400_AC", + "value": 8 + }, + { + "name": "SAE_J3400_DC", + "value": 9 + }, { "name": "OTHER", "value": 101 @@ -2949,6 +3042,152 @@ } ] }, + { + "name": "VehicleSizeClass", + "package": "android.hardware.automotive.vehicle", + "values": [ + { + "name": "EPA_TWO_SEATER", + "value": 256 + }, + { + "name": "EPA_MINICOMPACT", + "value": 257 + }, + { + "name": "EPA_SUBCOMPACT", + "value": 258 + }, + { + "name": "EPA_COMPACT", + "value": 259 + }, + { + "name": "EPA_MIDSIZE", + "value": 260 + }, + { + "name": "EPA_LARGE", + "value": 261 + }, + { + "name": "EPA_SMALL_STATION_WAGON", + "value": 262 + }, + { + "name": "EPA_MIDSIZE_STATION_WAGON", + "value": 263 + }, + { + "name": "EPA_LARGE_STATION_WAGON", + "value": 264 + }, + { + "name": "EPA_SMALL_PICKUP_TRUCK", + "value": 265 + }, + { + "name": "EPA_STANDARD_PICKUP_TRUCK", + "value": 266 + }, + { + "name": "EPA_VAN", + "value": 267 + }, + { + "name": "EPA_MINIVAN", + "value": 268 + }, + { + "name": "EPA_SMALL_SUV", + "value": 269 + }, + { + "name": "EPA_STANDARD_SUV", + "value": 270 + }, + { + "name": "EU_A_SEGMENT", + "value": 512 + }, + { + "name": "EU_B_SEGMENT", + "value": 513 + }, + { + "name": "EU_C_SEGMENT", + "value": 514 + }, + { + "name": "EU_D_SEGMENT", + "value": 515 + }, + { + "name": "EU_E_SEGMENT", + "value": 516 + }, + { + "name": "EU_F_SEGMENT", + "value": 517 + }, + { + "name": "EU_J_SEGMENT", + "value": 518 + }, + { + "name": "EU_M_SEGMENT", + "value": 519 + }, + { + "name": "EU_S_SEGMENT", + "value": 520 + }, + { + "name": "JPN_KEI", + "value": 768 + }, + { + "name": "JPN_SMALL_SIZE", + "value": 769 + }, + { + "name": "JPN_NORMAL_SIZE", + "value": 770 + }, + { + "name": "US_GVWR_CLASS_1_CV", + "value": 1024 + }, + { + "name": "US_GVWR_CLASS_2_CV", + "value": 1025 + }, + { + "name": "US_GVWR_CLASS_3_CV", + "value": 1026 + }, + { + "name": "US_GVWR_CLASS_4_CV", + "value": 1027 + }, + { + "name": "US_GVWR_CLASS_5_CV", + "value": 1028 + }, + { + "name": "US_GVWR_CLASS_6_CV", + "value": 1029 + }, + { + "name": "US_GVWR_CLASS_7_CV", + "value": 1030 + }, + { + "name": "US_GVWR_CLASS_8_CV", + "value": 1031 + } + ] + }, { "name": "VehicleTurnSignal", "package": "android.hardware.automotive.vehicle", diff --git a/automotive/vehicle/aidl/generated_lib/3/cpp/Android.bp b/automotive/vehicle/aidl/generated_lib/3/cpp/Android.bp index 7ff27a466035a9ed22e48d5e927075bc6f141632..612ed6471f9d04b17dd80b54210d2463fff90935 100644 --- a/automotive/vehicle/aidl/generated_lib/3/cpp/Android.bp +++ b/automotive/vehicle/aidl/generated_lib/3/cpp/Android.bp @@ -18,11 +18,20 @@ package { default_applicable_licenses: ["Android-Apache-2.0"], } +cc_library_headers { + name: "IVehicleGeneratedHeaders-V3-default", + vendor_available: true, + local_include_dirs: ["."], + export_include_dirs: ["."], + defaults: ["VehicleHalInterfaceDefaults-V3"], + host_supported: true, +} + cc_library_headers { name: "IVehicleGeneratedHeaders-V3", vendor_available: true, local_include_dirs: ["."], export_include_dirs: ["."], - defaults: ["VehicleHalInterfaceDefaults"], + defaults: ["VehicleHalInterfaceDefaults-V3"], host_supported: true, } diff --git a/automotive/vehicle/aidl/generated_lib/4/cpp/AccessForVehicleProperty.h b/automotive/vehicle/aidl/generated_lib/4/cpp/AccessForVehicleProperty.h index 6d07fe5c008262e9e30c42d6938ba38de11abbc3..8441af31dea6547480cb36cff3646f417bfc9763 100644 --- a/automotive/vehicle/aidl/generated_lib/4/cpp/AccessForVehicleProperty.h +++ b/automotive/vehicle/aidl/generated_lib/4/cpp/AccessForVehicleProperty.h @@ -49,11 +49,15 @@ std::unordered_map AccessForVehiclePrope {VehicleProperty::INFO_DRIVER_SEAT, VehiclePropertyAccess::READ}, {VehicleProperty::INFO_EXTERIOR_DIMENSIONS, VehiclePropertyAccess::READ}, {VehicleProperty::INFO_MULTI_EV_PORT_LOCATIONS, VehiclePropertyAccess::READ}, + {VehicleProperty::INFO_MODEL_TRIM, VehiclePropertyAccess::READ}, + {VehicleProperty::INFO_VEHICLE_SIZE_CLASS, VehiclePropertyAccess::READ}, {VehicleProperty::PERF_ODOMETER, VehiclePropertyAccess::READ}, {VehicleProperty::PERF_VEHICLE_SPEED, VehiclePropertyAccess::READ}, {VehicleProperty::PERF_VEHICLE_SPEED_DISPLAY, VehiclePropertyAccess::READ}, {VehicleProperty::PERF_STEERING_ANGLE, VehiclePropertyAccess::READ}, {VehicleProperty::PERF_REAR_STEERING_ANGLE, VehiclePropertyAccess::READ}, + {VehicleProperty::INSTANTANEOUS_FUEL_ECONOMY, VehiclePropertyAccess::READ}, + {VehicleProperty::INSTANTANEOUS_EV_EFFICIENCY, VehiclePropertyAccess::READ}, {VehicleProperty::ENGINE_COOLANT_TEMP, VehiclePropertyAccess::READ}, {VehicleProperty::ENGINE_OIL_LEVEL, VehiclePropertyAccess::READ}, {VehicleProperty::ENGINE_OIL_TEMP, VehiclePropertyAccess::READ}, @@ -70,8 +74,14 @@ std::unordered_map AccessForVehiclePrope {VehicleProperty::EV_BATTERY_AVERAGE_TEMPERATURE, VehiclePropertyAccess::READ}, {VehicleProperty::TIRE_PRESSURE, VehiclePropertyAccess::READ}, {VehicleProperty::CRITICALLY_LOW_TIRE_PRESSURE, VehiclePropertyAccess::READ}, + {VehicleProperty::ACCELERATOR_PEDAL_COMPRESSION_PERCENTAGE, VehiclePropertyAccess::READ}, + {VehicleProperty::BRAKE_PEDAL_COMPRESSION_PERCENTAGE, VehiclePropertyAccess::READ}, + {VehicleProperty::BRAKE_PAD_WEAR_PERCENTAGE, VehiclePropertyAccess::READ}, + {VehicleProperty::BRAKE_FLUID_LEVEL_LOW, VehiclePropertyAccess::READ}, + {VehicleProperty::VEHICLE_PASSIVE_SUSPENSION_HEIGHT, VehiclePropertyAccess::READ}, {VehicleProperty::ENGINE_IDLE_AUTO_STOP_ENABLED, VehiclePropertyAccess::READ_WRITE}, {VehicleProperty::IMPACT_DETECTED, VehiclePropertyAccess::READ}, + {VehicleProperty::VEHICLE_HORN_ENGAGED, VehiclePropertyAccess::READ_WRITE}, {VehicleProperty::GEAR_SELECTION, VehiclePropertyAccess::READ}, {VehicleProperty::CURRENT_GEAR, VehiclePropertyAccess::READ}, {VehicleProperty::PARKING_BRAKE_ON, VehiclePropertyAccess::READ}, @@ -86,6 +96,8 @@ std::unordered_map AccessForVehiclePrope {VehicleProperty::EV_STOPPING_MODE, VehiclePropertyAccess::READ_WRITE}, {VehicleProperty::ELECTRONIC_STABILITY_CONTROL_ENABLED, VehiclePropertyAccess::READ_WRITE}, {VehicleProperty::ELECTRONIC_STABILITY_CONTROL_STATE, VehiclePropertyAccess::READ}, + {VehicleProperty::TURN_SIGNAL_LIGHT_STATE, VehiclePropertyAccess::READ}, + {VehicleProperty::TURN_SIGNAL_SWITCH, VehiclePropertyAccess::READ_WRITE}, {VehicleProperty::HVAC_FAN_SPEED, VehiclePropertyAccess::READ_WRITE}, {VehicleProperty::HVAC_FAN_DIRECTION, VehiclePropertyAccess::READ_WRITE}, {VehicleProperty::HVAC_TEMPERATURE_CURRENT, VehiclePropertyAccess::READ}, @@ -262,6 +274,7 @@ std::unordered_map AccessForVehiclePrope {VehicleProperty::VEHICLE_IN_USE, VehiclePropertyAccess::READ_WRITE}, {VehicleProperty::CLUSTER_HEARTBEAT, VehiclePropertyAccess::WRITE}, {VehicleProperty::VEHICLE_DRIVING_AUTOMATION_CURRENT_LEVEL, VehiclePropertyAccess::READ}, + {VehicleProperty::VEHICLE_DRIVING_AUTOMATION_TARGET_LEVEL, VehiclePropertyAccess::READ}, {VehicleProperty::CAMERA_SERVICE_CURRENT_STATE, VehiclePropertyAccess::WRITE}, {VehicleProperty::PER_DISPLAY_MAX_BRIGHTNESS, VehiclePropertyAccess::READ}, {VehicleProperty::AUTOMATIC_EMERGENCY_BRAKING_ENABLED, VehiclePropertyAccess::READ_WRITE}, diff --git a/automotive/vehicle/aidl/generated_lib/4/cpp/ChangeModeForVehicleProperty.h b/automotive/vehicle/aidl/generated_lib/4/cpp/ChangeModeForVehicleProperty.h index 5ecee9570848a522a103f496fe3af15cbf8e923e..3775f1872218c181ed9aa9bb67e39c9c198fed32 100644 --- a/automotive/vehicle/aidl/generated_lib/4/cpp/ChangeModeForVehicleProperty.h +++ b/automotive/vehicle/aidl/generated_lib/4/cpp/ChangeModeForVehicleProperty.h @@ -49,11 +49,15 @@ std::unordered_map ChangeModeForVehi {VehicleProperty::INFO_DRIVER_SEAT, VehiclePropertyChangeMode::STATIC}, {VehicleProperty::INFO_EXTERIOR_DIMENSIONS, VehiclePropertyChangeMode::STATIC}, {VehicleProperty::INFO_MULTI_EV_PORT_LOCATIONS, VehiclePropertyChangeMode::STATIC}, + {VehicleProperty::INFO_MODEL_TRIM, VehiclePropertyChangeMode::STATIC}, + {VehicleProperty::INFO_VEHICLE_SIZE_CLASS, VehiclePropertyChangeMode::STATIC}, {VehicleProperty::PERF_ODOMETER, VehiclePropertyChangeMode::CONTINUOUS}, {VehicleProperty::PERF_VEHICLE_SPEED, VehiclePropertyChangeMode::CONTINUOUS}, {VehicleProperty::PERF_VEHICLE_SPEED_DISPLAY, VehiclePropertyChangeMode::CONTINUOUS}, {VehicleProperty::PERF_STEERING_ANGLE, VehiclePropertyChangeMode::CONTINUOUS}, {VehicleProperty::PERF_REAR_STEERING_ANGLE, VehiclePropertyChangeMode::CONTINUOUS}, + {VehicleProperty::INSTANTANEOUS_FUEL_ECONOMY, VehiclePropertyChangeMode::CONTINUOUS}, + {VehicleProperty::INSTANTANEOUS_EV_EFFICIENCY, VehiclePropertyChangeMode::CONTINUOUS}, {VehicleProperty::ENGINE_COOLANT_TEMP, VehiclePropertyChangeMode::CONTINUOUS}, {VehicleProperty::ENGINE_OIL_LEVEL, VehiclePropertyChangeMode::ON_CHANGE}, {VehicleProperty::ENGINE_OIL_TEMP, VehiclePropertyChangeMode::CONTINUOUS}, @@ -70,8 +74,14 @@ std::unordered_map ChangeModeForVehi {VehicleProperty::EV_BATTERY_AVERAGE_TEMPERATURE, VehiclePropertyChangeMode::CONTINUOUS}, {VehicleProperty::TIRE_PRESSURE, VehiclePropertyChangeMode::CONTINUOUS}, {VehicleProperty::CRITICALLY_LOW_TIRE_PRESSURE, VehiclePropertyChangeMode::STATIC}, + {VehicleProperty::ACCELERATOR_PEDAL_COMPRESSION_PERCENTAGE, VehiclePropertyChangeMode::CONTINUOUS}, + {VehicleProperty::BRAKE_PEDAL_COMPRESSION_PERCENTAGE, VehiclePropertyChangeMode::CONTINUOUS}, + {VehicleProperty::BRAKE_PAD_WEAR_PERCENTAGE, VehiclePropertyChangeMode::ON_CHANGE}, + {VehicleProperty::BRAKE_FLUID_LEVEL_LOW, VehiclePropertyChangeMode::ON_CHANGE}, + {VehicleProperty::VEHICLE_PASSIVE_SUSPENSION_HEIGHT, VehiclePropertyChangeMode::CONTINUOUS}, {VehicleProperty::ENGINE_IDLE_AUTO_STOP_ENABLED, VehiclePropertyChangeMode::ON_CHANGE}, {VehicleProperty::IMPACT_DETECTED, VehiclePropertyChangeMode::ON_CHANGE}, + {VehicleProperty::VEHICLE_HORN_ENGAGED, VehiclePropertyChangeMode::ON_CHANGE}, {VehicleProperty::GEAR_SELECTION, VehiclePropertyChangeMode::ON_CHANGE}, {VehicleProperty::CURRENT_GEAR, VehiclePropertyChangeMode::ON_CHANGE}, {VehicleProperty::PARKING_BRAKE_ON, VehiclePropertyChangeMode::ON_CHANGE}, @@ -86,6 +96,8 @@ std::unordered_map ChangeModeForVehi {VehicleProperty::EV_STOPPING_MODE, VehiclePropertyChangeMode::ON_CHANGE}, {VehicleProperty::ELECTRONIC_STABILITY_CONTROL_ENABLED, VehiclePropertyChangeMode::ON_CHANGE}, {VehicleProperty::ELECTRONIC_STABILITY_CONTROL_STATE, VehiclePropertyChangeMode::ON_CHANGE}, + {VehicleProperty::TURN_SIGNAL_LIGHT_STATE, VehiclePropertyChangeMode::ON_CHANGE}, + {VehicleProperty::TURN_SIGNAL_SWITCH, VehiclePropertyChangeMode::ON_CHANGE}, {VehicleProperty::HVAC_FAN_SPEED, VehiclePropertyChangeMode::ON_CHANGE}, {VehicleProperty::HVAC_FAN_DIRECTION, VehiclePropertyChangeMode::ON_CHANGE}, {VehicleProperty::HVAC_TEMPERATURE_CURRENT, VehiclePropertyChangeMode::ON_CHANGE}, @@ -262,6 +274,7 @@ std::unordered_map ChangeModeForVehi {VehicleProperty::VEHICLE_IN_USE, VehiclePropertyChangeMode::ON_CHANGE}, {VehicleProperty::CLUSTER_HEARTBEAT, VehiclePropertyChangeMode::ON_CHANGE}, {VehicleProperty::VEHICLE_DRIVING_AUTOMATION_CURRENT_LEVEL, VehiclePropertyChangeMode::ON_CHANGE}, + {VehicleProperty::VEHICLE_DRIVING_AUTOMATION_TARGET_LEVEL, VehiclePropertyChangeMode::ON_CHANGE}, {VehicleProperty::CAMERA_SERVICE_CURRENT_STATE, VehiclePropertyChangeMode::ON_CHANGE}, {VehicleProperty::PER_DISPLAY_MAX_BRIGHTNESS, VehiclePropertyChangeMode::STATIC}, {VehicleProperty::AUTOMATIC_EMERGENCY_BRAKING_ENABLED, VehiclePropertyChangeMode::ON_CHANGE}, diff --git a/automotive/vehicle/aidl/generated_lib/4/cpp/VersionForVehicleProperty.h b/automotive/vehicle/aidl/generated_lib/4/cpp/VersionForVehicleProperty.h index 8b9c1bdf39d9b2c5879382e014d37f7ad018d6f8..0a28b68594e158e4e3f09a6b55766b693b6e682c 100644 --- a/automotive/vehicle/aidl/generated_lib/4/cpp/VersionForVehicleProperty.h +++ b/automotive/vehicle/aidl/generated_lib/4/cpp/VersionForVehicleProperty.h @@ -48,11 +48,15 @@ std::unordered_map VersionForVehicleProperty = { {VehicleProperty::INFO_DRIVER_SEAT, 2}, {VehicleProperty::INFO_EXTERIOR_DIMENSIONS, 2}, {VehicleProperty::INFO_MULTI_EV_PORT_LOCATIONS, 2}, + {VehicleProperty::INFO_MODEL_TRIM, 4}, + {VehicleProperty::INFO_VEHICLE_SIZE_CLASS, 4}, {VehicleProperty::PERF_ODOMETER, 2}, {VehicleProperty::PERF_VEHICLE_SPEED, 2}, {VehicleProperty::PERF_VEHICLE_SPEED_DISPLAY, 2}, {VehicleProperty::PERF_STEERING_ANGLE, 2}, {VehicleProperty::PERF_REAR_STEERING_ANGLE, 2}, + {VehicleProperty::INSTANTANEOUS_FUEL_ECONOMY, 4}, + {VehicleProperty::INSTANTANEOUS_EV_EFFICIENCY, 4}, {VehicleProperty::ENGINE_COOLANT_TEMP, 2}, {VehicleProperty::ENGINE_OIL_LEVEL, 2}, {VehicleProperty::ENGINE_OIL_TEMP, 2}, @@ -69,8 +73,14 @@ std::unordered_map VersionForVehicleProperty = { {VehicleProperty::EV_BATTERY_AVERAGE_TEMPERATURE, 3}, {VehicleProperty::TIRE_PRESSURE, 2}, {VehicleProperty::CRITICALLY_LOW_TIRE_PRESSURE, 2}, + {VehicleProperty::ACCELERATOR_PEDAL_COMPRESSION_PERCENTAGE, 4}, + {VehicleProperty::BRAKE_PEDAL_COMPRESSION_PERCENTAGE, 4}, + {VehicleProperty::BRAKE_PAD_WEAR_PERCENTAGE, 4}, + {VehicleProperty::BRAKE_FLUID_LEVEL_LOW, 4}, + {VehicleProperty::VEHICLE_PASSIVE_SUSPENSION_HEIGHT, 4}, {VehicleProperty::ENGINE_IDLE_AUTO_STOP_ENABLED, 2}, {VehicleProperty::IMPACT_DETECTED, 3}, + {VehicleProperty::VEHICLE_HORN_ENGAGED, 4}, {VehicleProperty::GEAR_SELECTION, 2}, {VehicleProperty::CURRENT_GEAR, 2}, {VehicleProperty::PARKING_BRAKE_ON, 2}, @@ -85,6 +95,8 @@ std::unordered_map VersionForVehicleProperty = { {VehicleProperty::EV_STOPPING_MODE, 2}, {VehicleProperty::ELECTRONIC_STABILITY_CONTROL_ENABLED, 3}, {VehicleProperty::ELECTRONIC_STABILITY_CONTROL_STATE, 3}, + {VehicleProperty::TURN_SIGNAL_LIGHT_STATE, 4}, + {VehicleProperty::TURN_SIGNAL_SWITCH, 4}, {VehicleProperty::HVAC_FAN_SPEED, 2}, {VehicleProperty::HVAC_FAN_DIRECTION, 2}, {VehicleProperty::HVAC_TEMPERATURE_CURRENT, 2}, @@ -261,6 +273,7 @@ std::unordered_map VersionForVehicleProperty = { {VehicleProperty::VEHICLE_IN_USE, 2}, {VehicleProperty::CLUSTER_HEARTBEAT, 3}, {VehicleProperty::VEHICLE_DRIVING_AUTOMATION_CURRENT_LEVEL, 3}, + {VehicleProperty::VEHICLE_DRIVING_AUTOMATION_TARGET_LEVEL, 4}, {VehicleProperty::CAMERA_SERVICE_CURRENT_STATE, 3}, {VehicleProperty::PER_DISPLAY_MAX_BRIGHTNESS, 3}, {VehicleProperty::AUTOMATIC_EMERGENCY_BRAKING_ENABLED, 2}, diff --git a/automotive/vehicle/aidl/generated_lib/4/java/AccessForVehicleProperty.java b/automotive/vehicle/aidl/generated_lib/4/java/AccessForVehicleProperty.java index e9f35a5e9b2c7b5af4f83c94dd32fcd115428337..1a68d4d213c1bc57c106d1bac18747de237bf51a 100644 --- a/automotive/vehicle/aidl/generated_lib/4/java/AccessForVehicleProperty.java +++ b/automotive/vehicle/aidl/generated_lib/4/java/AccessForVehicleProperty.java @@ -42,11 +42,15 @@ public final class AccessForVehicleProperty { Map.entry(VehicleProperty.INFO_DRIVER_SEAT, VehiclePropertyAccess.READ), Map.entry(VehicleProperty.INFO_EXTERIOR_DIMENSIONS, VehiclePropertyAccess.READ), Map.entry(VehicleProperty.INFO_MULTI_EV_PORT_LOCATIONS, VehiclePropertyAccess.READ), + Map.entry(VehicleProperty.INFO_MODEL_TRIM, VehiclePropertyAccess.READ), + Map.entry(VehicleProperty.INFO_VEHICLE_SIZE_CLASS, VehiclePropertyAccess.READ), Map.entry(VehicleProperty.PERF_ODOMETER, VehiclePropertyAccess.READ), Map.entry(VehicleProperty.PERF_VEHICLE_SPEED, VehiclePropertyAccess.READ), Map.entry(VehicleProperty.PERF_VEHICLE_SPEED_DISPLAY, VehiclePropertyAccess.READ), Map.entry(VehicleProperty.PERF_STEERING_ANGLE, VehiclePropertyAccess.READ), Map.entry(VehicleProperty.PERF_REAR_STEERING_ANGLE, VehiclePropertyAccess.READ), + Map.entry(VehicleProperty.INSTANTANEOUS_FUEL_ECONOMY, VehiclePropertyAccess.READ), + Map.entry(VehicleProperty.INSTANTANEOUS_EV_EFFICIENCY, VehiclePropertyAccess.READ), Map.entry(VehicleProperty.ENGINE_COOLANT_TEMP, VehiclePropertyAccess.READ), Map.entry(VehicleProperty.ENGINE_OIL_LEVEL, VehiclePropertyAccess.READ), Map.entry(VehicleProperty.ENGINE_OIL_TEMP, VehiclePropertyAccess.READ), @@ -63,8 +67,14 @@ public final class AccessForVehicleProperty { Map.entry(VehicleProperty.EV_BATTERY_AVERAGE_TEMPERATURE, VehiclePropertyAccess.READ), Map.entry(VehicleProperty.TIRE_PRESSURE, VehiclePropertyAccess.READ), Map.entry(VehicleProperty.CRITICALLY_LOW_TIRE_PRESSURE, VehiclePropertyAccess.READ), + Map.entry(VehicleProperty.ACCELERATOR_PEDAL_COMPRESSION_PERCENTAGE, VehiclePropertyAccess.READ), + Map.entry(VehicleProperty.BRAKE_PEDAL_COMPRESSION_PERCENTAGE, VehiclePropertyAccess.READ), + Map.entry(VehicleProperty.BRAKE_PAD_WEAR_PERCENTAGE, VehiclePropertyAccess.READ), + Map.entry(VehicleProperty.BRAKE_FLUID_LEVEL_LOW, VehiclePropertyAccess.READ), + Map.entry(VehicleProperty.VEHICLE_PASSIVE_SUSPENSION_HEIGHT, VehiclePropertyAccess.READ), Map.entry(VehicleProperty.ENGINE_IDLE_AUTO_STOP_ENABLED, VehiclePropertyAccess.READ_WRITE), Map.entry(VehicleProperty.IMPACT_DETECTED, VehiclePropertyAccess.READ), + Map.entry(VehicleProperty.VEHICLE_HORN_ENGAGED, VehiclePropertyAccess.READ_WRITE), Map.entry(VehicleProperty.GEAR_SELECTION, VehiclePropertyAccess.READ), Map.entry(VehicleProperty.CURRENT_GEAR, VehiclePropertyAccess.READ), Map.entry(VehicleProperty.PARKING_BRAKE_ON, VehiclePropertyAccess.READ), @@ -79,6 +89,8 @@ public final class AccessForVehicleProperty { Map.entry(VehicleProperty.EV_STOPPING_MODE, VehiclePropertyAccess.READ_WRITE), Map.entry(VehicleProperty.ELECTRONIC_STABILITY_CONTROL_ENABLED, VehiclePropertyAccess.READ_WRITE), Map.entry(VehicleProperty.ELECTRONIC_STABILITY_CONTROL_STATE, VehiclePropertyAccess.READ), + Map.entry(VehicleProperty.TURN_SIGNAL_LIGHT_STATE, VehiclePropertyAccess.READ), + Map.entry(VehicleProperty.TURN_SIGNAL_SWITCH, VehiclePropertyAccess.READ_WRITE), Map.entry(VehicleProperty.HVAC_FAN_SPEED, VehiclePropertyAccess.READ_WRITE), Map.entry(VehicleProperty.HVAC_FAN_DIRECTION, VehiclePropertyAccess.READ_WRITE), Map.entry(VehicleProperty.HVAC_TEMPERATURE_CURRENT, VehiclePropertyAccess.READ), @@ -255,6 +267,7 @@ public final class AccessForVehicleProperty { Map.entry(VehicleProperty.VEHICLE_IN_USE, VehiclePropertyAccess.READ_WRITE), Map.entry(VehicleProperty.CLUSTER_HEARTBEAT, VehiclePropertyAccess.WRITE), Map.entry(VehicleProperty.VEHICLE_DRIVING_AUTOMATION_CURRENT_LEVEL, VehiclePropertyAccess.READ), + Map.entry(VehicleProperty.VEHICLE_DRIVING_AUTOMATION_TARGET_LEVEL, VehiclePropertyAccess.READ), Map.entry(VehicleProperty.CAMERA_SERVICE_CURRENT_STATE, VehiclePropertyAccess.WRITE), Map.entry(VehicleProperty.PER_DISPLAY_MAX_BRIGHTNESS, VehiclePropertyAccess.READ), Map.entry(VehicleProperty.AUTOMATIC_EMERGENCY_BRAKING_ENABLED, VehiclePropertyAccess.READ_WRITE), diff --git a/automotive/vehicle/aidl/generated_lib/4/java/ChangeModeForVehicleProperty.java b/automotive/vehicle/aidl/generated_lib/4/java/ChangeModeForVehicleProperty.java index 3fb52b771e115718a6b9f393098936cd97837220..a0dab663d30f387ee1e6f8fb0504d83526d3e0a4 100644 --- a/automotive/vehicle/aidl/generated_lib/4/java/ChangeModeForVehicleProperty.java +++ b/automotive/vehicle/aidl/generated_lib/4/java/ChangeModeForVehicleProperty.java @@ -42,11 +42,15 @@ public final class ChangeModeForVehicleProperty { Map.entry(VehicleProperty.INFO_DRIVER_SEAT, VehiclePropertyChangeMode.STATIC), Map.entry(VehicleProperty.INFO_EXTERIOR_DIMENSIONS, VehiclePropertyChangeMode.STATIC), Map.entry(VehicleProperty.INFO_MULTI_EV_PORT_LOCATIONS, VehiclePropertyChangeMode.STATIC), + Map.entry(VehicleProperty.INFO_MODEL_TRIM, VehiclePropertyChangeMode.STATIC), + Map.entry(VehicleProperty.INFO_VEHICLE_SIZE_CLASS, VehiclePropertyChangeMode.STATIC), Map.entry(VehicleProperty.PERF_ODOMETER, VehiclePropertyChangeMode.CONTINUOUS), Map.entry(VehicleProperty.PERF_VEHICLE_SPEED, VehiclePropertyChangeMode.CONTINUOUS), Map.entry(VehicleProperty.PERF_VEHICLE_SPEED_DISPLAY, VehiclePropertyChangeMode.CONTINUOUS), Map.entry(VehicleProperty.PERF_STEERING_ANGLE, VehiclePropertyChangeMode.CONTINUOUS), Map.entry(VehicleProperty.PERF_REAR_STEERING_ANGLE, VehiclePropertyChangeMode.CONTINUOUS), + Map.entry(VehicleProperty.INSTANTANEOUS_FUEL_ECONOMY, VehiclePropertyChangeMode.CONTINUOUS), + Map.entry(VehicleProperty.INSTANTANEOUS_EV_EFFICIENCY, VehiclePropertyChangeMode.CONTINUOUS), Map.entry(VehicleProperty.ENGINE_COOLANT_TEMP, VehiclePropertyChangeMode.CONTINUOUS), Map.entry(VehicleProperty.ENGINE_OIL_LEVEL, VehiclePropertyChangeMode.ON_CHANGE), Map.entry(VehicleProperty.ENGINE_OIL_TEMP, VehiclePropertyChangeMode.CONTINUOUS), @@ -63,8 +67,14 @@ public final class ChangeModeForVehicleProperty { Map.entry(VehicleProperty.EV_BATTERY_AVERAGE_TEMPERATURE, VehiclePropertyChangeMode.CONTINUOUS), Map.entry(VehicleProperty.TIRE_PRESSURE, VehiclePropertyChangeMode.CONTINUOUS), Map.entry(VehicleProperty.CRITICALLY_LOW_TIRE_PRESSURE, VehiclePropertyChangeMode.STATIC), + Map.entry(VehicleProperty.ACCELERATOR_PEDAL_COMPRESSION_PERCENTAGE, VehiclePropertyChangeMode.CONTINUOUS), + Map.entry(VehicleProperty.BRAKE_PEDAL_COMPRESSION_PERCENTAGE, VehiclePropertyChangeMode.CONTINUOUS), + Map.entry(VehicleProperty.BRAKE_PAD_WEAR_PERCENTAGE, VehiclePropertyChangeMode.ON_CHANGE), + Map.entry(VehicleProperty.BRAKE_FLUID_LEVEL_LOW, VehiclePropertyChangeMode.ON_CHANGE), + Map.entry(VehicleProperty.VEHICLE_PASSIVE_SUSPENSION_HEIGHT, VehiclePropertyChangeMode.CONTINUOUS), Map.entry(VehicleProperty.ENGINE_IDLE_AUTO_STOP_ENABLED, VehiclePropertyChangeMode.ON_CHANGE), Map.entry(VehicleProperty.IMPACT_DETECTED, VehiclePropertyChangeMode.ON_CHANGE), + Map.entry(VehicleProperty.VEHICLE_HORN_ENGAGED, VehiclePropertyChangeMode.ON_CHANGE), Map.entry(VehicleProperty.GEAR_SELECTION, VehiclePropertyChangeMode.ON_CHANGE), Map.entry(VehicleProperty.CURRENT_GEAR, VehiclePropertyChangeMode.ON_CHANGE), Map.entry(VehicleProperty.PARKING_BRAKE_ON, VehiclePropertyChangeMode.ON_CHANGE), @@ -79,6 +89,8 @@ public final class ChangeModeForVehicleProperty { Map.entry(VehicleProperty.EV_STOPPING_MODE, VehiclePropertyChangeMode.ON_CHANGE), Map.entry(VehicleProperty.ELECTRONIC_STABILITY_CONTROL_ENABLED, VehiclePropertyChangeMode.ON_CHANGE), Map.entry(VehicleProperty.ELECTRONIC_STABILITY_CONTROL_STATE, VehiclePropertyChangeMode.ON_CHANGE), + Map.entry(VehicleProperty.TURN_SIGNAL_LIGHT_STATE, VehiclePropertyChangeMode.ON_CHANGE), + Map.entry(VehicleProperty.TURN_SIGNAL_SWITCH, VehiclePropertyChangeMode.ON_CHANGE), Map.entry(VehicleProperty.HVAC_FAN_SPEED, VehiclePropertyChangeMode.ON_CHANGE), Map.entry(VehicleProperty.HVAC_FAN_DIRECTION, VehiclePropertyChangeMode.ON_CHANGE), Map.entry(VehicleProperty.HVAC_TEMPERATURE_CURRENT, VehiclePropertyChangeMode.ON_CHANGE), @@ -255,6 +267,7 @@ public final class ChangeModeForVehicleProperty { Map.entry(VehicleProperty.VEHICLE_IN_USE, VehiclePropertyChangeMode.ON_CHANGE), Map.entry(VehicleProperty.CLUSTER_HEARTBEAT, VehiclePropertyChangeMode.ON_CHANGE), Map.entry(VehicleProperty.VEHICLE_DRIVING_AUTOMATION_CURRENT_LEVEL, VehiclePropertyChangeMode.ON_CHANGE), + Map.entry(VehicleProperty.VEHICLE_DRIVING_AUTOMATION_TARGET_LEVEL, VehiclePropertyChangeMode.ON_CHANGE), Map.entry(VehicleProperty.CAMERA_SERVICE_CURRENT_STATE, VehiclePropertyChangeMode.ON_CHANGE), Map.entry(VehicleProperty.PER_DISPLAY_MAX_BRIGHTNESS, VehiclePropertyChangeMode.STATIC), Map.entry(VehicleProperty.AUTOMATIC_EMERGENCY_BRAKING_ENABLED, VehiclePropertyChangeMode.ON_CHANGE), diff --git a/automotive/vehicle/aidl/generated_lib/4/java/EnumForVehicleProperty.java b/automotive/vehicle/aidl/generated_lib/4/java/EnumForVehicleProperty.java index 0f86bfa14dcbb8c994e9e853ddfe8332f9045fc1..7ab14ecf8eb28da9f086c5f34605b32c619f938e 100644 --- a/automotive/vehicle/aidl/generated_lib/4/java/EnumForVehicleProperty.java +++ b/automotive/vehicle/aidl/generated_lib/4/java/EnumForVehicleProperty.java @@ -36,6 +36,7 @@ public final class EnumForVehicleProperty { Map.entry(VehicleProperty.INFO_EV_PORT_LOCATION, List.of(PortLocationType.class)), Map.entry(VehicleProperty.INFO_DRIVER_SEAT, List.of(VehicleAreaSeat.class)), Map.entry(VehicleProperty.INFO_MULTI_EV_PORT_LOCATIONS, List.of(PortLocationType.class)), + Map.entry(VehicleProperty.INFO_VEHICLE_SIZE_CLASS, List.of(VehicleSizeClass.class)), Map.entry(VehicleProperty.ENGINE_OIL_LEVEL, List.of(VehicleOilLevel.class)), Map.entry(VehicleProperty.IMPACT_DETECTED, List.of(ImpactSensorLocation.class)), Map.entry(VehicleProperty.GEAR_SELECTION, List.of(VehicleGear.class)), @@ -44,6 +45,8 @@ public final class EnumForVehicleProperty { Map.entry(VehicleProperty.IGNITION_STATE, List.of(VehicleIgnitionState.class)), Map.entry(VehicleProperty.EV_STOPPING_MODE, List.of(EvStoppingMode.class)), Map.entry(VehicleProperty.ELECTRONIC_STABILITY_CONTROL_STATE, List.of(ElectronicStabilityControlState.class, ErrorState.class)), + Map.entry(VehicleProperty.TURN_SIGNAL_LIGHT_STATE, List.of(VehicleTurnSignal.class)), + Map.entry(VehicleProperty.TURN_SIGNAL_SWITCH, List.of(VehicleTurnSignal.class)), Map.entry(VehicleProperty.HVAC_FAN_DIRECTION, List.of(VehicleHvacFanDirection.class)), Map.entry(VehicleProperty.HVAC_TEMPERATURE_DISPLAY_UNITS, List.of(VehicleUnit.class)), Map.entry(VehicleProperty.HVAC_FAN_DIRECTION_AVAILABLE, List.of(VehicleHvacFanDirection.class)), @@ -51,6 +54,7 @@ public final class EnumForVehicleProperty { Map.entry(VehicleProperty.FUEL_VOLUME_DISPLAY_UNITS, List.of(VehicleUnit.class)), Map.entry(VehicleProperty.TIRE_PRESSURE_DISPLAY_UNITS, List.of(VehicleUnit.class)), Map.entry(VehicleProperty.EV_BATTERY_DISPLAY_UNITS, List.of(VehicleUnit.class)), + Map.entry(VehicleProperty.VEHICLE_SPEED_DISPLAY_UNITS, List.of(VehicleUnit.class)), Map.entry(VehicleProperty.HW_ROTARY_INPUT, List.of(RotaryInputType.class)), Map.entry(VehicleProperty.HW_CUSTOM_INPUT, List.of(CustomInputType.class)), Map.entry(VehicleProperty.SEAT_FOOTWELL_LIGHTS_STATE, List.of(VehicleLightState.class)), @@ -85,6 +89,7 @@ public final class EnumForVehicleProperty { Map.entry(VehicleProperty.GENERAL_SAFETY_REGULATION_COMPLIANCE_REQUIREMENT, List.of(GsrComplianceRequirementType.class)), Map.entry(VehicleProperty.SHUTDOWN_REQUEST, List.of(VehicleApPowerStateShutdownParam.class)), Map.entry(VehicleProperty.VEHICLE_DRIVING_AUTOMATION_CURRENT_LEVEL, List.of(VehicleAutonomousState.class)), + Map.entry(VehicleProperty.VEHICLE_DRIVING_AUTOMATION_TARGET_LEVEL, List.of(VehicleAutonomousState.class)), Map.entry(VehicleProperty.CAMERA_SERVICE_CURRENT_STATE, List.of(CameraServiceState.class)), Map.entry(VehicleProperty.AUTOMATIC_EMERGENCY_BRAKING_STATE, List.of(AutomaticEmergencyBrakingState.class, ErrorState.class)), Map.entry(VehicleProperty.FORWARD_COLLISION_WARNING_STATE, List.of(ForwardCollisionWarningState.class, ErrorState.class)), diff --git a/automotive/vehicle/aidl/impl/3/Android.bp b/automotive/vehicle/aidl/impl/3/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..e575061c8c021d1ab3266d4a04f610677b6a4d21 --- /dev/null +++ b/automotive/vehicle/aidl/impl/3/Android.bp @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +cc_defaults { + name: "VehicleHalDefaults-V3", + static_libs: [ + "android-automotive-large-parcelable-lib", + "libmath", + ], + shared_libs: [ + "libbase", + "liblog", + "libutils", + ], + cflags: [ + "-Wall", + "-Wextra", + "-Werror", + "-Wthread-safety", + ], + defaults: [ + "VehicleHalInterfaceDefaults-V3", + "android-automotive-large-parcelable-defaults", + ], +} diff --git a/automotive/vehicle/aidl/impl/3/README.md b/automotive/vehicle/aidl/impl/3/README.md new file mode 100644 index 0000000000000000000000000000000000000000..bf80122905a4e92e0b53ac44f8fdcbb8e377d65a --- /dev/null +++ b/automotive/vehicle/aidl/impl/3/README.md @@ -0,0 +1,58 @@ +# AIDL VHAL libraries and reference implementation. +--- + +This directory stores the libraries useful for implementing vendor AIDL VHAL. +This directory also stores a reference fake implementation for AIDL VHAL. + +## default_config + +Stores the default vehicle property configurations for reference vehicle HAL. +Vendor implementation could copy this library but must update the configuration +to meet their own requirements, e.g. enable or disable certain properties or +update the initial value for certain properties. + +## fake_impl + +Contains libraries used specifically for the fake reference VHAL implementation. +These libraries are for test only and must not be directly used for vendor +VHAL implementation. + +These libraries contain test-spcific logic and must not run directly on a real +vehicle. + +## grpc + +Stores code for GRPC based VHAL implementation. + +## hardware + +Defines an interface `IVehicleHardware.h` which vendor must implement for +vehicle-specific logic if they want to follow our reference VHAL design. + +## proto + +Stores Some protobuf files translated from AIDL VHAL interface types. These +files are used in GRPC VHAL implementation. + +## utils + +Defines a library `VehicleHalUtils-V3` which provides useful utility functions for +VHAL implementation. Vendor VHAL could use this library. + +## vhal + +Defines a library `DefaultVehicleHal` which provides generic logic for all VHAL +implementations (including reference VHAL). Vendor VHAL implementation could +use this library, along with their own implementation for `IVehicleHardware` +interface. + +Also defines a binary `android.hardware.automotive.vehicle@V3-default-service` +which is the reference VHAL implementation. It implements `IVehicle.aidl` +interface. It uses `DefaultVehicleHal`, along with `FakeVehicleHardware` +(in fake_impl). It simulates the vehicle bus interaction by using an +in-memory map. Meaning that all properties (except for some special ones) are +just written into a hash map and read from a hash map without relying on any +hardware. As a result, the reference implementation can run on emulator or +any host environment. + +Vendor must not directly use the reference implementation for a real vehicle. \ No newline at end of file diff --git a/automotive/vehicle/aidl/impl/3/default_config/JsonConfigLoader/Android.bp b/automotive/vehicle/aidl/impl/3/default_config/JsonConfigLoader/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..727c1931dbdd9bbb29925b81aac2acc3ee43d8f2 --- /dev/null +++ b/automotive/vehicle/aidl/impl/3/default_config/JsonConfigLoader/Android.bp @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +cc_library { + name: "VehicleHalJsonConfigLoader-V3", + vendor: true, + srcs: ["src/*.cpp"], + local_include_dirs: ["include"], + export_include_dirs: ["include"], + defaults: ["VehicleHalDefaults-V3"], + static_libs: ["VehicleHalUtils-V3"], + header_libs: [ + "IVehicleGeneratedHeaders-V3-default", + ], + shared_libs: ["libjsoncpp"], +} + +cc_library { + name: "VehicleHalJsonConfigLoaderEnableTestProperties-V3", + vendor: true, + srcs: [ + "src/*.cpp", + ":VhalTestVendorProperties-V3", + ], + local_include_dirs: ["include"], + export_include_dirs: ["include"], + defaults: ["VehicleHalDefaults-V3"], + static_libs: ["VehicleHalUtils-V3"], + header_libs: [ + "IVehicleGeneratedHeaders-V3-default", + "libbinder_headers", + ], + cflags: ["-DENABLE_VEHICLE_HAL_TEST_PROPERTIES"], + shared_libs: ["libjsoncpp"], + host_supported: true, +} + +cc_library_headers { + name: "VehicleHalJsonConfigLoaderHeaders-V3", + vendor: true, + local_include_dirs: ["include"], + export_include_dirs: ["include"], + defaults: ["VehicleHalDefaults-V3"], + static_libs: ["VehicleHalUtils-V3"], + header_libs: [ + "IVehicleGeneratedHeaders-V3-default", + ], + shared_libs: ["libjsoncpp"], +} diff --git a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/include/ConfigDeclaration.h b/automotive/vehicle/aidl/impl/3/default_config/JsonConfigLoader/include/ConfigDeclaration.h similarity index 100% rename from automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/include/ConfigDeclaration.h rename to automotive/vehicle/aidl/impl/3/default_config/JsonConfigLoader/include/ConfigDeclaration.h diff --git a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/include/JsonConfigLoader.h b/automotive/vehicle/aidl/impl/3/default_config/JsonConfigLoader/include/JsonConfigLoader.h similarity index 100% rename from automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/include/JsonConfigLoader.h rename to automotive/vehicle/aidl/impl/3/default_config/JsonConfigLoader/include/JsonConfigLoader.h diff --git a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp b/automotive/vehicle/aidl/impl/3/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp rename to automotive/vehicle/aidl/impl/3/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp diff --git a/automotive/vehicle/aidl/impl/3/default_config/JsonConfigLoader/test/Android.bp b/automotive/vehicle/aidl/impl/3/default_config/JsonConfigLoader/test/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..1ed4df77906ef6bbe619a8cf840f9d459473cd95 --- /dev/null +++ b/automotive/vehicle/aidl/impl/3/default_config/JsonConfigLoader/test/Android.bp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + default_team: "trendy_team_aaos_framework", + default_applicable_licenses: ["Android-Apache-2.0"], +} + +cc_test { + name: "JsonConfigLoaderUnitTest-V3", + vendor: true, + srcs: ["*.cpp"], + static_libs: [ + "VehicleHalJsonConfigLoader-V3", + "VehicleHalUtils-V3", + "libgtest", + "libjsoncpp", + ], + defaults: ["VehicleHalDefaults-V3"], + test_suites: ["device-tests"], +} + +cc_test { + name: "JsonConfigLoaderUnitTestEnableTestProperties-V3", + vendor: true, + srcs: ["*.cpp"], + static_libs: [ + "VehicleHalJsonConfigLoaderEnableTestProperties-V3", + "VehicleHalUtils-V3", + "libgtest", + "libjsoncpp", + ], + defaults: ["VehicleHalDefaults-V3"], + test_suites: ["device-tests"], +} diff --git a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/test/JsonConfigLoaderUnitTest.cpp b/automotive/vehicle/aidl/impl/3/default_config/JsonConfigLoader/test/JsonConfigLoaderUnitTest.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/test/JsonConfigLoaderUnitTest.cpp rename to automotive/vehicle/aidl/impl/3/default_config/JsonConfigLoader/test/JsonConfigLoaderUnitTest.cpp diff --git a/automotive/vehicle/aidl/impl/default_config/TEST_MAPPING b/automotive/vehicle/aidl/impl/3/default_config/TEST_MAPPING similarity index 100% rename from automotive/vehicle/aidl/impl/default_config/TEST_MAPPING rename to automotive/vehicle/aidl/impl/3/default_config/TEST_MAPPING diff --git a/automotive/vehicle/aidl/impl/3/default_config/config/Android.bp b/automotive/vehicle/aidl/impl/3/default_config/config/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..bf1aa90bfd5e2b810e67a777eb83b9e76aa66bb2 --- /dev/null +++ b/automotive/vehicle/aidl/impl/3/default_config/config/Android.bp @@ -0,0 +1,68 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +filegroup { + name: "VehicleHalDefaultProperties_JSON-V3", + srcs: ["DefaultProperties.json"], +} + +filegroup { + name: "VehicleHalTestProperties_JSON-V3", + srcs: ["TestProperties.json"], +} + +filegroup { + name: "VehicleHalVendorClusterTestProperties_JSON-V3", + srcs: ["VendorClusterTestProperties.json"], +} + +prebuilt_etc { + name: "Prebuilt_VehicleHalDefaultProperties_JSON-V3", + filename_from_src: true, + src: "DefaultProperties.json", + sub_dir: "automotive/vhalconfig/3/", + vendor: true, +} + +prebuilt_etc { + name: "Prebuilt_VehicleHalTestProperties_JSON-V3", + filename_from_src: true, + src: "TestProperties.json", + sub_dir: "automotive/vhalconfig/3/", + vendor: true, +} + +prebuilt_etc { + name: "Prebuilt_VehicleHalVendorClusterTestProperties_JSON-V3", + filename_from_src: true, + src: "VendorClusterTestProperties.json", + sub_dir: "automotive/vhalconfig/3/", + vendor: true, +} + +prebuilt_etc_host { + name: "Host_Prebuilt_VehicleHalDefaultProperties_JSON-V3", + filename_from_src: true, + src: "DefaultProperties.json", + relative_install_path: "automotive/vhalconfig/3/", +} + +prebuilt_etc_host { + name: "Host_Prebuilt_VehicleHalTestProperties_JSON-V3", + filename_from_src: true, + src: "TestProperties.json", + relative_install_path: "automotive/vhalconfig/3/", +} + +prebuilt_etc_host { + name: "Host_Prebuilt_VehicleHalVendorClusterTestProperties_JSON-V3", + filename_from_src: true, + src: "VendorClusterTestProperties.json", + relative_install_path: "automotive/vhalconfig/3/", +} diff --git a/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json b/automotive/vehicle/aidl/impl/3/default_config/config/DefaultProperties.json similarity index 100% rename from automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json rename to automotive/vehicle/aidl/impl/3/default_config/config/DefaultProperties.json diff --git a/automotive/vehicle/aidl/impl/default_config/config/README.md b/automotive/vehicle/aidl/impl/3/default_config/config/README.md similarity index 100% rename from automotive/vehicle/aidl/impl/default_config/config/README.md rename to automotive/vehicle/aidl/impl/3/default_config/config/README.md diff --git a/automotive/vehicle/aidl/impl/default_config/config/TestProperties.json b/automotive/vehicle/aidl/impl/3/default_config/config/TestProperties.json similarity index 100% rename from automotive/vehicle/aidl/impl/default_config/config/TestProperties.json rename to automotive/vehicle/aidl/impl/3/default_config/config/TestProperties.json diff --git a/automotive/vehicle/aidl/impl/default_config/config/VendorClusterTestProperties.json b/automotive/vehicle/aidl/impl/3/default_config/config/VendorClusterTestProperties.json similarity index 100% rename from automotive/vehicle/aidl/impl/default_config/config/VendorClusterTestProperties.json rename to automotive/vehicle/aidl/impl/3/default_config/config/VendorClusterTestProperties.json diff --git a/automotive/vehicle/aidl/impl/3/default_config/test/Android.bp b/automotive/vehicle/aidl/impl/3/default_config/test/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..d125d43fa6e4b320e7419ef064c20640658bce82 --- /dev/null +++ b/automotive/vehicle/aidl/impl/3/default_config/test/Android.bp @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + default_team: "trendy_team_aaos_framework", + default_applicable_licenses: ["Android-Apache-2.0"], +} + +cc_test { + name: "VehicleHalDefaultConfigTest-V3", + vendor: true, + defaults: ["VehicleHalDefaults-V3"], + srcs: ["*.cpp"], + static_libs: [ + "VehicleHalJsonConfigLoader-V3", + "VehicleHalUtils-V3", + "libgmock", + "libgtest", + "libjsoncpp", + ], + header_libs: [ + "IVehicleGeneratedHeaders-V3-default", + ], + data: [ + ":VehicleHalDefaultProperties_JSON-V3", + ], + test_suites: ["device-tests"], +} + +cc_test { + name: "VehicleHalDefaultConfigTestEnableTestProperties-V3", + vendor: true, + defaults: ["VehicleHalDefaults-V3"], + srcs: ["*.cpp"], + static_libs: [ + "VehicleHalJsonConfigLoaderEnableTestProperties-V3", + "VehicleHalUtils-V3", + "libgmock", + "libgtest", + "libjsoncpp", + ], + cflags: [ + "-DENABLE_VEHICLE_HAL_TEST_PROPERTIES", + ], + header_libs: [ + "IVehicleGeneratedHeaders-V3-default", + ], + data: [ + ":VehicleHalDefaultProperties_JSON-V3", + ":VehicleHalTestProperties_JSON-V3", + ":VehicleHalVendorClusterTestProperties_JSON-V3", + ], + test_suites: ["device-tests"], +} diff --git a/automotive/vehicle/aidl/impl/default_config/test/DefaultConfigTest.cpp b/automotive/vehicle/aidl/impl/3/default_config/test/DefaultConfigTest.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/default_config/test/DefaultConfigTest.cpp rename to automotive/vehicle/aidl/impl/3/default_config/test/DefaultConfigTest.cpp diff --git a/automotive/vehicle/aidl/impl/3/fake_impl/GeneratorHub/Android.bp b/automotive/vehicle/aidl/impl/3/fake_impl/GeneratorHub/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..10e4b7e1c92908ab97023a0944ed9e392f0ab1ac --- /dev/null +++ b/automotive/vehicle/aidl/impl/3/fake_impl/GeneratorHub/Android.bp @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +cc_library { + name: "FakeVehicleHalValueGenerators-V3", + vendor: true, + srcs: ["src/*.cpp"], + local_include_dirs: ["include"], + export_include_dirs: ["include"], + defaults: ["VehicleHalDefaults-V3"], + static_libs: [ + "VehicleHalUtils-V3", + "FakeObd2Frame-V3", + ], + shared_libs: [ + "libjsoncpp", + ], + host_supported: true, +} diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/FakeValueGenerator.h b/automotive/vehicle/aidl/impl/3/fake_impl/GeneratorHub/include/FakeValueGenerator.h similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/FakeValueGenerator.h rename to automotive/vehicle/aidl/impl/3/fake_impl/GeneratorHub/include/FakeValueGenerator.h diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/GeneratorHub.h b/automotive/vehicle/aidl/impl/3/fake_impl/GeneratorHub/include/GeneratorHub.h similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/GeneratorHub.h rename to automotive/vehicle/aidl/impl/3/fake_impl/GeneratorHub/include/GeneratorHub.h diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/JsonFakeValueGenerator.h b/automotive/vehicle/aidl/impl/3/fake_impl/GeneratorHub/include/JsonFakeValueGenerator.h similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/JsonFakeValueGenerator.h rename to automotive/vehicle/aidl/impl/3/fake_impl/GeneratorHub/include/JsonFakeValueGenerator.h diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/LinearFakeValueGenerator.h b/automotive/vehicle/aidl/impl/3/fake_impl/GeneratorHub/include/LinearFakeValueGenerator.h similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/LinearFakeValueGenerator.h rename to automotive/vehicle/aidl/impl/3/fake_impl/GeneratorHub/include/LinearFakeValueGenerator.h diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/GeneratorHub.cpp b/automotive/vehicle/aidl/impl/3/fake_impl/GeneratorHub/src/GeneratorHub.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/GeneratorHub.cpp rename to automotive/vehicle/aidl/impl/3/fake_impl/GeneratorHub/src/GeneratorHub.cpp diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/JsonFakeValueGenerator.cpp b/automotive/vehicle/aidl/impl/3/fake_impl/GeneratorHub/src/JsonFakeValueGenerator.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/JsonFakeValueGenerator.cpp rename to automotive/vehicle/aidl/impl/3/fake_impl/GeneratorHub/src/JsonFakeValueGenerator.cpp diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/LinearFakeValueGenerator.cpp b/automotive/vehicle/aidl/impl/3/fake_impl/GeneratorHub/src/LinearFakeValueGenerator.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/LinearFakeValueGenerator.cpp rename to automotive/vehicle/aidl/impl/3/fake_impl/GeneratorHub/src/LinearFakeValueGenerator.cpp diff --git a/automotive/vehicle/aidl/impl/3/fake_impl/GeneratorHub/test/Android.bp b/automotive/vehicle/aidl/impl/3/fake_impl/GeneratorHub/test/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..623417b3c749adb0de14409fe74698316697233d --- /dev/null +++ b/automotive/vehicle/aidl/impl/3/fake_impl/GeneratorHub/test/Android.bp @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + default_team: "trendy_team_automotive", + default_applicable_licenses: ["Android-Apache-2.0"], +} + +cc_test { + name: "FakeVehicleHalValueGeneratorsTest-V3", + vendor: true, + srcs: ["*.cpp"], + defaults: ["VehicleHalDefaults-V3"], + static_libs: [ + "VehicleHalUtils-V3", + "FakeVehicleHalValueGenerators-V3", + "FakeObd2Frame-V3", + "libjsoncpp", + ], + data: [ + ":FakeVehicleHalValueGeneratorsTestFiles-V3", + ], + test_suites: ["device-tests"], +} + +filegroup { + name: "FakeVehicleHalValueGeneratorsTestFiles-V3", + srcs: [ + "prop.json", + "prop_different_types.json", + "prop_invalid.json", + ], +} diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/FakeVehicleHalValueGeneratorsTest.cpp b/automotive/vehicle/aidl/impl/3/fake_impl/GeneratorHub/test/FakeVehicleHalValueGeneratorsTest.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/FakeVehicleHalValueGeneratorsTest.cpp rename to automotive/vehicle/aidl/impl/3/fake_impl/GeneratorHub/test/FakeVehicleHalValueGeneratorsTest.cpp diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/fakedata/prop.json b/automotive/vehicle/aidl/impl/3/fake_impl/GeneratorHub/test/prop.json similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/hardware/test/fakedata/prop.json rename to automotive/vehicle/aidl/impl/3/fake_impl/GeneratorHub/test/prop.json diff --git a/automotive/vehicle/aidl/impl/3/fake_impl/GeneratorHub/test/prop_different_types.json b/automotive/vehicle/aidl/impl/3/fake_impl/GeneratorHub/test/prop_different_types.json new file mode 100644 index 0000000000000000000000000000000000000000..38cd86b53a889eb961383c047cddab5591f44c6d --- /dev/null +++ b/automotive/vehicle/aidl/impl/3/fake_impl/GeneratorHub/test/prop_different_types.json @@ -0,0 +1,74 @@ +[ + { + "timestamp": 1000000, + "areaId": 0, + "value": 1, + "prop": 287310600 + }, + { + "timestamp": 1000000, + "areaId": 0, + "value": 2, + "prop": 289408000 + }, + { + "timestamp": 1000000, + "areaId": 0, + "value": 3.3, + "prop": 291504905 + }, + { + "timestamp": 1000000, + "areaId": 0, + "value": 4, + "prop": 290457096 + }, + { + "timestamp": 1000000, + "areaId": 0, + "value": "test", + "prop": 286265094 + }, + { + "timestamp": 1000000, + "areaId": 0, + "value": [ + 1, + 2 + ], + "prop": 289476368 + }, + { + "timestamp": 1000000, + "areaId": 0, + "value": { + "int32Values": [ + 1, + 2 + ], + "int64Values": [ + 3, + 4 + ], + "floatValues": [ + 5.5, + 6.6 + ], + "stringValue": "test" + }, + "prop": 299896626 + }, + { + "timestamp": 1000000, + "areaId": 0, + "value": { + "int32Values": [ + 1 + ], + "floatValues": [ + 1 + ] + }, + "prop": 299896064 + } +] \ No newline at end of file diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/prop_invalid.json b/automotive/vehicle/aidl/impl/3/fake_impl/GeneratorHub/test/prop_invalid.json similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/prop_invalid.json rename to automotive/vehicle/aidl/impl/3/fake_impl/GeneratorHub/test/prop_invalid.json diff --git a/automotive/vehicle/aidl/impl/3/fake_impl/README.md b/automotive/vehicle/aidl/impl/3/fake_impl/README.md new file mode 100644 index 0000000000000000000000000000000000000000..5e1df942701ff1eac5c063456e3ea80ffff897c4 --- /dev/null +++ b/automotive/vehicle/aidl/impl/3/fake_impl/README.md @@ -0,0 +1,28 @@ +# Fake reference AIDL VHAL implementation libraries +--- + +This directory stores libraries for implementing a fake reference AIDL VHAL. + +WARNING: All the libraries here are for TEST ONLY. + +## GeneratorHub + +Defines a library `FakeVehicleHalValueGenerators-V3` that could generate fake +vehicle property values for testing. + +## hardware + +Defines a fake implementation for device-specifc interface `IVehicleHardware`: +`FakeVehicleHardware`. This implementation uses a in-memory map for storing +property values and does not communicate with or depending on any specific +vehicle bus. + +## obd2frame + +Defines a library `FakeObd2Frame` that generates fake OBD2 frame for OBD2 +properties. + +## userhal + +Defines a library `FakeUserHal` that emulates a real User HAL behavior by +parsing debug commands. diff --git a/automotive/vehicle/aidl/impl/3/fake_impl/hardware/Android.bp b/automotive/vehicle/aidl/impl/3/fake_impl/hardware/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..9b9b4f498b24a03ed4d6a5c67e503ec64565b7e7 --- /dev/null +++ b/automotive/vehicle/aidl/impl/3/fake_impl/hardware/Android.bp @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +cc_library { + name: "FakeVehicleHardware-V3", + vendor: true, + srcs: [ + "src/*.cpp", + ":VhalTestVendorProperties-V3", + ], + local_include_dirs: ["include"], + export_include_dirs: ["include"], + cflags: [ + "-DENABLE_VEHICLE_HAL_TEST_PROPERTIES", + ], + defaults: [ + "VehicleHalDefaults-V3", + "FakeVehicleHardwareDefaults-V3", + ], + whole_static_libs: [ + "wakeup_client_protos", + ], + host_supported: true, +} + +cc_defaults { + name: "FakeVehicleHardwareDefaults-V3", + header_libs: [ + "IVehicleHardware-V3", + "libbinder_headers", + ], + export_header_lib_headers: ["IVehicleHardware-V3"], + static_libs: [ + "VehicleHalJsonConfigLoaderEnableTestProperties-V3", + "VehicleHalUtils-V3", + "FakeVehicleHalValueGenerators-V3", + "FakeObd2Frame-V3", + "FakeUserHal-V3", + ], + required: [ + "Prebuilt_VehicleHalDefaultProperties_JSON-V3", + "Prebuilt_VehicleHalTestProperties_JSON-V3", + "Prebuilt_VehicleHalVendorClusterTestProperties_JSON-V3", + ], + shared_libs: [ + "libgrpc++", + "libjsoncpp", + "libprotobuf-cpp-full", + ], + export_static_lib_headers: ["VehicleHalUtils-V3"], +} diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h b/automotive/vehicle/aidl/impl/3/fake_impl/hardware/include/FakeVehicleHardware.h similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h rename to automotive/vehicle/aidl/impl/3/fake_impl/hardware/include/FakeVehicleHardware.h diff --git a/automotive/vehicle/aidl/impl/3/fake_impl/hardware/src/FakeVehicleHardware.cpp b/automotive/vehicle/aidl/impl/3/fake_impl/hardware/src/FakeVehicleHardware.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fbd20c5c3c1978d130468548f0b0f16a08e54a7d --- /dev/null +++ b/automotive/vehicle/aidl/impl/3/fake_impl/hardware/src/FakeVehicleHardware.cpp @@ -0,0 +1,2617 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "FakeVehicleHardware" +#define ATRACE_TAG ATRACE_TAG_HAL +#define FAKE_VEHICLEHARDWARE_DEBUG false // STOPSHIP if true. + +#include "FakeVehicleHardware.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace fake { + +namespace { + +#define PROP_ID_TO_CSTR(A) (propIdToString(A).c_str()) + +using ::aidl::android::hardware::automotive::vehicle::CruiseControlCommand; +using ::aidl::android::hardware::automotive::vehicle::CruiseControlType; +using ::aidl::android::hardware::automotive::vehicle::DriverDistractionState; +using ::aidl::android::hardware::automotive::vehicle::DriverDistractionWarning; +using ::aidl::android::hardware::automotive::vehicle::DriverDrowsinessAttentionState; +using ::aidl::android::hardware::automotive::vehicle::DriverDrowsinessAttentionWarning; +using ::aidl::android::hardware::automotive::vehicle::ErrorState; +using ::aidl::android::hardware::automotive::vehicle::GetValueRequest; +using ::aidl::android::hardware::automotive::vehicle::GetValueResult; +using ::aidl::android::hardware::automotive::vehicle::RawPropValues; +using ::aidl::android::hardware::automotive::vehicle::SetValueRequest; +using ::aidl::android::hardware::automotive::vehicle::SetValueResult; +using ::aidl::android::hardware::automotive::vehicle::StatusCode; +using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions; +using ::aidl::android::hardware::automotive::vehicle::toString; +using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReport; +using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq; +using ::aidl::android::hardware::automotive::vehicle::VehicleArea; +using ::aidl::android::hardware::automotive::vehicle::VehicleHwKeyInputAction; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig; +using ::aidl::android::hardware::automotive::vehicle::VehicleProperty; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyChangeMode; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; +using ::aidl::android::hardware::automotive::vehicle::VehicleUnit; + +using ::android::hardware::automotive::remoteaccess::GetApPowerBootupReasonRequest; +using ::android::hardware::automotive::remoteaccess::GetApPowerBootupReasonResponse; +using ::android::hardware::automotive::remoteaccess::IsVehicleInUseRequest; +using ::android::hardware::automotive::remoteaccess::IsVehicleInUseResponse; +using ::android::hardware::automotive::remoteaccess::PowerController; + +using ::android::base::EqualsIgnoreCase; +using ::android::base::Error; +using ::android::base::GetIntProperty; +using ::android::base::ParseFloat; +using ::android::base::Result; +using ::android::base::ScopedLockAssertion; +using ::android::base::StartsWith; +using ::android::base::StringPrintf; + +// In order to test large number of vehicle property configs, we might generate additional fake +// property config start from this ID. These fake properties are for getPropertyList, +// getPropertiesAsync, and setPropertiesAsync. +// 0x21403000 +constexpr int32_t STARTING_VENDOR_CODE_PROPERTIES_FOR_TEST = + 0x3000 | toInt(VehiclePropertyGroup::VENDOR) | toInt(VehicleArea::GLOBAL) | + toInt(VehiclePropertyType::INT32); +// 0x21405000 +constexpr int32_t ENDING_VENDOR_CODE_PROPERTIES_FOR_TEST = + 0x5000 | toInt(VehiclePropertyGroup::VENDOR) | toInt(VehicleArea::GLOBAL) | + toInt(VehiclePropertyType::INT32); +// The directory for default property configuration file. +// For config file format, see impl/default_config/config/README.md. +constexpr char DEFAULT_CONFIG_DIR[] = "/vendor/etc/automotive/vhalconfig/3/"; +// The directory for property configuration file that overrides the default configuration file. +// For config file format, see impl/default_config/config/README.md. +constexpr char OVERRIDE_CONFIG_DIR[] = "/vendor/etc/automotive/vhaloverride/"; +// The optional config file for power controller grpc service that provides vehicleInUse and +// ApPowerBootupReason property. +constexpr char GRPC_SERVICE_CONFIG_FILE[] = "/vendor/etc/automotive/powercontroller/serverconfig"; +// If OVERRIDE_PROPERTY is set, we will use the configuration files from OVERRIDE_CONFIG_DIR to +// overwrite the default configs. +constexpr char OVERRIDE_PROPERTY[] = "persist.vendor.vhal_init_value_override"; +constexpr char POWER_STATE_REQ_CONFIG_PROPERTY[] = "ro.vendor.fake_vhal.ap_power_state_req.config"; +// The value to be returned if VENDOR_PROPERTY_FOR_ERROR_CODE_TESTING is set as the property +constexpr int VENDOR_ERROR_CODE = 0x00ab0005; +// A list of supported options for "--set" command. +const std::unordered_set SET_PROP_OPTIONS = { + // integer. + "-i", + // 64bit integer. + "-i64", + // float. + "-f", + // string. + "-s", + // bytes in hex format, e.g. 0xDEADBEEF. + "-b", + // Area id in integer. + "-a", + // Timestamp in int64. + "-t"}; + +// ADAS _ENABLED property to list of ADAS state properties using ErrorState enum. +const std::unordered_map> mAdasEnabledPropToAdasPropWithErrorState = { + // AEB + { + toInt(VehicleProperty::AUTOMATIC_EMERGENCY_BRAKING_ENABLED), + { + toInt(VehicleProperty::AUTOMATIC_EMERGENCY_BRAKING_STATE), + }, + }, + // FCW + { + toInt(VehicleProperty::FORWARD_COLLISION_WARNING_ENABLED), + { + toInt(VehicleProperty::FORWARD_COLLISION_WARNING_STATE), + }, + }, + // BSW + { + toInt(VehicleProperty::BLIND_SPOT_WARNING_ENABLED), + { + toInt(VehicleProperty::BLIND_SPOT_WARNING_STATE), + }, + }, + // LDW + { + toInt(VehicleProperty::LANE_DEPARTURE_WARNING_ENABLED), + { + toInt(VehicleProperty::LANE_DEPARTURE_WARNING_STATE), + }, + }, + // LKA + { + toInt(VehicleProperty::LANE_KEEP_ASSIST_ENABLED), + { + toInt(VehicleProperty::LANE_KEEP_ASSIST_STATE), + }, + }, + // LCA + { + toInt(VehicleProperty::LANE_CENTERING_ASSIST_ENABLED), + { + toInt(VehicleProperty::LANE_CENTERING_ASSIST_STATE), + }, + }, + // ELKA + { + toInt(VehicleProperty::EMERGENCY_LANE_KEEP_ASSIST_ENABLED), + { + toInt(VehicleProperty::EMERGENCY_LANE_KEEP_ASSIST_STATE), + }, + }, + // CC + { + toInt(VehicleProperty::CRUISE_CONTROL_ENABLED), + { + toInt(VehicleProperty::CRUISE_CONTROL_TYPE), + toInt(VehicleProperty::CRUISE_CONTROL_STATE), + }, + }, + // HOD + { + toInt(VehicleProperty::HANDS_ON_DETECTION_ENABLED), + { + toInt(VehicleProperty::HANDS_ON_DETECTION_DRIVER_STATE), + toInt(VehicleProperty::HANDS_ON_DETECTION_WARNING), + }, + }, + // Driver Drowsiness and Attention + { + toInt(VehicleProperty::DRIVER_DROWSINESS_ATTENTION_SYSTEM_ENABLED), + { + toInt(VehicleProperty::DRIVER_DROWSINESS_ATTENTION_STATE), + }, + }, + // Driver Drowsiness and Attention Warning + { + toInt(VehicleProperty::DRIVER_DROWSINESS_ATTENTION_WARNING_ENABLED), + { + toInt(VehicleProperty::DRIVER_DROWSINESS_ATTENTION_WARNING), + }, + }, + // Driver Distraction + { + toInt(VehicleProperty::DRIVER_DISTRACTION_SYSTEM_ENABLED), + { + toInt(VehicleProperty::DRIVER_DISTRACTION_STATE), + toInt(VehicleProperty::DRIVER_DISTRACTION_WARNING), + }, + }, + // Driver Distraction Warning + { + toInt(VehicleProperty::DRIVER_DISTRACTION_WARNING_ENABLED), + { + toInt(VehicleProperty::DRIVER_DISTRACTION_WARNING), + }, + }, + // LSCW + { + toInt(VehicleProperty::LOW_SPEED_COLLISION_WARNING_ENABLED), + { + toInt(VehicleProperty::LOW_SPEED_COLLISION_WARNING_STATE), + }, + }, + // ESC + { + toInt(VehicleProperty::ELECTRONIC_STABILITY_CONTROL_ENABLED), + { + toInt(VehicleProperty::ELECTRONIC_STABILITY_CONTROL_STATE), + }, + }, + // CTMW + { + toInt(VehicleProperty::CROSS_TRAFFIC_MONITORING_ENABLED), + { + toInt(VehicleProperty::CROSS_TRAFFIC_MONITORING_WARNING_STATE), + }, + }, + // LSAEB + { + toInt(VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED), + { + toInt(VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE), + }, + }, +}; + +// The list of VHAL properties that might be handled by an external power controller. +const std::unordered_set mPowerPropIds = {toInt(VehicleProperty::VEHICLE_IN_USE), + toInt(VehicleProperty::AP_POWER_BOOTUP_REASON)}; + +void maybeGetGrpcServiceInfo(std::string* address) { + std::ifstream ifs(GRPC_SERVICE_CONFIG_FILE); + if (!ifs) { + ALOGI("Cannot open grpc service config file at: %s, assume no service is available", + GRPC_SERVICE_CONFIG_FILE); + return; + } + ifs >> *address; + ifs.close(); +} + +inline std::string vecToStringOfHexValues(const std::vector& vec) { + std::stringstream ss; + ss << "["; + for (size_t i = 0; i < vec.size(); i++) { + if (i != 0) { + ss << ","; + } + ss << std::showbase << std::hex << vec[i]; + } + ss << "]"; + return ss.str(); +} + +} // namespace + +void FakeVehicleHardware::storePropInitialValue(const ConfigDeclaration& config) { + const VehiclePropConfig& vehiclePropConfig = config.config; + int propId = vehiclePropConfig.prop; + + // A global property will have only a single area + bool globalProp = isGlobalProp(propId); + size_t numAreas = globalProp ? 1 : vehiclePropConfig.areaConfigs.size(); + + if (propId == toInt(VehicleProperty::HVAC_POWER_ON)) { + const auto& configArray = vehiclePropConfig.configArray; + hvacPowerDependentProps.insert(configArray.begin(), configArray.end()); + } + + for (size_t i = 0; i < numAreas; i++) { + int32_t curArea = globalProp ? 0 : vehiclePropConfig.areaConfigs[i].areaId; + + // Create a separate instance for each individual zone + VehiclePropValue prop = { + .timestamp = elapsedRealtimeNano(), + .areaId = curArea, + .prop = propId, + .value = {}, + }; + + if (config.initialAreaValues.empty()) { + if (config.initialValue == RawPropValues{}) { + // Skip empty initial values. + continue; + } + prop.value = config.initialValue; + } else if (auto valueForAreaIt = config.initialAreaValues.find(curArea); + valueForAreaIt != config.initialAreaValues.end()) { + prop.value = valueForAreaIt->second; + } else { + ALOGW("failed to get default value for prop 0x%x area 0x%x", propId, curArea); + continue; + } + + auto result = + mServerSidePropStore->writeValue(mValuePool->obtain(prop), /*updateStatus=*/true); + if (!result.ok()) { + ALOGE("failed to write default config value, error: %s, status: %d", + getErrorMsg(result).c_str(), getIntErrorCode(result)); + } + } +} + +FakeVehicleHardware::FakeVehicleHardware() + : FakeVehicleHardware(DEFAULT_CONFIG_DIR, OVERRIDE_CONFIG_DIR, false) {} + +FakeVehicleHardware::FakeVehicleHardware(std::string defaultConfigDir, + std::string overrideConfigDir, bool forceOverride) + : FakeVehicleHardware(defaultConfigDir, overrideConfigDir, forceOverride, + /*s2rS2dConfig=*/ + GetIntProperty(POWER_STATE_REQ_CONFIG_PROPERTY, /*default_value=*/0)) {} + +FakeVehicleHardware::FakeVehicleHardware(std::string defaultConfigDir, + std::string overrideConfigDir, bool forceOverride, + int32_t s2rS2dConfig) + : mValuePool(std::make_unique()), + mServerSidePropStore(new VehiclePropertyStore(mValuePool)), + mDefaultConfigDir(defaultConfigDir), + mOverrideConfigDir(overrideConfigDir), + mFakeObd2Frame(new obd2frame::FakeObd2Frame(mServerSidePropStore)), + mFakeUserHal(new FakeUserHal(mValuePool)), + mRecurrentTimer(new RecurrentTimer()), + mGeneratorHub(new GeneratorHub( + [this](const VehiclePropValue& value) { eventFromVehicleBus(value); })), + mPendingGetValueRequests(this), + mPendingSetValueRequests(this), + mForceOverride(forceOverride) { + init(s2rS2dConfig); +} + +FakeVehicleHardware::~FakeVehicleHardware() { + mPendingGetValueRequests.stop(); + mPendingSetValueRequests.stop(); + mGeneratorHub.reset(); +} + +bool FakeVehicleHardware::UseOverrideConfigDir() { + return mForceOverride || + android::base::GetBoolProperty(OVERRIDE_PROPERTY, /*default_value=*/false); +} + +std::unordered_map FakeVehicleHardware::loadConfigDeclarations() { + std::unordered_map configsByPropId; + bool defaultConfigLoaded = loadPropConfigsFromDir(mDefaultConfigDir, &configsByPropId); + if (!defaultConfigLoaded) { + // This cannot work without a valid default config. + ALOGE("Failed to load default config, exiting"); + exit(1); + } + if (UseOverrideConfigDir()) { + loadPropConfigsFromDir(mOverrideConfigDir, &configsByPropId); + } + return configsByPropId; +} + +void FakeVehicleHardware::init(int32_t s2rS2dConfig) { + maybeGetGrpcServiceInfo(&mPowerControllerServiceAddress); + + for (auto& [_, configDeclaration] : loadConfigDeclarations()) { + VehiclePropConfig cfg = configDeclaration.config; + VehiclePropertyStore::TokenFunction tokenFunction = nullptr; + + if (cfg.prop == toInt(VehicleProperty::AP_POWER_STATE_REQ)) { + cfg.configArray[0] = s2rS2dConfig; + } else if (cfg.prop == OBD2_FREEZE_FRAME) { + tokenFunction = [](const VehiclePropValue& propValue) { return propValue.timestamp; }; + } + + mServerSidePropStore->registerProperty(cfg, tokenFunction); + if (obd2frame::FakeObd2Frame::isDiagnosticProperty(cfg)) { + // Ignore storing default value for diagnostic property. They have special get/set + // logic. + continue; + } + storePropInitialValue(configDeclaration); + } + + // OBD2_LIVE_FRAME and OBD2_FREEZE_FRAME must be configured in default configs. + auto maybeObd2LiveFrame = mServerSidePropStore->getPropConfig(OBD2_LIVE_FRAME); + if (maybeObd2LiveFrame.has_value()) { + mFakeObd2Frame->initObd2LiveFrame(maybeObd2LiveFrame.value()); + } + auto maybeObd2FreezeFrame = mServerSidePropStore->getPropConfig(OBD2_FREEZE_FRAME); + if (maybeObd2FreezeFrame.has_value()) { + mFakeObd2Frame->initObd2FreezeFrame(maybeObd2FreezeFrame.value()); + } + + mServerSidePropStore->setOnValuesChangeCallback([this](std::vector values) { + return onValuesChangeCallback(std::move(values)); + }); +} + +std::vector FakeVehicleHardware::getAllPropertyConfigs() const { + std::vector allConfigs = mServerSidePropStore->getAllConfigs(); + if (mAddExtraTestVendorConfigs) { + generateVendorConfigs(/* outAllConfigs= */ allConfigs); + } + return allConfigs; +} + +VehiclePropValuePool::RecyclableType FakeVehicleHardware::createApPowerStateReq( + VehicleApPowerStateReq state) { + auto req = mValuePool->obtain(VehiclePropertyType::INT32_VEC, 2); + req->prop = toInt(VehicleProperty::AP_POWER_STATE_REQ); + req->areaId = 0; + req->timestamp = elapsedRealtimeNano(); + req->status = VehiclePropertyStatus::AVAILABLE; + req->value.int32Values[0] = toInt(state); + // Param = 0. + req->value.int32Values[1] = 0; + return req; +} + +VehiclePropValuePool::RecyclableType FakeVehicleHardware::createAdasStateReq(int32_t propertyId, + int32_t areaId, + int32_t state) { + auto req = mValuePool->obtain(VehiclePropertyType::INT32); + req->prop = propertyId; + req->areaId = areaId; + req->timestamp = elapsedRealtimeNano(); + req->status = VehiclePropertyStatus::AVAILABLE; + req->value.int32Values[0] = state; + return req; +} + +VhalResult FakeVehicleHardware::setApPowerStateReqShutdown(const VehiclePropValue& value) { + if (value.value.int32Values.size() != 1) { + return StatusError(StatusCode::INVALID_ARG) + << "Failed to set SHUTDOWN_REQUEST, expect 1 int value: " + << "VehicleApPowerStateShutdownParam"; + } + int powerStateShutdownParam = value.value.int32Values[0]; + auto prop = createApPowerStateReq(VehicleApPowerStateReq::SHUTDOWN_PREPARE); + prop->value.int32Values[1] = powerStateShutdownParam; + if (auto writeResult = mServerSidePropStore->writeValue( + std::move(prop), /*updateStatus=*/true, VehiclePropertyStore::EventMode::ALWAYS); + !writeResult.ok()) { + return StatusError(getErrorCode(writeResult)) + << "failed to write AP_POWER_STATE_REQ into property store, error: " + << getErrorMsg(writeResult); + } + return {}; +} + +VhalResult FakeVehicleHardware::setApPowerStateReport(const VehiclePropValue& value) { + auto updatedValue = mValuePool->obtain(value); + updatedValue->timestamp = elapsedRealtimeNano(); + + if (auto writeResult = mServerSidePropStore->writeValue(std::move(updatedValue)); + !writeResult.ok()) { + return StatusError(getErrorCode(writeResult)) + << "failed to write value into property store, error: " << getErrorMsg(writeResult); + } + + VehiclePropValuePool::RecyclableType prop; + int32_t state = value.value.int32Values[0]; + switch (state) { + case toInt(VehicleApPowerStateReport::DEEP_SLEEP_EXIT): + [[fallthrough]]; + case toInt(VehicleApPowerStateReport::HIBERNATION_EXIT): + [[fallthrough]]; + case toInt(VehicleApPowerStateReport::SHUTDOWN_CANCELLED): + [[fallthrough]]; + case toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL): + // CPMS is in WAIT_FOR_VHAL state, simply move to ON and send back to HAL. + prop = createApPowerStateReq(VehicleApPowerStateReq::ON); + + // ALWAYS update status for generated property value, and force a property update event + // because in the case when Car Service crashes, the power state would already be ON + // when we receive WAIT_FOR_VHAL and thus new property change event would be generated. + // However, Car Service always expect a property change event even though there is no + // actual state change. + if (auto writeResult = + mServerSidePropStore->writeValue(std::move(prop), /*updateStatus=*/true, + VehiclePropertyStore::EventMode::ALWAYS); + !writeResult.ok()) { + return StatusError(getErrorCode(writeResult)) + << "failed to write AP_POWER_STATE_REQ into property store, error: " + << getErrorMsg(writeResult); + } + break; + case toInt(VehicleApPowerStateReport::DEEP_SLEEP_ENTRY): + [[fallthrough]]; + case toInt(VehicleApPowerStateReport::HIBERNATION_ENTRY): + [[fallthrough]]; + case toInt(VehicleApPowerStateReport::SHUTDOWN_START): + // CPMS is in WAIT_FOR_FINISH state, send the FINISHED command + // Send back to HAL + // ALWAYS update status for generated property value + prop = createApPowerStateReq(VehicleApPowerStateReq::FINISHED); + if (auto writeResult = + mServerSidePropStore->writeValue(std::move(prop), /*updateStatus=*/true); + !writeResult.ok()) { + return StatusError(getErrorCode(writeResult)) + << "failed to write AP_POWER_STATE_REQ into property store, error: " + << getErrorMsg(writeResult); + } + break; + case toInt(VehicleApPowerStateReport::ON): + ALOGI("Received VehicleApPowerStateReport::ON, entering normal operating state"); + break; + default: + ALOGE("Unknown VehicleApPowerStateReport: %d", state); + break; + } + return {}; +} + +int FakeVehicleHardware::getHvacTempNumIncrements(int requestedTemp, int minTemp, int maxTemp, + int increment) { + requestedTemp = std::max(requestedTemp, minTemp); + requestedTemp = std::min(requestedTemp, maxTemp); + int numIncrements = std::round((requestedTemp - minTemp) / static_cast(increment)); + return numIncrements; +} + +void FakeVehicleHardware::updateHvacTemperatureValueSuggestionInput( + const std::vector& hvacTemperatureSetConfigArray, + std::vector* hvacTemperatureValueSuggestionInput) { + int minTempInCelsius = hvacTemperatureSetConfigArray[0]; + int maxTempInCelsius = hvacTemperatureSetConfigArray[1]; + int incrementInCelsius = hvacTemperatureSetConfigArray[2]; + + int minTempInFahrenheit = hvacTemperatureSetConfigArray[3]; + int maxTempInFahrenheit = hvacTemperatureSetConfigArray[4]; + int incrementInFahrenheit = hvacTemperatureSetConfigArray[5]; + + // The HVAC_TEMPERATURE_SET config array values are temperature values that have been multiplied + // by 10 and converted to integers. Therefore, requestedTemp must also be multiplied by 10 and + // converted to an integer in order for them to be the same units. + int requestedTemp = static_cast((*hvacTemperatureValueSuggestionInput)[0] * 10.0f); + int numIncrements = + (*hvacTemperatureValueSuggestionInput)[1] == toInt(VehicleUnit::CELSIUS) + ? getHvacTempNumIncrements(requestedTemp, minTempInCelsius, maxTempInCelsius, + incrementInCelsius) + : getHvacTempNumIncrements(requestedTemp, minTempInFahrenheit, + maxTempInFahrenheit, incrementInFahrenheit); + + int suggestedTempInCelsius = minTempInCelsius + incrementInCelsius * numIncrements; + int suggestedTempInFahrenheit = minTempInFahrenheit + incrementInFahrenheit * numIncrements; + // HVAC_TEMPERATURE_VALUE_SUGGESTION specifies the temperature values to be in the original + // floating point form so we divide by 10 and convert to float. + (*hvacTemperatureValueSuggestionInput)[2] = static_cast(suggestedTempInCelsius) / 10.0f; + (*hvacTemperatureValueSuggestionInput)[3] = + static_cast(suggestedTempInFahrenheit) / 10.0f; +} + +VhalResult FakeVehicleHardware::setHvacTemperatureValueSuggestion( + const VehiclePropValue& hvacTemperatureValueSuggestion) { + auto hvacTemperatureSetConfigResult = + mServerSidePropStore->getPropConfig(toInt(VehicleProperty::HVAC_TEMPERATURE_SET)); + + if (!hvacTemperatureSetConfigResult.ok()) { + return StatusError(getErrorCode(hvacTemperatureSetConfigResult)) << StringPrintf( + "Failed to set HVAC_TEMPERATURE_VALUE_SUGGESTION because" + " HVAC_TEMPERATURE_SET could not be retrieved. Error: %s", + getErrorMsg(hvacTemperatureSetConfigResult).c_str()); + } + + const auto& originalInput = hvacTemperatureValueSuggestion.value.floatValues; + if (originalInput.size() != 4) { + return StatusError(StatusCode::INVALID_ARG) << StringPrintf( + "Failed to set HVAC_TEMPERATURE_VALUE_SUGGESTION because float" + " array value is not size 4."); + } + + bool isTemperatureUnitSpecified = originalInput[1] == toInt(VehicleUnit::CELSIUS) || + originalInput[1] == toInt(VehicleUnit::FAHRENHEIT); + if (!isTemperatureUnitSpecified) { + return StatusError(StatusCode::INVALID_ARG) << StringPrintf( + "Failed to set HVAC_TEMPERATURE_VALUE_SUGGESTION because float" + " value at index 1 is not any of %d or %d, which corresponds to" + " VehicleUnit#CELSIUS and VehicleUnit#FAHRENHEIT respectively.", + toInt(VehicleUnit::CELSIUS), toInt(VehicleUnit::FAHRENHEIT)); + } + + auto updatedValue = mValuePool->obtain(hvacTemperatureValueSuggestion); + const auto& hvacTemperatureSetConfigArray = hvacTemperatureSetConfigResult.value().configArray; + auto& hvacTemperatureValueSuggestionInput = updatedValue->value.floatValues; + + updateHvacTemperatureValueSuggestionInput(hvacTemperatureSetConfigArray, + &hvacTemperatureValueSuggestionInput); + + updatedValue->timestamp = elapsedRealtimeNano(); + auto writeResult = mServerSidePropStore->writeValue(std::move(updatedValue), + /* updateStatus = */ true, + VehiclePropertyStore::EventMode::ALWAYS); + if (!writeResult.ok()) { + return StatusError(getErrorCode(writeResult)) + << StringPrintf("failed to write value into property store, error: %s", + getErrorMsg(writeResult).c_str()); + } + + return {}; +} + +bool FakeVehicleHardware::isHvacPropAndHvacNotAvailable(int32_t propId, int32_t areaId) const { + if (hvacPowerDependentProps.count(propId)) { + auto hvacPowerOnResults = + mServerSidePropStore->readValuesForProperty(toInt(VehicleProperty::HVAC_POWER_ON)); + if (!hvacPowerOnResults.ok()) { + ALOGW("failed to get HVAC_POWER_ON 0x%x, error: %s", + toInt(VehicleProperty::HVAC_POWER_ON), getErrorMsg(hvacPowerOnResults).c_str()); + return false; + } + auto& hvacPowerOnValues = hvacPowerOnResults.value(); + for (size_t j = 0; j < hvacPowerOnValues.size(); j++) { + auto hvacPowerOnValue = std::move(hvacPowerOnValues[j]); + if ((hvacPowerOnValue->areaId & areaId) == areaId) { + if (hvacPowerOnValue->value.int32Values.size() == 1 && + hvacPowerOnValue->value.int32Values[0] == 0) { + return true; + } + break; + } + } + } + return false; +} + +VhalResult FakeVehicleHardware::isAdasPropertyAvailable(int32_t adasStatePropertyId) const { + auto adasStateResult = mServerSidePropStore->readValue(adasStatePropertyId); + if (!adasStateResult.ok()) { + ALOGW("Failed to get ADAS ENABLED property 0x%x, error: %s", adasStatePropertyId, + getErrorMsg(adasStateResult).c_str()); + return {}; + } + + if (adasStateResult.value()->value.int32Values.size() == 1 && + adasStateResult.value()->value.int32Values[0] < 0) { + auto errorState = adasStateResult.value()->value.int32Values[0]; + switch (errorState) { + case toInt(ErrorState::NOT_AVAILABLE_DISABLED): + return StatusError(StatusCode::NOT_AVAILABLE_DISABLED) + << "ADAS feature is disabled."; + case toInt(ErrorState::NOT_AVAILABLE_SPEED_LOW): + return StatusError(StatusCode::NOT_AVAILABLE_SPEED_LOW) + << "ADAS feature is disabled because the vehicle speed is too low."; + case toInt(ErrorState::NOT_AVAILABLE_SPEED_HIGH): + return StatusError(StatusCode::NOT_AVAILABLE_SPEED_HIGH) + << "ADAS feature is disabled because the vehicle speed is too high."; + case toInt(ErrorState::NOT_AVAILABLE_POOR_VISIBILITY): + return StatusError(StatusCode::NOT_AVAILABLE_POOR_VISIBILITY) + << "ADAS feature is disabled because the visibility is too poor."; + case toInt(ErrorState::NOT_AVAILABLE_SAFETY): + return StatusError(StatusCode::NOT_AVAILABLE_SAFETY) + << "ADAS feature is disabled because of safety reasons."; + default: + return StatusError(StatusCode::NOT_AVAILABLE) << "ADAS feature is not available."; + } + } + + return {}; +} + +VhalResult FakeVehicleHardware::setUserHalProp(const VehiclePropValue& value) { + auto result = mFakeUserHal->onSetProperty(value); + if (!result.ok()) { + return StatusError(getErrorCode(result)) + << "onSetProperty(): HAL returned error: " << getErrorMsg(result); + } + auto& updatedValue = result.value(); + if (updatedValue != nullptr) { + ALOGI("onSetProperty(): updating property returned by HAL: %s", + updatedValue->toString().c_str()); + // Update timestamp otherwise writeValue might fail because the timestamp is outdated. + updatedValue->timestamp = elapsedRealtimeNano(); + if (auto writeResult = mServerSidePropStore->writeValue( + std::move(result.value()), + /*updateStatus=*/true, VehiclePropertyStore::EventMode::ALWAYS); + !writeResult.ok()) { + return StatusError(getErrorCode(writeResult)) + << "failed to write value into property store, error: " + << getErrorMsg(writeResult); + } + } + return {}; +} + +VhalResult FakeVehicleHardware::synchronizeHvacTemp(int32_t hvacDualOnAreaId, + std::optional newTempC) const { + auto hvacTemperatureSetResults = mServerSidePropStore->readValuesForProperty( + toInt(VehicleProperty::HVAC_TEMPERATURE_SET)); + if (!hvacTemperatureSetResults.ok()) { + return StatusError(StatusCode::NOT_AVAILABLE) + << "Failed to get HVAC_TEMPERATURE_SET, error: " + << getErrorMsg(hvacTemperatureSetResults); + } + auto& hvacTemperatureSetValues = hvacTemperatureSetResults.value(); + std::optional tempCToSynchronize = newTempC; + for (size_t i = 0; i < hvacTemperatureSetValues.size(); i++) { + int32_t areaId = hvacTemperatureSetValues[i]->areaId; + if ((hvacDualOnAreaId & areaId) != areaId) { + continue; + } + if (hvacTemperatureSetValues[i]->status != VehiclePropertyStatus::AVAILABLE) { + continue; + } + // When HVAC_DUAL_ON is initially enabled, synchronize all area IDs + // to the temperature of the first area ID, which is the driver's. + if (!tempCToSynchronize.has_value()) { + tempCToSynchronize = hvacTemperatureSetValues[i]->value.floatValues[0]; + continue; + } + auto updatedValue = std::move(hvacTemperatureSetValues[i]); + updatedValue->value.floatValues[0] = tempCToSynchronize.value(); + updatedValue->timestamp = elapsedRealtimeNano(); + // This will trigger a property change event for the current hvac property value. + auto writeResult = + mServerSidePropStore->writeValue(std::move(updatedValue), /*updateStatus=*/true, + VehiclePropertyStore::EventMode::ALWAYS); + if (!writeResult.ok()) { + return StatusError(getErrorCode(writeResult)) + << "Failed to write value into property store, error: " + << getErrorMsg(writeResult); + } + } + return {}; +} + +std::optional FakeVehicleHardware::getSyncedAreaIdIfHvacDualOn( + int32_t hvacTemperatureSetAreaId) const { + auto hvacDualOnResults = + mServerSidePropStore->readValuesForProperty(toInt(VehicleProperty::HVAC_DUAL_ON)); + if (!hvacDualOnResults.ok()) { + return std::nullopt; + } + auto& hvacDualOnValues = hvacDualOnResults.value(); + for (size_t i = 0; i < hvacDualOnValues.size(); i++) { + if ((hvacDualOnValues[i]->areaId & hvacTemperatureSetAreaId) == hvacTemperatureSetAreaId && + hvacDualOnValues[i]->value.int32Values.size() == 1 && + hvacDualOnValues[i]->value.int32Values[0] == 1) { + return hvacDualOnValues[i]->areaId; + } + } + return std::nullopt; +} + +FakeVehicleHardware::ValueResultType FakeVehicleHardware::getUserHalProp( + const VehiclePropValue& value) const { + auto propId = value.prop; + ALOGI("get(): getting value for prop %s from User HAL", PROP_ID_TO_CSTR(propId)); + + auto result = mFakeUserHal->onGetProperty(value); + if (!result.ok()) { + return StatusError(getErrorCode(result)) + << "get(): User HAL returned error: " << getErrorMsg(result); + } else { + auto& gotValue = result.value(); + if (gotValue != nullptr) { + ALOGI("get(): User HAL returned value: %s", gotValue->toString().c_str()); + gotValue->timestamp = elapsedRealtimeNano(); + return result; + } else { + return StatusError(StatusCode::INTERNAL_ERROR) << "get(): User HAL returned null value"; + } + } +} + +VhalResult FakeVehicleHardware::isCruiseControlTypeStandard() const { + auto isCruiseControlTypeAvailableResult = + isAdasPropertyAvailable(toInt(VehicleProperty::CRUISE_CONTROL_TYPE)); + if (!isCruiseControlTypeAvailableResult.ok()) { + return isCruiseControlTypeAvailableResult.error(); + } + auto cruiseControlTypeValue = + mServerSidePropStore->readValue(toInt(VehicleProperty::CRUISE_CONTROL_TYPE)); + return cruiseControlTypeValue.value()->value.int32Values[0] == + toInt(CruiseControlType::STANDARD); +} + +FakeVehicleHardware::ValueResultType FakeVehicleHardware::maybeGetSpecialValue( + const VehiclePropValue& value, bool* isSpecialValue) const { + *isSpecialValue = false; + int32_t propId = value.prop; + ValueResultType result; + + if (mPowerControllerServiceAddress != "") { + if (mPowerPropIds.find(propId) != mPowerPropIds.end()) { + *isSpecialValue = true; + return getPowerPropFromExternalService(propId); + } + } + + if (propId >= STARTING_VENDOR_CODE_PROPERTIES_FOR_TEST && + propId < ENDING_VENDOR_CODE_PROPERTIES_FOR_TEST) { + *isSpecialValue = true; + result = mValuePool->obtainInt32(/* value= */ 5); + + result.value()->prop = propId; + result.value()->areaId = 0; + result.value()->timestamp = elapsedRealtimeNano(); + return result; + } + + if (mFakeUserHal->isSupported(propId)) { + *isSpecialValue = true; + return getUserHalProp(value); + } + + if (isHvacPropAndHvacNotAvailable(propId, value.areaId)) { + *isSpecialValue = true; + return StatusError(StatusCode::NOT_AVAILABLE_DISABLED) << "hvac not available"; + } + + VhalResult isAdasPropertyAvailableResult; + switch (propId) { + case OBD2_FREEZE_FRAME: + *isSpecialValue = true; + result = mFakeObd2Frame->getObd2FreezeFrame(value); + if (result.ok()) { + result.value()->timestamp = elapsedRealtimeNano(); + } + return result; + case OBD2_FREEZE_FRAME_INFO: + *isSpecialValue = true; + result = mFakeObd2Frame->getObd2DtcInfo(); + if (result.ok()) { + result.value()->timestamp = elapsedRealtimeNano(); + } + return result; + case toInt(TestVendorProperty::ECHO_REVERSE_BYTES): + *isSpecialValue = true; + return getEchoReverseBytes(value); + case toInt(TestVendorProperty::VENDOR_PROPERTY_FOR_ERROR_CODE_TESTING): + *isSpecialValue = true; + return StatusError((StatusCode)VENDOR_ERROR_CODE); + case toInt(VehicleProperty::CRUISE_CONTROL_TARGET_SPEED): + isAdasPropertyAvailableResult = + isAdasPropertyAvailable(toInt(VehicleProperty::CRUISE_CONTROL_STATE)); + if (!isAdasPropertyAvailableResult.ok()) { + *isSpecialValue = true; + return isAdasPropertyAvailableResult.error(); + } + return nullptr; + case toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP): + [[fallthrough]]; + case toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_LEAD_VEHICLE_MEASURED_DISTANCE): { + isAdasPropertyAvailableResult = + isAdasPropertyAvailable(toInt(VehicleProperty::CRUISE_CONTROL_STATE)); + if (!isAdasPropertyAvailableResult.ok()) { + *isSpecialValue = true; + return isAdasPropertyAvailableResult.error(); + } + auto isCruiseControlTypeStandardResult = isCruiseControlTypeStandard(); + if (!isCruiseControlTypeStandardResult.ok()) { + *isSpecialValue = true; + return isCruiseControlTypeStandardResult.error(); + } + if (isCruiseControlTypeStandardResult.value()) { + *isSpecialValue = true; + return StatusError(StatusCode::NOT_AVAILABLE_DISABLED) + << "tried to get target time gap or lead vehicle measured distance value " + << "while on a standard CC setting"; + } + return nullptr; + } + default: + // Do nothing. + break; + } + + return nullptr; +} + +FakeVehicleHardware::ValueResultType FakeVehicleHardware::getPowerPropFromExternalService( + int32_t propId) const { + auto channel = + grpc::CreateChannel(mPowerControllerServiceAddress, grpc::InsecureChannelCredentials()); + auto clientStub = PowerController::NewStub(channel); + switch (propId) { + case toInt(VehicleProperty::VEHICLE_IN_USE): + return getVehicleInUse(clientStub.get()); + case toInt(VehicleProperty::AP_POWER_BOOTUP_REASON): + return getApPowerBootupReason(clientStub.get()); + default: + return StatusError(StatusCode::INTERNAL_ERROR) + << "Unsupported power property ID: " << propId; + } +} + +FakeVehicleHardware::ValueResultType FakeVehicleHardware::getVehicleInUse( + PowerController::Stub* clientStub) const { + IsVehicleInUseRequest request = {}; + IsVehicleInUseResponse response = {}; + grpc::ClientContext context; + auto status = clientStub->IsVehicleInUse(&context, request, &response); + if (!status.ok()) { + return StatusError(StatusCode::TRY_AGAIN) + << "Cannot connect to GRPC service " << ", error: " << status.error_message(); + } + auto result = mValuePool->obtainBoolean(response.isvehicleinuse()); + result->prop = toInt(VehicleProperty::VEHICLE_IN_USE); + result->areaId = 0; + result->status = VehiclePropertyStatus::AVAILABLE; + result->timestamp = elapsedRealtimeNano(); + return result; +} + +FakeVehicleHardware::ValueResultType FakeVehicleHardware::getApPowerBootupReason( + PowerController::Stub* clientStub) const { + GetApPowerBootupReasonRequest request = {}; + GetApPowerBootupReasonResponse response = {}; + grpc::ClientContext context; + auto status = clientStub->GetApPowerBootupReason(&context, request, &response); + if (!status.ok()) { + return StatusError(StatusCode::TRY_AGAIN) + << "Cannot connect to GRPC service " << ", error: " << status.error_message(); + } + auto result = mValuePool->obtainInt32(response.bootupreason()); + result->prop = toInt(VehicleProperty::AP_POWER_BOOTUP_REASON); + result->areaId = 0; + result->status = VehiclePropertyStatus::AVAILABLE; + result->timestamp = elapsedRealtimeNano(); + return result; +} + +FakeVehicleHardware::ValueResultType FakeVehicleHardware::getEchoReverseBytes( + const VehiclePropValue& value) const { + auto readResult = mServerSidePropStore->readValue(value); + if (!readResult.ok()) { + return readResult; + } + auto& gotValue = readResult.value(); + gotValue->timestamp = elapsedRealtimeNano(); + std::vector byteValues = gotValue->value.byteValues; + size_t byteSize = byteValues.size(); + for (size_t i = 0; i < byteSize; i++) { + gotValue->value.byteValues[i] = byteValues[byteSize - 1 - i]; + } + return std::move(gotValue); +} + +void FakeVehicleHardware::sendHvacPropertiesCurrentValues(int32_t areaId, int32_t hvacPowerOnVal) { + for (auto& powerPropId : hvacPowerDependentProps) { + auto powerPropResults = mServerSidePropStore->readValuesForProperty(powerPropId); + if (!powerPropResults.ok()) { + ALOGW("failed to get power prop 0x%x, error: %s", powerPropId, + getErrorMsg(powerPropResults).c_str()); + continue; + } + auto& powerPropValues = powerPropResults.value(); + for (size_t j = 0; j < powerPropValues.size(); j++) { + auto powerPropValue = std::move(powerPropValues[j]); + if ((powerPropValue->areaId & areaId) == powerPropValue->areaId) { + powerPropValue->status = hvacPowerOnVal ? VehiclePropertyStatus::AVAILABLE + : VehiclePropertyStatus::UNAVAILABLE; + powerPropValue->timestamp = elapsedRealtimeNano(); + // This will trigger a property change event for the current hvac property value. + mServerSidePropStore->writeValue(std::move(powerPropValue), /*updateStatus=*/true, + VehiclePropertyStore::EventMode::ALWAYS); + } + } + } +} + +void FakeVehicleHardware::sendAdasPropertiesState(int32_t propertyId, int32_t state) { + auto& adasDependentPropIds = mAdasEnabledPropToAdasPropWithErrorState.find(propertyId)->second; + for (auto dependentPropId : adasDependentPropIds) { + auto dependentPropConfigResult = mServerSidePropStore->getPropConfig(dependentPropId); + if (!dependentPropConfigResult.ok()) { + ALOGW("Failed to get config for ADAS property 0x%x, error: %s", dependentPropId, + getErrorMsg(dependentPropConfigResult).c_str()); + continue; + } + auto& dependentPropConfig = dependentPropConfigResult.value(); + for (auto& areaConfig : dependentPropConfig.areaConfigs) { + int32_t hardcoded_state = state; + // TODO: restore old/initial values here instead of hardcoded value (b/295542701) + if (state == 1 && dependentPropId == toInt(VehicleProperty::CRUISE_CONTROL_TYPE)) { + hardcoded_state = toInt(CruiseControlType::ADAPTIVE); + } + auto propValue = + createAdasStateReq(dependentPropId, areaConfig.areaId, hardcoded_state); + // This will trigger a property change event for the current ADAS property value. + mServerSidePropStore->writeValue(std::move(propValue), /*updateStatus=*/true, + VehiclePropertyStore::EventMode::ALWAYS); + } + } +} + +VhalResult FakeVehicleHardware::maybeSetSpecialValue(const VehiclePropValue& value, + bool* isSpecialValue) { + *isSpecialValue = false; + VehiclePropValuePool::RecyclableType updatedValue; + int32_t propId = value.prop; + + if (propId >= STARTING_VENDOR_CODE_PROPERTIES_FOR_TEST && + propId < ENDING_VENDOR_CODE_PROPERTIES_FOR_TEST) { + *isSpecialValue = true; + return {}; + } + + if (mFakeUserHal->isSupported(propId)) { + *isSpecialValue = true; + return setUserHalProp(value); + } + + if (isHvacPropAndHvacNotAvailable(propId, value.areaId)) { + *isSpecialValue = true; + return StatusError(StatusCode::NOT_AVAILABLE_DISABLED) << "hvac not available"; + } + + if (mAdasEnabledPropToAdasPropWithErrorState.count(propId) && + value.value.int32Values.size() == 1) { + if (value.value.int32Values[0] == 1) { + // Set default state to 1 when ADAS feature is enabled. + sendAdasPropertiesState(propId, /* state = */ 1); + } else { + sendAdasPropertiesState(propId, toInt(ErrorState::NOT_AVAILABLE_DISABLED)); + } + } + + VhalResult isAdasPropertyAvailableResult; + VhalResult isCruiseControlTypeStandardResult; + switch (propId) { + case toInt(VehicleProperty::DISPLAY_BRIGHTNESS): + case toInt(VehicleProperty::PER_DISPLAY_BRIGHTNESS): + ALOGD("DISPLAY_BRIGHTNESS: %s", value.toString().c_str()); + return {}; + case toInt(VehicleProperty::AP_POWER_STATE_REPORT): + *isSpecialValue = true; + return setApPowerStateReport(value); + case toInt(VehicleProperty::SHUTDOWN_REQUEST): + // If we receive SHUTDOWN_REQUEST, we should send this to an external component which + // should shutdown Android system via sending an AP_POWER_STATE_REQ event. Here we have + // no external components to notify, so we just send the event. + *isSpecialValue = true; + return setApPowerStateReqShutdown(value); + case toInt(VehicleProperty::VEHICLE_MAP_SERVICE): + // Placeholder for future implementation of VMS property in the default hal. For + // now, just returns OK; otherwise, hal clients crash with property not supported. + *isSpecialValue = true; + return {}; + case OBD2_FREEZE_FRAME_CLEAR: + *isSpecialValue = true; + return mFakeObd2Frame->clearObd2FreezeFrames(value); + case toInt(TestVendorProperty::VENDOR_PROPERTY_FOR_ERROR_CODE_TESTING): + *isSpecialValue = true; + return StatusError((StatusCode)VENDOR_ERROR_CODE); + case toInt(VehicleProperty::HVAC_POWER_ON): + if (value.value.int32Values.size() != 1) { + *isSpecialValue = true; + return StatusError(StatusCode::INVALID_ARG) + << "HVAC_POWER_ON requires only one int32 value"; + } + // When changing HVAC power state, send current hvac property values + // through on change event. + sendHvacPropertiesCurrentValues(value.areaId, value.value.int32Values[0]); + return {}; + case toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION): + *isSpecialValue = true; + return setHvacTemperatureValueSuggestion(value); + case toInt(VehicleProperty::HVAC_TEMPERATURE_SET): + if (value.value.floatValues.size() != 1) { + *isSpecialValue = true; + return StatusError(StatusCode::INVALID_ARG) + << "HVAC_DUAL_ON requires only one float value"; + } + if (auto hvacDualOnAreaId = getSyncedAreaIdIfHvacDualOn(value.areaId); + hvacDualOnAreaId.has_value()) { + *isSpecialValue = true; + return synchronizeHvacTemp(hvacDualOnAreaId.value(), value.value.floatValues[0]); + } + return {}; + case toInt(VehicleProperty::HVAC_DUAL_ON): + if (value.value.int32Values.size() != 1) { + *isSpecialValue = true; + return StatusError(StatusCode::INVALID_ARG) + << "HVAC_DUAL_ON requires only one int32 value"; + } + if (value.value.int32Values[0] == 1) { + synchronizeHvacTemp(value.areaId, std::nullopt); + } + return {}; + case toInt(VehicleProperty::LANE_CENTERING_ASSIST_COMMAND): { + isAdasPropertyAvailableResult = + isAdasPropertyAvailable(toInt(VehicleProperty::LANE_CENTERING_ASSIST_STATE)); + if (!isAdasPropertyAvailableResult.ok()) { + *isSpecialValue = true; + } + return isAdasPropertyAvailableResult; + } + case toInt(VehicleProperty::CRUISE_CONTROL_COMMAND): + isAdasPropertyAvailableResult = + isAdasPropertyAvailable(toInt(VehicleProperty::CRUISE_CONTROL_STATE)); + if (!isAdasPropertyAvailableResult.ok()) { + *isSpecialValue = true; + return isAdasPropertyAvailableResult; + } + isCruiseControlTypeStandardResult = isCruiseControlTypeStandard(); + if (!isCruiseControlTypeStandardResult.ok()) { + *isSpecialValue = true; + return isCruiseControlTypeStandardResult.error(); + } + if (isCruiseControlTypeStandardResult.value() && + (value.value.int32Values[0] == + toInt(CruiseControlCommand::INCREASE_TARGET_TIME_GAP) || + value.value.int32Values[0] == + toInt(CruiseControlCommand::DECREASE_TARGET_TIME_GAP))) { + *isSpecialValue = true; + return StatusError(StatusCode::NOT_AVAILABLE_DISABLED) + << "tried to use a change target time gap command while on a standard CC " + << "setting"; + } + return {}; + case toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP): { + isAdasPropertyAvailableResult = + isAdasPropertyAvailable(toInt(VehicleProperty::CRUISE_CONTROL_STATE)); + if (!isAdasPropertyAvailableResult.ok()) { + *isSpecialValue = true; + return isAdasPropertyAvailableResult; + } + isCruiseControlTypeStandardResult = isCruiseControlTypeStandard(); + if (!isCruiseControlTypeStandardResult.ok()) { + *isSpecialValue = true; + return isCruiseControlTypeStandardResult.error(); + } + if (isCruiseControlTypeStandardResult.value()) { + *isSpecialValue = true; + return StatusError(StatusCode::NOT_AVAILABLE_DISABLED) + << "tried to set target time gap or lead vehicle measured distance value " + << "while on a standard CC setting"; + } + return {}; + } + +#ifdef ENABLE_VEHICLE_HAL_TEST_PROPERTIES + case toInt(VehicleProperty::CLUSTER_REPORT_STATE): + [[fallthrough]]; + case toInt(VehicleProperty::CLUSTER_REQUEST_DISPLAY): + [[fallthrough]]; + case toInt(VehicleProperty::CLUSTER_NAVIGATION_STATE): + [[fallthrough]]; + case toInt(TestVendorProperty::VENDOR_CLUSTER_SWITCH_UI): + [[fallthrough]]; + case toInt(TestVendorProperty::VENDOR_CLUSTER_DISPLAY_STATE): + *isSpecialValue = true; + updatedValue = mValuePool->obtain(getPropType(value.prop)); + updatedValue->prop = value.prop & ~toInt(VehiclePropertyGroup::MASK); + if (getPropGroup(value.prop) == VehiclePropertyGroup::SYSTEM) { + updatedValue->prop |= toInt(VehiclePropertyGroup::VENDOR); + } else { + updatedValue->prop |= toInt(VehiclePropertyGroup::SYSTEM); + } + updatedValue->value = value.value; + updatedValue->timestamp = elapsedRealtimeNano(); + updatedValue->areaId = value.areaId; + if (auto writeResult = mServerSidePropStore->writeValue(std::move(updatedValue)); + !writeResult.ok()) { + return StatusError(getErrorCode(writeResult)) + << "failed to write value into property store, error: " + << getErrorMsg(writeResult); + } + return {}; +#endif // ENABLE_VEHICLE_HAL_TEST_PROPERTIES + + default: + break; + } + return {}; +} + +StatusCode FakeVehicleHardware::setValues(std::shared_ptr callback, + const std::vector& requests) { + for (auto& request : requests) { + if (FAKE_VEHICLEHARDWARE_DEBUG) { + ALOGD("Set value for property ID: %s", PROP_ID_TO_CSTR(request.value.prop)); + } + + // In a real VHAL implementation, you could either send the setValue request to vehicle bus + // here in the binder thread, or you could send the request in setValue which runs in + // the handler thread. If you decide to send the setValue request here, you should not + // wait for the response here and the handler thread should handle the setValue response. + mPendingSetValueRequests.addRequest(request, callback); + } + + return StatusCode::OK; +} + +VhalResult FakeVehicleHardware::setValue(const VehiclePropValue& value) { + // In a real VHAL implementation, this will send the request to vehicle bus if not already + // sent in setValues, and wait for the response from vehicle bus. + // Here we are just updating mValuePool. + bool isSpecialValue = false; + auto setSpecialValueResult = maybeSetSpecialValue(value, &isSpecialValue); + if (isSpecialValue) { + if (!setSpecialValueResult.ok()) { + return StatusError(getErrorCode(setSpecialValueResult)) << StringPrintf( + "failed to set special value for property ID: %s, error: %s", + PROP_ID_TO_CSTR(value.prop), getErrorMsg(setSpecialValueResult).c_str()); + } + return {}; + } + + auto updatedValue = mValuePool->obtain(value); + + auto writeResult = mServerSidePropStore->writeValue( + std::move(updatedValue), + /*updateStatus=*/false, /*mode=*/VehiclePropertyStore::EventMode::ON_VALUE_CHANGE, + /*useCurrentTimestamp=*/true); + if (!writeResult.ok()) { + return StatusError(getErrorCode(writeResult)) + << StringPrintf("failed to write value into property store, error: %s", + getErrorMsg(writeResult).c_str()); + } + + return {}; +} + +SetValueResult FakeVehicleHardware::handleSetValueRequest(const SetValueRequest& request) { + SetValueResult setValueResult; + setValueResult.requestId = request.requestId; + + if (auto result = setValue(request.value); !result.ok()) { + ALOGE("failed to set value, error: %s, code: %d", getErrorMsg(result).c_str(), + getIntErrorCode(result)); + setValueResult.status = getErrorCode(result); + } else { + setValueResult.status = StatusCode::OK; + } + + return setValueResult; +} + +StatusCode FakeVehicleHardware::getValues(std::shared_ptr callback, + const std::vector& requests) const { + for (auto& request : requests) { + if (FAKE_VEHICLEHARDWARE_DEBUG) { + ALOGD("getValues(%s)", PROP_ID_TO_CSTR(request.prop.prop)); + } + + // In a real VHAL implementation, you could either send the getValue request to vehicle bus + // here in the binder thread, or you could send the request in getValue which runs in + // the handler thread. If you decide to send the getValue request here, you should not + // wait for the response here and the handler thread should handle the getValue response. + mPendingGetValueRequests.addRequest(request, callback); + } + + return StatusCode::OK; +} + +GetValueResult FakeVehicleHardware::handleGetValueRequest(const GetValueRequest& request) { + GetValueResult getValueResult; + getValueResult.requestId = request.requestId; + + auto result = getValue(request.prop); + if (!result.ok()) { + ALOGE("failed to get value, error: %s, code: %d", getErrorMsg(result).c_str(), + getIntErrorCode(result)); + getValueResult.status = getErrorCode(result); + } else { + getValueResult.status = StatusCode::OK; + getValueResult.prop = *result.value(); + } + return getValueResult; +} + +FakeVehicleHardware::ValueResultType FakeVehicleHardware::getValue( + const VehiclePropValue& value) const { + // In a real VHAL implementation, this will send the request to vehicle bus if not already + // sent in getValues, and wait for the response from vehicle bus. + // Here we are just reading value from mValuePool. + bool isSpecialValue = false; + auto result = maybeGetSpecialValue(value, &isSpecialValue); + if (isSpecialValue) { + if (!result.ok()) { + return StatusError(getErrorCode(result)) + << StringPrintf("failed to get special value: %s, error: %s", + PROP_ID_TO_CSTR(value.prop), getErrorMsg(result).c_str()); + } else { + return result; + } + } + + auto readResult = mServerSidePropStore->readValue(value); + if (!readResult.ok()) { + StatusCode errorCode = getErrorCode(readResult); + if (errorCode == StatusCode::NOT_AVAILABLE) { + return StatusError(errorCode) << "value has not been set yet"; + } else { + return StatusError(errorCode) + << "failed to get value, error: " << getErrorMsg(readResult); + } + } + + return readResult; +} + +DumpResult FakeVehicleHardware::dump(const std::vector& options) { + DumpResult result; + result.callerShouldDumpState = false; + if (options.size() == 0) { + // We only want caller to dump default state when there is no options. + result.callerShouldDumpState = true; + result.buffer = dumpAllProperties(); + return result; + } + std::string option = options[0]; + if (EqualsIgnoreCase(option, "--help")) { + result.buffer = dumpHelp(); + return result; + } else if (EqualsIgnoreCase(option, "--list")) { + result.buffer = dumpListProperties(); + } else if (EqualsIgnoreCase(option, "--get")) { + result.buffer = dumpSpecificProperty(options); + } else if (EqualsIgnoreCase(option, "--getWithArg")) { + result.buffer = dumpGetPropertyWithArg(options); + } else if (EqualsIgnoreCase(option, "--set")) { + result.buffer = dumpSetProperties(options); + } else if (EqualsIgnoreCase(option, "--save-prop")) { + result.buffer = dumpSaveProperty(options); + } else if (EqualsIgnoreCase(option, "--restore-prop")) { + result.buffer = dumpRestoreProperty(options); + } else if (EqualsIgnoreCase(option, "--inject-event")) { + result.buffer = dumpInjectEvent(options); + } else if (EqualsIgnoreCase(option, kUserHalDumpOption)) { + result.buffer = mFakeUserHal->dump(); + } else if (EqualsIgnoreCase(option, "--genfakedata")) { + result.buffer = genFakeDataCommand(options); + } else if (EqualsIgnoreCase(option, "--genTestVendorConfigs")) { + mAddExtraTestVendorConfigs = true; + result.refreshPropertyConfigs = true; + result.buffer = "successfully generated vendor configs"; + } else if (EqualsIgnoreCase(option, "--restoreVendorConfigs")) { + mAddExtraTestVendorConfigs = false; + result.refreshPropertyConfigs = true; + result.buffer = "successfully restored vendor configs"; + } else if (EqualsIgnoreCase(option, "--dumpSub")) { + result.buffer = dumpSubscriptions(); + } else { + result.buffer = StringPrintf("Invalid option: %s\n", option.c_str()); + } + return result; +} + +std::string FakeVehicleHardware::genFakeDataHelp() { + return R"( +Generate Fake Data Usage: +--genfakedata --startlinear [propID] [mValue] [cValue] [dispersion] [increment] [interval]: " +Start a linear generator that generates event with floatValue within range: +[mValue - disperson, mValue + dispersion]. +propID(int32): ID for the property to generate event for. +mValue(float): The middle of the possible values for the property. +cValue(float): The start value for the property, must be within the range. +dispersion(float): The range the value can change. +increment(float): The step the value would increase by for each generated event, +if exceed the range, the value would loop back. +interval(int64): The interval in nanoseconds the event would generate by. + +--genfakedata --stoplinear [propID(int32)]: Stop a linear generator + +--genfakedata --startjson --path [jsonFilePath] [repetition]: +Start a JSON generator that would generate events according to a JSON file. +jsonFilePath(string): The path to a JSON file. The JSON content must be in the format of +[{ + "timestamp": 1000000, + "areaId": 0, + "value": 8, + "prop": 289408000 +}, {...}] +Each event in the JSON file would be generated by the same interval their timestamp is relative to +the first event's timestamp. +repetition(int32, optional): how many iterations the events would be generated. If it is not +provided, it would iterate indefinitely. + +--genfakedata --startjson --content [jsonContent]: Start a JSON generator using the content. + +--genfakedata --stopjson [generatorID(string)]: Stop a JSON generator. + +--genfakedata --keypress [keyCode(int32)] [display[int32]]: Generate key press. + +--genfakedata --keyinputv2 [area(int32)] [display(int32)] [keyCode[int32]] [action[int32]] + [repeatCount(int32)] + +--genfakedata --motioninput [area(int32)] [display(int32)] [inputType[int32]] [action[int32]] + [buttonState(int32)] --pointer [pointerId(int32)] [toolType(int32)] [xData(float)] [yData(float)] + [pressure(float)] [size(float)] + Generate a motion input event. --pointer option can be specified multiple times. + +--genTestVendorConfigs: Generates fake VehiclePropConfig ranging from 0x5000 to 0x8000 all with + vendor property group, global vehicle area, and int32 vehicle property type. This is mainly used + for testing + +--restoreVendorConfigs: Restores to to the default state if genTestVendorConfigs was used. + Otherwise this will do nothing. + +)"; +} + +std::string FakeVehicleHardware::parseErrMsg(std::string fieldName, std::string value, + std::string type) { + return StringPrintf("failed to parse %s as %s: \"%s\"\n%s", fieldName.c_str(), type.c_str(), + value.c_str(), genFakeDataHelp().c_str()); +} + +void FakeVehicleHardware::generateVendorConfigs( + std::vector& outAllConfigs) const { + for (int i = STARTING_VENDOR_CODE_PROPERTIES_FOR_TEST; + i < ENDING_VENDOR_CODE_PROPERTIES_FOR_TEST; i++) { + VehiclePropConfig config; + config.prop = i; + config.access = VehiclePropertyAccess::READ_WRITE; + outAllConfigs.push_back(config); + } +} + +std::string FakeVehicleHardware::genFakeDataCommand(const std::vector& options) { + if (options.size() < 2) { + return "No subcommand specified for genfakedata\n" + genFakeDataHelp(); + } + + std::string command = options[1]; + if (command == "--startlinear") { + // --genfakedata --startlinear [propID(int32)] [middleValue(float)] + // [currentValue(float)] [dispersion(float)] [increment(float)] [interval(int64)] + if (options.size() != 8) { + return "incorrect argument count, need 8 arguments for --genfakedata --startlinear\n" + + genFakeDataHelp(); + } + int32_t propId; + float middleValue; + float currentValue; + float dispersion; + float increment; + int64_t interval; + if (!android::base::ParseInt(options[2], &propId)) { + return parseErrMsg("propId", options[2], "int"); + } + if (!android::base::ParseFloat(options[3], &middleValue)) { + return parseErrMsg("middleValue", options[3], "float"); + } + if (!android::base::ParseFloat(options[4], ¤tValue)) { + return parseErrMsg("currentValue", options[4], "float"); + } + if (!android::base::ParseFloat(options[5], &dispersion)) { + return parseErrMsg("dispersion", options[5], "float"); + } + if (!android::base::ParseFloat(options[6], &increment)) { + return parseErrMsg("increment", options[6], "float"); + } + if (!android::base::ParseInt(options[7], &interval)) { + return parseErrMsg("interval", options[7], "int"); + } + auto generator = std::make_unique( + propId, middleValue, currentValue, dispersion, increment, interval); + mGeneratorHub->registerGenerator(propId, std::move(generator)); + return "Linear event generator started successfully"; + } else if (command == "--stoplinear") { + // --genfakedata --stoplinear [propID(int32)] + if (options.size() != 3) { + return "incorrect argument count, need 3 arguments for --genfakedata --stoplinear\n" + + genFakeDataHelp(); + } + int32_t propId; + if (!android::base::ParseInt(options[2], &propId)) { + return parseErrMsg("propId", options[2], "int"); + } + if (mGeneratorHub->unregisterGenerator(propId)) { + return "Linear event generator stopped successfully"; + } + return StringPrintf("No linear event generator found for property: %s", + PROP_ID_TO_CSTR(propId)); + } else if (command == "--startjson") { + // --genfakedata --startjson --path path repetition + // or + // --genfakedata --startjson --content content repetition. + if (options.size() != 4 && options.size() != 5) { + return "incorrect argument count, need 4 or 5 arguments for --genfakedata " + "--startjson\n"; + } + // Iterate infinitely if repetition number is not provided + int32_t repetition = -1; + if (options.size() == 5) { + if (!android::base::ParseInt(options[4], &repetition)) { + return parseErrMsg("repetition", options[4], "int"); + } + } + std::unique_ptr generator; + if (options[2] == "--path") { + const std::string& fileName = options[3]; + generator = std::make_unique(fileName, repetition); + if (!generator->hasNext()) { + return "invalid JSON file, no events"; + } + } else if (options[2] == "--content") { + const std::string& content = options[3]; + generator = + std::make_unique(/*unused=*/true, content, repetition); + if (!generator->hasNext()) { + return "invalid JSON content, no events"; + } + } + int32_t cookie = std::hash()(options[3]); + mGeneratorHub->registerGenerator(cookie, std::move(generator)); + return StringPrintf("JSON event generator started successfully, ID: %" PRId32, cookie); + } else if (command == "--stopjson") { + // --genfakedata --stopjson [generatorID(string)] + if (options.size() != 3) { + return "incorrect argument count, need 3 arguments for --genfakedata --stopjson\n"; + } + int32_t cookie; + if (!android::base::ParseInt(options[2], &cookie)) { + return parseErrMsg("cookie", options[2], "int"); + } + if (mGeneratorHub->unregisterGenerator(cookie)) { + return "JSON event generator stopped successfully"; + } else { + return StringPrintf("No JSON event generator found for ID: %s", options[2].c_str()); + } + } else if (command == "--keypress") { + int32_t keyCode; + int32_t display; + // --genfakedata --keypress [keyCode(int32)] [display[int32]] + if (options.size() != 4) { + return "incorrect argument count, need 4 arguments for --genfakedata --keypress\n"; + } + if (!android::base::ParseInt(options[2], &keyCode)) { + return parseErrMsg("keyCode", options[2], "int"); + } + if (!android::base::ParseInt(options[3], &display)) { + return parseErrMsg("display", options[3], "int"); + } + // Send back to HAL + onValueChangeCallback( + createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_DOWN, keyCode, display)); + onValueChangeCallback( + createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_UP, keyCode, display)); + return "keypress event generated successfully"; + } else if (command == "--keyinputv2") { + int32_t area; + int32_t display; + int32_t keyCode; + int32_t action; + int32_t repeatCount; + // --genfakedata --keyinputv2 [area(int32)] [display(int32)] [keyCode[int32]] + // [action[int32]] [repeatCount(int32)] + if (options.size() != 7) { + return "incorrect argument count, need 7 arguments for --genfakedata --keyinputv2\n"; + } + if (!android::base::ParseInt(options[2], &area)) { + return parseErrMsg("area", options[2], "int"); + } + if (!android::base::ParseInt(options[3], &display)) { + return parseErrMsg("display", options[3], "int"); + } + if (!android::base::ParseInt(options[4], &keyCode)) { + return parseErrMsg("keyCode", options[4], "int"); + } + if (!android::base::ParseInt(options[5], &action)) { + return parseErrMsg("action", options[5], "int"); + } + if (!android::base::ParseInt(options[6], &repeatCount)) { + return parseErrMsg("repeatCount", options[6], "int"); + } + // Send back to HAL + onValueChangeCallback(createHwKeyInputV2Prop(area, display, keyCode, action, repeatCount)); + return StringPrintf( + "keyinputv2 event generated successfully with area:%d, display:%d," + " keyCode:%d, action:%d, repeatCount:%d", + area, display, keyCode, action, repeatCount); + + } else if (command == "--motioninput") { + int32_t area; + int32_t display; + int32_t inputType; + int32_t action; + int32_t buttonState; + int32_t pointerCount; + + // --genfakedata --motioninput [area(int32)] [display(int32)] [inputType[int32]] + // [action[int32]] [buttonState(int32)] [pointerCount(int32)] + // --pointer [pointerId(int32)] [toolType(int32)] [xData(float)] [yData(float)] + // [pressure(float)] [size(float)] + int optionsSize = (int)options.size(); + if (optionsSize / 7 < 2) { + return "incorrect argument count, need at least 14 arguments for --genfakedata " + "--motioninput including at least 1 --pointer\n"; + } + + if (optionsSize % 7 != 0) { + return "incorrect argument count, need 6 arguments for every --pointer\n"; + } + pointerCount = (int)optionsSize / 7 - 1; + + if (!android::base::ParseInt(options[2], &area)) { + return parseErrMsg("area", options[2], "int"); + } + if (!android::base::ParseInt(options[3], &display)) { + return parseErrMsg("display", options[3], "int"); + } + if (!android::base::ParseInt(options[4], &inputType)) { + return parseErrMsg("inputType", options[4], "int"); + } + if (!android::base::ParseInt(options[5], &action)) { + return parseErrMsg("action", options[5], "int"); + } + if (!android::base::ParseInt(options[6], &buttonState)) { + return parseErrMsg("buttonState", options[6], "int"); + } + + int32_t pointerId[pointerCount]; + int32_t toolType[pointerCount]; + float xData[pointerCount]; + float yData[pointerCount]; + float pressure[pointerCount]; + float size[pointerCount]; + + for (int i = 7, pc = 0; i < optionsSize; i += 7, pc += 1) { + int offset = i; + if (options[offset] != "--pointer") { + return "--pointer is needed for the motion input\n"; + } + offset += 1; + if (!android::base::ParseInt(options[offset], &pointerId[pc])) { + return parseErrMsg("pointerId", options[offset], "int"); + } + offset += 1; + if (!android::base::ParseInt(options[offset], &toolType[pc])) { + return parseErrMsg("toolType", options[offset], "int"); + } + offset += 1; + if (!android::base::ParseFloat(options[offset], &xData[pc])) { + return parseErrMsg("xData", options[offset], "float"); + } + offset += 1; + if (!android::base::ParseFloat(options[offset], &yData[pc])) { + return parseErrMsg("yData", options[offset], "float"); + } + offset += 1; + if (!android::base::ParseFloat(options[offset], &pressure[pc])) { + return parseErrMsg("pressure", options[offset], "float"); + } + offset += 1; + if (!android::base::ParseFloat(options[offset], &size[pc])) { + return parseErrMsg("size", options[offset], "float"); + } + } + + // Send back to HAL + onValueChangeCallback(createHwMotionInputProp(area, display, inputType, action, buttonState, + pointerCount, pointerId, toolType, xData, + yData, pressure, size)); + + std::string successMessage = StringPrintf( + "motion event generated successfully with area:%d, display:%d," + " inputType:%d, action:%d, buttonState:%d, pointerCount:%d\n", + area, display, inputType, action, buttonState, pointerCount); + for (int i = 0; i < pointerCount; i++) { + successMessage += StringPrintf( + "Pointer #%d {\n" + " id:%d , tooltype:%d \n" + " x:%f , y:%f\n" + " pressure: %f, data: %f\n" + "}\n", + i, pointerId[i], toolType[i], xData[i], yData[i], pressure[i], size[i]); + } + return successMessage; + } + + return StringPrintf("Unknown command: \"%s\"\n%s", command.c_str(), genFakeDataHelp().c_str()); +} + +VehiclePropValue FakeVehicleHardware::createHwInputKeyProp(VehicleHwKeyInputAction action, + int32_t keyCode, int32_t targetDisplay) { + VehiclePropValue value = { + .timestamp = elapsedRealtimeNano(), + .areaId = 0, + .prop = toInt(VehicleProperty::HW_KEY_INPUT), + .status = VehiclePropertyStatus::AVAILABLE, + .value.int32Values = {toInt(action), keyCode, targetDisplay}, + }; + return value; +} + +VehiclePropValue FakeVehicleHardware::createHwKeyInputV2Prop(int32_t area, int32_t targetDisplay, + int32_t keyCode, int32_t action, + int32_t repeatCount) { + VehiclePropValue value = {.timestamp = elapsedRealtimeNano(), + .areaId = area, + .prop = toInt(VehicleProperty::HW_KEY_INPUT_V2), + .status = VehiclePropertyStatus::AVAILABLE, + .value.int32Values = {targetDisplay, keyCode, action, repeatCount}, + .value.int64Values = {elapsedRealtimeNano()}}; + return value; +} + +VehiclePropValue FakeVehicleHardware::createHwMotionInputProp( + int32_t area, int32_t display, int32_t inputType, int32_t action, int32_t buttonState, + int32_t pointerCount, int32_t pointerId[], int32_t toolType[], float xData[], float yData[], + float pressure[], float size[]) { + std::vector intValues; + intValues.push_back(display); + intValues.push_back(inputType); + intValues.push_back(action); + intValues.push_back(buttonState); + intValues.push_back(pointerCount); + for (int i = 0; i < pointerCount; i++) { + intValues.push_back(pointerId[i]); + } + for (int i = 0; i < pointerCount; i++) { + intValues.push_back(toolType[i]); + } + + std::vector floatValues; + for (int i = 0; i < pointerCount; i++) { + floatValues.push_back(xData[i]); + } + for (int i = 0; i < pointerCount; i++) { + floatValues.push_back(yData[i]); + } + for (int i = 0; i < pointerCount; i++) { + floatValues.push_back(pressure[i]); + } + for (int i = 0; i < pointerCount; i++) { + floatValues.push_back(size[i]); + } + + VehiclePropValue value = {.timestamp = elapsedRealtimeNano(), + .areaId = area, + .prop = toInt(VehicleProperty::HW_MOTION_INPUT), + .status = VehiclePropertyStatus::AVAILABLE, + .value.int32Values = intValues, + .value.floatValues = floatValues, + .value.int64Values = {elapsedRealtimeNano()}}; + return value; +} + +void FakeVehicleHardware::eventFromVehicleBus(const VehiclePropValue& value) { + mServerSidePropStore->writeValue(mValuePool->obtain(value)); +} + +std::string FakeVehicleHardware::dumpSubscriptions() { + std::scoped_lock lockGuard(mLock); + std::string result = "Subscriptions: \n"; + for (const auto& [interval, actionForInterval] : mActionByIntervalInNanos) { + for (const auto& propIdAreaId : actionForInterval.propIdAreaIdsToRefresh) { + const auto& refreshInfo = mRefreshInfoByPropIdAreaId[propIdAreaId]; + bool vur = (refreshInfo.eventMode == VehiclePropertyStore::EventMode::ON_VALUE_CHANGE); + float sampleRateHz = 1'000'000'000. / refreshInfo.intervalInNanos; + result += StringPrintf("Continuous{property: %s, areaId: %d, rate: %lf hz, vur: %b}\n", + PROP_ID_TO_CSTR(propIdAreaId.propId), propIdAreaId.areaId, + sampleRateHz, vur); + } + } + for (const auto& propIdAreaId : mSubOnChangePropIdAreaIds) { + result += StringPrintf("OnChange{property: %s, areaId: %d}\n", + PROP_ID_TO_CSTR(propIdAreaId.propId), propIdAreaId.areaId); + } + return result; +} + +std::string FakeVehicleHardware::dumpHelp() { + return "Usage: \n\n" + "[no args]: dumps (id and value) all supported properties \n" + "--help: shows this help\n" + "--list: lists the property IDs and their supported area IDs for all supported " + "properties\n" + "--get [PROP_ID_2] [PROP_ID_N]: dumps the value of specific properties. \n" + "--getWithArg [ValueArguments]: gets the value for a specific property. " + "The value arguments constructs a VehiclePropValue used in the getValue request. \n" + "--set [ValueArguments]: sets the value of property PROP_ID, the value " + "arguments constructs a VehiclePropValue used in the setValue request. \n" + "--save-prop [-a AREA_ID]: saves the current value for PROP_ID, integration " + "tests that modify prop value must call this before test and restore-prop after test. \n" + "--restore-prop [-a AREA_ID]: restores a previously saved property value. \n" + "--inject-event [ValueArguments]: inject a property update event from car\n\n" + "ValueArguments are in the format of [-a OPTIONAL_AREA_ID] " + "[-i INT_VALUE_1 [INT_VALUE_2 ...]] " + "[-i64 INT64_VALUE_1 [INT64_VALUE_2 ...]] " + "[-f FLOAT_VALUE_1 [FLOAT_VALUE_2 ...]] " + "[-s STR_VALUE] " + "[-b BYTES_VALUE].\n" + "For example: to set property ID 0x1234, areaId 0x1 to int32 values: [1, 2, 3], " + "use \"--set 0x1234 -a 0x1 -i 1 2 3\"\n" + "Note that the string, bytes and area value can be set just once, while the other can" + " have multiple values (so they're used in the respective array), " + "BYTES_VALUE is in the form of 0xXXXX, e.g. 0xdeadbeef.\n" + + genFakeDataHelp() + "Fake user HAL usage: \n" + mFakeUserHal->showDumpHelp(); +} + +std::string FakeVehicleHardware::dumpAllProperties() { + auto configs = mServerSidePropStore->getAllConfigs(); + if (configs.size() == 0) { + return "no properties to dump\n"; + } + std::string msg = StringPrintf("dumping %zu properties\n", configs.size()); + int rowNumber = 1; + for (const VehiclePropConfig& config : configs) { + msg += dumpOnePropertyByConfig(rowNumber++, config); + } + return msg; +} + +std::string FakeVehicleHardware::dumpOnePropertyByConfig(int rowNumber, + const VehiclePropConfig& config) { + size_t numberAreas = config.areaConfigs.size(); + std::string msg = ""; + if (numberAreas == 0) { + msg += StringPrintf("%d: ", rowNumber); + msg += dumpOnePropertyById(config.prop, /* areaId= */ 0); + return msg; + } + for (size_t j = 0; j < numberAreas; ++j) { + if (numberAreas > 1) { + msg += StringPrintf("%d-%zu: ", rowNumber, j); + } else { + msg += StringPrintf("%d: ", rowNumber); + } + msg += dumpOnePropertyById(config.prop, config.areaConfigs[j].areaId); + } + return msg; +} + +std::string FakeVehicleHardware::dumpOnePropertyById(int32_t propId, int32_t areaId) { + VehiclePropValue value = { + .areaId = areaId, + .prop = propId, + .value = {}, + }; + bool isSpecialValue = false; + auto result = maybeGetSpecialValue(value, &isSpecialValue); + if (!isSpecialValue) { + result = mServerSidePropStore->readValue(value); + } + if (!result.ok()) { + return StringPrintf("failed to read property value: %s, error: %s, code: %d\n", + PROP_ID_TO_CSTR(propId), getErrorMsg(result).c_str(), + getIntErrorCode(result)); + + } else { + return result.value()->toString() + "\n"; + } +} + +std::string FakeVehicleHardware::dumpListProperties() { + auto configs = mServerSidePropStore->getAllConfigs(); + if (configs.size() == 0) { + return "no properties to list\n"; + } + int rowNumber = 1; + std::stringstream ss; + ss << "listing " << configs.size() << " properties" << std::endl; + for (const auto& config : configs) { + std::vector areaIds; + for (const auto& areaConfig : config.areaConfigs) { + areaIds.push_back(areaConfig.areaId); + } + ss << rowNumber++ << ": " << PROP_ID_TO_CSTR(config.prop) << ", propID: " << std::showbase + << std::hex << config.prop << std::noshowbase << std::dec + << ", areaIDs: " << vecToStringOfHexValues(areaIds) << std::endl; + } + return ss.str(); +} + +Result FakeVehicleHardware::checkArgumentsSize(const std::vector& options, + size_t minSize) { + size_t size = options.size(); + if (size >= minSize) { + return {}; + } + return Error() << StringPrintf("Invalid number of arguments: required at least %zu, got %zu\n", + minSize, size); +} + +Result FakeVehicleHardware::parsePropId(const std::vector& options, + size_t index) { + const std::string& propIdStr = options[index]; + auto result = stringToPropId(propIdStr); + if (result.ok()) { + return result; + } + return safelyParseInt(index, propIdStr); +} + +// Parses areaId option ("-a"). It can be an Integer or a string in the form of "AREA_1" or +// "AREA_1 | AREA_2 | ..." +Result FakeVehicleHardware::parseAreaId(const std::vector& options, + size_t index, int32_t propId) { + const std::string& areaIdStr = options[index]; + auto result = safelyParseInt(index, areaIdStr); + if (result.ok()) { + return result; + } + + // Check for pattern matching "AREA_1 | AREA_2 | AREA_3". + std::regex pattern(R"(^\w+(?:( )?\|( )?\w+)*$)"); + std::smatch match; + int32_t areaId = 0; + if (!std::regex_match(areaIdStr, match, pattern)) { + return result; + } + pattern = R"(\w+)"; + + std::sregex_iterator end; + for (std::sregex_iterator it(areaIdStr.begin(), areaIdStr.end(), pattern); it != end; it++) { + // Parse each areas contained in this areaId. + auto result = stringToArea(it->str(), propId); + if (!result.ok()) { + return result; + } + areaId |= result.value(); + } + return areaId; +} + +std::string FakeVehicleHardware::dumpSpecificProperty(const std::vector& options) { + if (auto result = checkArgumentsSize(options, /*minSize=*/2); !result.ok()) { + return getErrorMsg(result); + } + + // options[0] is the command itself... + int rowNumber = 1; + size_t size = options.size(); + std::string msg = ""; + for (size_t i = 1; i < size; ++i) { + auto propResult = parsePropId(options, i); + if (!propResult.ok()) { + msg += getErrorMsg(propResult); + continue; + } + int32_t prop = propResult.value(); + auto result = mServerSidePropStore->getPropConfig(prop); + if (!result.ok()) { + msg += StringPrintf("No property %s\n", PROP_ID_TO_CSTR(prop)); + continue; + } + msg += dumpOnePropertyByConfig(rowNumber++, result.value()); + } + return msg; +} + +std::vector FakeVehicleHardware::getOptionValues( + const std::vector& options, size_t* index) { + std::vector values; + while (*index < options.size()) { + std::string option = options[*index]; + if (SET_PROP_OPTIONS.find(option) != SET_PROP_OPTIONS.end()) { + return values; + } + values.push_back(option); + (*index)++; + } + return values; +} + +Result FakeVehicleHardware::parsePropOptions( + const std::vector& options) { + // Options format: + // --set/get/inject-event PROP [-f f1 f2...] [-i i1 i2...] [-i64 i1 i2...] [-s s1 s2...] + // [-b b1 b2...] [-a a] [-t timestamp] + size_t optionIndex = 1; + auto result = parsePropId(options, optionIndex); + if (!result.ok()) { + return Error() << StringPrintf("Property ID/Name: \"%s\" is not valid: %s\n", + options[optionIndex].c_str(), getErrorMsg(result).c_str()); + } + VehiclePropValue prop = {}; + prop.prop = result.value(); + prop.status = VehiclePropertyStatus::AVAILABLE; + optionIndex++; + std::unordered_set parsedOptions; + int32_t areaIdIndex = -1; + + while (optionIndex < options.size()) { + std::string argType = options[optionIndex]; + optionIndex++; + + size_t currentIndex = optionIndex; + std::vector argValues = getOptionValues(options, &optionIndex); + if (parsedOptions.find(argType) != parsedOptions.end()) { + return Error() << StringPrintf("Duplicate \"%s\" options\n", argType.c_str()); + } + parsedOptions.insert(argType); + size_t argValuesSize = argValues.size(); + if (EqualsIgnoreCase(argType, "-i")) { + if (argValuesSize == 0) { + return Error() << "No values specified when using \"-i\"\n"; + } + prop.value.int32Values.resize(argValuesSize); + for (size_t i = 0; i < argValuesSize; i++) { + auto int32Result = safelyParseInt(currentIndex + i, argValues[i]); + if (!int32Result.ok()) { + return Error() + << StringPrintf("Value: \"%s\" is not a valid int: %s\n", + argValues[i].c_str(), getErrorMsg(int32Result).c_str()); + } + prop.value.int32Values[i] = int32Result.value(); + } + } else if (EqualsIgnoreCase(argType, "-i64")) { + if (argValuesSize == 0) { + return Error() << "No values specified when using \"-i64\"\n"; + } + prop.value.int64Values.resize(argValuesSize); + for (size_t i = 0; i < argValuesSize; i++) { + auto int64Result = safelyParseInt(currentIndex + i, argValues[i]); + if (!int64Result.ok()) { + return Error() + << StringPrintf("Value: \"%s\" is not a valid int64: %s\n", + argValues[i].c_str(), getErrorMsg(int64Result).c_str()); + } + prop.value.int64Values[i] = int64Result.value(); + } + } else if (EqualsIgnoreCase(argType, "-f")) { + if (argValuesSize == 0) { + return Error() << "No values specified when using \"-f\"\n"; + } + prop.value.floatValues.resize(argValuesSize); + for (size_t i = 0; i < argValuesSize; i++) { + auto floatResult = safelyParseFloat(currentIndex + i, argValues[i]); + if (!floatResult.ok()) { + return Error() + << StringPrintf("Value: \"%s\" is not a valid float: %s\n", + argValues[i].c_str(), getErrorMsg(floatResult).c_str()); + } + prop.value.floatValues[i] = floatResult.value(); + } + } else if (EqualsIgnoreCase(argType, "-s")) { + if (argValuesSize != 1) { + return Error() << "Expect exact one value when using \"-s\"\n"; + } + prop.value.stringValue = argValues[0]; + } else if (EqualsIgnoreCase(argType, "-b")) { + if (argValuesSize != 1) { + return Error() << "Expect exact one value when using \"-b\"\n"; + } + auto bytesResult = parseHexString(argValues[0]); + if (!bytesResult.ok()) { + return Error() << StringPrintf("value: \"%s\" is not a valid hex string: %s\n", + argValues[0].c_str(), + getErrorMsg(bytesResult).c_str()); + } + prop.value.byteValues = std::move(bytesResult.value()); + } else if (EqualsIgnoreCase(argType, "-a")) { + if (argValuesSize != 1) { + return Error() << "Expect exact one value when using \"-a\"\n"; + } + areaIdIndex = currentIndex; + } else if (EqualsIgnoreCase(argType, "-t")) { + if (argValuesSize != 1) { + return Error() << "Expect exact one value when using \"-t\"\n"; + } + auto int64Result = safelyParseInt(currentIndex, argValues[0]); + if (!int64Result.ok()) { + return Error() << StringPrintf("Timestamp: \"%s\" is not a valid int64: %s\n", + argValues[0].c_str(), + getErrorMsg(int64Result).c_str()); + } + prop.timestamp = int64Result.value(); + } else { + return Error() << StringPrintf("Unknown option: %s\n", argType.c_str()); + } + } + + if (areaIdIndex != -1) { + auto int32Result = parseAreaId(options, areaIdIndex, prop.prop); + if (!int32Result.ok()) { + return Error() << StringPrintf( + "Area ID: \"%s\" is not a valid int or " + "one or more area names: %s\n", + options[areaIdIndex].c_str(), getErrorMsg(int32Result).c_str()); + } + prop.areaId = int32Result.value(); + } + + return prop; +} + +std::string FakeVehicleHardware::dumpSetProperties(const std::vector& options) { + if (auto result = checkArgumentsSize(options, 3); !result.ok()) { + return getErrorMsg(result); + } + + auto parseResult = parsePropOptions(options); + if (!parseResult.ok()) { + return getErrorMsg(parseResult); + } + VehiclePropValue prop = std::move(parseResult.value()); + ALOGD("Dump: Setting property: %s", prop.toString().c_str()); + + bool isSpecialValue = false; + auto setResult = maybeSetSpecialValue(prop, &isSpecialValue); + + if (!isSpecialValue) { + auto updatedValue = mValuePool->obtain(prop); + updatedValue->timestamp = elapsedRealtimeNano(); + setResult = mServerSidePropStore->writeValue(std::move(updatedValue)); + } + + if (setResult.ok()) { + return StringPrintf("Set property: %s\n", prop.toString().c_str()); + } + return StringPrintf("failed to set property: %s, error: %s\n", prop.toString().c_str(), + getErrorMsg(setResult).c_str()); +} + +std::string FakeVehicleHardware::dumpGetPropertyWithArg(const std::vector& options) { + if (auto result = checkArgumentsSize(options, 3); !result.ok()) { + return getErrorMsg(result); + } + + auto parseResult = parsePropOptions(options); + if (!parseResult.ok()) { + return getErrorMsg(parseResult); + } + VehiclePropValue prop = std::move(parseResult.value()); + ALOGD("Dump: Getting property: %s", prop.toString().c_str()); + + bool isSpecialValue = false; + auto result = maybeGetSpecialValue(prop, &isSpecialValue); + + if (!isSpecialValue) { + result = mServerSidePropStore->readValue(prop); + } + + if (!result.ok()) { + return StringPrintf("failed to read property value: %s, error: %s, code: %d\n", + PROP_ID_TO_CSTR(prop.prop), getErrorMsg(result).c_str(), + getIntErrorCode(result)); + } + return StringPrintf("Get property result: %s\n", result.value()->toString().c_str()); +} + +std::string FakeVehicleHardware::dumpSaveProperty(const std::vector& options) { + // Format: --save-prop PROP [-a areaID] + if (auto result = checkArgumentsSize(options, 2); !result.ok()) { + return getErrorMsg(result); + } + + auto parseResult = parsePropOptions(options); + if (!parseResult.ok()) { + return getErrorMsg(parseResult); + } + // We are only using the prop and areaId option. + VehiclePropValue value = std::move(parseResult.value()); + int32_t propId = value.prop; + int32_t areaId = value.areaId; + + auto readResult = mServerSidePropStore->readValue(value); + if (!readResult.ok()) { + return StringPrintf("Failed to save current property value, error: %s", + getErrorMsg(readResult).c_str()); + } + + std::scoped_lock lockGuard(mLock); + mSavedProps[PropIdAreaId{ + .propId = propId, + .areaId = areaId, + }] = std::move(readResult.value()); + + return StringPrintf("Property: %" PRId32 ", areaID: %" PRId32 " saved", propId, areaId); +} + +std::string FakeVehicleHardware::dumpRestoreProperty(const std::vector& options) { + // Format: --restore-prop PROP [-a areaID] + if (auto result = checkArgumentsSize(options, 2); !result.ok()) { + return getErrorMsg(result); + } + + auto parseResult = parsePropOptions(options); + if (!parseResult.ok()) { + return getErrorMsg(parseResult); + } + // We are only using the prop and areaId option. + VehiclePropValue value = std::move(parseResult.value()); + int32_t propId = value.prop; + int32_t areaId = value.areaId; + VehiclePropValuePool::RecyclableType savedValue; + + { + std::scoped_lock lockGuard(mLock); + auto it = mSavedProps.find(PropIdAreaId{ + .propId = propId, + .areaId = areaId, + }); + if (it == mSavedProps.end()) { + return StringPrintf("No saved property for property: %" PRId32 ", areaID: %" PRId32, + propId, areaId); + } + + savedValue = std::move(it->second); + // Remove the saved property after restoring it. + mSavedProps.erase(it); + } + + // Update timestamp. + savedValue->timestamp = elapsedRealtimeNano(); + + auto writeResult = mServerSidePropStore->writeValue(std::move(savedValue)); + if (!writeResult.ok()) { + return StringPrintf("Failed to restore property value, error: %s", + getErrorMsg(writeResult).c_str()); + } + + return StringPrintf("Property: %" PRId32 ", areaID: %" PRId32 " restored", propId, areaId); +} + +std::string FakeVehicleHardware::dumpInjectEvent(const std::vector& options) { + if (auto result = checkArgumentsSize(options, 3); !result.ok()) { + return getErrorMsg(result); + } + + auto parseResult = parsePropOptions(options); + if (!parseResult.ok()) { + return getErrorMsg(parseResult); + } + VehiclePropValue prop = std::move(parseResult.value()); + ALOGD("Dump: Injecting event from vehicle bus: %s", prop.toString().c_str()); + + eventFromVehicleBus(prop); + + return StringPrintf("Event for property: %s injected", PROP_ID_TO_CSTR(prop.prop)); +} + +StatusCode FakeVehicleHardware::checkHealth() { + // Always return OK for checkHealth. + return StatusCode::OK; +} + +void FakeVehicleHardware::registerOnPropertyChangeEvent( + std::unique_ptr callback) { + if (mOnPropertyChangeCallback != nullptr) { + ALOGE("registerOnPropertyChangeEvent must only be called once"); + return; + } + mOnPropertyChangeCallback = std::move(callback); +} + +void FakeVehicleHardware::registerOnPropertySetErrorEvent( + std::unique_ptr callback) { + // In FakeVehicleHardware, we will never use mOnPropertySetErrorCallback. + if (mOnPropertySetErrorCallback != nullptr) { + ALOGE("registerOnPropertySetErrorEvent must only be called once"); + return; + } + mOnPropertySetErrorCallback = std::move(callback); +} + +StatusCode FakeVehicleHardware::subscribe(SubscribeOptions options) { + int32_t propId = options.propId; + + auto configResult = mServerSidePropStore->getPropConfig(propId); + if (!configResult.ok()) { + ALOGE("subscribe: property: %" PRId32 " is not supported", propId); + return StatusCode::INVALID_ARG; + } + + std::scoped_lock lockGuard(mLock); + for (int areaId : options.areaIds) { + if (StatusCode status = subscribePropIdAreaIdLocked(propId, areaId, options.sampleRate, + options.enableVariableUpdateRate, + configResult.value()); + status != StatusCode::OK) { + return status; + } + } + return StatusCode::OK; +} + +bool FakeVehicleHardware::isVariableUpdateRateSupported(const VehiclePropConfig& vehiclePropConfig, + int32_t areaId) { + for (size_t i = 0; i < vehiclePropConfig.areaConfigs.size(); i++) { + const auto& areaConfig = vehiclePropConfig.areaConfigs[i]; + if (areaConfig.areaId != areaId) { + continue; + } + if (areaConfig.supportVariableUpdateRate) { + return true; + } + break; + } + return false; +} + +void FakeVehicleHardware::refreshTimestampForInterval(int64_t intervalInNanos) { + std::unordered_map + eventModeByPropIdAreaId; + + { + std::scoped_lock lockGuard(mLock); + + if (mActionByIntervalInNanos.find(intervalInNanos) == mActionByIntervalInNanos.end()) { + ALOGE("No actions scheduled for the interval: %" PRId64 ", ignore the refresh request", + intervalInNanos); + return; + } + + ActionForInterval actionForInterval = mActionByIntervalInNanos[intervalInNanos]; + + // Make a copy so that we don't hold the lock while trying to refresh the timestamp. + // Refreshing the timestamp will inovke onValueChangeCallback which also requires lock, so + // we must not hold lock. + for (const PropIdAreaId& propIdAreaId : actionForInterval.propIdAreaIdsToRefresh) { + const RefreshInfo& refreshInfo = mRefreshInfoByPropIdAreaId[propIdAreaId]; + eventModeByPropIdAreaId[propIdAreaId] = refreshInfo.eventMode; + } + } + + mServerSidePropStore->refreshTimestamps(eventModeByPropIdAreaId); +} + +void FakeVehicleHardware::registerRefreshLocked(PropIdAreaId propIdAreaId, + VehiclePropertyStore::EventMode eventMode, + float sampleRateHz) { + if (mRefreshInfoByPropIdAreaId.find(propIdAreaId) != mRefreshInfoByPropIdAreaId.end()) { + unregisterRefreshLocked(propIdAreaId); + } + + int64_t intervalInNanos = static_cast(1'000'000'000. / sampleRateHz); + RefreshInfo refreshInfo = { + .eventMode = eventMode, + .intervalInNanos = intervalInNanos, + }; + mRefreshInfoByPropIdAreaId[propIdAreaId] = refreshInfo; + + if (mActionByIntervalInNanos.find(intervalInNanos) != mActionByIntervalInNanos.end()) { + // If we have already registered for this interval, then add the action info to the + // actions list. + mActionByIntervalInNanos[intervalInNanos].propIdAreaIdsToRefresh.insert(propIdAreaId); + return; + } + + // This is the first action for the interval, register a timer callback for that interval. + auto action = std::make_shared( + [this, intervalInNanos] { refreshTimestampForInterval(intervalInNanos); }); + mActionByIntervalInNanos[intervalInNanos] = ActionForInterval{ + .propIdAreaIdsToRefresh = {propIdAreaId}, + .recurrentAction = action, + }; + mRecurrentTimer->registerTimerCallback(intervalInNanos, action); +} + +void FakeVehicleHardware::unregisterRefreshLocked(PropIdAreaId propIdAreaId) { + if (mRefreshInfoByPropIdAreaId.find(propIdAreaId) == mRefreshInfoByPropIdAreaId.end()) { + ALOGW("PropId: %" PRId32 ", areaId: %" PRId32 " was not registered for refresh, ignore", + propIdAreaId.propId, propIdAreaId.areaId); + return; + } + + int64_t intervalInNanos = mRefreshInfoByPropIdAreaId[propIdAreaId].intervalInNanos; + auto& actionForInterval = mActionByIntervalInNanos[intervalInNanos]; + actionForInterval.propIdAreaIdsToRefresh.erase(propIdAreaId); + if (actionForInterval.propIdAreaIdsToRefresh.empty()) { + mRecurrentTimer->unregisterTimerCallback(actionForInterval.recurrentAction); + mActionByIntervalInNanos.erase(intervalInNanos); + } + mRefreshInfoByPropIdAreaId.erase(propIdAreaId); +} + +StatusCode FakeVehicleHardware::subscribePropIdAreaIdLocked( + int32_t propId, int32_t areaId, float sampleRateHz, bool enableVariableUpdateRate, + const VehiclePropConfig& vehiclePropConfig) { + PropIdAreaId propIdAreaId{ + .propId = propId, + .areaId = areaId, + }; + switch (vehiclePropConfig.changeMode) { + case VehiclePropertyChangeMode::STATIC: + ALOGW("subscribe to a static property, do nothing."); + return StatusCode::OK; + case VehiclePropertyChangeMode::ON_CHANGE: + mSubOnChangePropIdAreaIds.insert(std::move(propIdAreaId)); + return StatusCode::OK; + case VehiclePropertyChangeMode::CONTINUOUS: + if (sampleRateHz == 0.f) { + ALOGE("Must not use sample rate 0 for a continuous property"); + return StatusCode::INVALID_ARG; + } + // For continuous properties, we must generate a new onPropertyChange event + // periodically according to the sample rate. + auto eventMode = VehiclePropertyStore::EventMode::ALWAYS; + if (isVariableUpdateRateSupported(vehiclePropConfig, areaId) && + enableVariableUpdateRate) { + eventMode = VehiclePropertyStore::EventMode::ON_VALUE_CHANGE; + } + + registerRefreshLocked(propIdAreaId, eventMode, sampleRateHz); + return StatusCode::OK; + } +} + +StatusCode FakeVehicleHardware::unsubscribe(int32_t propId, int32_t areaId) { + std::scoped_lock lockGuard(mLock); + PropIdAreaId propIdAreaId{ + .propId = propId, + .areaId = areaId, + }; + if (mRefreshInfoByPropIdAreaId.find(propIdAreaId) != mRefreshInfoByPropIdAreaId.end()) { + unregisterRefreshLocked(propIdAreaId); + } + mSubOnChangePropIdAreaIds.erase(propIdAreaId); + return StatusCode::OK; +} + +void FakeVehicleHardware::onValueChangeCallback(const VehiclePropValue& value) { + ATRACE_CALL(); + onValuesChangeCallback({value}); +} + +void FakeVehicleHardware::onValuesChangeCallback(std::vector values) { + ATRACE_CALL(); + std::vector subscribedUpdatedValues; + + { + std::scoped_lock lockGuard(mLock); + if (mOnPropertyChangeCallback == nullptr) { + return; + } + + for (const auto& value : values) { + PropIdAreaId propIdAreaId{ + .propId = value.prop, + .areaId = value.areaId, + }; + if (mRefreshInfoByPropIdAreaId.find(propIdAreaId) == mRefreshInfoByPropIdAreaId.end() && + mSubOnChangePropIdAreaIds.find(propIdAreaId) == mSubOnChangePropIdAreaIds.end()) { + if (FAKE_VEHICLEHARDWARE_DEBUG) { + ALOGD("The updated property value: %s is not subscribed, ignore", + value.toString().c_str()); + } + continue; + } + + subscribedUpdatedValues.push_back(value); + } + } + + (*mOnPropertyChangeCallback)(std::move(subscribedUpdatedValues)); +} + +bool FakeVehicleHardware::loadPropConfigsFromDir( + const std::string& dirPath, + std::unordered_map* configsByPropId) { + ALOGI("loading properties from %s", dirPath.c_str()); + auto dir = opendir(dirPath.c_str()); + if (dir == nullptr) { + ALOGE("Failed to open config directory: %s", dirPath.c_str()); + return false; + } + + std::regex regJson(".*[.]json", std::regex::icase); + while (auto f = readdir(dir)) { + if (!std::regex_match(f->d_name, regJson)) { + continue; + } + std::string filePath = dirPath + "/" + std::string(f->d_name); + ALOGI("loading properties from %s", filePath.c_str()); + auto result = mLoader.loadPropConfig(filePath); + if (!result.ok()) { + ALOGE("failed to load config file: %s, error: %s", filePath.c_str(), + result.error().message().c_str()); + continue; + } + for (auto& [propId, configDeclaration] : result.value()) { + (*configsByPropId)[propId] = std::move(configDeclaration); + } + } + closedir(dir); + return true; +} + +Result FakeVehicleHardware::safelyParseFloat(int index, const std::string& s) { + float out; + if (!ParseFloat(s, &out)) { + return Error() << StringPrintf("non-float argument at index %d: %s\n", index, s.c_str()); + } + return out; +} + +Result> FakeVehicleHardware::parseHexString(const std::string& s) { + std::vector bytes; + if (s.size() % 2 != 0) { + return Error() << StringPrintf("invalid hex string: %s, should have even size\n", + s.c_str()); + } + if (!StartsWith(s, "0x")) { + return Error() << StringPrintf("hex string should start with \"0x\", got %s\n", s.c_str()); + } + std::string subs = s.substr(2); + std::transform(subs.begin(), subs.end(), subs.begin(), + [](unsigned char c) { return std::tolower(c); }); + + bool highDigit = true; + for (size_t i = 0; i < subs.size(); i++) { + char c = subs[i]; + uint8_t v; + if (c >= '0' && c <= '9') { + v = c - '0'; + } else if (c >= 'a' && c <= 'f') { + v = c - 'a' + 10; + } else { + return Error() << StringPrintf("invalid character %c in hex string %s\n", c, + subs.c_str()); + } + if (highDigit) { + bytes.push_back(v * 16); + } else { + bytes[bytes.size() - 1] += v; + } + highDigit = !highDigit; + } + return bytes; +} + +template +FakeVehicleHardware::PendingRequestHandler::PendingRequestHandler( + FakeVehicleHardware* hardware) + : mHardware(hardware) { + // Don't initialize mThread in initialization list because mThread depends on mRequests and we + // want mRequests to be initialized first. + mThread = std::thread([this] { + while (mRequests.waitForItems()) { + handleRequestsOnce(); + } + }); +} + +template +void FakeVehicleHardware::PendingRequestHandler::addRequest( + RequestType request, std::shared_ptr callback) { + mRequests.push({ + request, + callback, + }); +} + +template +void FakeVehicleHardware::PendingRequestHandler::stop() { + mRequests.deactivate(); + if (mThread.joinable()) { + mThread.join(); + } +} + +template <> +void FakeVehicleHardware::PendingRequestHandler::handleRequestsOnce() { + std::unordered_map, std::vector> + callbackToResults; + for (const auto& rwc : mRequests.flush()) { + ATRACE_BEGIN("FakeVehicleHardware:handleGetValueRequest"); + auto result = mHardware->handleGetValueRequest(rwc.request); + ATRACE_END(); + callbackToResults[rwc.callback].push_back(std::move(result)); + } + for (const auto& [callback, results] : callbackToResults) { + ATRACE_BEGIN("FakeVehicleHardware:call get value result callback"); + (*callback)(std::move(results)); + ATRACE_END(); + } +} + +template <> +void FakeVehicleHardware::PendingRequestHandler::handleRequestsOnce() { + std::unordered_map, std::vector> + callbackToResults; + for (const auto& rwc : mRequests.flush()) { + ATRACE_BEGIN("FakeVehicleHardware:handleSetValueRequest"); + auto result = mHardware->handleSetValueRequest(rwc.request); + ATRACE_END(); + callbackToResults[rwc.callback].push_back(std::move(result)); + } + for (const auto& [callback, results] : callbackToResults) { + ATRACE_BEGIN("FakeVehicleHardware:call set value result callback"); + (*callback)(std::move(results)); + ATRACE_END(); + } +} + +} // namespace fake +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/3/fake_impl/hardware/test/Android.bp b/automotive/vehicle/aidl/impl/3/fake_impl/hardware/test/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..e7e5ba7161e0dba1956a3cb2f82ba976f5753adf --- /dev/null +++ b/automotive/vehicle/aidl/impl/3/fake_impl/hardware/test/Android.bp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + default_team: "trendy_team_aaos_framework", + default_applicable_licenses: ["Android-Apache-2.0"], +} + +cc_test { + name: "FakeVehicleHardwareTest-V3", + vendor: true, + srcs: [ + "*.cpp", + ":VhalTestVendorProperties-V3", + ], + cflags: ["-DENABLE_VEHICLE_HAL_TEST_PROPERTIES"], + header_libs: [ + "IVehicleHardware-V3", + "libbinder_headers", + ], + static_libs: [ + "VehicleHalJsonConfigLoaderEnableTestProperties-V3", + "VehicleHalUtils-V3", + "FakeVehicleHardware-V3", + "FakeVehicleHalValueGenerators-V3", + "FakeObd2Frame-V3", + "FakeUserHal-V3", + "libgtest", + "libgmock", + "libjsoncpp", + ], + shared_libs: [ + "libgrpc++", + "libprotobuf-cpp-full", + ], + data: [ + ":VehicleHalDefaultProperties_JSON-V3", + ":VehicleHalTestProperties_JSON-V3", + ":VehicleHalVendorClusterTestProperties_JSON-V3", + ":FakeVehicleHardwareTestOverrideJson-V3", + ":FakeVehicleHardwareTestPropJson-V3", + ], + defaults: [ + "VehicleHalDefaults-V3", + ], + // Need root to use vendor lib: libgrpc++. + require_root: true, + test_suites: ["device-tests"], +} + +filegroup { + name: "FakeVehicleHardwareTestOverrideJson-V3", + srcs: ["override/*"], +} + +filegroup { + name: "FakeVehicleHardwareTestPropJson-V3", + srcs: ["fakedata/prop.json"], +} diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp b/automotive/vehicle/aidl/impl/3/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp rename to automotive/vehicle/aidl/impl/3/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp diff --git a/automotive/vehicle/aidl/impl/3/fake_impl/hardware/test/fakedata/prop.json b/automotive/vehicle/aidl/impl/3/fake_impl/hardware/test/fakedata/prop.json new file mode 100644 index 0000000000000000000000000000000000000000..7123a002cc3656e640e9bdec7d6ca726ac6edc8f --- /dev/null +++ b/automotive/vehicle/aidl/impl/3/fake_impl/hardware/test/fakedata/prop.json @@ -0,0 +1,26 @@ +[ + { + "timestamp": 1000000, + "areaId": 0, + "value": 8, + "prop": 289408000 + }, + { + "timestamp": 2000000, + "areaId": 0, + "value": 4, + "prop": 289408000 + }, + { + "timestamp": 3000000, + "areaId": 0, + "value": 16, + "prop": 289408000 + }, + { + "timestamp": 4000000, + "areaId": 0, + "value": 10, + "prop": 289408000 + } +] diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/override/gear_selection.json b/automotive/vehicle/aidl/impl/3/fake_impl/hardware/test/override/gear_selection.json similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/hardware/test/override/gear_selection.json rename to automotive/vehicle/aidl/impl/3/fake_impl/hardware/test/override/gear_selection.json diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/override/hvac_temperature_set.json b/automotive/vehicle/aidl/impl/3/fake_impl/hardware/test/override/hvac_temperature_set.json similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/hardware/test/override/hvac_temperature_set.json rename to automotive/vehicle/aidl/impl/3/fake_impl/hardware/test/override/hvac_temperature_set.json diff --git a/automotive/vehicle/aidl/impl/3/fake_impl/obd2frame/Android.bp b/automotive/vehicle/aidl/impl/3/fake_impl/obd2frame/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..1e71661bfdf89674ca6d87bf903fc192423480df --- /dev/null +++ b/automotive/vehicle/aidl/impl/3/fake_impl/obd2frame/Android.bp @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +cc_library { + name: "FakeObd2Frame-V3", + vendor: true, + srcs: ["src/*.cpp"], + local_include_dirs: ["include"], + export_include_dirs: ["include"], + defaults: ["VehicleHalDefaults-V3"], + static_libs: [ + "VehicleHalUtils-V3", + ], + export_static_lib_headers: ["VehicleHalUtils-V3"], + host_supported: true, +} diff --git a/automotive/vehicle/aidl/impl/fake_impl/obd2frame/include/FakeObd2Frame.h b/automotive/vehicle/aidl/impl/3/fake_impl/obd2frame/include/FakeObd2Frame.h similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/obd2frame/include/FakeObd2Frame.h rename to automotive/vehicle/aidl/impl/3/fake_impl/obd2frame/include/FakeObd2Frame.h diff --git a/automotive/vehicle/aidl/impl/fake_impl/obd2frame/include/Obd2SensorStore.h b/automotive/vehicle/aidl/impl/3/fake_impl/obd2frame/include/Obd2SensorStore.h similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/obd2frame/include/Obd2SensorStore.h rename to automotive/vehicle/aidl/impl/3/fake_impl/obd2frame/include/Obd2SensorStore.h diff --git a/automotive/vehicle/aidl/impl/fake_impl/obd2frame/src/FakeObd2Frame.cpp b/automotive/vehicle/aidl/impl/3/fake_impl/obd2frame/src/FakeObd2Frame.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/obd2frame/src/FakeObd2Frame.cpp rename to automotive/vehicle/aidl/impl/3/fake_impl/obd2frame/src/FakeObd2Frame.cpp diff --git a/automotive/vehicle/aidl/impl/fake_impl/obd2frame/src/Obd2SensorStore.cpp b/automotive/vehicle/aidl/impl/3/fake_impl/obd2frame/src/Obd2SensorStore.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/obd2frame/src/Obd2SensorStore.cpp rename to automotive/vehicle/aidl/impl/3/fake_impl/obd2frame/src/Obd2SensorStore.cpp diff --git a/automotive/vehicle/aidl/impl/3/fake_impl/obd2frame/test/Android.bp b/automotive/vehicle/aidl/impl/3/fake_impl/obd2frame/test/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..8b30477ec2a6199799267e6606ffca292c278a12 --- /dev/null +++ b/automotive/vehicle/aidl/impl/3/fake_impl/obd2frame/test/Android.bp @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + default_team: "trendy_team_aaos_framework", + default_applicable_licenses: ["Android-Apache-2.0"], +} + +cc_test { + name: "FakeObd2FrameTest-V3", + vendor: true, + srcs: ["*.cpp"], + defaults: ["VehicleHalDefaults-V3"], + static_libs: [ + "FakeObd2Frame-V3", + "VehicleHalUtils-V3", + ], + test_suites: ["device-tests"], +} diff --git a/automotive/vehicle/aidl/impl/fake_impl/obd2frame/test/FakeObd2FrameTest.cpp b/automotive/vehicle/aidl/impl/3/fake_impl/obd2frame/test/FakeObd2FrameTest.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/obd2frame/test/FakeObd2FrameTest.cpp rename to automotive/vehicle/aidl/impl/3/fake_impl/obd2frame/test/FakeObd2FrameTest.cpp diff --git a/automotive/vehicle/aidl/impl/fake_impl/obd2frame/test/Obd2SensorStoreTest.cpp b/automotive/vehicle/aidl/impl/3/fake_impl/obd2frame/test/Obd2SensorStoreTest.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/obd2frame/test/Obd2SensorStoreTest.cpp rename to automotive/vehicle/aidl/impl/3/fake_impl/obd2frame/test/Obd2SensorStoreTest.cpp diff --git a/automotive/vehicle/aidl/impl/3/fake_impl/userhal/Android.bp b/automotive/vehicle/aidl/impl/3/fake_impl/userhal/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..2adf7c4b09526c87b786be4549d5464967b438ef --- /dev/null +++ b/automotive/vehicle/aidl/impl/3/fake_impl/userhal/Android.bp @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +cc_library { + name: "FakeUserHal-V3", + vendor: true, + srcs: ["src/*.cpp"], + local_include_dirs: ["include"], + export_include_dirs: ["include"], + defaults: ["VehicleHalDefaults-V3"], + static_libs: [ + "VehicleHalUtils-V3", + ], + export_static_lib_headers: ["VehicleHalUtils-V3"], + host_supported: true, +} diff --git a/automotive/vehicle/aidl/impl/fake_impl/userhal/include/FakeUserHal.h b/automotive/vehicle/aidl/impl/3/fake_impl/userhal/include/FakeUserHal.h similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/userhal/include/FakeUserHal.h rename to automotive/vehicle/aidl/impl/3/fake_impl/userhal/include/FakeUserHal.h diff --git a/automotive/vehicle/aidl/impl/fake_impl/userhal/include/UserHalHelper.h b/automotive/vehicle/aidl/impl/3/fake_impl/userhal/include/UserHalHelper.h similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/userhal/include/UserHalHelper.h rename to automotive/vehicle/aidl/impl/3/fake_impl/userhal/include/UserHalHelper.h diff --git a/automotive/vehicle/aidl/impl/fake_impl/userhal/include/UserHalTypes.h b/automotive/vehicle/aidl/impl/3/fake_impl/userhal/include/UserHalTypes.h similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/userhal/include/UserHalTypes.h rename to automotive/vehicle/aidl/impl/3/fake_impl/userhal/include/UserHalTypes.h diff --git a/automotive/vehicle/aidl/impl/fake_impl/userhal/src/FakeUserHal.cpp b/automotive/vehicle/aidl/impl/3/fake_impl/userhal/src/FakeUserHal.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/userhal/src/FakeUserHal.cpp rename to automotive/vehicle/aidl/impl/3/fake_impl/userhal/src/FakeUserHal.cpp diff --git a/automotive/vehicle/aidl/impl/fake_impl/userhal/src/UserHalHelper.cpp b/automotive/vehicle/aidl/impl/3/fake_impl/userhal/src/UserHalHelper.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/userhal/src/UserHalHelper.cpp rename to automotive/vehicle/aidl/impl/3/fake_impl/userhal/src/UserHalHelper.cpp diff --git a/automotive/vehicle/aidl/impl/3/fake_impl/userhal/test/Android.bp b/automotive/vehicle/aidl/impl/3/fake_impl/userhal/test/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..55178dca67929a4b3dafb347dea335d018da81ac --- /dev/null +++ b/automotive/vehicle/aidl/impl/3/fake_impl/userhal/test/Android.bp @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + default_team: "trendy_team_aaos_framework", + default_applicable_licenses: ["Android-Apache-2.0"], +} + +cc_test { + name: "FakeUserHalTest-V3", + vendor: true, + srcs: ["*.cpp"], + defaults: ["VehicleHalDefaults-V3"], + static_libs: [ + "FakeUserHal-V3", + "VehicleHalUtils-V3", + "libgtest", + "libgmock", + ], + test_suites: ["device-tests"], +} diff --git a/automotive/vehicle/aidl/impl/fake_impl/userhal/test/UserHalHelper_test.cpp b/automotive/vehicle/aidl/impl/3/fake_impl/userhal/test/UserHalHelper_test.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/userhal/test/UserHalHelper_test.cpp rename to automotive/vehicle/aidl/impl/3/fake_impl/userhal/test/UserHalHelper_test.cpp diff --git a/automotive/vehicle/aidl/impl/3/grpc/Android.bp b/automotive/vehicle/aidl/impl/3/grpc/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..6fa2bfa29f8927ae6fa4d4c255a2d1f5f6a34f5e --- /dev/null +++ b/automotive/vehicle/aidl/impl/3/grpc/Android.bp @@ -0,0 +1,132 @@ +// Copyright (C) 2023 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +genrule { + name: "VehicleServerProtoStub_h@default-grpc-V3", + tools: [ + "aprotoc", + "protoc-gen-grpc-cpp-plugin", + ], + cmd: "$(location aprotoc) -I$$(dirname $(location proto/VehicleServer.proto)) -Ihardware/interfaces/automotive/vehicle/aidl/impl/3/proto -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(location proto/VehicleServer.proto) --grpc_opt=generate_mock_code=true --grpc_out=$(genDir) --cpp_out=$(genDir)", + srcs: [ + "proto/VehicleServer.proto", + ":libprotobuf-internal-protos", + ":VehicleHalProtoFiles-V3", + ], + out: [ + "VehicleServer.pb.h", + "VehicleServer.grpc.pb.h", + "VehicleServer_mock.grpc.pb.h", + ], + visibility: ["//visibility:private"], +} + +genrule { + name: "VehicleServerProtoStub_cc@default-grpc-V3", + tools: [ + "aprotoc", + "protoc-gen-grpc-cpp-plugin", + ], + cmd: "$(location aprotoc) -I$$(dirname $(location proto/VehicleServer.proto)) -Ihardware/interfaces/automotive/vehicle/aidl/impl/3/proto -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(location proto/VehicleServer.proto) --grpc_out=$(genDir) --cpp_out=$(genDir)", + srcs: [ + "proto/VehicleServer.proto", + ":libprotobuf-internal-protos", + ":VehicleHalProtoFiles-V3", + ], + out: [ + "VehicleServer.pb.cc", + "VehicleServer.grpc.pb.cc", + ], + visibility: ["//visibility:private"], +} + +cc_library_static { + name: "android.hardware.automotive.vehicle@default-grpc-libgrpc-V3", + vendor: true, + host_supported: true, + include_dirs: [ + "external/protobuf/src", + ], + generated_headers: [ + "VehicleServerProtoStub_h@default-grpc-V3", + ], + export_generated_headers: [ + "VehicleServerProtoStub_h@default-grpc-V3", + ], + generated_sources: [ + "VehicleServerProtoStub_cc@default-grpc-V3", + ], + whole_static_libs: [ + "VehicleHalProtos-V3", + ], + shared_libs: [ + "libgrpc++", + ], + cflags: [ + "-Wno-unused-parameter", + ], +} + +cc_library_static { + name: "android.hardware.automotive.vehicle@default-grpc-hardware-lib-V3", + defaults: ["VehicleHalDefaults-V3"], + vendor: true, + srcs: [ + "GRPCVehicleHardware.cpp", + ], + whole_static_libs: [ + "android.hardware.automotive.vehicle@default-grpc-libgrpc-V3", + "VehicleHalProtoMessageConverter-V3", + ], + header_libs: [ + "IVehicleHardware-V3", + ], + shared_libs: [ + "libgrpc++", + "libprotobuf-cpp-full", + ], + export_include_dirs: ["."], + cflags: [ + "-Wno-unused-parameter", + ], +} + +cc_library_static { + name: "android.hardware.automotive.vehicle@default-grpc-server-lib-V3", + defaults: ["VehicleHalDefaults-V3"], + vendor: true, + srcs: [ + "GRPCVehicleProxyServer.cpp", + ], + whole_static_libs: [ + "android.hardware.automotive.vehicle@default-grpc-libgrpc-V3", + "VehicleHalProtoMessageConverter-V3", + ], + header_libs: [ + "IVehicleHardware-V3", + ], + shared_libs: [ + "libgrpc++", + "libprotobuf-cpp-full", + ], + export_include_dirs: ["."], + cflags: [ + "-Wno-unused-parameter", + ], + host_supported: true, +} diff --git a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.cpp b/automotive/vehicle/aidl/impl/3/grpc/GRPCVehicleHardware.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.cpp rename to automotive/vehicle/aidl/impl/3/grpc/GRPCVehicleHardware.cpp diff --git a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h b/automotive/vehicle/aidl/impl/3/grpc/GRPCVehicleHardware.h similarity index 97% rename from automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h rename to automotive/vehicle/aidl/impl/3/grpc/GRPCVehicleHardware.h index 15f473c0bd9f344adf3592e03854c52530a1f596..ad2f5121869aa9660983bb75ab3f9917afcbdb0d 100644 --- a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h +++ b/automotive/vehicle/aidl/impl/3/grpc/GRPCVehicleHardware.h @@ -115,9 +115,8 @@ class GRPCVehicleHardware : public IVehicleHardware { // A map from [propId, areaId] to the latest timestamp this property is updated. // The key is a tuple, the first element is the external timestamp (timestamp set by VHAL // server), the second element is the Android timestamp (elapsedRealtimeNano). - mutable std::unordered_map, - PropIdAreaIdHash> mLatestUpdateTimestamps - GUARDED_BY(mLatestUpdateTimestampsMutex); + mutable std::unordered_map, PropIdAreaIdHash> + mLatestUpdateTimestamps GUARDED_BY(mLatestUpdateTimestampsMutex); // Only used for unit testing. GRPCVehicleHardware(std::unique_ptr stub, diff --git a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.cpp b/automotive/vehicle/aidl/impl/3/grpc/GRPCVehicleProxyServer.cpp similarity index 99% rename from automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.cpp rename to automotive/vehicle/aidl/impl/3/grpc/GRPCVehicleProxyServer.cpp index 7697c03d74fddf2f56384fb43b5bd8585b1519c0..927a5955e7bab4b5ca2841c5225a453f0f89fa12 100644 --- a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.cpp +++ b/automotive/vehicle/aidl/impl/3/grpc/GRPCVehicleProxyServer.cpp @@ -40,7 +40,7 @@ static std::shared_ptr<::grpc::ServerCredentials> getServerCredentials() { GrpcVehicleProxyServer::GrpcVehicleProxyServer(std::string serverAddr, std::unique_ptr&& hardware) - : GrpcVehicleProxyServer(std::vector({serverAddr}), std::move(hardware)){}; + : GrpcVehicleProxyServer(std::vector({serverAddr}), std::move(hardware)) {}; GrpcVehicleProxyServer::GrpcVehicleProxyServer(std::vector serverAddrs, std::unique_ptr&& hardware) diff --git a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.h b/automotive/vehicle/aidl/impl/3/grpc/GRPCVehicleProxyServer.h similarity index 100% rename from automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.h rename to automotive/vehicle/aidl/impl/3/grpc/GRPCVehicleProxyServer.h diff --git a/automotive/vehicle/aidl/impl/grpc/proto/VehicleServer.proto b/automotive/vehicle/aidl/impl/3/grpc/proto/VehicleServer.proto similarity index 100% rename from automotive/vehicle/aidl/impl/grpc/proto/VehicleServer.proto rename to automotive/vehicle/aidl/impl/3/grpc/proto/VehicleServer.proto diff --git a/automotive/vehicle/aidl/impl/3/grpc/test/Android.bp b/automotive/vehicle/aidl/impl/3/grpc/test/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..1ab946bc0fb1ce7265a14a643f7199ada1b8668e --- /dev/null +++ b/automotive/vehicle/aidl/impl/3/grpc/test/Android.bp @@ -0,0 +1,75 @@ +// Copyright (C) 2023 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + default_team: "trendy_team_automotive", + default_applicable_licenses: ["Android-Apache-2.0"], +} + +cc_test { + name: "GRPCVehicleHardwareUnitTest-V3", + vendor: true, + srcs: ["GRPCVehicleHardwareUnitTest.cpp"], + whole_static_libs: [ + "android.hardware.automotive.vehicle@default-grpc-hardware-lib-V3", + ], + header_libs: [ + "IVehicleHardware-V3", + ], + static_libs: [ + "libgtest", + "libgmock", + ], + shared_libs: [ + "libgrpc++", + "libprotobuf-cpp-full", + ], + // libgrpc++.so is installed as root, require root to access it. + require_root: true, + defaults: [ + "VehicleHalDefaults-V3", + ], + cflags: [ + "-Wno-unused-parameter", + ], + test_suites: ["device-tests"], +} + +cc_test { + name: "GRPCVehicleProxyServerUnitTest-V3", + vendor: true, + srcs: ["GRPCVehicleProxyServerUnitTest.cpp"], + header_libs: [ + "IVehicleHardware-V3", + ], + static_libs: [ + "android.hardware.automotive.vehicle@default-grpc-hardware-lib-V3", + "android.hardware.automotive.vehicle@default-grpc-server-lib-V3", + "libgtest", + "libgmock", + ], + shared_libs: [ + "libgrpc++", + "libprotobuf-cpp-full", + ], + // libgrpc++.so is installed as root, require root to access it. + require_root: true, + defaults: [ + "VehicleHalDefaults-V3", + ], + cflags: [ + "-Wno-unused-parameter", + ], + test_suites: ["device-tests"], +} diff --git a/automotive/vehicle/aidl/impl/grpc/test/GRPCVehicleHardwareUnitTest.cpp b/automotive/vehicle/aidl/impl/3/grpc/test/GRPCVehicleHardwareUnitTest.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/grpc/test/GRPCVehicleHardwareUnitTest.cpp rename to automotive/vehicle/aidl/impl/3/grpc/test/GRPCVehicleHardwareUnitTest.cpp diff --git a/automotive/vehicle/aidl/impl/grpc/test/GRPCVehicleProxyServerUnitTest.cpp b/automotive/vehicle/aidl/impl/3/grpc/test/GRPCVehicleProxyServerUnitTest.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/grpc/test/GRPCVehicleProxyServerUnitTest.cpp rename to automotive/vehicle/aidl/impl/3/grpc/test/GRPCVehicleProxyServerUnitTest.cpp diff --git a/automotive/vehicle/aidl/impl/3/grpc/utils/proto_message_converter/Android.bp b/automotive/vehicle/aidl/impl/3/grpc/utils/proto_message_converter/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..5ae94b5f8c58738d3dad081dff55ef8737076a94 --- /dev/null +++ b/automotive/vehicle/aidl/impl/3/grpc/utils/proto_message_converter/Android.bp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + default_team: "trendy_team_automotive", + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_library { + name: "VehicleHalProtoMessageConverter-V3", + srcs: [ + "src/*.cpp", + ], + vendor: true, + local_include_dirs: ["include"], + export_include_dirs: ["include"], + shared_libs: ["libprotobuf-cpp-full"], + static_libs: [ + "VehicleHalProtos-V3", + "VehicleHalUtils-V3", + ], + defaults: ["VehicleHalDefaults-V3"], + export_static_lib_headers: ["VehicleHalUtils-V3"], + host_supported: true, +} + +cc_test_host { + name: "VehicleHalProtoMessageConverterTest-V3", + srcs: [ + "test/*.cpp", + ], + vendor: true, + defaults: ["VehicleHalDefaults-V3"], + static_libs: [ + "VehicleHalJsonConfigLoaderEnableTestProperties-V3", + "VehicleHalProtoMessageConverter-V3", + "VehicleHalProtos-V3", + "VehicleHalUtils-V3", + "libgtest", + "libprotobuf-cpp-full", + "libjsoncpp", + ], + data: [ + ":VehicleHalDefaultProperties_JSON-V3", + ], + test_suites: ["device-tests"], +} diff --git a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/include/ProtoMessageConverter.h b/automotive/vehicle/aidl/impl/3/grpc/utils/proto_message_converter/include/ProtoMessageConverter.h similarity index 100% rename from automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/include/ProtoMessageConverter.h rename to automotive/vehicle/aidl/impl/3/grpc/utils/proto_message_converter/include/ProtoMessageConverter.h diff --git a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/src/ProtoMessageConverter.cpp b/automotive/vehicle/aidl/impl/3/grpc/utils/proto_message_converter/src/ProtoMessageConverter.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/src/ProtoMessageConverter.cpp rename to automotive/vehicle/aidl/impl/3/grpc/utils/proto_message_converter/src/ProtoMessageConverter.cpp diff --git a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp b/automotive/vehicle/aidl/impl/3/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp rename to automotive/vehicle/aidl/impl/3/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp diff --git a/automotive/vehicle/aidl/impl/3/hardware/Android.bp b/automotive/vehicle/aidl/impl/3/hardware/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..953760fce6472ac5a4483fdd25c0ee2dc17c9c2c --- /dev/null +++ b/automotive/vehicle/aidl/impl/3/hardware/Android.bp @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +cc_library_headers { + name: "IVehicleHardware-V3", + vendor: true, + export_include_dirs: [ + "include", + ], + header_libs: [ + "VehicleHalUtilHeaders-V3", + ], + export_header_lib_headers: [ + "VehicleHalUtilHeaders-V3", + ], + host_supported: true, +} diff --git a/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h b/automotive/vehicle/aidl/impl/3/hardware/include/IVehicleHardware.h similarity index 100% rename from automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h rename to automotive/vehicle/aidl/impl/3/hardware/include/IVehicleHardware.h diff --git a/automotive/vehicle/aidl/impl/3/proto/Android.bp b/automotive/vehicle/aidl/impl/3/proto/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..9840e637690a8d5a8173c97876d4c6f2d52b87e3 --- /dev/null +++ b/automotive/vehicle/aidl/impl/3/proto/Android.bp @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +filegroup { + name: "VehicleHalProtoFiles-V3", + srcs: ["**/*.proto"], + visibility: ["//hardware/interfaces/automotive/vehicle:__subpackages__"], +} + +genrule { + name: "VehicleProtoStub_h-V3", + tools: [ + "aprotoc", + "protoc-gen-grpc-cpp-plugin", + ], + cmd: "$(location aprotoc) -Ihardware/interfaces/automotive/vehicle/aidl/impl/3/proto -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(in) --grpc_out=$(genDir) --cpp_out=$(genDir)", + srcs: [ + ":VehicleHalProtoFiles-V3", + ], + out: [ + "android/hardware/automotive/vehicle/DumpOptions.pb.h", + "android/hardware/automotive/vehicle/DumpResult.pb.h", + "android/hardware/automotive/vehicle/StatusCode.pb.h", + "android/hardware/automotive/vehicle/VehicleAreaConfig.pb.h", + "android/hardware/automotive/vehicle/VehiclePropConfig.pb.h", + "android/hardware/automotive/vehicle/VehiclePropertyAccess.pb.h", + "android/hardware/automotive/vehicle/VehiclePropertyChangeMode.pb.h", + "android/hardware/automotive/vehicle/VehiclePropertyStatus.pb.h", + "android/hardware/automotive/vehicle/VehiclePropValue.pb.h", + "android/hardware/automotive/vehicle/VehiclePropValueRequest.pb.h", + "android/hardware/automotive/vehicle/SubscribeOptions.pb.h", + "android/hardware/automotive/vehicle/SubscribeRequest.pb.h", + "android/hardware/automotive/vehicle/UnsubscribeRequest.pb.h", + ], +} + +genrule { + name: "VehicleProtoStub_cc-V3", + tools: [ + "aprotoc", + "protoc-gen-grpc-cpp-plugin", + ], + cmd: "$(location aprotoc) -Ihardware/interfaces/automotive/vehicle/aidl/impl/3/proto -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(in) --grpc_out=$(genDir) --cpp_out=$(genDir)", + srcs: [ + ":VehicleHalProtoFiles-V3", + ], + out: [ + "android/hardware/automotive/vehicle/DumpOptions.pb.cc", + "android/hardware/automotive/vehicle/DumpResult.pb.cc", + "android/hardware/automotive/vehicle/StatusCode.pb.cc", + "android/hardware/automotive/vehicle/VehicleAreaConfig.pb.cc", + "android/hardware/automotive/vehicle/VehiclePropConfig.pb.cc", + "android/hardware/automotive/vehicle/VehiclePropertyAccess.pb.cc", + "android/hardware/automotive/vehicle/VehiclePropertyChangeMode.pb.cc", + "android/hardware/automotive/vehicle/VehiclePropertyStatus.pb.cc", + "android/hardware/automotive/vehicle/VehiclePropValue.pb.cc", + "android/hardware/automotive/vehicle/VehiclePropValueRequest.pb.cc", + "android/hardware/automotive/vehicle/SubscribeOptions.pb.cc", + "android/hardware/automotive/vehicle/SubscribeRequest.pb.cc", + "android/hardware/automotive/vehicle/UnsubscribeRequest.pb.cc", + ], +} + +cc_library_static { + name: "VehicleHalProtos-V3", + vendor: true, + host_supported: true, + include_dirs: [ + "external/protobuf/src", + ], + generated_headers: [ + "VehicleProtoStub_h-V3", + ], + export_generated_headers: [ + "VehicleProtoStub_h-V3", + ], + generated_sources: [ + "VehicleProtoStub_cc-V3", + ], + shared_libs: [ + "libgrpc++_unsecure", + ], + cflags: [ + "-Wno-unused-parameter", + ], +} + +rust_protobuf { + name: "libvehicle_hal_property_protos-V3", + crate_name: "vehicle_hal_property_protos", + protos: [":VehicleHalProtoFiles-V3"], + source_stem: "vehicle_hal_property_protos", + host_supported: true, + vendor_available: true, + product_available: true, + apex_available: [ + "//apex_available:platform", + "//apex_available:anyapex", + ], + exported_include_dirs: ["."], + proto_flags: [ + "-I external/protobuf/src", + ], +} diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/DumpOptions.proto b/automotive/vehicle/aidl/impl/3/proto/android/hardware/automotive/vehicle/DumpOptions.proto similarity index 100% rename from automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/DumpOptions.proto rename to automotive/vehicle/aidl/impl/3/proto/android/hardware/automotive/vehicle/DumpOptions.proto diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/DumpResult.proto b/automotive/vehicle/aidl/impl/3/proto/android/hardware/automotive/vehicle/DumpResult.proto similarity index 100% rename from automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/DumpResult.proto rename to automotive/vehicle/aidl/impl/3/proto/android/hardware/automotive/vehicle/DumpResult.proto diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/StatusCode.proto b/automotive/vehicle/aidl/impl/3/proto/android/hardware/automotive/vehicle/StatusCode.proto similarity index 100% rename from automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/StatusCode.proto rename to automotive/vehicle/aidl/impl/3/proto/android/hardware/automotive/vehicle/StatusCode.proto diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/SubscribeOptions.proto b/automotive/vehicle/aidl/impl/3/proto/android/hardware/automotive/vehicle/SubscribeOptions.proto similarity index 100% rename from automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/SubscribeOptions.proto rename to automotive/vehicle/aidl/impl/3/proto/android/hardware/automotive/vehicle/SubscribeOptions.proto diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/SubscribeRequest.proto b/automotive/vehicle/aidl/impl/3/proto/android/hardware/automotive/vehicle/SubscribeRequest.proto similarity index 100% rename from automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/SubscribeRequest.proto rename to automotive/vehicle/aidl/impl/3/proto/android/hardware/automotive/vehicle/SubscribeRequest.proto diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/UnsubscribeRequest.proto b/automotive/vehicle/aidl/impl/3/proto/android/hardware/automotive/vehicle/UnsubscribeRequest.proto similarity index 100% rename from automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/UnsubscribeRequest.proto rename to automotive/vehicle/aidl/impl/3/proto/android/hardware/automotive/vehicle/UnsubscribeRequest.proto diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehicleAreaConfig.proto b/automotive/vehicle/aidl/impl/3/proto/android/hardware/automotive/vehicle/VehicleAreaConfig.proto similarity index 100% rename from automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehicleAreaConfig.proto rename to automotive/vehicle/aidl/impl/3/proto/android/hardware/automotive/vehicle/VehicleAreaConfig.proto diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropConfig.proto b/automotive/vehicle/aidl/impl/3/proto/android/hardware/automotive/vehicle/VehiclePropConfig.proto similarity index 100% rename from automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropConfig.proto rename to automotive/vehicle/aidl/impl/3/proto/android/hardware/automotive/vehicle/VehiclePropConfig.proto diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropValue.proto b/automotive/vehicle/aidl/impl/3/proto/android/hardware/automotive/vehicle/VehiclePropValue.proto similarity index 100% rename from automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropValue.proto rename to automotive/vehicle/aidl/impl/3/proto/android/hardware/automotive/vehicle/VehiclePropValue.proto diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropValueRequest.proto b/automotive/vehicle/aidl/impl/3/proto/android/hardware/automotive/vehicle/VehiclePropValueRequest.proto similarity index 100% rename from automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropValueRequest.proto rename to automotive/vehicle/aidl/impl/3/proto/android/hardware/automotive/vehicle/VehiclePropValueRequest.proto diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropertyAccess.proto b/automotive/vehicle/aidl/impl/3/proto/android/hardware/automotive/vehicle/VehiclePropertyAccess.proto similarity index 100% rename from automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropertyAccess.proto rename to automotive/vehicle/aidl/impl/3/proto/android/hardware/automotive/vehicle/VehiclePropertyAccess.proto diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropertyChangeMode.proto b/automotive/vehicle/aidl/impl/3/proto/android/hardware/automotive/vehicle/VehiclePropertyChangeMode.proto similarity index 100% rename from automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropertyChangeMode.proto rename to automotive/vehicle/aidl/impl/3/proto/android/hardware/automotive/vehicle/VehiclePropertyChangeMode.proto diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropertyStatus.proto b/automotive/vehicle/aidl/impl/3/proto/android/hardware/automotive/vehicle/VehiclePropertyStatus.proto similarity index 100% rename from automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropertyStatus.proto rename to automotive/vehicle/aidl/impl/3/proto/android/hardware/automotive/vehicle/VehiclePropertyStatus.proto diff --git a/automotive/vehicle/aidl/impl/utils/README.md b/automotive/vehicle/aidl/impl/3/utils/README.md similarity index 100% rename from automotive/vehicle/aidl/impl/utils/README.md rename to automotive/vehicle/aidl/impl/3/utils/README.md diff --git a/automotive/vehicle/aidl/impl/3/utils/common/Android.bp b/automotive/vehicle/aidl/impl/3/utils/common/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..f653d9019ec32eabdb08f059d61ba8e18d30f84a --- /dev/null +++ b/automotive/vehicle/aidl/impl/3/utils/common/Android.bp @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +cc_library { + name: "VehicleHalUtils-V3", + srcs: ["src/*.cpp"], + vendor_available: true, + local_include_dirs: ["include"], + export_include_dirs: ["include"], + defaults: ["VehicleHalDefaults-V3"], + host_supported: true, +} + +cc_library_headers { + name: "VehicleHalUtilHeaders-V3", + export_include_dirs: ["include"], + vendor: true, + host_supported: true, +} diff --git a/automotive/vehicle/aidl/impl/utils/common/include/ConcurrentQueue.h b/automotive/vehicle/aidl/impl/3/utils/common/include/ConcurrentQueue.h similarity index 100% rename from automotive/vehicle/aidl/impl/utils/common/include/ConcurrentQueue.h rename to automotive/vehicle/aidl/impl/3/utils/common/include/ConcurrentQueue.h diff --git a/automotive/vehicle/aidl/impl/utils/common/include/ParcelableUtils.h b/automotive/vehicle/aidl/impl/3/utils/common/include/ParcelableUtils.h similarity index 100% rename from automotive/vehicle/aidl/impl/utils/common/include/ParcelableUtils.h rename to automotive/vehicle/aidl/impl/3/utils/common/include/ParcelableUtils.h diff --git a/automotive/vehicle/aidl/impl/utils/common/include/PendingRequestPool.h b/automotive/vehicle/aidl/impl/3/utils/common/include/PendingRequestPool.h similarity index 100% rename from automotive/vehicle/aidl/impl/utils/common/include/PendingRequestPool.h rename to automotive/vehicle/aidl/impl/3/utils/common/include/PendingRequestPool.h diff --git a/automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h b/automotive/vehicle/aidl/impl/3/utils/common/include/PropertyUtils.h similarity index 100% rename from automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h rename to automotive/vehicle/aidl/impl/3/utils/common/include/PropertyUtils.h diff --git a/automotive/vehicle/aidl/impl/utils/common/include/RecurrentTimer.h b/automotive/vehicle/aidl/impl/3/utils/common/include/RecurrentTimer.h similarity index 100% rename from automotive/vehicle/aidl/impl/utils/common/include/RecurrentTimer.h rename to automotive/vehicle/aidl/impl/3/utils/common/include/RecurrentTimer.h diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h b/automotive/vehicle/aidl/impl/3/utils/common/include/VehicleHalTypes.h similarity index 100% rename from automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h rename to automotive/vehicle/aidl/impl/3/utils/common/include/VehicleHalTypes.h diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleObjectPool.h b/automotive/vehicle/aidl/impl/3/utils/common/include/VehicleObjectPool.h similarity index 98% rename from automotive/vehicle/aidl/impl/utils/common/include/VehicleObjectPool.h rename to automotive/vehicle/aidl/impl/3/utils/common/include/VehicleObjectPool.h index 501ce40b385e1c4d3b16081cc754a57b00e294aa..e18413bcd59fd0460319e27d7b6f6c4a78c99906 100644 --- a/automotive/vehicle/aidl/impl/utils/common/include/VehicleObjectPool.h +++ b/automotive/vehicle/aidl/impl/3/utils/common/include/VehicleObjectPool.h @@ -50,7 +50,7 @@ template struct Deleter { using OnDeleteFunc = std::function; - explicit Deleter(const OnDeleteFunc& f) : mOnDelete(f){}; + explicit Deleter(const OnDeleteFunc& f) : mOnDelete(f) {}; Deleter() = default; Deleter(const Deleter&) = default; @@ -76,7 +76,7 @@ class ObjectPool { using GetSizeFunc = std::function; ObjectPool(size_t maxPoolObjectsSize, GetSizeFunc getSizeFunc) - : mMaxPoolObjectsSize(maxPoolObjectsSize), mGetSizeFunc(getSizeFunc){}; + : mMaxPoolObjectsSize(maxPoolObjectsSize), mGetSizeFunc(getSizeFunc) {}; virtual ~ObjectPool() = default; virtual recyclable_ptr obtain() { @@ -182,7 +182,7 @@ class VehiclePropValuePool { // approximately this pool would at-most take 4 * 4 * 10240 = 160k memory. VehiclePropValuePool(size_t maxRecyclableVectorSize = 4, size_t maxPoolObjectsSize = 10240) : mMaxRecyclableVectorSize(maxRecyclableVectorSize), - mMaxPoolObjectsSize(maxPoolObjectsSize){}; + mMaxPoolObjectsSize(maxPoolObjectsSize) {}; // Obtain a recyclable VehiclePropertyValue object from the pool for the given type. If the // given type is not MIXED or STRING, the internal value vector size would be set to 1. diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehiclePropertyStore.h b/automotive/vehicle/aidl/impl/3/utils/common/include/VehiclePropertyStore.h similarity index 100% rename from automotive/vehicle/aidl/impl/utils/common/include/VehiclePropertyStore.h rename to automotive/vehicle/aidl/impl/3/utils/common/include/VehiclePropertyStore.h diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h b/automotive/vehicle/aidl/impl/3/utils/common/include/VehicleUtils.h similarity index 100% rename from automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h rename to automotive/vehicle/aidl/impl/3/utils/common/include/VehicleUtils.h diff --git a/automotive/vehicle/aidl/impl/utils/common/src/PendingRequestPool.cpp b/automotive/vehicle/aidl/impl/3/utils/common/src/PendingRequestPool.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/utils/common/src/PendingRequestPool.cpp rename to automotive/vehicle/aidl/impl/3/utils/common/src/PendingRequestPool.cpp diff --git a/automotive/vehicle/aidl/impl/utils/common/src/RecurrentTimer.cpp b/automotive/vehicle/aidl/impl/3/utils/common/src/RecurrentTimer.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/utils/common/src/RecurrentTimer.cpp rename to automotive/vehicle/aidl/impl/3/utils/common/src/RecurrentTimer.cpp diff --git a/automotive/vehicle/aidl/impl/utils/common/src/VehicleObjectPool.cpp b/automotive/vehicle/aidl/impl/3/utils/common/src/VehicleObjectPool.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/utils/common/src/VehicleObjectPool.cpp rename to automotive/vehicle/aidl/impl/3/utils/common/src/VehicleObjectPool.cpp diff --git a/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp b/automotive/vehicle/aidl/impl/3/utils/common/src/VehiclePropertyStore.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp rename to automotive/vehicle/aidl/impl/3/utils/common/src/VehiclePropertyStore.cpp diff --git a/automotive/vehicle/aidl/impl/utils/common/src/VehicleUtils.cpp b/automotive/vehicle/aidl/impl/3/utils/common/src/VehicleUtils.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/utils/common/src/VehicleUtils.cpp rename to automotive/vehicle/aidl/impl/3/utils/common/src/VehicleUtils.cpp diff --git a/automotive/vehicle/aidl/impl/3/utils/common/test/Android.bp b/automotive/vehicle/aidl/impl/3/utils/common/test/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..0450e99bddb8ddb8729d84fc3f5fd5c38ca7d192 --- /dev/null +++ b/automotive/vehicle/aidl/impl/3/utils/common/test/Android.bp @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + default_team: "trendy_team_aaos_framework", + default_applicable_licenses: ["Android-Apache-2.0"], +} + +cc_test { + name: "VehicleHalVehicleUtilsTest-V3", + srcs: ["*.cpp"], + vendor: true, + static_libs: [ + "VehicleHalUtils-V3", + "libgtest", + "libgmock", + ], + defaults: ["VehicleHalDefaults-V3"], + test_suites: ["device-tests"], +} diff --git a/automotive/vehicle/aidl/impl/utils/common/test/PendingRequestPoolTest.cpp b/automotive/vehicle/aidl/impl/3/utils/common/test/PendingRequestPoolTest.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/utils/common/test/PendingRequestPoolTest.cpp rename to automotive/vehicle/aidl/impl/3/utils/common/test/PendingRequestPoolTest.cpp diff --git a/automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp b/automotive/vehicle/aidl/impl/3/utils/common/test/RecurrentTimerTest.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp rename to automotive/vehicle/aidl/impl/3/utils/common/test/RecurrentTimerTest.cpp diff --git a/automotive/vehicle/aidl/impl/utils/common/test/VehicleObjectPoolTest.cpp b/automotive/vehicle/aidl/impl/3/utils/common/test/VehicleObjectPoolTest.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/utils/common/test/VehicleObjectPoolTest.cpp rename to automotive/vehicle/aidl/impl/3/utils/common/test/VehicleObjectPoolTest.cpp diff --git a/automotive/vehicle/aidl/impl/utils/common/test/VehiclePropertyStoreTest.cpp b/automotive/vehicle/aidl/impl/3/utils/common/test/VehiclePropertyStoreTest.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/utils/common/test/VehiclePropertyStoreTest.cpp rename to automotive/vehicle/aidl/impl/3/utils/common/test/VehiclePropertyStoreTest.cpp diff --git a/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp b/automotive/vehicle/aidl/impl/3/utils/common/test/VehicleUtilsTest.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp rename to automotive/vehicle/aidl/impl/3/utils/common/test/VehicleUtilsTest.cpp diff --git a/automotive/vehicle/aidl/impl/3/utils/test_vendor_properties/Android.bp b/automotive/vehicle/aidl/impl/3/utils/test_vendor_properties/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..42e23173a6c26927a955f8df02c12728fc721e40 --- /dev/null +++ b/automotive/vehicle/aidl/impl/3/utils/test_vendor_properties/Android.bp @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +filegroup { + name: "VhalTestVendorProperties-V3", + srcs: [ + "**/*.aidl", + ], + visibility: [ + "//hardware/interfaces/automotive/vehicle/aidl:__subpackages__", + "//packages/services/Car:__subpackages__", + "//cts/tests/tests/car_permission_tests", + ], +} diff --git a/automotive/vehicle/aidl/impl/utils/test_vendor_properties/android/hardware/automotive/vehicle/TestVendorProperty.aidl b/automotive/vehicle/aidl/impl/3/utils/test_vendor_properties/android/hardware/automotive/vehicle/TestVendorProperty.aidl similarity index 100% rename from automotive/vehicle/aidl/impl/utils/test_vendor_properties/android/hardware/automotive/vehicle/TestVendorProperty.aidl rename to automotive/vehicle/aidl/impl/3/utils/test_vendor_properties/android/hardware/automotive/vehicle/TestVendorProperty.aidl diff --git a/automotive/vehicle/aidl/impl/3/vhal/Android.bp b/automotive/vehicle/aidl/impl/3/vhal/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..22ea23ddbf32722d9ec76bdd3882eb54a0af09ef --- /dev/null +++ b/automotive/vehicle/aidl/impl/3/vhal/Android.bp @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + default_team: "trendy_team_aaos_framework", + default_applicable_licenses: ["Android-Apache-2.0"], +} + +cc_binary { + name: "android.hardware.automotive.vehicle@V3-default-service", + vendor: true, + defaults: [ + "FakeVehicleHardwareDefaults-V3", + "VehicleHalDefaults-V3", + "android-automotive-large-parcelable-defaults", + ], + vintf_fragments: ["vhal-default-service-v3.xml"], + init_rc: ["vhal-default-service-v3.rc"], + relative_install_path: "hw", + srcs: ["src/VehicleService.cpp"], + static_libs: [ + "DefaultVehicleHal-V3", + "FakeVehicleHardware-V3", + "VehicleHalUtils-V3", + ], + header_libs: [ + "IVehicleHardware-V3", + ], + shared_libs: [ + "libbinder_ndk", + ], +} + +cc_library { + name: "DefaultVehicleHal-V3", + vendor: true, + host_supported: true, + defaults: [ + "VehicleHalDefaults-V3", + ], + local_include_dirs: ["include"], + export_include_dirs: ["include"], + srcs: [ + "src/ConnectedClient.cpp", + "src/DefaultVehicleHal.cpp", + "src/SubscriptionManager.cpp", + // A target to check whether the file + // android.hardware.automotive.vehicle-types-meta.json needs update. + // The output is just an empty cpp file and not actually used. + ":check_generated_enum_metadata_json", + ], + static_libs: [ + "VehicleHalUtils-V3", + ], + header_libs: [ + "IVehicleHardware-V3", + "IVehicleGeneratedHeaders-V3-default", + ], + shared_libs: [ + "libbinder_ndk", + ], +} + +cc_fuzz { + name: "android.hardware.automotive.vehicle-default-service_fuzzer-V3", + vendor: true, + defaults: [ + "FakeVehicleHardwareDefaults-V3", + "VehicleHalDefaults-V3", + "android-automotive-large-parcelable-defaults", + "service_fuzzer_defaults", + ], + static_libs: [ + "DefaultVehicleHal-V3", + "FakeVehicleHardware-V3", + "VehicleHalUtils-V3", + ], + srcs: ["src/fuzzer.cpp"], + fuzz_config: { + cc: [ + "keithmok@google.com", + ], + }, +} diff --git a/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h b/automotive/vehicle/aidl/impl/3/vhal/include/ConnectedClient.h similarity index 100% rename from automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h rename to automotive/vehicle/aidl/impl/3/vhal/include/ConnectedClient.h diff --git a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h b/automotive/vehicle/aidl/impl/3/vhal/include/DefaultVehicleHal.h similarity index 100% rename from automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h rename to automotive/vehicle/aidl/impl/3/vhal/include/DefaultVehicleHal.h diff --git a/automotive/vehicle/aidl/impl/vhal/include/SubscriptionManager.h b/automotive/vehicle/aidl/impl/3/vhal/include/SubscriptionManager.h similarity index 100% rename from automotive/vehicle/aidl/impl/vhal/include/SubscriptionManager.h rename to automotive/vehicle/aidl/impl/3/vhal/include/SubscriptionManager.h diff --git a/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp b/automotive/vehicle/aidl/impl/3/vhal/src/ConnectedClient.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp rename to automotive/vehicle/aidl/impl/3/vhal/src/ConnectedClient.cpp diff --git a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp b/automotive/vehicle/aidl/impl/3/vhal/src/DefaultVehicleHal.cpp similarity index 99% rename from automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp rename to automotive/vehicle/aidl/impl/3/vhal/src/DefaultVehicleHal.cpp index 0ead81934c9559cd26ffd305c5cf857ad7783af2..aa9ef53ce538caaf8180133e110677b77cb940ec 100644 --- a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp +++ b/automotive/vehicle/aidl/impl/3/vhal/src/DefaultVehicleHal.cpp @@ -110,7 +110,7 @@ class SCOPED_CAPABILITY UniqueScopedLockAssertion { } // namespace DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr vehicleHardware) - : DefaultVehicleHal(std::move(vehicleHardware), /* testInterfaceVersion= */ 0){}; + : DefaultVehicleHal(std::move(vehicleHardware), /* testInterfaceVersion= */ 0) {}; DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr vehicleHardware, int32_t testInterfaceVersion) diff --git a/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp b/automotive/vehicle/aidl/impl/3/vhal/src/SubscriptionManager.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp rename to automotive/vehicle/aidl/impl/3/vhal/src/SubscriptionManager.cpp diff --git a/automotive/vehicle/aidl/impl/vhal/src/VehicleService.cpp b/automotive/vehicle/aidl/impl/3/vhal/src/VehicleService.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/vhal/src/VehicleService.cpp rename to automotive/vehicle/aidl/impl/3/vhal/src/VehicleService.cpp diff --git a/automotive/vehicle/aidl/impl/vhal/src/fuzzer.cpp b/automotive/vehicle/aidl/impl/3/vhal/src/fuzzer.cpp similarity index 93% rename from automotive/vehicle/aidl/impl/vhal/src/fuzzer.cpp rename to automotive/vehicle/aidl/impl/3/vhal/src/fuzzer.cpp index 6d994bb4cf671853a484dfa4908750866846a695..ac1e3b1a56ab17a187adeeb838d7afc9f2b28cad 100644 --- a/automotive/vehicle/aidl/impl/vhal/src/fuzzer.cpp +++ b/automotive/vehicle/aidl/impl/3/vhal/src/fuzzer.cpp @@ -25,8 +25,6 @@ using ::android::hardware::automotive::vehicle::fake::FakeVehicleHardware; using ::ndk::SharedRefBase; extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - // TODO(b/183141167): need to rewrite 'dump' to avoid SIGPIPE. - signal(SIGPIPE, SIG_IGN); std::unique_ptr hardware = std::make_unique(); std::shared_ptr vhal = ::ndk::SharedRefBase::make(std::move(hardware)); diff --git a/automotive/vehicle/aidl/impl/3/vhal/test/Android.bp b/automotive/vehicle/aidl/impl/3/vhal/test/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..e86bc813035af42ae3f8d2ef7fbe6f06eccca926 --- /dev/null +++ b/automotive/vehicle/aidl/impl/3/vhal/test/Android.bp @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + default_team: "trendy_team_aaos_framework", + default_applicable_licenses: ["Android-Apache-2.0"], +} + +cc_test { + name: "DefaultVehicleHalTest-V3", + vendor: true, + srcs: ["*.cpp"], + static_libs: [ + "DefaultVehicleHal-V3", + "VehicleHalUtils-V3", + "libgtest", + "libgmock", + ], + shared_libs: [ + "libbase", + "libbinder_ndk", + "liblog", + "libutils", + ], + header_libs: [ + "IVehicleHardware-V3", + ], + defaults: [ + "VehicleHalDefaults-V3", + ], + test_suites: ["device-tests"], +} diff --git a/automotive/vehicle/aidl/impl/vhal/test/ConnectedClientTest.cpp b/automotive/vehicle/aidl/impl/3/vhal/test/ConnectedClientTest.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/vhal/test/ConnectedClientTest.cpp rename to automotive/vehicle/aidl/impl/3/vhal/test/ConnectedClientTest.cpp diff --git a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp b/automotive/vehicle/aidl/impl/3/vhal/test/DefaultVehicleHalTest.cpp similarity index 99% rename from automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp rename to automotive/vehicle/aidl/impl/3/vhal/test/DefaultVehicleHalTest.cpp index 4891bf56a90b88e12b626cbeb8ed4eae77d13410..ad34a4caca5b5f2868818a291ad39ea7eda0f305 100644 --- a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp +++ b/automotive/vehicle/aidl/impl/3/vhal/test/DefaultVehicleHalTest.cpp @@ -1849,6 +1849,12 @@ TEST_F(DefaultVehicleHalTest, testHeartbeatEvent) { std::this_thread::sleep_for(std::chrono::seconds(3)); auto maybeResults = getCallback()->nextOnPropertyEventResults(); + size_t retryCount = 0; + // Add a 1s (100ms * 10) buffer time. + while (!maybeResults.has_value() && retryCount < 10) { + retryCount++; + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } ASSERT_TRUE(maybeResults.has_value()) << "no results in callback"; ASSERT_EQ(maybeResults.value().payloads.size(), static_cast(1)); VehiclePropValue gotValue = maybeResults.value().payloads[0]; diff --git a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.cpp b/automotive/vehicle/aidl/impl/3/vhal/test/MockVehicleCallback.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.cpp rename to automotive/vehicle/aidl/impl/3/vhal/test/MockVehicleCallback.cpp diff --git a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.h b/automotive/vehicle/aidl/impl/3/vhal/test/MockVehicleCallback.h similarity index 100% rename from automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.h rename to automotive/vehicle/aidl/impl/3/vhal/test/MockVehicleCallback.h diff --git a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp b/automotive/vehicle/aidl/impl/3/vhal/test/MockVehicleHardware.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp rename to automotive/vehicle/aidl/impl/3/vhal/test/MockVehicleHardware.cpp diff --git a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h b/automotive/vehicle/aidl/impl/3/vhal/test/MockVehicleHardware.h similarity index 100% rename from automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h rename to automotive/vehicle/aidl/impl/3/vhal/test/MockVehicleHardware.h diff --git a/automotive/vehicle/aidl/impl/vhal/test/SubscriptionManagerTest.cpp b/automotive/vehicle/aidl/impl/3/vhal/test/SubscriptionManagerTest.cpp similarity index 100% rename from automotive/vehicle/aidl/impl/vhal/test/SubscriptionManagerTest.cpp rename to automotive/vehicle/aidl/impl/3/vhal/test/SubscriptionManagerTest.cpp diff --git a/automotive/vehicle/aidl/impl/vhal/vhal-default-service.rc b/automotive/vehicle/aidl/impl/3/vhal/vhal-default-service-v3.rc similarity index 100% rename from automotive/vehicle/aidl/impl/vhal/vhal-default-service.rc rename to automotive/vehicle/aidl/impl/3/vhal/vhal-default-service-v3.rc diff --git a/automotive/vehicle/aidl/impl/vhal/vhal-default-service.xml b/automotive/vehicle/aidl/impl/3/vhal/vhal-default-service-v3.xml similarity index 100% rename from automotive/vehicle/aidl/impl/vhal/vhal-default-service.xml rename to automotive/vehicle/aidl/impl/3/vhal/vhal-default-service-v3.xml diff --git a/automotive/vehicle/aidl/impl/Android.bp b/automotive/vehicle/aidl/impl/current/Android.bp similarity index 100% rename from automotive/vehicle/aidl/impl/Android.bp rename to automotive/vehicle/aidl/impl/current/Android.bp diff --git a/automotive/vehicle/aidl/impl/README.md b/automotive/vehicle/aidl/impl/current/README.md similarity index 100% rename from automotive/vehicle/aidl/impl/README.md rename to automotive/vehicle/aidl/impl/current/README.md diff --git a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/Android.bp b/automotive/vehicle/aidl/impl/current/default_config/JsonConfigLoader/Android.bp similarity index 100% rename from automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/Android.bp rename to automotive/vehicle/aidl/impl/current/default_config/JsonConfigLoader/Android.bp diff --git a/automotive/vehicle/aidl/impl/current/default_config/JsonConfigLoader/include/ConfigDeclaration.h b/automotive/vehicle/aidl/impl/current/default_config/JsonConfigLoader/include/ConfigDeclaration.h new file mode 100644 index 0000000000000000000000000000000000000000..40ac1293cdaa7cfafd226ef2ed9c4b98fa41d9c1 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/default_config/JsonConfigLoader/include/ConfigDeclaration.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_aidl_impl_default_config_JsonConfigLoader_include_ConfigDeclaration_H_ +#define android_hardware_automotive_vehicle_aidl_impl_default_config_JsonConfigLoader_include_ConfigDeclaration_H_ + +#include + +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +// ConfigDeclaration represents one property config, its optional initial value and its optional +// area configs and initial values for each area. +struct ConfigDeclaration { + aidl::android::hardware::automotive::vehicle::VehiclePropConfig config; + + // This value will be used as an initial value for the property. If this field is specified for + // property that supports multiple areas then it will be used for all areas unless particular + // area is overridden in initialAreaValue field. + aidl::android::hardware::automotive::vehicle::RawPropValues initialValue; + // Use initialAreaValues if it is necessary to specify different values per each area. + std::unordered_map + initialAreaValues; + + inline bool operator==(const ConfigDeclaration& other) const { + return (config == other.config && initialValue == other.initialValue && + initialAreaValues == other.initialAreaValues); + } + + friend std::ostream& operator<<(std::ostream& os, const ConfigDeclaration& c) { + return os << "Config Declaration for property: " + << aidl::android::hardware::automotive::vehicle::toString( + static_cast< + aidl::android::hardware::automotive::vehicle::VehicleProperty>( + c.config.prop)); + } +}; + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_aidl_impl_default_config_JsonConfigLoader_include_ConfigDeclaration_H_ diff --git a/automotive/vehicle/aidl/impl/current/default_config/JsonConfigLoader/include/JsonConfigLoader.h b/automotive/vehicle/aidl/impl/current/default_config/JsonConfigLoader/include/JsonConfigLoader.h new file mode 100644 index 0000000000000000000000000000000000000000..00c497f4d4f88f6a0be93949044ef39b106be024 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/default_config/JsonConfigLoader/include/JsonConfigLoader.h @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_aidl_impl_default_config_JsonConfigLoader_include_JsonConfigLoader_H_ +#define android_hardware_automotive_vehicle_aidl_impl_default_config_JsonConfigLoader_include_JsonConfigLoader_H_ + +#include +#include + +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +// private namespace +namespace jsonconfigloader_impl { + +// An abstract interface that represents a ValueParser for any constant value types. +class ConstantParserInterface { + public: + // Parses a constant variable name to its actual value. + virtual android::base::Result parseValue(const std::string& name) const = 0; + virtual ~ConstantParserInterface() = default; +}; + +// A class to parse a value field in JSON config file. +// If the field is a string and the field is in the format of "XX::XX", the value will be parsed +// as a constant value in the format of "TYPE::NAME". Otherwise, the field will be return as is +// converted to the expected type. +class JsonValueParser final { + public: + JsonValueParser(); + + android::base::Result parseStringValue(const std::string& fieldName, + const Json::Value& value) const; + + template + android::base::Result> parseArray(const std::string& fieldName, + const Json::Value& value) const; + + template + android::base::Result parseValue(const std::string& fieldName, + const Json::Value& value) const; + + private: + template + static android::base::Result convertValueToType(const std::string& fieldName, + const Json::Value& value); + + std::optional> maybeGetTypeAndValueName( + const std::string& jsonFieldValue) const; + + android::base::Result parseConstantValue( + const std::pair& typeValueName) const; + + const ConstantParserInterface* getParser(const std::string& type) const { + auto it = mConstantParsersByType.find(type); + if (it == mConstantParsersByType.end()) { + return nullptr; + } + return it->second.get(); + } + + private: + inline static const std::string DELIMITER = "::"; + std::unordered_map> + mConstantParsersByType; +}; + +// The main class to parse a VHAL config file in JSON format. +class JsonConfigParser { + public: + android::base::Result> parseJsonConfig( + std::istream& is); + + private: + JsonValueParser mValueParser; + + // Parses configuration for each property. + std::optional parseEachProperty(const Json::Value& propJsonValue, + std::vector* errors); + // Tries to parse a JSON value to a specific type. + // + // If fieldIsOptional is True, then if the field specified by "fieldName" does not exist, + // this method will return true without doing anything, otherwise, it will return false. + // + // @param parentJsonNode The parent node of the field you are going to parse. + // @param fieldName The name for the field. + // @param fieldIsOptional Whether the field is optional. + // @param outPtr The pointer to output to if the field exists and parsing succeeded. + // @param errors The error array to append error to if errors are found. + // @return true if the field is optional and does not exist or parsed successfully. + template + bool tryParseJsonValueToVariable(const Json::Value& parentJsonNode, + const std::string& fieldName, bool fieldIsOptional, T* outPtr, + std::vector* errors); + // Tries to parse a JSON value to an array of specific type. + // + // If fieldIsOptional is True, then if the field specified by "fieldName" does not exist, + // this method will return true without doing anything, otherwise, it will return false. + // + // @param parentJsonNode The parent node of the field you are going to parse. + // @param fieldName The name for the field. + // @param fieldIsOptional Whether the field is optional. + // @param outPtr The pointer to output to if the field exists and parsing succeeded. + // @param errors The error array to append error to if errors are found. + // @return true if the field is optional and does not exist or parsed successfully. + template + bool tryParseJsonArrayToVariable(const Json::Value& parentJsonNode, + const std::string& fieldName, bool fieldIsOptional, + std::vector* outPtr, std::vector* errors); + // Parses a JSON field to VehiclePropertyAccess or VehiclePropertyChangeMode. + template + void parseAccessChangeMode(const Json::Value& parentJsonNode, const std::string& fieldName, + const std::string& propStr, const T* defaultAccessChangeModePtr, + T* outPtr, std::vector* errors); + + // Parses a JSON field to RawPropValues. + // + // @return True if the field exist and can be parsed to a RawPropValues. + bool parsePropValues(const Json::Value& parentJsonNode, const std::string& fieldName, + aidl::android::hardware::automotive::vehicle::RawPropValues* outPtr, + std::vector* errors); + + // Prase a JSON field as an array of area configs. + void parseAreas(const Json::Value& parentJsonNode, const std::string& fieldName, + ConfigDeclaration* outPtr, std::vector* errors); +}; + +} // namespace jsonconfigloader_impl + +// A class to load vehicle property configs and initial values in JSON format. +class JsonConfigLoader final { + public: + JsonConfigLoader(); + + // Loads a JSON file stream and parses it to a map from propId to ConfigDeclarations. + android::base::Result> loadPropConfig( + std::istream& is); + + // Loads a JSON config file and parses it to a map from propId to ConfigDeclarations. + android::base::Result> loadPropConfig( + const std::string& configPath); + + private: + std::unique_ptr mParser; +}; + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_aidl_impl_default_config_JsonConfigLoader_include_JsonConfigLoader_H_ diff --git a/automotive/vehicle/aidl/impl/current/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp b/automotive/vehicle/aidl/impl/current/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7a1f0e0543b557a67597e03e893755215ab26254 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp @@ -0,0 +1,727 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include + +#ifdef ENABLE_VEHICLE_HAL_TEST_PROPERTIES +#include +#endif // ENABLE_VEHICLE_HAL_TEST_PROPERTIES + +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +namespace jsonconfigloader_impl { + +using ::aidl::android::hardware::automotive::vehicle::AccessForVehicleProperty; +using ::aidl::android::hardware::automotive::vehicle::AutomaticEmergencyBrakingState; +using ::aidl::android::hardware::automotive::vehicle::BlindSpotWarningState; +using ::aidl::android::hardware::automotive::vehicle::CameraServiceState; +using ::aidl::android::hardware::automotive::vehicle::ChangeModeForVehicleProperty; +using ::aidl::android::hardware::automotive::vehicle::CrossTrafficMonitoringWarningState; +using ::aidl::android::hardware::automotive::vehicle::CruiseControlCommand; +using ::aidl::android::hardware::automotive::vehicle::CruiseControlState; +using ::aidl::android::hardware::automotive::vehicle::CruiseControlType; +using ::aidl::android::hardware::automotive::vehicle::DriverDistractionState; +using ::aidl::android::hardware::automotive::vehicle::DriverDistractionWarning; +using ::aidl::android::hardware::automotive::vehicle::DriverDrowsinessAttentionState; +using ::aidl::android::hardware::automotive::vehicle::DriverDrowsinessAttentionWarning; +using ::aidl::android::hardware::automotive::vehicle::ElectronicStabilityControlState; +using ::aidl::android::hardware::automotive::vehicle::EmergencyLaneKeepAssistState; +using ::aidl::android::hardware::automotive::vehicle::ErrorState; +using ::aidl::android::hardware::automotive::vehicle::EvConnectorType; +using ::aidl::android::hardware::automotive::vehicle::EvsServiceState; +using ::aidl::android::hardware::automotive::vehicle::EvsServiceType; +using ::aidl::android::hardware::automotive::vehicle::ForwardCollisionWarningState; +using ::aidl::android::hardware::automotive::vehicle::FuelType; +using ::aidl::android::hardware::automotive::vehicle::GsrComplianceRequirementType; +using ::aidl::android::hardware::automotive::vehicle::HandsOnDetectionDriverState; +using ::aidl::android::hardware::automotive::vehicle::HandsOnDetectionWarning; +using ::aidl::android::hardware::automotive::vehicle::ImpactSensorLocation; +using ::aidl::android::hardware::automotive::vehicle::LaneCenteringAssistCommand; +using ::aidl::android::hardware::automotive::vehicle::LaneCenteringAssistState; +using ::aidl::android::hardware::automotive::vehicle::LaneDepartureWarningState; +using ::aidl::android::hardware::automotive::vehicle::LaneKeepAssistState; +using ::aidl::android::hardware::automotive::vehicle::LocationCharacterization; +using ::aidl::android::hardware::automotive::vehicle::LowSpeedAutomaticEmergencyBrakingState; +using ::aidl::android::hardware::automotive::vehicle::LowSpeedCollisionWarningState; +using ::aidl::android::hardware::automotive::vehicle::RawPropValues; +using ::aidl::android::hardware::automotive::vehicle::VehicleAirbagLocation; +using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerBootupReason; +using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReport; +using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq; +using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig; +using ::aidl::android::hardware::automotive::vehicle::VehicleAreaMirror; +using ::aidl::android::hardware::automotive::vehicle::VehicleAreaWindow; +using ::aidl::android::hardware::automotive::vehicle::VehicleAutonomousState; +using ::aidl::android::hardware::automotive::vehicle::VehicleGear; +using ::aidl::android::hardware::automotive::vehicle::VehicleHvacFanDirection; +using ::aidl::android::hardware::automotive::vehicle::VehicleIgnitionState; +using ::aidl::android::hardware::automotive::vehicle::VehicleOilLevel; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig; +using ::aidl::android::hardware::automotive::vehicle::VehicleProperty; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyChangeMode; +using ::aidl::android::hardware::automotive::vehicle::VehicleSeatOccupancyState; +using ::aidl::android::hardware::automotive::vehicle::VehicleSizeClass; +using ::aidl::android::hardware::automotive::vehicle::VehicleTurnSignal; +using ::aidl::android::hardware::automotive::vehicle::VehicleUnit; +using ::aidl::android::hardware::automotive::vehicle::VehicleVendorPermission; +using ::aidl::android::hardware::automotive::vehicle::WindshieldWipersState; +using ::aidl::android::hardware::automotive::vehicle::WindshieldWipersSwitch; + +using ::android::base::Error; +using ::android::base::Result; + +// Defines a map from constant names to constant values, the values defined here corresponds to +// the "Constants::XXXX" used in JSON config file. +const std::unordered_map CONSTANTS_BY_NAME = { + {"DOOR_1_RIGHT", DOOR_1_RIGHT}, + {"DOOR_1_LEFT", DOOR_1_LEFT}, + {"DOOR_2_RIGHT", DOOR_2_RIGHT}, + {"DOOR_2_LEFT", DOOR_2_LEFT}, + {"DOOR_REAR", DOOR_REAR}, + {"HVAC_ALL", HVAC_ALL}, + {"HVAC_LEFT", HVAC_LEFT}, + {"HVAC_RIGHT", HVAC_RIGHT}, + {"HVAC_FRONT_ROW", HVAC_FRONT_ROW}, + {"HVAC_REAR_ROW", HVAC_REAR_ROW}, + {"WINDOW_1_LEFT", WINDOW_1_LEFT}, + {"WINDOW_1_RIGHT", WINDOW_1_RIGHT}, + {"WINDOW_2_LEFT", WINDOW_2_LEFT}, + {"WINDOW_2_RIGHT", WINDOW_2_RIGHT}, + {"WINDOW_ROOF_TOP_1", WINDOW_ROOF_TOP_1}, + {"WINDOW_1_RIGHT_2_LEFT_2_RIGHT", WINDOW_1_RIGHT | WINDOW_2_LEFT | WINDOW_2_RIGHT}, + {"SEAT_1_LEFT", SEAT_1_LEFT}, + {"SEAT_1_RIGHT", SEAT_1_RIGHT}, + {"SEAT_2_LEFT", SEAT_2_LEFT}, + {"SEAT_2_RIGHT", SEAT_2_RIGHT}, + {"SEAT_2_CENTER", SEAT_2_CENTER}, + {"SEAT_2_LEFT_2_RIGHT_2_CENTER", SEAT_2_LEFT | SEAT_2_RIGHT | SEAT_2_CENTER}, + {"WHEEL_REAR_RIGHT", WHEEL_REAR_RIGHT}, + {"WHEEL_REAR_LEFT", WHEEL_REAR_LEFT}, + {"WHEEL_FRONT_RIGHT", WHEEL_FRONT_RIGHT}, + {"WHEEL_FRONT_LEFT", WHEEL_FRONT_LEFT}, + {"CHARGE_PORT_FRONT_LEFT", CHARGE_PORT_FRONT_LEFT}, + {"CHARGE_PORT_REAR_LEFT", CHARGE_PORT_REAR_LEFT}, + {"FAN_DIRECTION_UNKNOWN", toInt(VehicleHvacFanDirection::UNKNOWN)}, + {"FAN_DIRECTION_FLOOR", FAN_DIRECTION_FLOOR}, + {"FAN_DIRECTION_FACE", FAN_DIRECTION_FACE}, + {"FAN_DIRECTION_DEFROST", FAN_DIRECTION_DEFROST}, + {"FAN_DIRECTION_FACE_FLOOR", FAN_DIRECTION_FACE | FAN_DIRECTION_FLOOR}, + {"FAN_DIRECTION_FACE_DEFROST", FAN_DIRECTION_FACE | FAN_DIRECTION_DEFROST}, + {"FAN_DIRECTION_FLOOR_DEFROST", FAN_DIRECTION_FLOOR | FAN_DIRECTION_DEFROST}, + {"FAN_DIRECTION_FLOOR_DEFROST_FACE", + FAN_DIRECTION_FLOOR | FAN_DIRECTION_DEFROST | FAN_DIRECTION_FACE}, + {"FUEL_DOOR_REAR_LEFT", FUEL_DOOR_REAR_LEFT}, + {"LIGHT_STATE_ON", LIGHT_STATE_ON}, + {"LIGHT_STATE_OFF", LIGHT_STATE_OFF}, + {"LIGHT_SWITCH_OFF", LIGHT_SWITCH_OFF}, + {"LIGHT_SWITCH_ON", LIGHT_SWITCH_ON}, + {"LIGHT_SWITCH_AUTO", LIGHT_SWITCH_AUTO}, + {"EV_STOPPING_MODE_CREEP", EV_STOPPING_MODE_CREEP}, + {"EV_STOPPING_MODE_ROLL", EV_STOPPING_MODE_ROLL}, + {"EV_STOPPING_MODE_HOLD", EV_STOPPING_MODE_HOLD}, + {"MIRROR_DRIVER_LEFT_RIGHT", + toInt(VehicleAreaMirror::DRIVER_LEFT) | toInt(VehicleAreaMirror::DRIVER_RIGHT)}, +}; + +// A class to parse constant values for type T where T is defined as an enum in NDK AIDL backend. +template +class ConstantParser final : public ConstantParserInterface { + public: + ConstantParser() { + for (const T& v : ndk::enum_range()) { + std::string name = aidl::android::hardware::automotive::vehicle::toString(v); + // We use the same constant for both VehicleUnit::GALLON and VehicleUnit::US_GALLON, + // which caused toString() not work properly for US_GALLON. So we explicitly add the + // map here. + if (name == "GALLON") { + mValueByName["US_GALLON"] = toInt(v); + } + mValueByName[name] = toInt(v); + } + } + + ~ConstantParser() = default; + + Result parseValue(const std::string& name) const override { + auto it = mValueByName.find(name); + if (it == mValueByName.end()) { + return Error() << "Constant name: " << name << " is not defined"; + } + return it->second; + } + + private: + std::unordered_map mValueByName; +}; + +#ifdef ENABLE_VEHICLE_HAL_TEST_PROPERTIES +// A class to parse constant values for type T where T is defined as an enum in CPP AIDL backend. +template +class CppConstantParser final : public ConstantParserInterface { + public: + CppConstantParser() { + for (const T& v : android::enum_range()) { + std::string name = android::hardware::automotive::vehicle::toString(v); + mValueByName[name] = toInt(v); + } + } + + ~CppConstantParser() = default; + + Result parseValue(const std::string& name) const override { + auto it = mValueByName.find(name); + if (it == mValueByName.end()) { + return Error() << "Constant name: " << name << " is not defined"; + } + return it->second; + } + + private: + std::unordered_map mValueByName; +}; +#endif + +// A class to parse constant values defined in CONSTANTS_BY_NAME map. +class LocalVariableParser final : public ConstantParserInterface { + public: + ~LocalVariableParser() = default; + + Result parseValue(const std::string& name) const override { + auto constantsIt = CONSTANTS_BY_NAME.find(name); + if (constantsIt == CONSTANTS_BY_NAME.end()) { + return Error() << "Constant variable name: " << name << " is not defined"; + } + return constantsIt->second; + } +}; + +JsonValueParser::JsonValueParser() { + mConstantParsersByType["VehiclePropertyAccess"] = + std::make_unique>(); + mConstantParsersByType["VehiclePropertyChangeMode"] = + std::make_unique>(); + mConstantParsersByType["LocationCharacterization"] = + std::make_unique>(); + mConstantParsersByType["VehicleGear"] = std::make_unique>(); + mConstantParsersByType["VehicleAreaWindow"] = + std::make_unique>(); + mConstantParsersByType["VehicleAreaMirror"] = + std::make_unique>(); + mConstantParsersByType["VehicleOilLevel"] = std::make_unique>(); + mConstantParsersByType["VehicleUnit"] = std::make_unique>(); + mConstantParsersByType["VehicleSeatOccupancyState"] = + std::make_unique>(); + mConstantParsersByType["VehicleHvacFanDirection"] = + std::make_unique>(); + mConstantParsersByType["VehicleApPowerStateReport"] = + std::make_unique>(); + mConstantParsersByType["VehicleTurnSignal"] = + std::make_unique>(); + mConstantParsersByType["VehicleVendorPermission"] = + std::make_unique>(); + mConstantParsersByType["EvsServiceType"] = std::make_unique>(); + mConstantParsersByType["EvsServiceState"] = std::make_unique>(); + mConstantParsersByType["EvConnectorType"] = std::make_unique>(); + mConstantParsersByType["VehicleProperty"] = std::make_unique>(); + mConstantParsersByType["GsrComplianceRequirementType"] = + std::make_unique>(); + mConstantParsersByType["VehicleIgnitionState"] = + std::make_unique>(); + mConstantParsersByType["FuelType"] = std::make_unique>(); + mConstantParsersByType["WindshieldWipersState"] = + std::make_unique>(); + mConstantParsersByType["WindshieldWipersSwitch"] = + std::make_unique>(); + mConstantParsersByType["VehicleAutonomousState"] = + std::make_unique>(); + mConstantParsersByType["VehicleAirbagLocation"] = + std::make_unique>(); + mConstantParsersByType["ImpactSensorLocation"] = + std::make_unique>(); + mConstantParsersByType["VehicleSizeClass"] = + std::make_unique>(); + mConstantParsersByType["EmergencyLaneKeepAssistState"] = + std::make_unique>(); + mConstantParsersByType["CameraServiceState"] = + std::make_unique>(); + mConstantParsersByType["CruiseControlType"] = + std::make_unique>(); + mConstantParsersByType["CruiseControlState"] = + std::make_unique>(); + mConstantParsersByType["CruiseControlCommand"] = + std::make_unique>(); + mConstantParsersByType["HandsOnDetectionDriverState"] = + std::make_unique>(); + mConstantParsersByType["HandsOnDetectionWarning"] = + std::make_unique>(); + mConstantParsersByType["DriverDrowsinessAttentionState"] = + std::make_unique>(); + mConstantParsersByType["DriverDrowsinessAttentionWarning"] = + std::make_unique>(); + mConstantParsersByType["DriverDistractionState"] = + std::make_unique>(); + mConstantParsersByType["DriverDistractionWarning"] = + std::make_unique>(); + mConstantParsersByType["ErrorState"] = std::make_unique>(); + mConstantParsersByType["AutomaticEmergencyBrakingState"] = + std::make_unique>(); + mConstantParsersByType["ForwardCollisionWarningState"] = + std::make_unique>(); + mConstantParsersByType["BlindSpotWarningState"] = + std::make_unique>(); + mConstantParsersByType["LaneDepartureWarningState"] = + std::make_unique>(); + mConstantParsersByType["LaneKeepAssistState"] = + std::make_unique>(); + mConstantParsersByType["LaneCenteringAssistCommand"] = + std::make_unique>(); + mConstantParsersByType["LaneCenteringAssistState"] = + std::make_unique>(); + mConstantParsersByType["LowSpeedCollisionWarningState"] = + std::make_unique>(); + mConstantParsersByType["ElectronicStabilityControlState"] = + std::make_unique>(); + mConstantParsersByType["CrossTrafficMonitoringWarningState"] = + std::make_unique>(); + mConstantParsersByType["LowSpeedAutomaticEmergencyBrakingState"] = + std::make_unique>(); + mConstantParsersByType["VehicleApPowerBootupReason"] = + std::make_unique>(); + mConstantParsersByType["Constants"] = std::make_unique(); +#ifdef ENABLE_VEHICLE_HAL_TEST_PROPERTIES + mConstantParsersByType["TestVendorProperty"] = + std::make_unique>(); +#endif // ENABLE_VEHICLE_HAL_TEST_PROPERTIES +} + +template <> +Result JsonValueParser::convertValueToType(const std::string& fieldName, + const Json::Value& value) { + if (!value.isBool()) { + return Error() << "The value: " << value << " for field: " << fieldName + << " is not in correct type, expect bool"; + } + return value.asBool(); +} + +template <> +Result JsonValueParser::convertValueToType(const std::string& fieldName, + const Json::Value& value) { + if (!value.isInt()) { + return Error() << "The value: " << value << " for field: " << fieldName + << " is not in correct type, expect int"; + } + return static_cast(value.asInt()); +} + +template <> +Result JsonValueParser::convertValueToType(const std::string& fieldName, + const Json::Value& value) { + // isFloat value does not exist, so we use isDouble here. + if (!value.isDouble()) { + return Error() << "The value: " << value << " for field: " << fieldName + << " is not in correct type, expect float"; + } + return value.asFloat(); +} + +template <> +Result JsonValueParser::convertValueToType(const std::string& fieldName, + const Json::Value& value) { + if (!value.isInt64()) { + return Error() << "The value: " << value << " for field: " << fieldName + << " is not in correct type, expect int64"; + } + return static_cast(value.asInt64()); +} + +template <> +Result JsonValueParser::convertValueToType(const std::string& fieldName, + const Json::Value& value) { + if (!value.isString()) { + return Error() << "The value: " << value << " for field: " << fieldName + << " is not in correct type, expect string"; + } + return value.asString(); +} + +Result JsonValueParser::parseStringValue(const std::string& fieldName, + const Json::Value& value) const { + return convertValueToType(fieldName, value); +} + +template +Result JsonValueParser::parseValue(const std::string& fieldName, + const Json::Value& value) const { + if (!value.isString()) { + return convertValueToType(fieldName, value); + } + auto maybeTypeAndValue = maybeGetTypeAndValueName(value.asString()); + if (!maybeTypeAndValue.has_value()) { + return Error() << "Invalid constant value: " << value << " for field: " << fieldName; + } + auto constantParseResult = parseConstantValue(maybeTypeAndValue.value()); + if (!constantParseResult.ok()) { + return constantParseResult.error(); + } + int constantValue = constantParseResult.value(); + return static_cast(constantValue); +} + +template <> +Result JsonValueParser::parseValue(const std::string& fieldName, + const Json::Value& value) const { + return parseStringValue(fieldName, value); +} + +template +Result> JsonValueParser::parseArray(const std::string& fieldName, + const Json::Value& value) const { + if (!value.isArray()) { + return Error() << "The value: " << value << " for field: " << fieldName + << " is not in correct type, expect array"; + } + std::vector parsedValues; + for (unsigned int i = 0; i < value.size(); i++) { + auto result = parseValue(fieldName, value[i]); + if (!result.ok()) { + return result.error(); + } + parsedValues.push_back(result.value()); + } + return std::move(parsedValues); +} + +std::optional> JsonValueParser::maybeGetTypeAndValueName( + const std::string& jsonFieldValue) const { + size_t pos = jsonFieldValue.find(DELIMITER); + if (pos == std::string::npos) { + return {}; + } + std::string type = jsonFieldValue.substr(0, pos); + std::string valueName = jsonFieldValue.substr(pos + DELIMITER.length(), std::string::npos); + if (type != "Constants" && mConstantParsersByType.find(type) == mConstantParsersByType.end()) { + return {}; + } + return std::make_pair(type, valueName); +} + +Result JsonValueParser::parseConstantValue( + const std::pair& typeValueName) const { + const std::string& type = typeValueName.first; + const std::string& valueName = typeValueName.second; + auto it = mConstantParsersByType.find(type); + if (it == mConstantParsersByType.end()) { + return Error() << "Unrecognized type: " << type; + } + auto result = it->second->parseValue(valueName); + if (!result.ok()) { + return Error() << type << "::" << valueName << " undefined"; + } + return result; +} + +template +bool JsonConfigParser::tryParseJsonValueToVariable(const Json::Value& parentJsonNode, + const std::string& fieldName, + bool fieldIsOptional, T* outPtr, + std::vector* errors) { + if (!parentJsonNode.isObject()) { + errors->push_back("Node: " + parentJsonNode.toStyledString() + " is not an object"); + return false; + } + if (!parentJsonNode.isMember(fieldName)) { + if (!fieldIsOptional) { + errors->push_back("Missing required field: " + fieldName + + " in node: " + parentJsonNode.toStyledString()); + return false; + } + return true; + } + auto result = mValueParser.parseValue(fieldName, parentJsonNode[fieldName]); + if (!result.ok()) { + errors->push_back(result.error().message()); + return false; + } + *outPtr = std::move(result.value()); + return true; +} + +template +bool JsonConfigParser::tryParseJsonArrayToVariable(const Json::Value& parentJsonNode, + const std::string& fieldName, + bool fieldIsOptional, std::vector* outPtr, + std::vector* errors) { + if (!parentJsonNode.isObject()) { + errors->push_back("Node: " + parentJsonNode.toStyledString() + " is not an object"); + return false; + } + if (!parentJsonNode.isMember(fieldName)) { + if (!fieldIsOptional) { + errors->push_back("Missing required field: " + fieldName + + " in node: " + parentJsonNode.toStyledString()); + return false; + } + return true; + } + auto result = mValueParser.parseArray(fieldName, parentJsonNode[fieldName]); + if (!result.ok()) { + errors->push_back(result.error().message()); + return false; + } + *outPtr = std::move(result.value()); + return true; +} + +template +void JsonConfigParser::parseAccessChangeMode(const Json::Value& parentJsonNode, + const std::string& fieldName, + const std::string& propStr, + const T* defaultAccessChangeModeValuePtr, T* outPtr, + std::vector* errors) { + if (!parentJsonNode.isObject()) { + errors->push_back("Node: " + parentJsonNode.toStyledString() + " is not an object"); + return; + } + if (parentJsonNode.isMember(fieldName)) { + auto result = mValueParser.parseValue(fieldName, parentJsonNode[fieldName]); + if (!result.ok()) { + errors->push_back(result.error().message()); + return; + } + *outPtr = static_cast(result.value()); + return; + } + if (defaultAccessChangeModeValuePtr == NULL) { + errors->push_back("No " + fieldName + " specified for property: " + propStr); + return; + } + *outPtr = *defaultAccessChangeModeValuePtr; + return; +} + +bool JsonConfigParser::parsePropValues(const Json::Value& parentJsonNode, + const std::string& fieldName, RawPropValues* outPtr, + std::vector* errors) { + if (!parentJsonNode.isObject()) { + errors->push_back("Node: " + parentJsonNode.toStyledString() + " is not an object"); + return false; + } + if (!parentJsonNode.isMember(fieldName)) { + return false; + } + const Json::Value& jsonValue = parentJsonNode[fieldName]; + bool success = true; + success &= tryParseJsonArrayToVariable(jsonValue, "int32Values", + /*optional=*/true, &(outPtr->int32Values), errors); + success &= tryParseJsonArrayToVariable(jsonValue, "floatValues", + /*optional=*/true, &(outPtr->floatValues), errors); + success &= tryParseJsonArrayToVariable(jsonValue, "int64Values", + /*optional=*/true, &(outPtr->int64Values), errors); + // We don't support "byteValues" yet. + success &= tryParseJsonValueToVariable(jsonValue, "stringValue", + /*optional=*/true, &(outPtr->stringValue), errors); + return success; +} + +void JsonConfigParser::parseAreas(const Json::Value& parentJsonNode, const std::string& fieldName, + ConfigDeclaration* config, std::vector* errors) { + if (!parentJsonNode.isObject()) { + errors->push_back("Node: " + parentJsonNode.toStyledString() + " is not an object"); + return; + } + if (!parentJsonNode.isMember(fieldName)) { + return; + } + std::string propStr = parentJsonNode["property"].toStyledString(); + const Json::Value& jsonValue = parentJsonNode[fieldName]; + + if (!jsonValue.isArray()) { + errors->push_back("Field: " + fieldName + " is not an array"); + return; + } + for (unsigned int i = 0; i < jsonValue.size(); i++) { + int32_t areaId; + const Json::Value& jsonAreaConfig = jsonValue[i]; + if (!tryParseJsonValueToVariable(jsonAreaConfig, "areaId", + /*optional=*/false, &areaId, errors)) { + continue; + } + VehicleAreaConfig areaConfig = {}; + areaConfig.areaId = areaId; + parseAccessChangeMode(jsonAreaConfig, "access", propStr, &(config->config.access), + &areaConfig.access, errors); + tryParseJsonValueToVariable(jsonAreaConfig, "minInt32Value", /*optional=*/true, + &areaConfig.minInt32Value, errors); + tryParseJsonValueToVariable(jsonAreaConfig, "maxInt32Value", /*optional=*/true, + &areaConfig.maxInt32Value, errors); + tryParseJsonValueToVariable(jsonAreaConfig, "minInt64Value", /*optional=*/true, + &areaConfig.minInt64Value, errors); + tryParseJsonValueToVariable(jsonAreaConfig, "maxInt64Value", /*optional=*/true, + &areaConfig.maxInt64Value, errors); + tryParseJsonValueToVariable(jsonAreaConfig, "minFloatValue", /*optional=*/true, + &areaConfig.minFloatValue, errors); + tryParseJsonValueToVariable(jsonAreaConfig, "maxFloatValue", /*optional=*/true, + &areaConfig.maxFloatValue, errors); + + // By default we support variable update rate for all properties except it is explicitly + // disabled. + areaConfig.supportVariableUpdateRate = true; + tryParseJsonValueToVariable(jsonAreaConfig, "supportVariableUpdateRate", /*optional=*/true, + &areaConfig.supportVariableUpdateRate, errors); + + std::vector supportedEnumValues; + tryParseJsonArrayToVariable(jsonAreaConfig, "supportedEnumValues", /*optional=*/true, + &supportedEnumValues, errors); + if (!supportedEnumValues.empty()) { + areaConfig.supportedEnumValues = std::move(supportedEnumValues); + } + config->config.areaConfigs.push_back(std::move(areaConfig)); + + RawPropValues areaValue = {}; + if (parsePropValues(jsonAreaConfig, "defaultValue", &areaValue, errors)) { + config->initialAreaValues[areaId] = std::move(areaValue); + } + } +} + +std::optional JsonConfigParser::parseEachProperty( + const Json::Value& propJsonValue, std::vector* errors) { + size_t initialErrorCount = errors->size(); + ConfigDeclaration configDecl = {}; + int32_t propId; + + if (!tryParseJsonValueToVariable(propJsonValue, "property", /*optional=*/false, &propId, + errors)) { + return std::nullopt; + } + + configDecl.config.prop = propId; + std::string propStr = propJsonValue["property"].toStyledString(); + VehiclePropertyAccess* defaultAccessMode = NULL; + auto itAccess = AccessForVehicleProperty.find(static_cast(propId)); + if (itAccess != AccessForVehicleProperty.end()) { + defaultAccessMode = &itAccess->second; + } + VehiclePropertyChangeMode* defaultChangeMode = NULL; + auto itChangeMode = ChangeModeForVehicleProperty.find(static_cast(propId)); + if (itChangeMode != ChangeModeForVehicleProperty.end()) { + defaultChangeMode = &itChangeMode->second; + } + parseAccessChangeMode(propJsonValue, "access", propStr, defaultAccessMode, + &configDecl.config.access, errors); + + parseAccessChangeMode(propJsonValue, "changeMode", propStr, defaultChangeMode, + &configDecl.config.changeMode, errors); + + tryParseJsonValueToVariable(propJsonValue, "configString", /*optional=*/true, + &configDecl.config.configString, errors); + + tryParseJsonArrayToVariable(propJsonValue, "configArray", /*optional=*/true, + &configDecl.config.configArray, errors); + + parsePropValues(propJsonValue, "defaultValue", &configDecl.initialValue, errors); + + tryParseJsonValueToVariable(propJsonValue, "minSampleRate", /*optional=*/true, + &configDecl.config.minSampleRate, errors); + + tryParseJsonValueToVariable(propJsonValue, "maxSampleRate", /*optional=*/true, + &configDecl.config.maxSampleRate, errors); + + parseAreas(propJsonValue, "areas", &configDecl, errors); + + // If there is no area config, by default we allow variable update rate, so we have to add + // a global area config. + if (configDecl.config.areaConfigs.size() == 0) { + VehicleAreaConfig areaConfig = { + .areaId = 0, + .access = configDecl.config.access, + .supportVariableUpdateRate = true, + }; + configDecl.config.areaConfigs.push_back(std::move(areaConfig)); + } + + if (errors->size() != initialErrorCount) { + return std::nullopt; + } + + return configDecl; +} + +Result> JsonConfigParser::parseJsonConfig( + std::istream& is) { + Json::CharReaderBuilder builder; + Json::Value root; + std::unordered_map configsByPropId; + std::string errs; + if (!Json::parseFromStream(builder, is, &root, &errs)) { + return Error() << "Failed to parse property config file as JSON, error: " << errs; + } + if (!root.isObject()) { + return Error() << "root element must be an object"; + } + if (!root.isMember("properties") || !root["properties"].isArray()) { + return Error() << "Missing 'properties' field in root or the field is not an array"; + } + Json::Value properties = root["properties"]; + std::vector errors; + for (unsigned int i = 0; i < properties.size(); i++) { + if (auto maybeConfig = parseEachProperty(properties[i], &errors); maybeConfig.has_value()) { + configsByPropId[maybeConfig.value().config.prop] = std::move(maybeConfig.value()); + } + } + if (!errors.empty()) { + return Error() << android::base::Join(errors, '\n'); + } + return configsByPropId; +} + +} // namespace jsonconfigloader_impl + +JsonConfigLoader::JsonConfigLoader() { + mParser = std::make_unique(); +} + +android::base::Result> +JsonConfigLoader::loadPropConfig(std::istream& is) { + return mParser->parseJsonConfig(is); +} + +android::base::Result> +JsonConfigLoader::loadPropConfig(const std::string& configPath) { + std::ifstream ifs(configPath.c_str()); + if (!ifs) { + return android::base::Error() << "couldn't open " << configPath << " for parsing."; + } + + return loadPropConfig(ifs); +} + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/test/Android.bp b/automotive/vehicle/aidl/impl/current/default_config/JsonConfigLoader/test/Android.bp similarity index 100% rename from automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/test/Android.bp rename to automotive/vehicle/aidl/impl/current/default_config/JsonConfigLoader/test/Android.bp diff --git a/automotive/vehicle/aidl/impl/current/default_config/JsonConfigLoader/test/JsonConfigLoaderUnitTest.cpp b/automotive/vehicle/aidl/impl/current/default_config/JsonConfigLoader/test/JsonConfigLoaderUnitTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..54afbd4f7624340c8f82954862f14213820c9372 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/default_config/JsonConfigLoader/test/JsonConfigLoaderUnitTest.cpp @@ -0,0 +1,809 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +using ::aidl::android::hardware::automotive::vehicle::RawPropValues; +using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig; +using ::aidl::android::hardware::automotive::vehicle::VehicleProperty; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyChangeMode; + +class JsonConfigLoaderUnitTest : public ::testing::Test { + protected: + JsonConfigLoader mLoader; +}; + +TEST_F(JsonConfigLoaderUnitTest, testBasic) { + std::istringstream iss(R"( + { + "properties": [{ + "property": 291504388 + }] + } + )"); + + auto result = mLoader.loadPropConfig(iss); + + ASSERT_TRUE(result.ok()) << result.error().message(); + + auto configs = result.value(); + ASSERT_EQ(configs.size(), 1u); + ASSERT_EQ(configs.begin()->second.config.prop, 291504388); +} + +TEST_F(JsonConfigLoaderUnitTest, testRootNotObject) { + std::istringstream iss(R"( + [] + )"); + + ASSERT_FALSE(mLoader.loadPropConfig(iss).ok()) << "root is not an object must cause error"; +} + +TEST_F(JsonConfigLoaderUnitTest, testMissingPropertiesField) { + std::istringstream iss(R"( + { + "abcd": 1234 + } + )"); + + ASSERT_FALSE(mLoader.loadPropConfig(iss).ok()) << "Missing 'properties' field must cause error"; +} + +TEST_F(JsonConfigLoaderUnitTest, testPropertiesFieldNotArray) { + std::istringstream iss(R"( + { + "properties': {'a': 'b'} + } + )"); + + ASSERT_FALSE(mLoader.loadPropConfig(iss).ok()) + << "'properties' field is not an array must cause error"; +} + +TEST_F(JsonConfigLoaderUnitTest, testPropertyIsEnum) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::INFO_FUEL_CAPACITY" + }] + } + )"); + + auto result = mLoader.loadPropConfig(iss); + + ASSERT_TRUE(result.ok()) << result.error().message(); + + auto configs = result.value(); + ASSERT_EQ(configs.size(), 1u); + ASSERT_EQ(configs.begin()->second.config.prop, toInt(VehicleProperty::INFO_FUEL_CAPACITY)); +} + +TEST_F(JsonConfigLoaderUnitTest, testPropertyEnum_FailInvalidEnum) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::BLAH" + }] + } + )"); + + ASSERT_FALSE(mLoader.loadPropConfig(iss).ok()) + << "Invalid VehicleProperty enum must cause error"; +} + +TEST_F(JsonConfigLoaderUnitTest, testPropertyEnum_FailInvalidType) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "test" + }] + } + )"); + + ASSERT_FALSE(mLoader.loadPropConfig(iss).ok()) + << "Invalid VehicleProperty type must cause error"; +} + +TEST_F(JsonConfigLoaderUnitTest, testProperty_FailInvalidJson) { + std::istringstream iss(R"( + { + "properties": [{ + } + )"); + + ASSERT_FALSE(mLoader.loadPropConfig(iss).ok()) << "Invalid JSON format must cause error"; +} + +TEST_F(JsonConfigLoaderUnitTest, testConfigArray) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::INFO_FUEL_CAPACITY", + "configArray": [1, 2, 3] + }] + } + )"); + + auto result = mLoader.loadPropConfig(iss); + + ASSERT_TRUE(result.ok()) << result.error().message(); + + auto configs = result.value(); + ASSERT_EQ(configs.size(), 1u); + ASSERT_EQ(configs.begin()->second.config.configArray, std::vector({1, 2, 3})); +} + +TEST_F(JsonConfigLoaderUnitTest, testConfigArrayConstants) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::INFO_FUEL_CAPACITY", + "configArray": [1, 2, "Constants::FUEL_DOOR_REAR_LEFT"] + }] + } + )"); + + auto result = mLoader.loadPropConfig(iss); + + ASSERT_TRUE(result.ok()) << result.error().message(); + + auto configs = result.value(); + ASSERT_EQ(configs.size(), 1u); + ASSERT_EQ(configs.begin()->second.config.configArray, + std::vector({1, 2, FUEL_DOOR_REAR_LEFT})); +} + +// We have special logic to deal with GALLON and US_GALLON since they share the same value. +TEST_F(JsonConfigLoaderUnitTest, testConfigArrayUnitGallon) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::INFO_FUEL_CAPACITY", + "configArray": [1, 2, "VehicleUnit::GALLON"] + }] + } + )"); + + auto result = mLoader.loadPropConfig(iss); + + ASSERT_TRUE(result.ok()) << result.error().message(); +} + +TEST_F(JsonConfigLoaderUnitTest, testConfigArrayUnitUsGallon) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::INFO_FUEL_CAPACITY", + "configArray": [1, 2, "VehicleUnit::US_GALLON"] + }] + } + )"); + + auto result = mLoader.loadPropConfig(iss); + + ASSERT_TRUE(result.ok()) << result.error().message(); +} + +TEST_F(JsonConfigLoaderUnitTest, testConfigArray_FailInvalidEnum) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::INFO_FUEL_CAPACITY", + "configArray": [1, 2, "VehicleUnits::BLAH"] + }] + } + )"); + + ASSERT_FALSE(mLoader.loadPropConfig(iss).ok()) + << "Invalid enum in ConfigArray must cause error"; +} + +TEST_F(JsonConfigLoaderUnitTest, testConfigArray_FailNotArray) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::INFO_FUEL_CAPACITY", + "configArray": "123" + }] + } + )"); + + ASSERT_FALSE(mLoader.loadPropConfig(iss).ok()) + << "ConfigArray is not an array must cause error"; +} + +TEST_F(JsonConfigLoaderUnitTest, testConfigString) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::INFO_FUEL_CAPACITY", + "configString": "test" + }] + } + )"); + + auto result = mLoader.loadPropConfig(iss); + + ASSERT_TRUE(result.ok()) << result.error().message(); + + auto configs = result.value(); + ASSERT_EQ(configs.size(), 1u); + ASSERT_EQ(configs.begin()->second.config.configString, "test"); +} + +TEST_F(JsonConfigLoaderUnitTest, testConfigString_FailNotString) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::INFO_FUEL_CAPACITY", + "configString": 1234 + }] + } + )"); + + ASSERT_FALSE(mLoader.loadPropConfig(iss).ok()) + << "ConfigString is not a String must cause error"; +} + +TEST_F(JsonConfigLoaderUnitTest, testCheckDefaultAccessChangeMode) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::INFO_FUEL_CAPACITY" + }] + } + )"); + + auto result = mLoader.loadPropConfig(iss); + + ASSERT_TRUE(result.ok()) << result.error().message(); + auto configs = result.value(); + ASSERT_EQ(configs.size(), 1u); + + const VehiclePropConfig& propConfig = configs.begin()->second.config; + ASSERT_EQ(propConfig.access, VehiclePropertyAccess::READ); + ASSERT_EQ(propConfig.areaConfigs[0].access, VehiclePropertyAccess::READ); + ASSERT_EQ(propConfig.changeMode, VehiclePropertyChangeMode::STATIC); +} + +TEST_F(JsonConfigLoaderUnitTest, testAccessOverride) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::INFO_FUEL_CAPACITY", + "access": "VehiclePropertyAccess::WRITE" + }] + } + )"); + + auto result = mLoader.loadPropConfig(iss); + + ASSERT_TRUE(result.ok()) << result.error().message(); + auto configs = result.value(); + ASSERT_EQ(configs.size(), 1u); + + const VehiclePropConfig& propConfig = configs.begin()->second.config; + ASSERT_EQ(propConfig.access, VehiclePropertyAccess::WRITE); + ASSERT_EQ(propConfig.areaConfigs[0].access, VehiclePropertyAccess::WRITE); + ASSERT_EQ(propConfig.changeMode, VehiclePropertyChangeMode::STATIC); +} + +TEST_F(JsonConfigLoaderUnitTest, testChangeModeOverride) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::INFO_FUEL_CAPACITY", + "changeMode": "VehiclePropertyChangeMode::ON_CHANGE" + }] + } + )"); + + auto result = mLoader.loadPropConfig(iss); + + ASSERT_TRUE(result.ok()) << result.error().message(); + auto configs = result.value(); + ASSERT_EQ(configs.size(), 1u); + + const VehiclePropConfig& propConfig = configs.begin()->second.config; + ASSERT_EQ(propConfig.access, VehiclePropertyAccess::READ); + ASSERT_EQ(propConfig.areaConfigs[0].access, VehiclePropertyAccess::READ); + ASSERT_EQ(propConfig.changeMode, VehiclePropertyChangeMode::ON_CHANGE); +} + +TEST_F(JsonConfigLoaderUnitTest, testCustomProp) { + std::istringstream iss(R"( + { + "properties": [{ + "property": 1234, + "access": "VehiclePropertyAccess::WRITE", + "changeMode": "VehiclePropertyChangeMode::ON_CHANGE" + }] + } + )"); + + auto result = mLoader.loadPropConfig(iss); + + ASSERT_TRUE(result.ok()) << result.error().message(); + auto configs = result.value(); + ASSERT_EQ(configs.size(), 1u); + + const VehiclePropConfig& propConfig = configs.begin()->second.config; + ASSERT_EQ(propConfig.access, VehiclePropertyAccess::WRITE); + ASSERT_EQ(propConfig.areaConfigs[0].access, VehiclePropertyAccess::WRITE); + ASSERT_EQ(propConfig.changeMode, VehiclePropertyChangeMode::ON_CHANGE); +} + +TEST_F(JsonConfigLoaderUnitTest, testCustomProp_FailMissingAccess) { + std::istringstream iss(R"( + { + "properties": [{ + "property": 1234, + "changeMode": "VehiclePropertyChangeMode::ON_CHANGE" + }] + } + )"); + + ASSERT_FALSE(mLoader.loadPropConfig(iss).ok()) + << "Missing access for custom property must cause error"; +} + +TEST_F(JsonConfigLoaderUnitTest, testCustomProp_FailMissingChangeMode) { + std::istringstream iss(R"( + { + "properties": [{ + "property": 1234, + "access": "VehiclePropertyAccess::WRITE" + }] + } + )"); + + ASSERT_FALSE(mLoader.loadPropConfig(iss).ok()) + << "Missing change mode for custom property must cause error"; +} + +TEST_F(JsonConfigLoaderUnitTest, testMinSampleRate) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::INFO_FUEL_CAPACITY", + "minSampleRate": 1, + }] + } + )"); + + auto result = mLoader.loadPropConfig(iss); + + ASSERT_TRUE(result.ok()) << result.error().message(); + + auto configs = result.value(); + ASSERT_EQ(configs.size(), 1u); + ASSERT_EQ(configs.begin()->second.config.minSampleRate, 1); +} + +TEST_F(JsonConfigLoaderUnitTest, testMinSampleRate_FailInvalidType) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::INFO_FUEL_CAPACITY", + "minSampleRate": "abcd", + }] + } + )"); + + ASSERT_FALSE(mLoader.loadPropConfig(iss).ok()) + << "Wrong type for MinSampleRate must cause error"; +} + +TEST_F(JsonConfigLoaderUnitTest, testMaxSampleRate) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::INFO_FUEL_CAPACITY", + "maxSampleRate": 1, + }] + } + )"); + + auto result = mLoader.loadPropConfig(iss); + + ASSERT_TRUE(result.ok()) << result.error().message(); + + auto configs = result.value(); + ASSERT_EQ(configs.size(), 1u); + ASSERT_EQ(configs.begin()->second.config.maxSampleRate, 1); +} + +TEST_F(JsonConfigLoaderUnitTest, testMaxSampleRate_FailInvalidType) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::INFO_FUEL_CAPACITY", + "maxSampleRate": "abcd", + }] + } + )"); + + ASSERT_FALSE(mLoader.loadPropConfig(iss).ok()) + << "Wrong type for MaxSampleRate must cause error"; +} + +TEST_F(JsonConfigLoaderUnitTest, testDefaultValue_Simple) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::INFO_FUEL_CAPACITY", + "defaultValue": { + "int32Values": [1, 2] + } + }] + } + )"); + + auto result = mLoader.loadPropConfig(iss); + + ASSERT_TRUE(result.ok()) << result.error().message(); + + auto configs = result.value(); + ASSERT_EQ(configs.size(), 1u); + ASSERT_EQ(configs.begin()->second.initialValue.int32Values, std::vector({1, 2})); +} + +TEST_F(JsonConfigLoaderUnitTest, testDefaultValue_Mixed) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::INFO_FUEL_CAPACITY", + "defaultValue": { + "int32Values": [1, "Constants::FUEL_DOOR_REAR_LEFT"], + "int64Values": [2, "Constants::FUEL_DOOR_REAR_LEFT"], + "floatValues": [3.0, "Constants::FUEL_DOOR_REAR_LEFT"], + "stringValue": "abcd" + } + }] + } + )"); + + auto result = mLoader.loadPropConfig(iss); + + ASSERT_TRUE(result.ok()) << result.error().message(); + + auto configs = result.value(); + ASSERT_EQ(configs.size(), 1u); + + const RawPropValues& initialValue = configs.begin()->second.initialValue; + ASSERT_EQ(initialValue.int32Values, std::vector({1, FUEL_DOOR_REAR_LEFT})); + ASSERT_EQ(initialValue.int64Values, + std::vector({2, static_cast(FUEL_DOOR_REAR_LEFT)})); + ASSERT_EQ(initialValue.floatValues, + std::vector({3.0, static_cast(FUEL_DOOR_REAR_LEFT)})); + ASSERT_EQ(initialValue.stringValue, "abcd"); +} + +TEST_F(JsonConfigLoaderUnitTest, testDefaultValue_FailNotObject) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::INFO_FUEL_CAPACITY", + "defaultValue": [] + }] + } + )"); + + ASSERT_FALSE(mLoader.loadPropConfig(iss).ok()) + << "DefaultValue is not an object must cause error"; +} + +TEST_F(JsonConfigLoaderUnitTest, testDefaultValue_FailInvalidType) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::INFO_FUEL_CAPACITY", + "defaultValue": { + "int32Values": [1.1] + } + }] + } + )"); + + ASSERT_FALSE(mLoader.loadPropConfig(iss).ok()) + << "Wrong type for DefaultValue must cause error"; +} + +TEST_F(JsonConfigLoaderUnitTest, testAreas_Simple) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::INFO_FUEL_CAPACITY", + "areas": [{ + "areaId": "Constants::HVAC_ALL", + "minInt32Value": 1, + "maxInt32Value": 7 + }] + }] + } + )"); + + auto result = mLoader.loadPropConfig(iss); + + auto configs = result.value(); + ASSERT_EQ(configs.size(), 1u); + + const VehiclePropConfig& config = configs.begin()->second.config; + ASSERT_EQ(config.access, VehiclePropertyAccess::READ); + ASSERT_EQ(config.areaConfigs.size(), 1u); + const VehicleAreaConfig& areaConfig = config.areaConfigs[0]; + ASSERT_EQ(areaConfig.minInt32Value, 1); + ASSERT_EQ(areaConfig.maxInt32Value, 7); + ASSERT_EQ(areaConfig.access, VehiclePropertyAccess::READ); + ASSERT_EQ(areaConfig.areaId, HVAC_ALL); +} + +TEST_F(JsonConfigLoaderUnitTest, testAreas_DefaultValueForEachArea) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::INFO_FUEL_CAPACITY", + "areas": [{ + "areaId": "Constants::HVAC_LEFT", + "defaultValue": { + "int32Values": [1] + } + }, { + "areaId": "Constants::HVAC_RIGHT", + "defaultValue": { + "int32Values": [2] + } + }] + }] + } + )"); + + auto result = mLoader.loadPropConfig(iss); + + auto configs = result.value(); + ASSERT_EQ(configs.size(), 1u); + + const VehiclePropConfig& config = configs.begin()->second.config; + ASSERT_EQ(config.areaConfigs.size(), 2u); + ASSERT_EQ(config.areaConfigs[0].areaId, HVAC_LEFT); + ASSERT_EQ(config.areaConfigs[1].areaId, HVAC_RIGHT); + ASSERT_EQ(configs.begin()->second.initialAreaValues[HVAC_LEFT], + RawPropValues{.int32Values = {1}}); + ASSERT_EQ(configs.begin()->second.initialAreaValues[HVAC_RIGHT], + RawPropValues{.int32Values = {2}}); +} + +TEST_F(JsonConfigLoaderUnitTest, testAreas_FailInvalidTypeForOneAreaValue) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::INFO_FUEL_CAPACITY", + "areas": [{ + "areaId": "Constants::HVAC_LEFT", + "defaultValue": { + "int32Values": [1] + } + }, { + "areaId": "Constants::HVAC_RIGHT", + "defaultValue": { + "int32Values": [2.1] + } + }] + }] + } + )"); + + ASSERT_FALSE(mLoader.loadPropConfig(iss).ok()) + << "Wrong type for DefaultValue for one area must cause error"; +} + +TEST_F(JsonConfigLoaderUnitTest, testAreas_HandlesNoSupportedEnumValuesDeclared) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::CABIN_LIGHTS_STATE", + "areas": [{ + "areaId": 0, + }] + }] + } + )"); + + auto result = mLoader.loadPropConfig(iss); + ASSERT_TRUE(result.ok()); + + auto configs = result.value(); + ASSERT_EQ(configs.size(), 1u); + + const VehiclePropConfig& config = configs.begin()->second.config; + ASSERT_EQ(config.access, VehiclePropertyAccess::READ); + ASSERT_EQ(config.areaConfigs.size(), 1u); + + const VehicleAreaConfig& areaConfig = config.areaConfigs[0]; + ASSERT_EQ(areaConfig.access, VehiclePropertyAccess::READ); + ASSERT_EQ(areaConfig.areaId, 0); + ASSERT_FALSE(areaConfig.supportedEnumValues); +} + +TEST_F(JsonConfigLoaderUnitTest, testAreas_HandlesSupportedEnumValues) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::CABIN_LIGHTS_STATE", + "areas": [{ + "areaId": 0, + "supportedEnumValues": ["Constants::LIGHT_STATE_ON", "Constants::LIGHT_STATE_OFF"] + }] + }] + } + )"); + + auto result = mLoader.loadPropConfig(iss); + ASSERT_TRUE(result.ok()); + + auto configs = result.value(); + ASSERT_EQ(configs.size(), 1u); + + const VehiclePropConfig& config = configs.begin()->second.config; + ASSERT_EQ(config.access, VehiclePropertyAccess::READ); + ASSERT_EQ(config.areaConfigs.size(), 1u); + + const VehicleAreaConfig& areaConfig = config.areaConfigs[0]; + ASSERT_EQ(areaConfig.access, VehiclePropertyAccess::READ); + ASSERT_EQ(areaConfig.areaId, 0); + ASSERT_TRUE(areaConfig.supportedEnumValues); + ASSERT_EQ(areaConfig.supportedEnumValues.value().size(), 2u); + ASSERT_EQ(areaConfig.supportedEnumValues.value(), + std::vector({LIGHT_STATE_ON, LIGHT_STATE_OFF})); +} + +TEST_F(JsonConfigLoaderUnitTest, testAreas_HandlesEmptySupportedEnumValues) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::CABIN_LIGHTS_STATE", + "areas": [{ + "areaId": 0, + "supportedEnumValues": [] + }] + }] + } + )"); + + auto result = mLoader.loadPropConfig(iss); + ASSERT_TRUE(result.ok()); + + auto configs = result.value(); + ASSERT_EQ(configs.size(), 1u); + + const VehiclePropConfig& config = configs.begin()->second.config; + ASSERT_EQ(config.access, VehiclePropertyAccess::READ); + ASSERT_EQ(config.areaConfigs.size(), 1u); + + const VehicleAreaConfig& areaConfig = config.areaConfigs[0]; + ASSERT_EQ(areaConfig.access, VehiclePropertyAccess::READ); + ASSERT_EQ(areaConfig.areaId, 0); + ASSERT_FALSE(areaConfig.supportedEnumValues); +} + +TEST_F(JsonConfigLoaderUnitTest, testAccess_areaOverrideGlobalDefault) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::CABIN_LIGHTS_SWITCH", + "areas": [{ + "access": "VehiclePropertyAccess::READ", + "areaId": 0 + }] + }] + } + )"); + + auto result = mLoader.loadPropConfig(iss); + ASSERT_TRUE(result.ok()); + + auto configs = result.value(); + ASSERT_EQ(configs.size(), 1u); + + const VehiclePropConfig& config = configs.begin()->second.config; + ASSERT_EQ(config.access, VehiclePropertyAccess::READ_WRITE); + ASSERT_EQ(config.areaConfigs.size(), 1u); + + const VehicleAreaConfig& areaConfig = config.areaConfigs[0]; + ASSERT_EQ(areaConfig.access, VehiclePropertyAccess::READ); + ASSERT_EQ(areaConfig.areaId, 0); +} + +TEST_F(JsonConfigLoaderUnitTest, testAccess_globalOverrideDefault) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::CABIN_LIGHTS_SWITCH", + "areas": [{ + "areaId": 0 + }], + "access": "VehiclePropertyAccess::READ" + }] + } + )"); + + auto result = mLoader.loadPropConfig(iss); + ASSERT_TRUE(result.ok()); + + auto configs = result.value(); + ASSERT_EQ(configs.size(), 1u); + + const VehiclePropConfig& config = configs.begin()->second.config; + ASSERT_EQ(config.access, VehiclePropertyAccess::READ); + ASSERT_EQ(config.areaConfigs.size(), 1u); + + const VehicleAreaConfig& areaConfig = config.areaConfigs[0]; + ASSERT_EQ(areaConfig.access, VehiclePropertyAccess::READ); + ASSERT_EQ(areaConfig.areaId, 0); +} + +TEST_F(JsonConfigLoaderUnitTest, testAccess_areaOverrideGlobal) { + std::istringstream iss(R"( + { + "properties": [{ + "property": "VehicleProperty::CABIN_LIGHTS_SWITCH", + "areas": [{ + "access": "VehiclePropertyAccess::WRITE", + "areaId": 0 + }, + { + "areaId": 1 + }], + "access": "VehiclePropertyAccess::READ", + }] + } + )"); + + auto result = mLoader.loadPropConfig(iss); + ASSERT_TRUE(result.ok()); + + auto configs = result.value(); + ASSERT_EQ(configs.size(), 1u); + + const VehiclePropConfig& config = configs.begin()->second.config; + ASSERT_EQ(config.access, VehiclePropertyAccess::READ); + ASSERT_EQ(config.areaConfigs.size(), 2u); + + const VehicleAreaConfig& areaConfig1 = config.areaConfigs[0]; + ASSERT_EQ(areaConfig1.access, VehiclePropertyAccess::WRITE); + ASSERT_EQ(areaConfig1.areaId, 0); + + const VehicleAreaConfig& areaConfig2 = config.areaConfigs[1]; + ASSERT_EQ(areaConfig2.access, VehiclePropertyAccess::READ); + ASSERT_EQ(areaConfig2.areaId, 1); +} + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/current/default_config/TEST_MAPPING b/automotive/vehicle/aidl/impl/current/default_config/TEST_MAPPING new file mode 100644 index 0000000000000000000000000000000000000000..15ac9cb6b6bcaf2e67bff57ff60e193a56bc3a13 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/default_config/TEST_MAPPING @@ -0,0 +1,8 @@ +{ + "ravenwood-presubmit": [ + { + "name": "CarServiceHostUnitTest", + "host": true + } + ] +} diff --git a/automotive/vehicle/aidl/impl/default_config/config/Android.bp b/automotive/vehicle/aidl/impl/current/default_config/config/Android.bp similarity index 100% rename from automotive/vehicle/aidl/impl/default_config/config/Android.bp rename to automotive/vehicle/aidl/impl/current/default_config/config/Android.bp diff --git a/automotive/vehicle/aidl/impl/current/default_config/config/DefaultProperties.json b/automotive/vehicle/aidl/impl/current/default_config/config/DefaultProperties.json new file mode 100644 index 0000000000000000000000000000000000000000..86ac92e93361921e1a92b64a321c7b3fdc70fdf7 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/default_config/config/DefaultProperties.json @@ -0,0 +1,5260 @@ +{ + "apiVersion": 1, + "properties": [ + { + "property": "VehicleProperty::INFO_FUEL_CAPACITY", + "defaultValue": { + "floatValues": [ + 15000.0 + ] + } + }, + { + "property": "VehicleProperty::INFO_FUEL_TYPE", + "defaultValue": { + "int32Values": [ + "FuelType::FUEL_TYPE_UNLEADED" + ] + } + }, + { + "property": "VehicleProperty::INFO_EV_BATTERY_CAPACITY", + "defaultValue": { + "floatValues": [ + 150000.0 + ] + } + }, + { + "property": "VehicleProperty::INFO_EV_CONNECTOR_TYPE", + "defaultValue": { + "int32Values": [ + "EvConnectorType::IEC_TYPE_1_AC" + ] + } + }, + { + "property": "VehicleProperty::INFO_FUEL_DOOR_LOCATION", + "defaultValue": { + "int32Values": [ + "Constants::FUEL_DOOR_REAR_LEFT" + ] + } + }, + { + "property": "VehicleProperty::INFO_EV_PORT_LOCATION", + "defaultValue": { + "int32Values": [ + "Constants::CHARGE_PORT_FRONT_LEFT" + ] + } + }, + { + "property": "VehicleProperty::INFO_MULTI_EV_PORT_LOCATIONS", + "defaultValue": { + "int32Values": [ + "Constants::CHARGE_PORT_FRONT_LEFT", + "Constants::CHARGE_PORT_REAR_LEFT" + ] + } + }, + { + "property": "VehicleProperty::INFO_VIN", + "defaultValue": { + "stringValue": "1GCARVIN123456789" + } + }, + { + "property": "VehicleProperty::INFO_MAKE", + "defaultValue": { + "stringValue": "Toy Vehicle" + } + }, + { + "property": "VehicleProperty::INFO_MODEL", + "defaultValue": { + "stringValue": "Speedy Model" + } + }, + { + "property": "VehicleProperty::INFO_MODEL_YEAR", + "defaultValue": { + "int32Values": [ + 2023 + ] + } + }, + { + "property": "VehicleProperty::INFO_EXTERIOR_DIMENSIONS", + "defaultValue": { + "int32Values": [ + 1776, + 4950, + 2008, + 2140, + 2984, + 1665, + 1667, + 11800 + ] + } + }, + { + "property": "VehicleProperty::INFO_MODEL_TRIM", + "defaultValue": { + "stringValue": "Sport" + } + }, + { + "property": "VehicleProperty::INFO_VEHICLE_SIZE_CLASS", + "defaultValue": { + "int32Values": [ + "VehicleSizeClass::EU_A_SEGMENT", + "VehicleSizeClass::JPN_KEI" + ] + } + }, + { + "property": "VehicleProperty::PERF_VEHICLE_SPEED", + "defaultValue": { + "floatValues": [ + 0.0 + ] + }, + "maxSampleRate": 10.0, + "minSampleRate": 1.0 + }, + { + "property": "VehicleProperty::PERF_VEHICLE_SPEED_DISPLAY", + "defaultValue": { + "floatValues": [ + 0.0 + ] + }, + "maxSampleRate": 10.0, + "minSampleRate": 1.0 + }, + { + "property": "VehicleProperty::VEHICLE_SPEED_DISPLAY_UNITS", + "defaultValue": { + "int32Values": [ + "VehicleUnit::MILES_PER_HOUR" + ] + }, + "configArray": [ + "VehicleUnit::METER_PER_SEC", + "VehicleUnit::MILES_PER_HOUR", + "VehicleUnit::KILOMETERS_PER_HOUR" + ] + }, + { + "property": "VehicleProperty::EV_BATTERY_DISPLAY_UNITS", + "defaultValue": { + "int32Values": [ + "VehicleUnit::KILOWATT_HOUR" + ] + }, + "configArray": [ + "VehicleUnit::WATT_HOUR", + "VehicleUnit::AMPERE_HOURS", + "VehicleUnit::KILOWATT_HOUR" + ] + }, + { + "property": "VehicleProperty::SEAT_MEMORY_SELECT", + "defaultValue": { + "int32Values": [ + 1 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": 0, + "maxInt32Value": 3 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": 0, + "maxInt32Value": 3 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": 0, + "maxInt32Value": 3 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": 0, + "maxInt32Value": 3 + } + ] + }, + { + "property": "VehicleProperty::SEAT_MEMORY_SET", + "defaultValue": { + "int32Values": [ + 1 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": 0, + "maxInt32Value": 3 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": 0, + "maxInt32Value": 3 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": 0, + "maxInt32Value": 3 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": 0, + "maxInt32Value": 3 + } + ] + }, + { + "property": "VehicleProperty::SEAT_BELT_BUCKLED", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT" + }, + { + "areaId": "Constants::SEAT_1_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_LEFT" + }, + { + "areaId": "Constants::SEAT_2_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_CENTER" + } + ] + }, + { + "property": "VehicleProperty::SEAT_BELT_HEIGHT_POS", + "defaultValue": { + "int32Values": [ + 10 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": 0, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": 0, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": 0, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": 0, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": 0, + "maxInt32Value": 10 + } + ] + }, + { + "property": "VehicleProperty::SEAT_BELT_HEIGHT_MOVE", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": -1, + "maxInt32Value": 1 + } + ] + }, + { + "property": "VehicleProperty::SEAT_FORE_AFT_POS", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": -10, + "maxInt32Value": 10 + } + ] + }, + { + "property": "VehicleProperty::SEAT_FORE_AFT_MOVE", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": -1, + "maxInt32Value": 1 + } + ] + }, + { + "property": "VehicleProperty::SEAT_BACKREST_ANGLE_1_POS", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": -10, + "maxInt32Value": 10 + } + ] + }, + { + "property": "VehicleProperty::SEAT_BACKREST_ANGLE_1_MOVE", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": -1, + "maxInt32Value": 1 + } + ] + }, + { + "property": "VehicleProperty::SEAT_BACKREST_ANGLE_2_POS", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": -10, + "maxInt32Value": 10 + } + ] + }, + { + "property": "VehicleProperty::SEAT_BACKREST_ANGLE_2_MOVE", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": -1, + "maxInt32Value": 1 + } + ] + }, + { + "property": "VehicleProperty::SEAT_HEIGHT_POS", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": -10, + "maxInt32Value": 10 + } + ] + }, + { + "property": "VehicleProperty::SEAT_HEIGHT_MOVE", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": -1, + "maxInt32Value": 1 + } + ] + }, + { + "property": "VehicleProperty::SEAT_DEPTH_POS", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": -10, + "maxInt32Value": 10 + } + ] + }, + { + "property": "VehicleProperty::SEAT_DEPTH_MOVE", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": -1, + "maxInt32Value": 1 + } + ] + }, + { + "property": "VehicleProperty::SEAT_TILT_POS", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": -10, + "maxInt32Value": 10 + } + ] + }, + { + "property": "VehicleProperty::SEAT_TILT_MOVE", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": -1, + "maxInt32Value": 1 + } + ] + }, + { + "property": "VehicleProperty::SEAT_LUMBAR_FORE_AFT_POS", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": -10, + "maxInt32Value": 10 + } + ] + }, + { + "property": "VehicleProperty::SEAT_LUMBAR_FORE_AFT_MOVE", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": -1, + "maxInt32Value": 1 + } + ] + }, + { + "property": "VehicleProperty::SEAT_LUMBAR_SIDE_SUPPORT_POS", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": -10, + "maxInt32Value": 10 + } + ] + }, + { + "property": "VehicleProperty::SEAT_LUMBAR_SIDE_SUPPORT_MOVE", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": -1, + "maxInt32Value": 1 + } + ] + }, + { + "property": "VehicleProperty::SEAT_HEADREST_HEIGHT_POS_V2", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": 0, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": 0, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": 0, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": 0, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": 0, + "maxInt32Value": 10 + } + ] + }, + { + "property": "VehicleProperty::SEAT_HEADREST_HEIGHT_MOVE", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": -1, + "maxInt32Value": 1 + } + ] + }, + { + "property": "VehicleProperty::SEAT_HEADREST_ANGLE_POS", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": -10, + "maxInt32Value": 10 + } + ] + }, + { + "property": "VehicleProperty::SEAT_HEADREST_ANGLE_MOVE", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": -1, + "maxInt32Value": 1 + } + ] + }, + { + "property": "VehicleProperty::SEAT_HEADREST_FORE_AFT_POS", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": -10, + "maxInt32Value": 10 + } + ] + }, + { + "property": "VehicleProperty::SEAT_HEADREST_FORE_AFT_MOVE", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": -1, + "maxInt32Value": 1 + } + ] + }, + { + "property": "VehicleProperty::SEAT_FOOTWELL_LIGHTS_STATE", + "defaultValue": { + "int32Values": [ + "Constants::LIGHT_STATE_OFF" + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "supportedEnumValues": [ + "Constants::LIGHT_STATE_OFF", + "Constants::LIGHT_STATE_ON" + ] + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "supportedEnumValues": [ + "Constants::LIGHT_STATE_OFF", + "Constants::LIGHT_STATE_ON" + ] + }, + { + "areaId": "Constants::SEAT_2_LEFT_2_RIGHT_2_CENTER", + "supportedEnumValues": [ + "Constants::LIGHT_STATE_OFF", + "Constants::LIGHT_STATE_ON" + ] + } + ] + }, + { + "property": "VehicleProperty::SEAT_FOOTWELL_LIGHTS_SWITCH", + "defaultValue": { + "int32Values": [ + "Constants::LIGHT_SWITCH_OFF" + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "supportedEnumValues": [ + "Constants::LIGHT_SWITCH_OFF", + "Constants::LIGHT_SWITCH_ON", + "Constants::LIGHT_SWITCH_AUTO" + ] + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "supportedEnumValues": [ + "Constants::LIGHT_SWITCH_OFF", + "Constants::LIGHT_SWITCH_ON", + "Constants::LIGHT_SWITCH_AUTO" + ] + }, + { + "areaId": "Constants::SEAT_2_LEFT_2_RIGHT_2_CENTER", + "supportedEnumValues": [ + "Constants::LIGHT_SWITCH_OFF", + "Constants::LIGHT_SWITCH_ON", + "Constants::LIGHT_SWITCH_AUTO" + ] + } + ] + }, + { + "property": "VehicleProperty::SEAT_EASY_ACCESS_ENABLED", + "defaultValue": { + "int32Values": [ + 1 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT" + }, + { + "areaId": "Constants::SEAT_1_RIGHT" + } + ] + }, + { + "property": "VehicleProperty::SEAT_AIRBAG_ENABLED", + "defaultValue": { + "int32Values": [ + 1 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT" + }, + { + "areaId": "Constants::SEAT_1_RIGHT" + } + ] + }, + { + "property": "VehicleProperty::SEAT_CUSHION_SIDE_SUPPORT_POS", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": -10, + "maxInt32Value": 10 + } + ] + }, + { + "property": "VehicleProperty::SEAT_CUSHION_SIDE_SUPPORT_MOVE", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": -1, + "maxInt32Value": 1 + } + ] + }, + { + "property": "VehicleProperty::SEAT_LUMBAR_VERTICAL_POS", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": -10, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": -10, + "maxInt32Value": 10 + } + ] + }, + { + "property": "VehicleProperty::SEAT_LUMBAR_VERTICAL_MOVE", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": -1, + "maxInt32Value": 1 + } + ] + }, + { + "property": "VehicleProperty::SEAT_WALK_IN_POS", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": 0, + "maxInt32Value": 5 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": 0, + "maxInt32Value": 5 + } + ] + }, + { + "property": "VehicleProperty::SEAT_AIRBAGS_DEPLOYED", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "supportedEnumValues": [ + "VehicleAirbagLocation::FRONT", + "VehicleAirbagLocation::KNEE", + "VehicleAirbagLocation::LEFT_SIDE", + "VehicleAirbagLocation::RIGHT_SIDE", + "VehicleAirbagLocation::CURTAIN" + ] + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "supportedEnumValues": [ + "VehicleAirbagLocation::FRONT", + "VehicleAirbagLocation::KNEE", + "VehicleAirbagLocation::LEFT_SIDE", + "VehicleAirbagLocation::RIGHT_SIDE", + "VehicleAirbagLocation::CURTAIN" + ] + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "supportedEnumValues": [ + "VehicleAirbagLocation::FRONT", + "VehicleAirbagLocation::CURTAIN" + ] + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "supportedEnumValues": [ + "VehicleAirbagLocation::FRONT", + "VehicleAirbagLocation::CURTAIN" + ] + } + ] + }, + { + "property": "VehicleProperty::SEAT_BELT_PRETENSIONER_DEPLOYED", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT" + }, + { + "areaId": "Constants::SEAT_1_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_LEFT" + }, + { + "areaId": "Constants::SEAT_2_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_CENTER" + } + ] + }, + { + "property": "VehicleProperty::SEAT_OCCUPANCY", + "defaultValue": { + "int32Values": [ + "VehicleSeatOccupancyState::VACANT" + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT" + }, + { + "areaId": "Constants::SEAT_1_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_LEFT" + }, + { + "areaId": "Constants::SEAT_2_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_CENTER" + } + ] + }, + { + "property": "VehicleProperty::INFO_DRIVER_SEAT", + "defaultValue": { + "int32Values": [ + "Constants::SEAT_1_LEFT" + ] + }, + "areas": [ + { + "areaId": 0 + } + ] + }, + { + "property": "VehicleProperty::PERF_ODOMETER", + "defaultValue": { + "floatValues": [ + 0.0 + ] + }, + "maxSampleRate": 10.0, + "minSampleRate": 1.0 + }, + { + "property": "VehicleProperty::PERF_STEERING_ANGLE", + "defaultValue": { + "floatValues": [ + 0.0 + ] + }, + "maxSampleRate": 10.0, + "minSampleRate": 1.0 + }, + { + "property": "VehicleProperty::PERF_REAR_STEERING_ANGLE", + "defaultValue": { + "floatValues": [ + 0.0 + ] + }, + "maxSampleRate": 10.0, + "minSampleRate": 1.0 + }, + { + "property": "VehicleProperty::INSTANTANEOUS_FUEL_ECONOMY", + "defaultValue": { + "floatValues": [ + 0.0 + ] + }, + "maxSampleRate": 10.0, + "minSampleRate": 1.0 + }, + { + "property": "VehicleProperty::INSTANTANEOUS_EV_EFFICIENCY", + "defaultValue": { + "floatValues": [ + 0.0 + ] + }, + "maxSampleRate": 10.0, + "minSampleRate": 1.0 + }, + { + "property": "VehicleProperty::ENGINE_RPM", + "defaultValue": { + "floatValues": [ + 0.0 + ] + }, + "maxSampleRate": 10.0, + "minSampleRate": 1.0 + }, + { + "property": "VehicleProperty::FUEL_LEVEL", + "defaultValue": { + "floatValues": [ + 15000.0 + ] + }, + "maxSampleRate": 100.0, + "minSampleRate": 1.0 + }, + { + "property": "VehicleProperty::FUEL_DOOR_OPEN", + "defaultValue": { + "int32Values": [ + 0 + ] + } + }, + { + "property": "VehicleProperty::EV_BATTERY_LEVEL", + "defaultValue": { + "floatValues": [ + 150000.0 + ] + }, + "maxSampleRate": 100.0, + "minSampleRate": 1.0 + }, + { + "property": "VehicleProperty::EV_CURRENT_BATTERY_CAPACITY", + "defaultValue": { + "floatValues": [ + 150000.0 + ] + } + }, + { + "property": "VehicleProperty::EV_CHARGE_PORT_OPEN", + "defaultValue": { + "int32Values": [ + 0 + ] + } + }, + { + "property": "VehicleProperty::EV_CHARGE_PORT_CONNECTED", + "defaultValue": { + "int32Values": [ + 0 + ] + } + }, + { + "property": "VehicleProperty::EV_BATTERY_INSTANTANEOUS_CHARGE_RATE", + "defaultValue": { + "floatValues": [ + 0.0 + ] + }, + "maxSampleRate": 10.0, + "minSampleRate": 1.0 + }, + { + "property": "VehicleProperty::EV_CHARGE_CURRENT_DRAW_LIMIT", + "defaultValue": { + "floatValues": [ + 12.5 + ] + }, + "comment": "ConfigArray specifies Max current draw allowed by vehicle in amperes", + "configArray": [ + 20 + ] + }, + { + "property": "VehicleProperty::EV_CHARGE_PERCENT_LIMIT", + "defaultValue": { + "floatValues": [ + 40.0 + ] + }, + "configArray": [ + 20, + 40, + 60, + 80, + 100 + ] + }, + { + "property": "VehicleProperty::EV_CHARGE_STATE", + "defaultValue": { + "int32Values": [ + 2 + ] + } + }, + { + "property": "VehicleProperty::EV_CHARGE_SWITCH", + "defaultValue": { + "int32Values": [ + 0 + ] + } + }, + { + "property": "VehicleProperty::EV_CHARGE_TIME_REMAINING", + "defaultValue": { + "int32Values": [ + 20 + ] + }, + "maxSampleRate": 10.0, + "minSampleRate": 1.0 + }, + { + "property": "VehicleProperty::EV_REGENERATIVE_BRAKING_STATE", + "defaultValue": { + "int32Values": [ + 2 + ] + } + }, + { + "property": "VehicleProperty::TRAILER_PRESENT", + "defaultValue": { + "int32Values": [ + 2 + ] + } + }, + { + "property": "VehicleProperty::VEHICLE_CURB_WEIGHT", + "defaultValue": { + "int32Values": [ + 2211 + ] + }, + "configArray": [ + 2948 + ], + "comment": "unit is kg" + }, + { + "property": "VehicleProperty::RANGE_REMAINING", + "defaultValue": { + "floatValues": [ + 50000.0 + ] + }, + "comment": "units in meter", + "maxSampleRate": 2.0, + "minSampleRate": 1.0 + }, + { + "property": "VehicleProperty::EV_BATTERY_AVERAGE_TEMPERATURE", + "defaultValue": { + "floatValues": [ + 25.0 + ] + }, + "maxSampleRate": 2.0, + "minSampleRate": 1.0 + }, + { + "property": "VehicleProperty::TIRE_PRESSURE", + "defaultValue": { + "floatValues": [ + 200.0 + ] + }, + "areas": [ + { + "areaId": "Constants::WHEEL_FRONT_LEFT", + "minFloatValue": 193.0, + "maxFloatValue": 300.0 + }, + { + "areaId": "Constants::WHEEL_FRONT_RIGHT", + "minFloatValue": 193.0, + "maxFloatValue": 300.0 + }, + { + "areaId": "Constants::WHEEL_REAR_LEFT", + "minFloatValue": 193.0, + "maxFloatValue": 300.0 + }, + { + "areaId": "Constants::WHEEL_REAR_RIGHT", + "minFloatValue": 193.0, + "maxFloatValue": 300.0 + } + ], + "comment": "Units in kpa", + "maxSampleRate": 2.0, + "minSampleRate": 1.0 + }, + { + "property": "VehicleProperty::CRITICALLY_LOW_TIRE_PRESSURE", + "areas": [ + { + "defaultValue": { + "floatValues": [ + 137.0 + ] + }, + "areaId": "Constants::WHEEL_FRONT_LEFT" + }, + { + "defaultValue": { + "floatValues": [ + 137.0 + ] + }, + "areaId": "Constants::WHEEL_FRONT_RIGHT" + }, + { + "defaultValue": { + "floatValues": [ + 137.0 + ] + }, + "areaId": "Constants::WHEEL_REAR_RIGHT" + }, + { + "defaultValue": { + "floatValues": [ + 137.0 + ] + }, + "areaId": "Constants::WHEEL_REAR_LEFT" + } + ] + }, + { + "property": "VehicleProperty::ACCELERATOR_PEDAL_COMPRESSION_PERCENTAGE", + "defaultValue": { + "floatValues": [ + 0.0 + ] + }, + "maxSampleRate": 10.0, + "minSampleRate": 1.0 + }, + { + "property": "VehicleProperty::BRAKE_PEDAL_COMPRESSION_PERCENTAGE", + "defaultValue": { + "floatValues": [ + 0.0 + ] + }, + "maxSampleRate": 10.0, + "minSampleRate": 1.0 + }, + { + "property": "VehicleProperty::BRAKE_PAD_WEAR_PERCENTAGE", + "areas": [ + { + "areaId": "Constants::WHEEL_FRONT_LEFT", + "defaultValue": { + "floatValues": [ + 0.0 + ] + } + }, + { + "areaId": "Constants::WHEEL_FRONT_RIGHT", + "defaultValue": { + "floatValues": [ + 0.0 + ] + } + }, + { + "areaId": "Constants::WHEEL_REAR_LEFT", + "defaultValue": { + "floatValues": [ + 0.0 + ] + } + }, + { + "areaId": "Constants::WHEEL_REAR_RIGHT", + "defaultValue": { + "floatValues": [ + 0.0 + ] + } + } + ] + }, + { + "property": "VehicleProperty::BRAKE_FLUID_LEVEL_LOW", + "defaultValue": { + "int32Values": [ + 0 + ] + } + }, + { + "property": "VehicleProperty::VEHICLE_PASSIVE_SUSPENSION_HEIGHT", + "areas": [ + { + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areaId": "Constants::WHEEL_FRONT_LEFT", + "minInt32Value": -100, + "maxInt32Value": 100 + }, + { + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areaId": "Constants::WHEEL_FRONT_RIGHT", + "minInt32Value": -100, + "maxInt32Value": 100 + }, + { + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areaId": "Constants::WHEEL_REAR_RIGHT", + "minInt32Value": -100, + "maxInt32Value": 100 + }, + { + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areaId": "Constants::WHEEL_REAR_LEFT", + "minInt32Value": -100, + "maxInt32Value": 100 + } + ], + "maxSampleRate": 10.0, + "minSampleRate": 1.0 + }, + { + "property": "VehicleProperty::TIRE_PRESSURE_DISPLAY_UNITS", + "defaultValue": { + "int32Values": [ + "VehicleUnit::PSI" + ] + }, + "configArray": [ + "VehicleUnit::KILOPASCAL", + "VehicleUnit::PSI", + "VehicleUnit::BAR" + ] + }, + { + "property": "VehicleProperty::CURRENT_GEAR", + "defaultValue": { + "int32Values": [ + "VehicleGear::GEAR_PARK" + ] + }, + "configArray": [ + "VehicleGear::GEAR_PARK", + "VehicleGear::GEAR_NEUTRAL", + "VehicleGear::GEAR_REVERSE", + "VehicleGear::GEAR_1", + "VehicleGear::GEAR_2", + "VehicleGear::GEAR_3", + "VehicleGear::GEAR_4", + "VehicleGear::GEAR_5" + ] + }, + { + "property": "VehicleProperty::PARKING_BRAKE_ON", + "defaultValue": { + "int32Values": [ + 1 + ] + } + }, + { + "property": "VehicleProperty::PARKING_BRAKE_AUTO_APPLY", + "defaultValue": { + "int32Values": [ + 1 + ] + } + }, + { + "property": "VehicleProperty::EV_BRAKE_REGENERATION_LEVEL", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": 0, + "minInt32Value": 0, + "maxInt32Value": 3 + } + ] + }, + { + "property": "VehicleProperty::EV_STOPPING_MODE", + "defaultValue": { + "int32Values": [ + "Constants::EV_STOPPING_MODE_CREEP" + ] + }, + "areas": [ + { + "areaId": 0, + "supportedEnumValues": [ + "Constants::EV_STOPPING_MODE_CREEP", + "Constants::EV_STOPPING_MODE_ROLL", + "Constants::EV_STOPPING_MODE_HOLD" + ] + } + ] + }, + { + "property": "VehicleProperty::FUEL_LEVEL_LOW", + "defaultValue": { + "int32Values": [ + 0 + ] + } + }, + { + "property": "VehicleProperty::FUEL_VOLUME_DISPLAY_UNITS", + "defaultValue": { + "int32Values": [ + "VehicleUnit::US_GALLON" + ] + }, + "configArray": [ + "VehicleUnit::LITER", + "VehicleUnit::US_GALLON" + ] + }, + { + "property": "VehicleProperty::FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME", + "defaultValue": { + "int32Values": [ + 1 + ] + } + }, + { + "property": "VehicleProperty::HW_KEY_INPUT", + "defaultValue": { + "int32Values": [ + 0, + 0, + 0 + ] + } + }, + { + "property": "VehicleProperty::HW_KEY_INPUT_V2", + "defaultValue": { + "int32Values": [ + 0, + 0, + 0, + 0 + ], + "int64Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT" + }, + { + "areaId": "Constants::SEAT_1_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_LEFT" + }, + { + "areaId": "Constants::SEAT_2_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_CENTER" + } + ] + }, + { + "property": "VehicleProperty::HW_MOTION_INPUT", + "defaultValue": { + "int32Values": [ + 0, + 0, + 0, + 0, + 1, + 0, + 0 + ], + "floatValues": [ + 0, + 0, + 0, + 0 + ], + "int64Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT" + }, + { + "areaId": "Constants::SEAT_1_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_LEFT" + }, + { + "areaId": "Constants::SEAT_2_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_CENTER" + } + ] + }, + { + "property": "VehicleProperty::HW_ROTARY_INPUT", + "defaultValue": { + "int32Values": [ + 0, + 0, + 0 + ] + } + }, + { + "property": "VehicleProperty::HW_CUSTOM_INPUT", + "defaultValue": { + "int32Values": [ + 0, + 0, + 0 + ] + }, + "configArray": [ + 0, + 0, + 0, + 3, + 0, + 0, + 0, + 0, + 0 + ] + }, + { + "property": "VehicleProperty::HVAC_ACTUAL_FAN_SPEED_RPM", + "defaultValue": { + "int32Values": [ + 50 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT" + }, + { + "areaId": "Constants::SEAT_1_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_LEFT" + }, + { + "areaId": "Constants::SEAT_2_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_CENTER" + } + ] + }, + { + "property": "VehicleProperty::HVAC_POWER_ON", + "defaultValue": { + "int32Values": [ + 1 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT" + }, + { + "areaId": "Constants::SEAT_1_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_LEFT" + }, + { + "areaId": "Constants::SEAT_2_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_CENTER" + } + ], + "configArray": [ + "VehicleProperty::HVAC_ACTUAL_FAN_SPEED_RPM", + "VehicleProperty::HVAC_AC_ON", + "VehicleProperty::HVAC_AUTO_ON", + "VehicleProperty::HVAC_AUTO_RECIRC_ON", + "VehicleProperty::HVAC_FAN_DIRECTION", + "VehicleProperty::HVAC_FAN_SPEED", + "VehicleProperty::HVAC_MAX_AC_ON", + "VehicleProperty::HVAC_RECIRC_ON", + "VehicleProperty::HVAC_TEMPERATURE_CURRENT", + "VehicleProperty::HVAC_TEMPERATURE_SET" + ] + }, + { + "property": "VehicleProperty::HVAC_DEFROSTER", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "VehicleAreaWindow::FRONT_WINDSHIELD" + }, + { + "areaId": "VehicleAreaWindow::REAR_WINDSHIELD" + } + ], + "comment": "0 means using for all areas" + }, + { + "property": "VehicleProperty::HVAC_ELECTRIC_DEFROSTER_ON", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "VehicleAreaWindow::FRONT_WINDSHIELD" + }, + { + "areaId": "VehicleAreaWindow::REAR_WINDSHIELD" + } + ], + "comment": "0 means using for all areas" + }, + { + "property": "VehicleProperty::HVAC_MAX_DEFROST_ON", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::HVAC_FRONT_ROW" + }, + { + "areaId": "Constants::HVAC_REAR_ROW" + } + ] + }, + { + "property": "VehicleProperty::HVAC_RECIRC_ON", + "defaultValue": { + "int32Values": [ + 1 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT" + }, + { + "areaId": "Constants::SEAT_1_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_LEFT" + }, + { + "areaId": "Constants::SEAT_2_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_CENTER" + } + ] + }, + { + "property": "VehicleProperty::HVAC_AUTO_RECIRC_ON", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT" + }, + { + "areaId": "Constants::SEAT_1_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_LEFT" + }, + { + "areaId": "Constants::SEAT_2_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_CENTER" + } + ] + }, + { + "property": "VehicleProperty::HVAC_AC_ON", + "defaultValue": { + "int32Values": [ + 1 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT" + }, + { + "areaId": "Constants::SEAT_1_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_LEFT" + }, + { + "areaId": "Constants::SEAT_2_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_CENTER" + } + ] + }, + { + "property": "VehicleProperty::HVAC_MAX_AC_ON", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT" + }, + { + "areaId": "Constants::SEAT_1_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_LEFT" + }, + { + "areaId": "Constants::SEAT_2_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_CENTER" + } + ] + }, + { + "property": "VehicleProperty::HVAC_AUTO_ON", + "defaultValue": { + "int32Values": [ + 1 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT" + }, + { + "areaId": "Constants::SEAT_1_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_LEFT" + }, + { + "areaId": "Constants::SEAT_2_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_CENTER" + } + ] + }, + { + "property": "VehicleProperty::HVAC_DUAL_ON", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::HVAC_ALL" + } + ] + }, + { + "property": "VehicleProperty::HVAC_FAN_SPEED", + "defaultValue": { + "int32Values": [ + 3 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": 1, + "maxInt32Value": 7 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": 1, + "maxInt32Value": 7 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": 1, + "maxInt32Value": 7 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": 1, + "maxInt32Value": 7 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": 1, + "maxInt32Value": 7 + } + ] + }, + { + "property": "VehicleProperty::HVAC_FAN_DIRECTION", + "defaultValue": { + "int32Values": [ + "VehicleHvacFanDirection::FACE" + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT" + }, + { + "areaId": "Constants::SEAT_1_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_LEFT" + }, + { + "areaId": "Constants::SEAT_2_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_CENTER" + } + ] + }, + { + "property": "VehicleProperty::HVAC_FAN_DIRECTION_AVAILABLE", + "defaultValue": { + "int32Values": [ + "Constants::FAN_DIRECTION_UNKNOWN", + "Constants::FAN_DIRECTION_FACE", + "Constants::FAN_DIRECTION_FLOOR", + "Constants::FAN_DIRECTION_FACE_FLOOR", + "Constants::FAN_DIRECTION_DEFROST", + "Constants::FAN_DIRECTION_FACE_DEFROST", + "Constants::FAN_DIRECTION_FLOOR_DEFROST", + "Constants::FAN_DIRECTION_FLOOR_DEFROST_FACE" + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT" + }, + { + "areaId": "Constants::SEAT_1_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_LEFT" + }, + { + "areaId": "Constants::SEAT_2_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_CENTER" + } + ] + }, + { + "property": "VehicleProperty::HVAC_SEAT_VENTILATION", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": 0, + "maxInt32Value": 3 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": 0, + "maxInt32Value": 3 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": 0, + "maxInt32Value": 3 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": 0, + "maxInt32Value": 3 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": 0, + "maxInt32Value": 3 + } + ], + "comment": "0 is off and +ve values indicate ventilation level." + }, + { + "property": "VehicleProperty::HVAC_STEERING_WHEEL_HEAT", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": 0, + "minInt32Value": -2, + "maxInt32Value": 2 + } + ], + "comment": "+ve values for heating and -ve for cooling" + }, + { + "property": "VehicleProperty::HVAC_SEAT_TEMPERATURE", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minInt32Value": -2, + "maxInt32Value": 2 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": -2, + "maxInt32Value": 2 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minInt32Value": -2, + "maxInt32Value": 2 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minInt32Value": -2, + "maxInt32Value": 2 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minInt32Value": -2, + "maxInt32Value": 2 + } + ], + "comment": "+ve values for heating and -ve for cooling" + }, + { + "property": "VehicleProperty::HVAC_SIDE_MIRROR_HEAT", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::MIRROR_DRIVER_LEFT_RIGHT", + "minInt32Value": 0, + "maxInt32Value": 2 + } + ] + }, + { + "property": "VehicleProperty::HVAC_TEMPERATURE_CURRENT", + "defaultValue": { + "floatValues": [ + 19.1 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT" + }, + { + "areaId": "Constants::SEAT_1_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_LEFT" + }, + { + "areaId": "Constants::SEAT_2_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_CENTER" + } + ] + }, + { + "property": "VehicleProperty::HVAC_TEMPERATURE_SET", + "defaultValue": { + "floatValues": [ + 17.0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT", + "minFloatValue": 16.0, + "maxFloatValue": 28.0 + }, + { + "areaId": "Constants::SEAT_1_RIGHT", + "minFloatValue": 16.0, + "maxFloatValue": 28.0 + }, + { + "areaId": "Constants::SEAT_2_LEFT", + "minFloatValue": 16.0, + "maxFloatValue": 28.0 + }, + { + "areaId": "Constants::SEAT_2_RIGHT", + "minFloatValue": 16.0, + "maxFloatValue": 28.0 + }, + { + "areaId": "Constants::SEAT_2_CENTER", + "minFloatValue": 16.0, + "maxFloatValue": 28.0 + } + ], + "comment": + "minFloatValue and maxFloatValue in area config should match corresponding values in configArray", + "configArray": [ + 160, + 280, + 5, + 608, + 824, + 9 + ] + }, + { + "property": "VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION", + "defaultValue": { + "floatValues": [ + 66.19999694824219, + "VehicleUnit::FAHRENHEIT", + 19.0, + 66.2 + ] + } + }, + { + "property": "VehicleProperty::ENV_OUTSIDE_TEMPERATURE", + "defaultValue": { + "floatValues": [ + 25.0 + ] + }, + "maxSampleRate": 2.0, + "minSampleRate": 1.0 + }, + { + "property": "VehicleProperty::HVAC_TEMPERATURE_DISPLAY_UNITS", + "defaultValue": { + "int32Values": [ + "VehicleUnit::FAHRENHEIT" + ] + }, + "configArray": [ + "VehicleUnit::FAHRENHEIT", + "VehicleUnit::CELSIUS" + ] + }, + { + "property": "VehicleProperty::DISTANCE_DISPLAY_UNITS", + "defaultValue": { + "int32Values": [ + "VehicleUnit::MILE" + ] + }, + "areas": [ + { + "areaId": 0 + } + ], + "configArray": [ + "VehicleUnit::KILOMETER", + "VehicleUnit::MILE" + ] + }, + { + "property": "VehicleProperty::NIGHT_MODE", + "defaultValue": { + "int32Values": [ + 0 + ] + } + }, + { + "property": "VehicleProperty::GEAR_SELECTION", + "defaultValue": { + "int32Values": [ + "VehicleGear::GEAR_PARK" + ] + }, + "configArray": [ + "VehicleGear::GEAR_PARK", + "VehicleGear::GEAR_NEUTRAL", + "VehicleGear::GEAR_REVERSE", + "VehicleGear::GEAR_DRIVE", + "VehicleGear::GEAR_1", + "VehicleGear::GEAR_2", + "VehicleGear::GEAR_3", + "VehicleGear::GEAR_4", + "VehicleGear::GEAR_5" + ] + }, + { + "property": "VehicleProperty::TURN_SIGNAL_LIGHT_STATE", + "defaultValue": { + "int32Values": [ + "VehicleTurnSignal::NONE" + ] + } + }, + { + "property": "VehicleProperty::TURN_SIGNAL_SWITCH", + "defaultValue": { + "int32Values": [ + "VehicleTurnSignal::NONE" + ] + } + }, + { + "property": "VehicleProperty::IGNITION_STATE", + "defaultValue": { + "int32Values": [ + "VehicleIgnitionState::ON" + ] + } + }, + { + "property": "VehicleProperty::ENGINE_COOLANT_TEMP", + "defaultValue": { + "floatValues": [ + 75.0 + ] + }, + "maxSampleRate": 10.0, + "minSampleRate": 1.0 + }, + { + "property": "VehicleProperty::ENGINE_OIL_LEVEL", + "defaultValue": { + "int32Values": [ + "VehicleOilLevel::NORMAL" + ] + } + }, + { + "property": "VehicleProperty::ENGINE_OIL_TEMP", + "defaultValue": { + "floatValues": [ + 101.0 + ] + }, + "maxSampleRate": 10.0, + "minSampleRate": 0.10000000149011612 + }, + { + "property": "VehicleProperty::ENGINE_IDLE_AUTO_STOP_ENABLED", + "defaultValue": { + "int32Values": [ + 1 + ] + } + }, + { + "property": "VehicleProperty::IMPACT_DETECTED", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": 0, + "supportedEnumValues": [ + "ImpactSensorLocation::FRONT", + "ImpactSensorLocation::FRONT_LEFT_DOOR_SIDE", + "ImpactSensorLocation::FRONT_RIGHT_DOOR_SIDE", + "ImpactSensorLocation::REAR_LEFT_DOOR_SIDE", + "ImpactSensorLocation::REAR_RIGHT_DOOR_SIDE", + "ImpactSensorLocation::REAR" + ] + } + ] + }, + { + "property": "VehicleProperty::VEHICLE_HORN_ENGAGED", + "defaultValue": { + "int32Values": [ + 0 + ] + } + }, + { + "property": "VehicleProperty::DOOR_LOCK", + "areas": [ + { + "defaultValue": { + "int32Values": [ + 1 + ] + }, + "areaId": "Constants::DOOR_1_LEFT" + }, + { + "defaultValue": { + "int32Values": [ + 1 + ] + }, + "areaId": "Constants::DOOR_1_RIGHT" + }, + { + "defaultValue": { + "int32Values": [ + 1 + ] + }, + "areaId": "Constants::DOOR_2_LEFT" + }, + { + "defaultValue": { + "int32Values": [ + 1 + ] + }, + "areaId": "Constants::DOOR_2_RIGHT" + } + ] + }, + { + "property": "VehicleProperty::DOOR_CHILD_LOCK_ENABLED", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::DOOR_2_LEFT" + }, + { + "areaId": "Constants::DOOR_2_RIGHT" + } + ] + }, + { + "property": "VehicleProperty::DOOR_POS", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::DOOR_1_LEFT", + "minInt32Value": 0, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::DOOR_1_RIGHT", + "minInt32Value": 0, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::DOOR_2_LEFT", + "minInt32Value": 0, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::DOOR_2_RIGHT", + "minInt32Value": 0, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::DOOR_REAR", + "minInt32Value": 0, + "maxInt32Value": 1 + } + ] + }, + { + "property": "VehicleProperty::DOOR_MOVE", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::DOOR_1_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::DOOR_1_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::DOOR_2_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::DOOR_2_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + } + ] + }, + { + "property": "VehicleProperty::MIRROR_Z_POS", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "VehicleAreaMirror::DRIVER_LEFT", + "minInt32Value": -3, + "maxInt32Value": 3 + }, + { + "areaId": "VehicleAreaMirror::DRIVER_RIGHT", + "minInt32Value": -3, + "maxInt32Value": 3 + }, + { + "areaId": "VehicleAreaMirror::DRIVER_CENTER", + "minInt32Value": -3, + "maxInt32Value": 3 + } + ] + }, + { + "property": "VehicleProperty::MIRROR_Z_MOVE", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "VehicleAreaMirror::DRIVER_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "VehicleAreaMirror::DRIVER_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "VehicleAreaMirror::DRIVER_CENTER", + "minInt32Value": -1, + "maxInt32Value": 1 + } + ] + }, + { + "property": "VehicleProperty::MIRROR_Y_POS", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "VehicleAreaMirror::DRIVER_LEFT", + "minInt32Value": -3, + "maxInt32Value": 3 + }, + { + "areaId": "VehicleAreaMirror::DRIVER_RIGHT", + "minInt32Value": -3, + "maxInt32Value": 3 + }, + { + "areaId": "VehicleAreaMirror::DRIVER_CENTER", + "minInt32Value": -3, + "maxInt32Value": 3 + } + ] + }, + { + "property": "VehicleProperty::MIRROR_Y_MOVE", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "VehicleAreaMirror::DRIVER_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "VehicleAreaMirror::DRIVER_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "VehicleAreaMirror::DRIVER_CENTER", + "minInt32Value": -1, + "maxInt32Value": 1 + } + ] + }, + { + "property": "VehicleProperty::MIRROR_LOCK", + "defaultValue": { + "int32Values": [ + 1 + ] + } + }, + { + "property": "VehicleProperty::MIRROR_FOLD", + "defaultValue": { + "int32Values": [ + 1 + ] + } + }, + { + "property": "VehicleProperty::MIRROR_AUTO_FOLD_ENABLED", + "defaultValue": { + "int32Values": [ + 1 + ] + }, + "areas": [ + { + "areaId": "Constants::MIRROR_DRIVER_LEFT_RIGHT" + } + ] + }, + { + "property": "VehicleProperty::MIRROR_AUTO_TILT_ENABLED", + "defaultValue": { + "int32Values": [ + 1 + ] + }, + "areas": [ + { + "areaId": "Constants::MIRROR_DRIVER_LEFT_RIGHT" + } + ] + }, + { + "property": "VehicleProperty::WINDOW_LOCK", + "areas": [ + { + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areaId": "Constants::WINDOW_1_RIGHT_2_LEFT_2_RIGHT" + } + ] + }, + { + "property": "VehicleProperty::WINDOW_POS", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::WINDOW_1_LEFT", + "minInt32Value": 0, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::WINDOW_1_RIGHT", + "minInt32Value": 0, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::WINDOW_2_LEFT", + "minInt32Value": 0, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::WINDOW_2_RIGHT", + "minInt32Value": 0, + "maxInt32Value": 10 + }, + { + "areaId": "Constants::WINDOW_ROOF_TOP_1", + "minInt32Value": -10, + "maxInt32Value": 10 + } + ] + }, + { + "property": "VehicleProperty::WINDOW_MOVE", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::WINDOW_1_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::WINDOW_1_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::WINDOW_2_LEFT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::WINDOW_2_RIGHT", + "minInt32Value": -1, + "maxInt32Value": 1 + }, + { + "areaId": "Constants::WINDOW_ROOF_TOP_1", + "minInt32Value": -1, + "maxInt32Value": 1 + } + ] + }, + { + "property": "VehicleProperty::WINDSHIELD_WIPERS_PERIOD", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "VehicleAreaWindow::FRONT_WINDSHIELD", + "minInt32Value": 0, + "maxInt32Value": 3000 + }, + { + "areaId": "VehicleAreaWindow::REAR_WINDSHIELD", + "minInt32Value": 0, + "maxInt32Value": 3000 + } + ] + }, + { + "property": "VehicleProperty::WINDSHIELD_WIPERS_STATE", + "defaultValue": { + "int32Values": [ + "WindshieldWipersState::OFF" + ] + }, + "areas": [ + { + "areaId": "VehicleAreaWindow::FRONT_WINDSHIELD", + "supportedEnumValues": [ + "WindshieldWipersState::OFF", + "WindshieldWipersState::ON", + "WindshieldWipersState::SERVICE" + ] + }, + { + "areaId": "VehicleAreaWindow::REAR_WINDSHIELD", + "supportedEnumValues": [ + "WindshieldWipersState::OFF", + "WindshieldWipersState::ON" + ] + } + ] + }, + { + "property": "VehicleProperty::WINDSHIELD_WIPERS_SWITCH", + "defaultValue": { + "int32Values": [ + "WindshieldWipersSwitch::OFF" + ] + }, + "areas": [ + { + "areaId": "VehicleAreaWindow::FRONT_WINDSHIELD", + "supportedEnumValues": [ + "WindshieldWipersSwitch::OFF", + "WindshieldWipersSwitch::MIST", + "WindshieldWipersSwitch::INTERMITTENT_LEVEL_1", + "WindshieldWipersSwitch::INTERMITTENT_LEVEL_2", + "WindshieldWipersSwitch::INTERMITTENT_LEVEL_3", + "WindshieldWipersSwitch::INTERMITTENT_LEVEL_4", + "WindshieldWipersSwitch::INTERMITTENT_LEVEL_5", + "WindshieldWipersSwitch::CONTINUOUS_LEVEL_1", + "WindshieldWipersSwitch::CONTINUOUS_LEVEL_2", + "WindshieldWipersSwitch::CONTINUOUS_LEVEL_3", + "WindshieldWipersSwitch::CONTINUOUS_LEVEL_4", + "WindshieldWipersSwitch::CONTINUOUS_LEVEL_5", + "WindshieldWipersSwitch::AUTO", + "WindshieldWipersSwitch::SERVICE" + ] + }, + { + "areaId": "VehicleAreaWindow::REAR_WINDSHIELD", + "supportedEnumValues": [ + "WindshieldWipersSwitch::OFF", + "WindshieldWipersSwitch::INTERMITTENT_LEVEL_1", + "WindshieldWipersSwitch::INTERMITTENT_LEVEL_2", + "WindshieldWipersSwitch::CONTINUOUS_LEVEL_1", + "WindshieldWipersSwitch::CONTINUOUS_LEVEL_2", + "WindshieldWipersSwitch::AUTO", + "WindshieldWipersSwitch::SERVICE" + ] + } + ] + }, + { + "property": "VehicleProperty::STEERING_WHEEL_DEPTH_POS", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": 0, + "minInt32Value": 0, + "maxInt32Value": 10 + } + ] + }, + { + "property": "VehicleProperty::STEERING_WHEEL_DEPTH_MOVE", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": 0, + "minInt32Value": -2, + "maxInt32Value": 2 + } + ] + }, + { + "property": "VehicleProperty::STEERING_WHEEL_HEIGHT_POS", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": 0, + "minInt32Value": 0, + "maxInt32Value": 10 + } + ] + }, + { + "property": "VehicleProperty::STEERING_WHEEL_HEIGHT_MOVE", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": 0, + "minInt32Value": -2, + "maxInt32Value": 2 + } + ] + }, + { + "property": "VehicleProperty::STEERING_WHEEL_THEFT_LOCK_ENABLED", + "defaultValue": { + "int32Values": [ + 0 + ] + } + }, + { + "property": "VehicleProperty::STEERING_WHEEL_LOCKED", + "defaultValue": { + "int32Values": [ + 0 + ] + } + }, + { + "property": "VehicleProperty::STEERING_WHEEL_EASY_ACCESS_ENABLED", + "defaultValue": { + "int32Values": [ + 0 + ] + } + }, + { + "property": "VehicleProperty::GLOVE_BOX_DOOR_POS", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_RIGHT", + "minInt32Value": 0, + "maxInt32Value": 10 + } + ] + }, + { + "property": "VehicleProperty::GLOVE_BOX_LOCKED", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_RIGHT" + } + ] + }, + { + "property": "VehicleProperty::WHEEL_TICK", + "defaultValue": { + "int64Values": [ + 0, + 100000, + 200000, + 300000, + 400000 + ] + }, + "configArray": [ + 15, + 50000, + 50000, + 50000, + 50000 + ], + "maxSampleRate": 10.0, + "minSampleRate": 1.0 + }, + { + "property": "VehicleProperty::ABS_ACTIVE", + "defaultValue": { + "int32Values": [ + 0 + ] + } + }, + { + "property": "VehicleProperty::TRACTION_CONTROL_ACTIVE", + "defaultValue": { + "int32Values": [ + 0 + ] + } + }, + { + "property": "VehicleProperty::AP_POWER_STATE_REQ", + "configArray": [ + 0 + ] + }, + { + "property": "VehicleProperty::AP_POWER_STATE_REPORT", + "defaultValue": { + "int32Values": [ + "VehicleApPowerStateReport::WAIT_FOR_VHAL", + 0 + ] + } + }, + { + "property": "VehicleProperty::AP_POWER_BOOTUP_REASON", + "defaultValue": { + "int32Values": [ + "VehicleApPowerBootupReason::USER_POWER_ON" + ] + } + }, + { + "property": "VehicleProperty::PER_DISPLAY_BRIGHTNESS" + }, + { + "property": "VehicleProperty::PER_DISPLAY_MAX_BRIGHTNESS", + "defaultValue": { + "int32Values": [ + 0, + 100, + 1, + 100, + 2, + 100, + 3, + 100 + ] + } + }, + { + "property": "VehicleProperty::VALET_MODE_ENABLED", + "defaultValue": { + "int32Values": [ + 0 + ] + } + }, + { + "property": "VehicleProperty::HEAD_UP_DISPLAY_ENABLED", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT" + } + ] + }, + { + "property": "VehicleProperty::OBD2_LIVE_FRAME", + "configArray": [ + 0, + 0 + ] + }, + { + "property": "VehicleProperty::OBD2_FREEZE_FRAME", + "configArray": [ + 0, + 0 + ] + }, + { + "property": "VehicleProperty::OBD2_FREEZE_FRAME_INFO" + }, + { + "property": "VehicleProperty::OBD2_FREEZE_FRAME_CLEAR", + "configArray": [ + 1 + ] + }, + { + "property": "VehicleProperty::HEADLIGHTS_STATE", + "defaultValue": { + "int32Values": [ + "Constants::LIGHT_STATE_ON" + ] + } + }, + { + "property": "VehicleProperty::HIGH_BEAM_LIGHTS_STATE", + "defaultValue": { + "int32Values": [ + "Constants::LIGHT_STATE_ON" + ] + } + }, + { + "property": "VehicleProperty::FRONT_FOG_LIGHTS_STATE", + "defaultValue": { + "int32Values": [ + "Constants::LIGHT_STATE_ON" + ] + } + }, + { + "property": "VehicleProperty::REAR_FOG_LIGHTS_STATE", + "defaultValue": { + "int32Values": [ + "Constants::LIGHT_STATE_ON" + ] + } + }, + { + "property": "VehicleProperty::HAZARD_LIGHTS_STATE", + "defaultValue": { + "int32Values": [ + "Constants::LIGHT_STATE_ON" + ] + } + }, + { + "property": "VehicleProperty::CABIN_LIGHTS_STATE", + "defaultValue": { + "int32Values": [ + "Constants::LIGHT_STATE_ON" + ] + } + }, + { + "property": "VehicleProperty::READING_LIGHTS_STATE", + "defaultValue": { + "int32Values": [ + "Constants::LIGHT_STATE_ON" + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT" + }, + { + "areaId": "Constants::SEAT_1_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_LEFT" + }, + { + "areaId": "Constants::SEAT_2_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_CENTER" + } + ] + }, + { + "property": "VehicleProperty::STEERING_WHEEL_LIGHTS_STATE", + "defaultValue": { + "int32Values": [ + "Constants::LIGHT_STATE_ON" + ] + }, + "areas": [ + { + "areaId": 0, + "supportedEnumValues": [ + "Constants::LIGHT_STATE_OFF", + "Constants::LIGHT_STATE_ON" + ] + } + ] + }, + { + "property": "VehicleProperty::HEADLIGHTS_SWITCH", + "defaultValue": { + "int32Values": [ + "Constants::LIGHT_SWITCH_AUTO" + ] + } + }, + { + "property": "VehicleProperty::HIGH_BEAM_LIGHTS_SWITCH", + "defaultValue": { + "int32Values": [ + "Constants::LIGHT_SWITCH_AUTO" + ] + } + }, + { + "property": "VehicleProperty::FRONT_FOG_LIGHTS_SWITCH", + "defaultValue": { + "int32Values": [ + "Constants::LIGHT_SWITCH_AUTO" + ] + } + }, + { + "property": "VehicleProperty::REAR_FOG_LIGHTS_SWITCH", + "defaultValue": { + "int32Values": [ + "Constants::LIGHT_SWITCH_AUTO" + ] + } + }, + { + "property": "VehicleProperty::HAZARD_LIGHTS_SWITCH", + "defaultValue": { + "int32Values": [ + "Constants::LIGHT_SWITCH_AUTO" + ] + } + }, + { + "property": "VehicleProperty::CABIN_LIGHTS_SWITCH", + "defaultValue": { + "int32Values": [ + "Constants::LIGHT_SWITCH_OFF" + ] + } + }, + { + "property": "VehicleProperty::READING_LIGHTS_SWITCH", + "defaultValue": { + "int32Values": [ + "Constants::LIGHT_SWITCH_OFF" + ] + }, + "areas": [ + { + "areaId": "Constants::SEAT_1_LEFT" + }, + { + "areaId": "Constants::SEAT_1_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_LEFT" + }, + { + "areaId": "Constants::SEAT_2_RIGHT" + }, + { + "areaId": "Constants::SEAT_2_CENTER" + } + ] + }, + { + "property": "VehicleProperty::STEERING_WHEEL_LIGHTS_SWITCH", + "defaultValue": { + "int32Values": [ + "Constants::LIGHT_SWITCH_AUTO" + ] + }, + "areas": [ + { + "areaId": 0, + "supportedEnumValues": [ + "Constants::LIGHT_SWITCH_OFF", + "Constants::LIGHT_SWITCH_ON", + "Constants::LIGHT_SWITCH_AUTO" + ] + } + ] + }, + { + "property": "VehicleProperty::EVS_SERVICE_REQUEST", + "defaultValue": { + "int32Values": [ + "EvsServiceType::REARVIEW", + "EvsServiceState::OFF" + ] + } + }, + { + "property": "VehicleProperty::VEHICLE_MAP_SERVICE" + }, + { + "property": "VehicleProperty::LOCATION_CHARACTERIZATION", + "defaultValue": { + "int32Values": [ + "LocationCharacterization::RAW_GNSS_ONLY" + ] + } + }, + { + "property": "VehicleProperty::ULTRASONICS_SENSOR_POSITION", + "comment": + "Default values for 12 individual ultrasonic sensors installed on the vehicle. Six sensors on the front bumper. Six sensors on the back bumper.", + "areas": [ + { + "defaultValue": { + "int32Values": [ + -1000, + 3900, + 0 + ] + }, + "areaId": 1, + "comment": "Rough numbers representing front left most sensor." + }, + { + "defaultValue": { + "int32Values": [ + -600, + 4000, + 0 + ] + }, + "areaId": 2, + "comment": "Rough numbers representing front 2nd to the left sensor." + }, + { + "defaultValue": { + "int32Values": [ + -200, + 4000, + 0 + ] + }, + "areaId": 4, + "comment": "Rough numbers representing front 3rd to the left sensor." + }, + { + "defaultValue": { + "int32Values": [ + 200, + 4000, + 0 + ] + }, + "areaId": 8, + "comment": "Rough numbers representing front 3rd to the right sensor." + }, + { + "defaultValue": { + "int32Values": [ + 600, + 4000, + 0 + ] + }, + "areaId": 16, + "comment": "Rough numbers representing front 2nd to the right sensor." + }, + { + "defaultValue": { + "int32Values": [ + 1000, + 3900, + 0 + ] + }, + "areaId": 32, + "comment": "Rough numbers representing front right most sensor." + }, + { + "defaultValue": { + "int32Values": [ + -1000, + -900, + 0 + ] + }, + "areaId": 64, + "comment": "Rough numbers representing back left most sensor." + }, + { + "defaultValue": { + "int32Values": [ + -600, + -1000, + 0 + ] + }, + "areaId": 128, + "comment": "Rough numbers representing back 2nd to the left sensor." + }, + { + "defaultValue": { + "int32Values": [ + -200, + -1000, + 0 + ] + }, + "areaId": 256, + "comment": "Rough numbers representing back 3rd to the left sensor." + }, + { + "defaultValue": { + "int32Values": [ + 200, + -1000, + 0 + ] + }, + "areaId": 512, + "comment": "Rough numbers representing back 3rd to the right sensor." + }, + { + "defaultValue": { + "int32Values": [ + 600, + -1000, + 0 + ] + }, + "areaId": 1024, + "comment": "Rough numbers representing back 2nd to the right sensor." + }, + { + "defaultValue": { + "int32Values": [ + 1000, + -900, + 0 + ] + }, + "areaId": 2048, + "comment": "Rough numbers representing back right most sensor." + } + ] + }, + { + "property": "VehicleProperty::ULTRASONICS_SENSOR_ORIENTATION", + "comment": + "Default values for 12 individual ultrasonic sensors installed on the vehicle. Six sensors on the front bumper. Six sensors on the back bumper.", + "areas": [ + { + "defaultValue": { + "floatValues": [ + 0.924, + 0, + 0, + 0.383 + ] + }, + "areaId": 1, + "comment": + "Rough quaternion values [w, x, y, z] representing front left most sensor rotated 45 degrees counter-clockwise." + }, + { + "defaultValue": { + "floatValues": [ + 1, + 0, + 0, + 0 + ] + }, + "areaId": 2, + "comment": + "Rough quaternion values [w, x, y, z] representing front 2nd to the left sensor rotated 0 degrees" + }, + { + "defaultValue": { + "floatValues": [ + 1, + 0, + 0, + 0 + ] + }, + "areaId": 4, + "comment": + "Rough quaternion values [w, x, y, z] representing front 3rd to the left sensor rotated 0 degrees" + }, + { + "defaultValue": { + "floatValues": [ + 1, + 0, + 0, + 0 + ] + }, + "areaId": 8, + "comment": + "Rough quaternion values [w, x, y, z] representing front 3rd to the right sensor rotated 0 degrees" + }, + { + "defaultValue": { + "floatValues": [ + 1, + 0, + 0, + 0 + ] + }, + "areaId": 16, + "comment": + "Rough quaternion values [w, x, y, z] representing front 2nd to the right sensor rotated 0 degrees" + }, + { + "defaultValue": { + "floatValues": [ + 0.924, + 0, + 0, + -0.383 + ] + }, + "areaId": 32, + "comment": + "Rough quaternion values [w, x, y, z] representing front right most sensor rotated 45 degrees clockwise." + }, + { + "defaultValue": { + "floatValues": [ + 60, + 61, + 62, + 63 + ] + }, + "areaId": 64, + "comment": + "Rough quaternion values [w, x, y, z] representing back left most sensor rotated 45 degrees counter-clockwise." + }, + { + "defaultValue": { + "floatValues": [ + 70, + 71, + 72, + 73 + ] + }, + "areaId": 128, + "comment": + "Rough quaternion values [w, x, y, z] representing back 2nd to the left sensor rotated 0 degrees" + }, + { + "defaultValue": { + "floatValues": [ + 81, + 82, + 83, + 84 + ] + }, + "areaId": 256, + "comment": + "Rough quaternion values [w, x, y, z] representing back 3rd to the right sensor rotated 0 degrees" + }, + { + "defaultValue": { + "floatValues": [ + 90, + 91, + 92, + 93 + ] + }, + "areaId": 512, + "comment": + "Rough quaternion values [w, x, y, z] representing back 3rd to the right sensor rotated 0 degrees" + }, + { + "defaultValue": { + "floatValues": [ + 100, + 101, + 102, + 103 + ] + }, + "areaId": 1024, + "comment": + "Rough quaternion values [w, x, y, z] representing back 2nd to the right sensor rotated 0 degrees" + }, + { + "defaultValue": { + "floatValues": [ + 110, + 111, + 112, + 113 + ] + }, + "areaId": 2048, + "comment": + "Rough quaternion values [w, x, y, z] representing back right most sensor rotated 45 degrees clockwise." + } + ] + }, + { + "property": "VehicleProperty::ULTRASONICS_SENSOR_FIELD_OF_VIEW", + "comment": + "Default values for 12 individual ultrasonic sensors installed on the vehicle. Six sensors on the front bumper. Six sensors on the back bumper.", + "areas": [ + { + "defaultValue": { + "int32Values": [ + 85, + 45 + ] + }, + "areaId": 1, + "comment": "Rough values representing front left most sensor." + }, + { + "defaultValue": { + "int32Values": [ + 75, + 45 + ] + }, + "areaId": 2, + "comment": "Rough values representing front 2nd to the left sensor." + }, + { + "defaultValue": { + "int32Values": [ + 75, + 45 + ] + }, + "areaId": 4, + "comment": "Rough values representing front 3rd to the left sensor." + }, + { + "defaultValue": { + "int32Values": [ + 75, + 45 + ] + }, + "areaId": 8, + "comment": "Rough values representing front 3rd to the right sensor." + }, + { + "defaultValue": { + "int32Values": [ + 75, + 45 + ] + }, + "areaId": 16, + "comment": "Rough values representing front 2nd to the right sensor." + }, + { + "defaultValue": { + "int32Values": [ + 85, + 45 + ] + }, + "areaId": 32, + "comment": "Rough values representing front right most sensor." + }, + { + "defaultValue": { + "int32Values": [ + 85, + 45 + ] + }, + "areaId": 64, + "comment": "Rough values representing back left most sensor." + }, + { + "defaultValue": { + "int32Values": [ + 75, + 45 + ] + }, + "areaId": 128, + "comment": "Rough values representing back 2nd to the left sensor." + }, + { + "defaultValue": { + "int32Values": [ + 75, + 45 + ] + }, + "areaId": 256, + "comment": "Rough values representing back 3rd to the left sensor." + }, + { + "defaultValue": { + "int32Values": [ + 75, + 45 + ] + }, + "areaId": 512, + "comment": "Rough values representing back 3rd to the right sensor." + }, + { + "defaultValue": { + "int32Values": [ + 75, + 45 + ] + }, + "areaId": 1024, + "comment": "Rough values representing back 2nd to the right sensor." + }, + { + "defaultValue": { + "int32Values": [ + 85, + 45 + ] + }, + "areaId": 2048, + "comment": "Rough values representing back right most sensor." + } + ] + }, + { + "property": "VehicleProperty::ULTRASONICS_SENSOR_DETECTION_RANGE", + "areas": [ + { + "defaultValue": { + "int32Values": [ + 150, + 4000 + ] + }, + "areaId": 1, + "comment": "Rough values representing front left most sensor." + }, + { + "defaultValue": { + "int32Values": [ + 150, + 3000 + ] + }, + "areaId": 2, + "comment": "Rough values representing front 2nd to the left sensor." + }, + { + "defaultValue": { + "int32Values": [ + 150, + 3000 + ] + }, + "areaId": 4, + "comment": "Rough values representing front 3rd to the left sensor." + }, + { + "defaultValue": { + "int32Values": [ + 150, + 3000 + ] + }, + "areaId": 8, + "comment": "Rough values representing front 3rd to the right sensor." + }, + { + "defaultValue": { + "int32Values": [ + 150, + 3000 + ] + }, + "areaId": 16, + "comment": "Rough values representing front 2nd to the right sensor." + }, + { + "defaultValue": { + "int32Values": [ + 150, + 4000 + ] + }, + "areaId": 32, + "comment": "Rough values representing front right most sensor." + }, + { + "defaultValue": { + "int32Values": [ + 150, + 4000 + ] + }, + "areaId": 64, + "comment": "Rough values representing back left most sensor." + }, + { + "defaultValue": { + "int32Values": [ + 150, + 3000 + ] + }, + "areaId": 128, + "comment": "Rough values representing back 2nd to the left sensor." + }, + { + "defaultValue": { + "int32Values": [ + 150, + 3000 + ] + }, + "areaId": 256, + "comment": "Rough values representing back 3rd to the left sensor." + }, + { + "defaultValue": { + "int32Values": [ + 150, + 3000 + ] + }, + "areaId": 512, + "comment": "Rough values representing back 3rd to the right sensor." + }, + { + "defaultValue": { + "int32Values": [ + 150, + 3000 + ] + }, + "areaId": 1024, + "comment": "Rough values representing back 2nd to the right sensor." + }, + { + "defaultValue": { + "int32Values": [ + 150, + 4000 + ] + }, + "areaId": 2048, + "comment": "Rough values representing back right most sensor." + } + ] + }, + { + "property": "VehicleProperty::ULTRASONICS_SENSOR_SUPPORTED_RANGES", + "areas": [ + { + "defaultValue": { + "int32Values": [ + 150, + 999, + 1000, + 1999, + 2000, + 4000 + ] + }, + "areaId": 1, + "comment": "Rough values representing front left most sensor." + }, + { + "defaultValue": { + "int32Values": [ + 150, + 999, + 1000, + 1999, + 2000, + 3000 + ] + }, + "areaId": 2, + "comment": "Rough values representing front 2nd to the left sensor." + }, + { + "defaultValue": { + "int32Values": [ + 150, + 999, + 1000, + 1999, + 2000, + 3000 + ] + }, + "areaId": 4, + "comment": "Rough values representing front 3rd to the left sensor." + }, + { + "defaultValue": { + "int32Values": [ + 150, + 999, + 1000, + 1999, + 2000, + 3000 + ] + }, + "areaId": 8, + "comment": "Rough values representing front 3rd to the right sensor." + }, + { + "defaultValue": { + "int32Values": [ + 150, + 999, + 1000, + 1999, + 2000, + 3000 + ] + }, + "areaId": 16, + "comment": "Rough values representing front 2nd to the right sensor." + }, + { + "defaultValue": { + "int32Values": [ + 150, + 999, + 1000, + 1999, + 2000, + 4000 + ] + }, + "areaId": 32, + "comment": "Rough values representing front right most sensor." + }, + { + "defaultValue": { + "int32Values": [ + 150, + 999, + 1000, + 1999, + 2000, + 4000 + ] + }, + "areaId": 64, + "comment": "Rough values representing back left most sensor." + }, + { + "defaultValue": { + "int32Values": [ + 150, + 999, + 1000, + 1999, + 2000, + 3000 + ] + }, + "areaId": 128, + "comment": "Rough values representing back 2nd to the left sensor." + }, + { + "defaultValue": { + "int32Values": [ + 150, + 999, + 1000, + 3000 + ] + }, + "areaId": 256, + "comment": "Rough values representing back 3rd to the left sensor." + }, + { + "defaultValue": { + "int32Values": [ + 150, + 999, + 1000, + 3000 + ] + }, + "areaId": 512, + "comment": "Rough values representing back 3rd to the right sensor." + }, + { + "defaultValue": { + "int32Values": [ + 150, + 999, + 1000, + 1999, + 2000, + 3000 + ] + }, + "areaId": 1024, + "comment": "Rough values representing back 2nd to the right sensor." + }, + { + "defaultValue": { + "int32Values": [ + 150, + 999, + 1000, + 1999, + 2000, + 4000 + ] + }, + "areaId": 2048, + "comment": "Rough values representing back right most sensor." + } + ] + }, + { + "property": "VehicleProperty::ULTRASONICS_SENSOR_MEASURED_DISTANCE", + "areas": [ + { + "defaultValue": { + "int32Values": [ + 2000, + 10 + ] + }, + "areaId": 1, + "comment": "Rough values representing front left most sensor." + }, + { + "defaultValue": { + "int32Values": [] + }, + "areaId": 2, + "comment": + "Rough values representing front 2nd to the left sensor. Nothing detected." + }, + { + "defaultValue": { + "int32Values": [] + }, + "areaId": 4, + "comment": + "Rough values representing front 3rd to the left sensor. Nothing detected." + }, + { + "defaultValue": { + "int32Values": [] + }, + "areaId": 8, + "comment": + "Rough values representing front 3rd to the right sensor. Nothing detected." + }, + { + "defaultValue": { + "int32Values": [] + }, + "areaId": 16, + "comment": + "Rough values representing front 2nd to the right sensor. Nothing detected." + }, + { + "defaultValue": { + "int32Values": [] + }, + "areaId": 32, + "comment": + "Rough values representing front right most sensor. Nothing detected." + }, + { + "defaultValue": { + "int32Values": [] + }, + "areaId": 64, + "comment": "Rough values representing back left most sensor. Nothing detected." + }, + { + "defaultValue": { + "int32Values": [] + }, + "areaId": 128, + "comment": + "Rough values representing back 2nd to the left sensor. Nothing detected." + }, + { + "defaultValue": { + "int32Values": [] + }, + "areaId": 256, + "comment": + "Rough values representing back 3rd to the left sensor. Nothing detected." + }, + { + "defaultValue": { + "int32Values": [ + 1000 + ] + }, + "areaId": 512, + "comment": + "Rough values representing back 3rd to the right sensor. Nothing detected." + }, + { + "defaultValue": { + "int32Values": [ + 2000, + 50 + ] + }, + "areaId": 1024, + "comment": "Rough values representing back 2nd to the right sensor." + }, + { + "defaultValue": { + "int32Values": [ + 2000 + ] + }, + "areaId": 2048, + "comment": + "Rough values representing back right most sensor. No distance error." + } + ], + "maxSampleRate": 10.0, + "minSampleRate": 1.0 + }, + { + "property": "VehicleProperty::ELECTRONIC_TOLL_COLLECTION_CARD_TYPE", + "defaultValue": { + "int32Values": [ + 0 + ] + } + }, + { + "property": "VehicleProperty::ELECTRONIC_TOLL_COLLECTION_CARD_STATUS", + "defaultValue": { + "int32Values": [ + 0 + ] + } + }, + { + "property": "VehicleProperty::EMERGENCY_LANE_KEEP_ASSIST_ENABLED", + "defaultValue": { + "int32Values": [ + 1 + ] + } + }, + { + "property": "VehicleProperty::EMERGENCY_LANE_KEEP_ASSIST_STATE", + "defaultValue": { + "int32Values": [ + "EmergencyLaneKeepAssistState::ENABLED" + ] + }, + "areas": [ + { + "areaId": 0, + "supportedEnumValues": [ + "ErrorState::NOT_AVAILABLE_SAFETY", + "ErrorState::NOT_AVAILABLE_SPEED_HIGH", + "ErrorState::NOT_AVAILABLE_SPEED_LOW", + "ErrorState::NOT_AVAILABLE_DISABLED", + "EmergencyLaneKeepAssistState::ENABLED", + "EmergencyLaneKeepAssistState::WARNING_LEFT", + "EmergencyLaneKeepAssistState::WARNING_RIGHT", + "EmergencyLaneKeepAssistState::ACTIVATED_STEER_LEFT", + "EmergencyLaneKeepAssistState::ACTIVATED_STEER_RIGHT", + "EmergencyLaneKeepAssistState::USER_OVERRIDE" + ] + } + ] + }, + { + "property": "VehicleProperty::CRUISE_CONTROL_ENABLED", + "defaultValue": { + "int32Values": [ + 1 + ] + } + }, + { + "property": "VehicleProperty::CRUISE_CONTROL_TYPE", + "defaultValue": { + "int32Values": [ + "CruiseControlType::ADAPTIVE" + ] + }, + "areas": [ + { + "areaId": 0, + "supportedEnumValues": [ + "ErrorState::NOT_AVAILABLE_SAFETY", + "ErrorState::NOT_AVAILABLE_SPEED_HIGH", + "ErrorState::NOT_AVAILABLE_SPEED_LOW", + "ErrorState::NOT_AVAILABLE_DISABLED", + "CruiseControlType::STANDARD", + "CruiseControlType::ADAPTIVE", + "CruiseControlType::PREDICTIVE" + ] + } + ] + }, + { + "property": "VehicleProperty::CRUISE_CONTROL_STATE", + "defaultValue": { + "int32Values": [ + "CruiseControlState::ENABLED" + ] + }, + "areas": [ + { + "areaId": 0, + "supportedEnumValues": [ + "ErrorState::NOT_AVAILABLE_SAFETY", + "ErrorState::NOT_AVAILABLE_SPEED_HIGH", + "ErrorState::NOT_AVAILABLE_SPEED_LOW", + "ErrorState::NOT_AVAILABLE_DISABLED", + "CruiseControlState::ENABLED", + "CruiseControlState::ACTIVATED", + "CruiseControlState::USER_OVERRIDE", + "CruiseControlState::SUSPENDED", + "CruiseControlState::FORCED_DEACTIVATION_WARNING" + ] + } + ] + }, + { + "property": "VehicleProperty::CRUISE_CONTROL_COMMAND", + "areas": [ + { + "areaId": 0, + "supportedEnumValues": [ + "CruiseControlCommand::ACTIVATE", + "CruiseControlCommand::SUSPEND", + "CruiseControlCommand::INCREASE_TARGET_SPEED", + "CruiseControlCommand::DECREASE_TARGET_SPEED", + "CruiseControlCommand::INCREASE_TARGET_TIME_GAP", + "CruiseControlCommand::DECREASE_TARGET_TIME_GAP" + ] + } + ] + }, + { + "property": "VehicleProperty::CRUISE_CONTROL_TARGET_SPEED", + "defaultValue": { + "floatValues": [ + 25.0 + ] + }, + "areas": [ + { + "areaId": 0, + "minFloatValue": 20.0, + "maxFloatValue": 35.0 + } + ] + }, + { + "property": "VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP", + "defaultValue": { + "int32Values": [ + 1200 + ] + }, + "configArray": [ + 1200, + 1400, + 1600, + 1800, + 2000, + 2200 + ] + }, + { + "property": "VehicleProperty::ADAPTIVE_CRUISE_CONTROL_LEAD_VEHICLE_MEASURED_DISTANCE", + "defaultValue": { + "int32Values": [ + 100000 + ] + }, + "areas": [ + { + "areaId": 0, + "minInt32Value": 0, + "maxInt32Value": 200000 + } + ], + "maxSampleRate": 10.0, + "minSampleRate": 1.0 + }, + { + "property": "VehicleProperty::HANDS_ON_DETECTION_ENABLED", + "defaultValue": { + "int32Values": [ + 1 + ] + } + }, + { + "property": "VehicleProperty::HANDS_ON_DETECTION_DRIVER_STATE", + "defaultValue": { + "int32Values": [ + "HandsOnDetectionDriverState::HANDS_ON" + ] + }, + "areas": [ + { + "areaId": 0, + "supportedEnumValues": [ + "ErrorState::NOT_AVAILABLE_DISABLED", + "HandsOnDetectionDriverState::HANDS_ON", + "HandsOnDetectionDriverState::HANDS_OFF" + ] + } + ] + }, + { + "property": "VehicleProperty::HANDS_ON_DETECTION_WARNING", + "defaultValue": { + "int32Values": [ + "HandsOnDetectionWarning::NO_WARNING" + ] + }, + "areas": [ + { + "areaId": 0, + "supportedEnumValues": [ + "ErrorState::NOT_AVAILABLE_DISABLED", + "HandsOnDetectionWarning::NO_WARNING", + "HandsOnDetectionWarning::WARNING" + ] + } + ] + }, + { + "property": "VehicleProperty::DRIVER_DROWSINESS_ATTENTION_SYSTEM_ENABLED", + "defaultValue": { + "int32Values": [ + 1 + ] + } + }, + { + "property": "VehicleProperty::DRIVER_DROWSINESS_ATTENTION_STATE", + "defaultValue": { + "int32Values": [ + "DriverDrowsinessAttentionState::KSS_RATING_3_ALERT" + ] + }, + "areas": [ + { + "areaId": 0, + "supportedEnumValues": [ + "ErrorState::NOT_AVAILABLE_DISABLED", + "DriverDrowsinessAttentionState::KSS_RATING_1_EXTREMELY_ALERT", + "DriverDrowsinessAttentionState::KSS_RATING_2_VERY_ALERT", + "DriverDrowsinessAttentionState::KSS_RATING_3_ALERT", + "DriverDrowsinessAttentionState::KSS_RATING_4_RATHER_ALERT", + "DriverDrowsinessAttentionState::KSS_RATING_5_NEITHER_ALERT_NOR_SLEEPY", + "DriverDrowsinessAttentionState::KSS_RATING_6_SOME_SLEEPINESS", + "DriverDrowsinessAttentionState::KSS_RATING_7_SLEEPY_NO_EFFORT", + "DriverDrowsinessAttentionState::KSS_RATING_8_SLEEPY_SOME_EFFORT", + "DriverDrowsinessAttentionState::KSS_RATING_9_VERY_SLEEPY" + ] + } + ] + }, + { + "property": "VehicleProperty::DRIVER_DROWSINESS_ATTENTION_WARNING_ENABLED", + "defaultValue": { + "int32Values": [ + 1 + ] + } + }, + { + "property": "VehicleProperty::DRIVER_DROWSINESS_ATTENTION_WARNING", + "defaultValue": { + "int32Values": [ + "DriverDrowsinessAttentionWarning::NO_WARNING" + ] + }, + "areas": [ + { + "areaId": 0, + "supportedEnumValues": [ + "ErrorState::NOT_AVAILABLE_DISABLED", + "DriverDrowsinessAttentionWarning::NO_WARNING", + "DriverDrowsinessAttentionWarning::WARNING" + ] + } + ] + }, + { + "property": "VehicleProperty::DRIVER_DISTRACTION_SYSTEM_ENABLED", + "defaultValue": { + "int32Values": [ + 1 + ] + } + }, + { + "property": "VehicleProperty::DRIVER_DISTRACTION_STATE", + "defaultValue": { + "int32Values": [ + "DriverDistractionState::NOT_DISTRACTED" + ] + }, + "areas": [ + { + "areaId": 0, + "supportedEnumValues": [ + "ErrorState::NOT_AVAILABLE_DISABLED", + "DriverDistractionState::NOT_DISTRACTED", + "DriverDistractionState::DISTRACTED" + ] + } + ] + }, + { + "property": "VehicleProperty::DRIVER_DISTRACTION_WARNING_ENABLED", + "defaultValue": { + "int32Values": [ + 1 + ] + } + }, + { + "property": "VehicleProperty::DRIVER_DISTRACTION_WARNING", + "defaultValue": { + "int32Values": [ + "DriverDistractionWarning::NO_WARNING" + ] + }, + "areas": [ + { + "areaId": 0, + "supportedEnumValues": [ + "ErrorState::NOT_AVAILABLE_DISABLED", + "DriverDistractionWarning::NO_WARNING", + "DriverDistractionWarning::WARNING" + ] + } + ] + }, + { + "property": "VehicleProperty::INITIAL_USER_INFO" + }, + { + "property": "VehicleProperty::SWITCH_USER" + }, + { + "property": "VehicleProperty::CREATE_USER" + }, + { + "property": "VehicleProperty::REMOVE_USER" + }, + { + "property": "VehicleProperty::USER_IDENTIFICATION_ASSOCIATION" + }, + { + "property": "VehicleProperty::POWER_POLICY_REQ" + }, + { + "property": "VehicleProperty::POWER_POLICY_GROUP_REQ" + }, + { + "property": "VehicleProperty::CURRENT_POWER_POLICY" + }, + { + "property": "VehicleProperty::ANDROID_EPOCH_TIME" + }, + { + "property": "VehicleProperty::WATCHDOG_ALIVE" + }, + { + "property": "VehicleProperty::WATCHDOG_TERMINATED_PROCESS" + }, + { + "property": "VehicleProperty::VHAL_HEARTBEAT", + "areas": [ + { + "areaId": 0, + "supportVariableUpdateRate": false + } + ] + }, + { + "property": "VehicleProperty::CLUSTER_SWITCH_UI", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "comment": "0 means ClusterHome" + }, + { + "property": "VehicleProperty::CLUSTER_DISPLAY_STATE", + "defaultValue": { + "int32Values": [ + 0, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1 + ] + }, + "comment": + "Value means: 0 /* Off */, -1, -1, -1, -1 /* Bounds */, -1, -1, -1, -1 /* Insets */" + }, + { + "property": "VehicleProperty::CLUSTER_REPORT_STATE", + "configArray": [ + 0, + 0, + 0, + 11, + 0, + 0, + 0, + 0, + 16 + ] + }, + { + "property": "VehicleProperty::CLUSTER_REQUEST_DISPLAY" + }, + { + "property": "VehicleProperty::CLUSTER_NAVIGATION_STATE" + }, + { + "property": "VehicleProperty::CLUSTER_HEARTBEAT", + "configArray": [ + 0, + 0, + 0, + 0, + 0, + 2, + 0, + 0, + 16 + ], + "areas": [ + { + "areaId": 0, + "supportVariableUpdateRate": false + } + ], + "comment": "configArray specifies it consists of int64[2] and byte[16]." + }, + { + "property": "VehicleProperty::GENERAL_SAFETY_REGULATION_COMPLIANCE_REQUIREMENT", + "defaultValue": { + "int32Values": [ + "GsrComplianceRequirementType::GSR_COMPLIANCE_REQUIRED_V1" + ] + } + }, + { + "property": "VehicleProperty::SHUTDOWN_REQUEST" + }, + { + "property": "VehicleProperty::VEHICLE_IN_USE", + "defaultValue": { + "int32Values": [ + 1 + ] + } + }, + { + "property": "VehicleProperty::VEHICLE_DRIVING_AUTOMATION_CURRENT_LEVEL", + "defaultValue": { + "int32Values": [ + "VehicleAutonomousState::LEVEL_0" + ] + } + }, + { + "property": "VehicleProperty::VEHICLE_DRIVING_AUTOMATION_TARGET_LEVEL", + "defaultValue": { + "int32Values": [ + "VehicleAutonomousState::LEVEL_0" + ] + } + }, + { + "property": "VehicleProperty::AUTOMATIC_EMERGENCY_BRAKING_ENABLED", + "defaultValue": { + "int32Values": [ + 0 + ] + } + }, + { + "property": "VehicleProperty::AUTOMATIC_EMERGENCY_BRAKING_STATE", + "defaultValue": { + "int32Values": [ + "ErrorState::NOT_AVAILABLE_DISABLED" + ] + }, + "areas": [ + { + "areaId": 0, + "supportedEnumValues": [ + "ErrorState::NOT_AVAILABLE_SAFETY", + "ErrorState::NOT_AVAILABLE_POOR_VISIBILITY", + "ErrorState::NOT_AVAILABLE_SPEED_HIGH", + "ErrorState::NOT_AVAILABLE_SPEED_LOW", + "ErrorState::NOT_AVAILABLE_DISABLED", + "AutomaticEmergencyBrakingState::ENABLED", + "AutomaticEmergencyBrakingState::ACTIVATED", + "AutomaticEmergencyBrakingState::USER_OVERRIDE" + ] + } + ] + }, + { + "property": "VehicleProperty::FORWARD_COLLISION_WARNING_ENABLED", + "defaultValue": { + "int32Values": [ + 1 + ] + } + }, + { + "property": "VehicleProperty::FORWARD_COLLISION_WARNING_STATE", + "defaultValue": { + "int32Values": [ + "ForwardCollisionWarningState::NO_WARNING" + ] + }, + "areas": [ + { + "areaId": 0, + "supportedEnumValues": [ + "ErrorState::NOT_AVAILABLE_SAFETY", + "ErrorState::NOT_AVAILABLE_POOR_VISIBILITY", + "ErrorState::NOT_AVAILABLE_SPEED_HIGH", + "ErrorState::NOT_AVAILABLE_SPEED_LOW", + "ErrorState::NOT_AVAILABLE_DISABLED", + "ForwardCollisionWarningState::NO_WARNING", + "ForwardCollisionWarningState::WARNING" + ] + } + ] + }, + { + "property": "VehicleProperty::BLIND_SPOT_WARNING_ENABLED", + "defaultValue": { + "int32Values": [ + 1 + ] + } + }, + { + "property": "VehicleProperty::BLIND_SPOT_WARNING_STATE", + "defaultValue": { + "int32Values": [ + "BlindSpotWarningState::NO_WARNING" + ] + }, + "areas": [ + { + "areaId": "VehicleAreaMirror::DRIVER_LEFT", + "supportedEnumValues": [ + "ErrorState::NOT_AVAILABLE_SAFETY", + "ErrorState::NOT_AVAILABLE_POOR_VISIBILITY", + "ErrorState::NOT_AVAILABLE_SPEED_HIGH", + "ErrorState::NOT_AVAILABLE_SPEED_LOW", + "ErrorState::NOT_AVAILABLE_DISABLED", + "BlindSpotWarningState::NO_WARNING", + "BlindSpotWarningState::WARNING" + ] + }, + { + "areaId": "VehicleAreaMirror::DRIVER_RIGHT", + "supportedEnumValues": [ + "ErrorState::NOT_AVAILABLE_SAFETY", + "ErrorState::NOT_AVAILABLE_POOR_VISIBILITY", + "ErrorState::NOT_AVAILABLE_SPEED_HIGH", + "ErrorState::NOT_AVAILABLE_SPEED_LOW", + "ErrorState::NOT_AVAILABLE_DISABLED", + "BlindSpotWarningState::NO_WARNING", + "BlindSpotWarningState::WARNING" + ] + } + ] + }, + { + "property": "VehicleProperty::LANE_DEPARTURE_WARNING_ENABLED", + "defaultValue": { + "int32Values": [ + 1 + ] + } + }, + { + "property": "VehicleProperty::LANE_DEPARTURE_WARNING_STATE", + "defaultValue": { + "int32Values": [ + "LaneDepartureWarningState::NO_WARNING" + ] + }, + "areas": [ + { + "areaId": 0, + "supportedEnumValues": [ + "ErrorState::NOT_AVAILABLE_SAFETY", + "ErrorState::NOT_AVAILABLE_SPEED_HIGH", + "ErrorState::NOT_AVAILABLE_SPEED_LOW", + "ErrorState::NOT_AVAILABLE_DISABLED", + "LaneDepartureWarningState::NO_WARNING", + "LaneDepartureWarningState::WARNING_LEFT", + "LaneDepartureWarningState::WARNING_RIGHT" + ] + } + ] + }, + { + "property": "VehicleProperty::LANE_KEEP_ASSIST_ENABLED", + "defaultValue": { + "int32Values": [ + 1 + ] + } + }, + { + "property": "VehicleProperty::LANE_KEEP_ASSIST_STATE", + "defaultValue": { + "int32Values": [ + "LaneKeepAssistState::ENABLED" + ] + }, + "areas": [ + { + "areaId": 0, + "supportedEnumValues": [ + "ErrorState::NOT_AVAILABLE_SAFETY", + "ErrorState::NOT_AVAILABLE_SPEED_HIGH", + "ErrorState::NOT_AVAILABLE_SPEED_LOW", + "ErrorState::NOT_AVAILABLE_DISABLED", + "LaneKeepAssistState::ENABLED", + "LaneKeepAssistState::ACTIVATED_STEER_LEFT", + "LaneKeepAssistState::ACTIVATED_STEER_RIGHT", + "LaneKeepAssistState::USER_OVERRIDE" + ] + } + ] + }, + { + "property": "VehicleProperty::LANE_CENTERING_ASSIST_ENABLED", + "defaultValue": { + "int32Values": [ + 1 + ] + } + }, + { + "property": "VehicleProperty::LANE_CENTERING_ASSIST_COMMAND" + }, + { + "property": "VehicleProperty::LANE_CENTERING_ASSIST_STATE", + "defaultValue": { + "int32Values": [ + "LaneCenteringAssistState::ENABLED" + ] + }, + "areas": [ + { + "areaId": 0, + "supportedEnumValues": [ + "ErrorState::NOT_AVAILABLE_SAFETY", + "ErrorState::NOT_AVAILABLE_SPEED_HIGH", + "ErrorState::NOT_AVAILABLE_SPEED_LOW", + "ErrorState::NOT_AVAILABLE_DISABLED", + "LaneCenteringAssistState::ENABLED", + "LaneCenteringAssistState::ACTIVATION_REQUESTED", + "LaneCenteringAssistState::ACTIVATED", + "LaneCenteringAssistState::USER_OVERRIDE", + "LaneCenteringAssistState::FORCED_DEACTIVATION_WARNING" + ] + } + ] + }, + { + "property": "VehicleProperty::LOW_SPEED_COLLISION_WARNING_ENABLED", + "defaultValue": { + "int32Values": [ + 1 + ] + } + }, + { + "property": "VehicleProperty::LOW_SPEED_COLLISION_WARNING_STATE", + "defaultValue": { + "int32Values": [ + "LowSpeedCollisionWarningState::NO_WARNING" + ] + }, + "areas": [ + { + "areaId": 0, + "supportedEnumValues": [ + "ErrorState::NOT_AVAILABLE_SAFETY", + "ErrorState::NOT_AVAILABLE_POOR_VISIBILITY", + "ErrorState::NOT_AVAILABLE_SPEED_HIGH", + "ErrorState::NOT_AVAILABLE_DISABLED", + "LowSpeedCollisionWarningState::NO_WARNING", + "LowSpeedCollisionWarningState::WARNING" + ] + } + ] + }, + { + "property": "VehicleProperty::ELECTRONIC_STABILITY_CONTROL_ENABLED", + "defaultValue": { + "int32Values": [ + 1 + ] + } + }, + { + "property": "VehicleProperty::ELECTRONIC_STABILITY_CONTROL_STATE", + "defaultValue": { + "int32Values": [ + "ElectronicStabilityControlState::ENABLED" + ] + }, + "areas": [ + { + "areaId": 0, + "supportedEnumValues": [ + "ErrorState::NOT_AVAILABLE_SAFETY", + "ErrorState::NOT_AVAILABLE_SPEED_HIGH", + "ErrorState::NOT_AVAILABLE_SPEED_LOW", + "ErrorState::NOT_AVAILABLE_DISABLED", + "ElectronicStabilityControlState::ENABLED", + "ElectronicStabilityControlState::ACTIVATED" + ] + } + ] + }, + { + "property": "VehicleProperty::CROSS_TRAFFIC_MONITORING_ENABLED", + "defaultValue": { + "int32Values": [ + 1 + ] + } + }, + { + "property": "VehicleProperty::CROSS_TRAFFIC_MONITORING_WARNING_STATE", + "defaultValue": { + "int32Values": [ + "CrossTrafficMonitoringWarningState::NO_WARNING" + ] + }, + "areas": [ + { + "areaId": 0, + "supportedEnumValues": [ + "ErrorState::NOT_AVAILABLE_SAFETY", + "ErrorState::NOT_AVAILABLE_POOR_VISIBILITY", + "ErrorState::NOT_AVAILABLE_SPEED_HIGH", + "ErrorState::NOT_AVAILABLE_DISABLED", + "CrossTrafficMonitoringWarningState::NO_WARNING", + "CrossTrafficMonitoringWarningState::WARNING_FRONT_LEFT", + "CrossTrafficMonitoringWarningState::WARNING_FRONT_RIGHT", + "CrossTrafficMonitoringWarningState::WARNING_FRONT_BOTH", + "CrossTrafficMonitoringWarningState::WARNING_REAR_LEFT", + "CrossTrafficMonitoringWarningState::WARNING_REAR_RIGHT", + "CrossTrafficMonitoringWarningState::WARNING_REAR_BOTH" + ] + } + ] + }, + { + "property": "VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED", + "defaultValue": { + "int32Values": [ + 1 + ] + } + }, + { + "property": "VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE", + "defaultValue": { + "int32Values": [ + "LowSpeedAutomaticEmergencyBrakingState::ENABLED" + ] + }, + "areas": [ + { + "areaId": 0, + "supportedEnumValues": [ + "ErrorState::NOT_AVAILABLE_SAFETY", + "ErrorState::NOT_AVAILABLE_POOR_VISIBILITY", + "ErrorState::NOT_AVAILABLE_SPEED_HIGH", + "ErrorState::NOT_AVAILABLE_DISABLED", + "LowSpeedAutomaticEmergencyBrakingState::ENABLED", + "LowSpeedAutomaticEmergencyBrakingState::ACTIVATED", + "LowSpeedAutomaticEmergencyBrakingState::USER_OVERRIDE" + ] + } + ] + }, + { + "property": "VehicleProperty::CAMERA_SERVICE_CURRENT_STATE", + "defaultValue": { + "int32Values": [ + "CameraServiceState::UNAVAILABLE", + "CameraServiceState::UNAVAILABLE", + "CameraServiceState::UNAVAILABLE", + "CameraServiceState::UNAVAILABLE", + "CameraServiceState::UNAVAILABLE", + "CameraServiceState::UNAVAILABLE", + "CameraServiceState::UNAVAILABLE", + "CameraServiceState::UNAVAILABLE" + ] + } + } + ] +} diff --git a/automotive/vehicle/aidl/impl/current/default_config/config/README.md b/automotive/vehicle/aidl/impl/current/default_config/config/README.md new file mode 100644 index 0000000000000000000000000000000000000000..6e82de577399790726b4b31821d5724ca7920db6 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/default_config/config/README.md @@ -0,0 +1,171 @@ +# Property Configuration Files + +Each JSON file in this folder is a property configuration file for reference +Vehicle HAL. They contain VehiclePropConfig information along with initial +value information. + +## JSON schema + +Each JSON file must be in a schema like the following example: +(The comment starting with "//" is for documentation only and must be removed +from the actual JSON file. The "comment" field is used for comment in the +actual JSON file and will be ignored by the parser) + +``` +{ + // (number) The version for the JSON schema. + "apiVersion": 1, + // (non-empty array of objects) The property configuration list. + // + // Each object is a configuration for one property. + "properties": [ + { + // (number/string) The ID for the property. + // This value is defined in a string value + // which represents a constant value, see the "JSON Number-type + // Field Values" section for detail. + "property": "VehicleProperty::INFO_FUEL_CAPACITY", + // (optional, number/string) The access mode for the property. + // If specified, this overwrite the default access mode specified in + // VehicleProperty.aidl. Must be specified for vendor properties. + "access": "VehiclePropertyAccess::READ", + // (optional, number/string) The change mode for the property. + // If specified, this overwrite the default change mode specified in + // VehicleProperty.aidl. Must be specified for vendor properties. + "changeMode": "VehiclePropertyChangeMode::STATIC", + // (optional, string) The config string. + "configString": "blahblah", + // (optional, array of number/string) The config array. + "configArray": [1, 2, "Constants::HVAC_ALL"], + // (optional, object) The default value for the property. + // If not specified, the property will be shown as unavailable + // until its value is set. + "defaultValue": { + // (optional, array of int number/string) Int values. + "int32Values": [1, 2, "Constants::HVAC_ALL"], + // (optional, array of int number/string) Long values. + "int64Values": [1, 2], + // (optional, array of float number/string) Float values. + "floatValues": [1.1, 2.2], + // (optional, string) String value. + "stringValue": "test" + }, + // (optional, number/string) The minimum sample rate in HZ. + // Only work for VehiclePropertyChangeMode::CONTINUOUS property. + // Must be specified for continuous property. + "minSampleRate": 1, + // (optional, number/string) The maximum sample rate in HZ. + // Only work for VehiclePropertyChangeMode::CONTINUOUS property. + // Must be specified for continuous property. + "maxSampleRate": 10, + // (optional, array of objects) The area configs. + "areas:" [ + { + // (number/string) The area ID. + "areaId": "Constants::DOOR_1_LEFT", + // (optional number/string) The minimum int value. + "minInt32Value": 1, + // (optional number/string) The maximum int value. + "maxInt32Value": 10, + // (optional number/string) The minimum long value. + "minInt64Value": 1, + // (optional number/string) The maximum long value. + "maxInt64Value": 10, + // (optional number/string) The minimum float value. + "minFloatValue": 1, + // (optional number/string) The maximum float value. + "maxFloatValue": 10, + // (optional object) The default value for this area. + // Uses the same format as the "defaultValue" field for + // property object. If specified, this overwrite the global + // defaultValue. + "defaultValue": { + "int32Values": [1, 2, "Constants::HVAC_ALL"], + "int64Values": [1, 2], + "floatValues": [1.1, 2.2], + "stringValue": "test" + } + } + ] + } + ] +} +``` + +## JSON Number-type Field Values + +For number type field values, they can either be defined as a numeric number, +e.g., `{"minInt32Value": 1}` or be defined as a string which represents a +defined constant value, e.g., +`{"property": "VehicleProperty::INFO_FUEL_CAPACITY"}`. + +For constant values, they must be a string in the format of `XXX::XXX`, where +the field before `::` is the constant type, and the field after `::` is the +variable name. + +We support the following constant types: + +* VehiclePropertyAccess + +* VehiclePropertyChangeMode + +* VehicleGear + +* VehicleAreaWindow + +* VehicleOilLevel + +* VehicleUnit + +* VehicleSeatOccupancyState + +* VehicleHvacFanDirection + +* VehicleApPowerStateReport + +* VehicleTurnSignal + +* VehicleVendorPermission + +* EvsServiceType + +* EvsServiceState + +* EvConnectorType + +* VehicleProperty + +* GsrComplianceRequirementType + +* VehicleIgnitionState + +* FuelType + +* AutomaticEmergencyBrakingState + +* ForwardCollisionWarningState + +* BlindSpotWarningState + +* LaneDepartureWarningState + +* LaneKeepAssistState + +* LaneCenteringAssistCommand + +* LaneCenteringAssistState + +* ErrorState + +* WindshieldWipersState + +* WindshieldWipersSwitch + +* Constants + +Every constant type except "Constants" corresponds to a enum defined in Vehicle +HAL interfac. E.g. "VehicleProperty" corresponds to the enums defined in +"VehicleProperty.aidl". + +"Constants" type refers to the constant variables defined in the paresr. +Specifically, the "CONSTANTS_BY_NAME" map defined in "JsonConfigLoader.cpp". diff --git a/automotive/vehicle/aidl/impl/current/default_config/config/TestProperties.json b/automotive/vehicle/aidl/impl/current/default_config/config/TestProperties.json new file mode 100644 index 0000000000000000000000000000000000000000..73e4d44d0cf61ffe7ebf8a9a8745e534dd04314c --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/default_config/config/TestProperties.json @@ -0,0 +1,209 @@ +{ + "properties": [ + { + "property": "TestVendorProperty::MIXED_TYPE_PROPERTY_FOR_TEST", + "defaultValue": { + "floatValues": [ + 4.5 + ], + "int32Values": [ + 1, + 2, + 3 + ], + "stringValue": "MIXED property" + }, + "configArray": [ + 1, + 1, + 0, + 2, + 0, + 0, + 1, + 0, + 0 + ], + "access": "VehiclePropertyAccess::READ_WRITE", + "changeMode": "VehiclePropertyChangeMode::ON_CHANGE" + }, + { + "property": "TestVendorProperty::VENDOR_EXTENSION_BOOLEAN_PROPERTY", + "areas": [ + { + "defaultValue": { + "int32Values": [ + 1 + ] + }, + "areaId": "Constants::DOOR_1_LEFT" + }, + { + "defaultValue": { + "int32Values": [ + 1 + ] + }, + "areaId": "Constants::DOOR_1_RIGHT" + }, + { + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areaId": "Constants::DOOR_2_LEFT" + }, + { + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areaId": "Constants::DOOR_2_RIGHT" + } + ], + "access": "VehiclePropertyAccess::READ_WRITE", + "changeMode": "VehiclePropertyChangeMode::ON_CHANGE" + }, + { + "property": "TestVendorProperty::VENDOR_EXTENSION_FLOAT_PROPERTY", + "areas": [ + { + "defaultValue": { + "floatValues": [ + 1.0 + ] + }, + "areaId": "Constants::HVAC_LEFT", + "minFloatValue": -10.0, + "maxFloatValue": 10.0 + }, + { + "defaultValue": { + "floatValues": [ + 2.0 + ] + }, + "areaId": "Constants::HVAC_RIGHT", + "minFloatValue": -10.0, + "maxFloatValue": 10.0 + } + ], + "access": "VehiclePropertyAccess::READ_WRITE", + "changeMode": "VehiclePropertyChangeMode::ON_CHANGE" + }, + { + "property": "TestVendorProperty::VENDOR_EXTENSION_INT_PROPERTY", + "areas": [ + { + "defaultValue": { + "int32Values": [ + 1 + ] + }, + "areaId": "VehicleAreaWindow::FRONT_WINDSHIELD", + "minInt32Value": -100, + "maxInt32Value": 100 + }, + { + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "areaId": "VehicleAreaWindow::REAR_WINDSHIELD", + "minInt32Value": -100, + "maxInt32Value": 100 + }, + { + "defaultValue": { + "int32Values": [ + -1 + ] + }, + "areaId": "VehicleAreaWindow::ROOF_TOP_1", + "minInt32Value": -100, + "maxInt32Value": 100 + } + ], + "access": "VehiclePropertyAccess::READ_WRITE", + "changeMode": "VehiclePropertyChangeMode::ON_CHANGE" + }, + { + "property": "TestVendorProperty::VENDOR_EXTENSION_STRING_PROPERTY", + "defaultValue": { + "stringValue": "Vendor String Property" + }, + "access": "VehiclePropertyAccess::READ_WRITE", + "changeMode": "VehiclePropertyChangeMode::ON_CHANGE" + }, + { + "property": "TestVendorProperty::PLACEHOLDER_PROPERTY_INT", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "access": "VehiclePropertyAccess::READ_WRITE", + "changeMode": "VehiclePropertyChangeMode::ON_CHANGE" + }, + { + "property": "TestVendorProperty::PLACEHOLDER_PROPERTY_FLOAT", + "defaultValue": { + "floatValues": [ + 0.0 + ] + }, + "access": "VehiclePropertyAccess::READ_WRITE", + "changeMode": "VehiclePropertyChangeMode::ON_CHANGE" + }, + { + "property": "TestVendorProperty::PLACEHOLDER_PROPERTY_BOOLEAN", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "access": "VehiclePropertyAccess::READ_WRITE", + "changeMode": "VehiclePropertyChangeMode::ON_CHANGE" + }, + { + "property": "TestVendorProperty::PLACEHOLDER_PROPERTY_STRING", + "defaultValue": { + "stringValue": "Test" + }, + "access": "VehiclePropertyAccess::READ_WRITE", + "changeMode": "VehiclePropertyChangeMode::ON_CHANGE" + }, + { + "property": "TestVendorProperty::ECHO_REVERSE_BYTES", + "access": "VehiclePropertyAccess::READ_WRITE", + "changeMode": "VehiclePropertyChangeMode::ON_CHANGE" + }, + { + "property": "TestVendorProperty::VENDOR_PROPERTY_FOR_ERROR_CODE_TESTING", + "access": "VehiclePropertyAccess::READ_WRITE", + "changeMode": "VehiclePropertyChangeMode::ON_CHANGE" + }, + { + "property": "VehicleProperty::SUPPORT_CUSTOMIZE_VENDOR_PERMISSION", + "defaultValue": { + "int32Values": [ + 1 + ] + }, + "configArray": [ + "TestVendorProperty::MIXED_TYPE_PROPERTY_FOR_TEST", + "VehicleVendorPermission::PERMISSION_GET_VENDOR_CATEGORY_INFO", + "VehicleVendorPermission::PERMISSION_SET_VENDOR_CATEGORY_INFO", + "TestVendorProperty::VENDOR_EXTENSION_INT_PROPERTY", + "VehicleVendorPermission::PERMISSION_GET_VENDOR_CATEGORY_SEAT", + "VehicleVendorPermission::PERMISSION_NOT_ACCESSIBLE", + "TestVendorProperty::VENDOR_EXTENSION_FLOAT_PROPERTY", + "VehicleVendorPermission::PERMISSION_DEFAULT", + "VehicleVendorPermission::PERMISSION_DEFAULT" + ] + } + ] +} \ No newline at end of file diff --git a/automotive/vehicle/aidl/impl/current/default_config/config/VendorClusterTestProperties.json b/automotive/vehicle/aidl/impl/current/default_config/config/VendorClusterTestProperties.json new file mode 100644 index 0000000000000000000000000000000000000000..8c2bc93e1cd235758b09a74d34e24c8a513d440f --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/default_config/config/VendorClusterTestProperties.json @@ -0,0 +1,63 @@ +{ + "properties": [ + { + "property": "TestVendorProperty::VENDOR_CLUSTER_SWITCH_UI", + "access": "VehiclePropertyAccess::WRITE", + "changeMode": "VehiclePropertyChangeMode::ON_CHANGE" + }, + { + "property": "TestVendorProperty::VENDOR_CLUSTER_DISPLAY_STATE", + "access": "VehiclePropertyAccess::WRITE", + "changeMode": "VehiclePropertyChangeMode::ON_CHANGE" + }, + { + "property": "TestVendorProperty::VENDOR_CLUSTER_REPORT_STATE", + "defaultValue": { + "int32Values": [ + 0, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + 0, + -1 + ] + }, + "configArray": [ + 0, + 0, + 0, + 11, + 0, + 0, + 0, + 0, + 16 + ], + "access": "VehiclePropertyAccess::READ", + "changeMode": "VehiclePropertyChangeMode::ON_CHANGE", + "comment": + "Value means 0 /* Off */, -1, -1, -1, -1 /* Bounds */, -1, -1, -1, -1 /* Insets */, 0 /* ClusterHome */, -1 /* ClusterNone */" + }, + { + "property": "TestVendorProperty::VENDOR_CLUSTER_REQUEST_DISPLAY", + "defaultValue": { + "int32Values": [ + 0 + ] + }, + "access": "VehiclePropertyAccess::READ", + "changeMode": "VehiclePropertyChangeMode::ON_CHANGE", + "comment": "0 means ClusterHome" + }, + { + "property": "TestVendorProperty::VENDOR_CLUSTER_NAVIGATION_STATE", + "access": "VehiclePropertyAccess::READ", + "changeMode": "VehiclePropertyChangeMode::ON_CHANGE" + } + ] +} \ No newline at end of file diff --git a/automotive/vehicle/aidl/impl/default_config/test/Android.bp b/automotive/vehicle/aidl/impl/current/default_config/test/Android.bp similarity index 100% rename from automotive/vehicle/aidl/impl/default_config/test/Android.bp rename to automotive/vehicle/aidl/impl/current/default_config/test/Android.bp diff --git a/automotive/vehicle/aidl/impl/current/default_config/test/DefaultConfigTest.cpp b/automotive/vehicle/aidl/impl/current/default_config/test/DefaultConfigTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..95fecfe2d99eb6e73be6acdf97505de5be6f7fdc --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/default_config/test/DefaultConfigTest.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +namespace test { + +using ::android::base::Error; +using ::android::base::Result; +using ::testing::UnorderedElementsAreArray; + +constexpr char kDefaultPropertiesConfigFile[] = "DefaultProperties.json"; + +#ifdef ENABLE_VEHICLE_HAL_TEST_PROPERTIES +constexpr char kTestPropertiesConfigFile[] = "TestProperties.json"; +constexpr char kVendorClusterTestPropertiesConfigFile[] = "VendorClusterTestProperties.json"; +#endif // ENABLE_VEHICLE_HAL_TEST_PROPERTIES + +std::string getTestFilePath(const char* filename) { + static std::string baseDir = android::base::GetExecutableDirectory(); + return baseDir + "/" + filename; +} + +Result> loadConfig(JsonConfigLoader& loader, + const char* path) { + std::string configPath = getTestFilePath(path); + std::ifstream ifs(configPath.c_str()); + if (!ifs) { + return Error() << "couldn't open %s for parsing." << configPath; + } + + return loader.loadPropConfig(ifs); +} + +TEST(DefaultConfigTest, TestloadDefaultProperties) { + JsonConfigLoader loader; + auto result = loadConfig(loader, kDefaultPropertiesConfigFile); + + ASSERT_TRUE(result.ok()) << result.error().message(); +} + +#ifdef ENABLE_VEHICLE_HAL_TEST_PROPERTIES + +TEST(DefaultConfigTest, TestloadTestProperties) { + JsonConfigLoader loader; + auto result = loadConfig(loader, kTestPropertiesConfigFile); + + ASSERT_TRUE(result.ok()) << result.error().message(); +} + +TEST(DefaultConfigTest, TestloadVendorClusterTestProperties) { + JsonConfigLoader loader; + auto result = loadConfig(loader, kVendorClusterTestPropertiesConfigFile); + + ASSERT_TRUE(result.ok()) << result.error().message(); +} + +#endif // ENABLE_VEHICLE_HAL_TEST_PROPERTIES + +} // namespace test + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/Android.bp b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/Android.bp similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/Android.bp rename to automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/Android.bp diff --git a/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/include/FakeValueGenerator.h b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/include/FakeValueGenerator.h new file mode 100644 index 0000000000000000000000000000000000000000..5c90c301bc608d71b70b0c4601da3cfee96ac7c0 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/include/FakeValueGenerator.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_FakeValueGenerator_H_ +#define android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_FakeValueGenerator_H_ + +#include + +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace fake { + +// A abstract class for all fake value generators. +class FakeValueGenerator { + public: + virtual ~FakeValueGenerator() = default; + + // Returns the next event if there is one or {@code std::nullopt} if there is none. + virtual std::optional + nextEvent() = 0; +}; + +} // namespace fake +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_FakeValueGenerator_H_ diff --git a/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/include/GeneratorHub.h b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/include/GeneratorHub.h new file mode 100644 index 0000000000000000000000000000000000000000..f96b6ecbd4d4d971f8e492516595515e51711ad1 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/include/GeneratorHub.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_interfaces_automotive_vehicle_aidl_fake_impl_GeneratorHub_include_GeneratorHub_h_ +#define android_hardware_interfaces_automotive_vehicle_aidl_fake_impl_GeneratorHub_include_GeneratorHub_h_ + +#include "FakeValueGenerator.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace fake { + +// This is the scheduler for all VHAL event generators. It manages all generators and uses priority +// queue to maintain generated events ordered by timestamp. The scheduler uses a single thread to +// keep querying and updating the event queue to make sure events from all generators are produced +// in order. +class GeneratorHub { + public: + using OnHalEvent = std::function; + + explicit GeneratorHub(OnHalEvent&& onHalEvent); + ~GeneratorHub(); + + // Register a new generator. The generator will be discarded if it could not produce next event. + // The existing generator will be overridden if it has the same generatorId. + void registerGenerator(int32_t generatorId, std::unique_ptr generator); + + // Unregister a generator with the generatorId. If no registered generator is found, this + // function does nothing. Returns true if the generator is unregistered. + bool unregisterGenerator(int32_t generatorId); + + private: + struct VhalEvent { + int32_t generatorId; + aidl::android::hardware::automotive::vehicle::VehiclePropValue val; + }; + + // Comparator used by priority queue to keep track of soonest event. + struct GreaterByTime { + bool operator()(const VhalEvent& lhs, const VhalEvent& rhs) const { + return lhs.val.timestamp > rhs.val.timestamp; + } + }; + + std::priority_queue, GreaterByTime> mEventQueue; + std::mutex mGeneratorsLock; + std::unordered_map> mGenerators + GUARDED_BY(mGeneratorsLock); + OnHalEvent mOnHalEvent; + std::condition_variable mCond; + std::thread mThread; + std::atomic mShuttingDownFlag{false}; + + // Main loop of the single thread to producing event and updating event queue. + void run(); +}; + +} // namespace fake +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_interfaces_automotive_vehicle_aidl_fake_impl_GeneratorHub_include_GeneratorHub_h_ diff --git a/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/include/JsonFakeValueGenerator.h b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/include/JsonFakeValueGenerator.h new file mode 100644 index 0000000000000000000000000000000000000000..42b1bd3c6c2469471a02c0cb14b5dc5f389ee50a --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/include/JsonFakeValueGenerator.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_JsonFakeValueGenerator_H_ +#define android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_JsonFakeValueGenerator_H_ + +#include "FakeValueGenerator.h" + +#include + +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace fake { + +class JsonFakeValueGenerator : public FakeValueGenerator { + public: + // Create a new JSON fake value generator. {@code request.value.stringValue} is the JSON file + // name. {@code request.value.int32Values[1]} if exists, is the number of iterations. If + // {@code int32Values} has less than 2 elements, number of iterations would be set to -1, which + // means iterate indefinitely. + explicit JsonFakeValueGenerator( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& request); + // Create a new JSON fake value generator using the specified JSON file path. All the events + // in the JSON file would be generated for number of {@code iteration}. If iteration is 0, no + // value would be generated. If iteration is less than 0, it would iterate indefinitely. + explicit JsonFakeValueGenerator(const std::string& path, int32_t iteration); + // Create a new JSON fake value generator using the specified JSON file path. All the events + // in the JSON file would be generated once. + explicit JsonFakeValueGenerator(const std::string& path); + // Create a new JSON fake value generator using the JSON content. The first argument is just + // used to differentiate this function with the one that takes path as input. + explicit JsonFakeValueGenerator(bool unused, const std::string& content, int32_t iteration); + + ~JsonFakeValueGenerator() = default; + + std::optional nextEvent() + override; + const std::vector& + getAllEvents(); + + // Whether there are events left to replay for this generator. + bool hasNext(); + + private: + size_t mEventIndex = 0; + std::vector mEvents; + int64_t mLastEventTimestamp = 0; + int32_t mNumOfIterations = 0; + + void setBit(std::vector& bytes, size_t idx); + void initWithPath(const std::string& path, int32_t iteration); + void initWithStream(std::istream& is, int32_t iteration); +}; + +} // namespace fake +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_JsonFakeValueGenerator_H_ diff --git a/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/include/LinearFakeValueGenerator.h b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/include/LinearFakeValueGenerator.h new file mode 100644 index 0000000000000000000000000000000000000000..2378676387fb8f843108f97ac3050258117f3978 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/include/LinearFakeValueGenerator.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_LinearFakeValueGenerator_H_ +#define android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_LinearFakeValueGenerator_H_ + +#include "FakeValueGenerator.h" + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace fake { + +class LinearFakeValueGenerator : public FakeValueGenerator { + public: + // A linear value generator initialized using values in request. + // int32Values[1]: propId + // floatValues[0]: middleValue and currentValue + // floatValues[1]: dispersion + // floatValues[2]: increment + // int64Values[0]: interval + // {@code propId} must be INT32 or INT64 or FLOAT type. + explicit LinearFakeValueGenerator( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& request); + // A linear value generator in range [middleValue - dispersion, middleValue + dispersion), + // starts at 'currentValue' and at each 'interval', increase by 'increment' and loop back if + // exceeds middleValue + dispersion. {@code propId} must be INT32 or INT64 or FLOAT type. + explicit LinearFakeValueGenerator(int32_t propId, float middleValue, float initValue, + float dispersion, float increment, int64_t interval); + ~LinearFakeValueGenerator() = default; + + std::optional nextEvent() + override; + + private: + // In every timer tick we may want to generate new value based on initial value for debug + // purpose. It's better to have sequential values to see if events gets delivered in order + // to the client. + struct GeneratorCfg { + int32_t propId; + float middleValue; + float currentValue; // Should be in range (middleValue +/- dispersion). + float dispersion; // Defines minimum and maximum value based on initial value. + float increment; // Value that we will be added to currentValue with each timer tick. + int64_t interval; + int64_t lastEventTimestamp; + }; + + GeneratorCfg mGenCfg; + + void initGenCfg(int32_t propId, float middleValue, float initValue, float dispersion, + float increment, int64_t interval); +}; + +} // namespace fake +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_LinearFakeValueGenerator_H_ diff --git a/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/src/GeneratorHub.cpp b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/src/GeneratorHub.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d815456a56fedb208ee51cb49cc1592c157bf315 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/src/GeneratorHub.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "GeneratorHub" + +#include "GeneratorHub.h" + +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace fake { + +using ::android::base::ScopedLockAssertion; + +GeneratorHub::GeneratorHub(OnHalEvent&& onHalEvent) : mOnHalEvent(onHalEvent) { + mThread = std::thread(&GeneratorHub::run, this); +} + +GeneratorHub::~GeneratorHub() { + { + // Even if the shared variable is atomic, it must be modified under the + // mutex in order to correctly publish the modification to the waiting + // thread. + std::unique_lock lock(mGeneratorsLock); + mShuttingDownFlag.store(true); + } + mCond.notify_all(); + if (mThread.joinable()) { + mThread.join(); + } +} + +void GeneratorHub::registerGenerator(int32_t id, std::unique_ptr generator) { + { + std::scoped_lock lockGuard(mGeneratorsLock); + auto maybeNextEvent = generator->nextEvent(); + // Register only if the generator can produce at least one event. + if (maybeNextEvent.has_value()) { + // Push the next event if it is a new generator + if (mGenerators.find(id) == mGenerators.end()) { + ALOGI("%s: Registering new generator, id: %d", __func__, id); + mEventQueue.push({id, maybeNextEvent.value()}); + } + mGenerators[id] = std::move(generator); + ALOGI("%s: Registered generator, id: %d", __func__, id); + } + } + mCond.notify_one(); +} + +bool GeneratorHub::unregisterGenerator(int32_t id) { + bool removed; + { + std::scoped_lock lockGuard(mGeneratorsLock); + removed = mGenerators.erase(id); + } + mCond.notify_one(); + ALOGI("%s: Unregistered generator, id: %d", __func__, id); + return removed; +} + +void GeneratorHub::run() { + while (!mShuttingDownFlag.load()) { + std::unique_lock lock(mGeneratorsLock); + ScopedLockAssertion lock_assertion(mGeneratorsLock); + // Pop events whose generator does not exist (may be already unregistered) + while (!mEventQueue.empty() && + mGenerators.find(mEventQueue.top().generatorId) == mGenerators.end()) { + mEventQueue.pop(); + } + // Wait until event queue is not empty or shutting down flag is set. + // This would unlock mGeneratorsLock and reacquire later. + mCond.wait(lock, [this] { return !mEventQueue.empty() || mShuttingDownFlag.load(); }); + if (mShuttingDownFlag.load()) { + break; + } + + const VhalEvent& curEvent = mEventQueue.top(); + long currentTime = elapsedRealtimeNano(); + long waitTime = + curEvent.val.timestamp > currentTime ? curEvent.val.timestamp - currentTime : 0; + if (waitTime != 0) { + // Wait until the soonest event happen + if (mCond.wait_for(lock, std::chrono::nanoseconds(waitTime)) != + std::cv_status::timeout) { + // It is possible that a new generator is registered and produced a sooner event, or + // current generator is unregistered, in this case the thread will re-evaluate the + // soonest event + ALOGI("Something happened while waiting"); + continue; + } + } + // Now it's time to handle current event. + mOnHalEvent(curEvent.val); + // Update queue by popping current event and producing next event from the same generator + int32_t id = curEvent.generatorId; + mEventQueue.pop(); + if (mGenerators.find(id) != mGenerators.end()) { + auto maybeNextEvent = mGenerators[id]->nextEvent(); + if (maybeNextEvent.has_value()) { + mEventQueue.push({id, maybeNextEvent.value()}); + continue; + } + } + + ALOGI("%s: Generator ended, unregister it, id: %d", __func__, id); + mGenerators.erase(id); + } +} + +} // namespace fake +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/src/JsonFakeValueGenerator.cpp b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/src/JsonFakeValueGenerator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cb42317195620399a285d11bfd503248908b1095 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/src/JsonFakeValueGenerator.cpp @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "JsonFakeValueGenerator" + +#include "JsonFakeValueGenerator.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace fake { + +namespace { + +using ::aidl::android::hardware::automotive::vehicle::DiagnosticFloatSensorIndex; +using ::aidl::android::hardware::automotive::vehicle::DiagnosticIntegerSensorIndex; +using ::aidl::android::hardware::automotive::vehicle::RawPropValues; +using ::aidl::android::hardware::automotive::vehicle::VehicleProperty; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; + +bool isDiagnosticProperty(int32_t prop) { + return prop == toInt(VehicleProperty::OBD2_LIVE_FRAME) || + prop == toInt(VehicleProperty::OBD2_FREEZE_FRAME); +} + +void setBit(std::vector& bytes, size_t idx) { + uint8_t mask = 1 << (idx % 8); + bytes[idx / 8] |= mask; +} + +template +void copyJsonArray(const Json::Value& jsonArray, std::vector& dest) { + dest.resize(jsonArray.size()); + for (Json::Value::ArrayIndex i = 0; i < jsonArray.size(); i++) { + if (std::is_same::value) { + dest[i] = jsonArray[i].asInt(); + } else if (std::is_same::value) { + dest[i] = jsonArray[i].asInt64(); + } else if (std::is_same::value) { + dest[i] = jsonArray[i].asFloat(); + } + } +} + +void copyMixedValueJson(const Json::Value& jsonValue, RawPropValues& dest) { + copyJsonArray(jsonValue["int32Values"], dest.int32Values); + copyJsonArray(jsonValue["int64Values"], dest.int64Values); + copyJsonArray(jsonValue["floatValues"], dest.floatValues); + dest.stringValue = jsonValue["stringValue"].asString(); +} + +std::vector generateDiagnosticBytes(const RawPropValues& diagnosticValue) { + size_t lastIntegerSensorIndex = static_cast( + obd2frame::Obd2SensorStore::getLastIndex()); + size_t lastFloatSensorIndex = static_cast( + obd2frame::Obd2SensorStore::getLastIndex()); + + size_t byteSize = (lastIntegerSensorIndex + lastFloatSensorIndex + 2); + std::vector bytes((byteSize + 7) / 8); + + auto& int32Values = diagnosticValue.int32Values; + for (size_t i = 0; i < int32Values.size(); i++) { + if (int32Values[i] != 0) { + setBit(bytes, i); + } + } + + auto& floatValues = diagnosticValue.floatValues; + for (size_t i = 0; i < floatValues.size(); i++) { + if (floatValues[i] != 0.0) { + setBit(bytes, i + lastIntegerSensorIndex + 1); + } + } + return bytes; +} + +std::vector parseFakeValueJson(std::istream& is) { + std::vector fakeVhalEvents; + + Json::CharReaderBuilder builder; + Json::Value rawEvents; + std::string errorMessage; + if (!Json::parseFromStream(builder, is, &rawEvents, &errorMessage)) { + ALOGE("%s: Failed to parse fake data JSON file. Error: %s", __func__, errorMessage.c_str()); + return fakeVhalEvents; + } + + for (Json::Value::ArrayIndex i = 0; i < rawEvents.size(); i++) { + Json::Value rawEvent = rawEvents[i]; + if (!rawEvent.isObject()) { + ALOGE("%s: VHAL JSON event should be an object, %s", __func__, + rawEvent.toStyledString().c_str()); + continue; + } + if (rawEvent["prop"].empty() || rawEvent["areaId"].empty() || rawEvent["value"].empty() || + rawEvent["timestamp"].empty()) { + ALOGE("%s: VHAL JSON event has missing fields, skip it, %s", __func__, + rawEvent.toStyledString().c_str()); + continue; + } + VehiclePropValue event = { + .timestamp = rawEvent["timestamp"].asInt64(), + .areaId = rawEvent["areaId"].asInt(), + .prop = rawEvent["prop"].asInt(), + }; + + Json::Value rawEventValue = rawEvent["value"]; + auto& value = event.value; + int32_t count; + switch (getPropType(event.prop)) { + case VehiclePropertyType::BOOLEAN: + case VehiclePropertyType::INT32: + value.int32Values.resize(1); + value.int32Values[0] = rawEventValue.asInt(); + break; + case VehiclePropertyType::INT64: + value.int64Values.resize(1); + value.int64Values[0] = rawEventValue.asInt64(); + break; + case VehiclePropertyType::FLOAT: + value.floatValues.resize(1); + value.floatValues[0] = rawEventValue.asFloat(); + break; + case VehiclePropertyType::STRING: + value.stringValue = rawEventValue.asString(); + break; + case VehiclePropertyType::INT32_VEC: + value.int32Values.resize(rawEventValue.size()); + count = 0; + for (auto& it : rawEventValue) { + value.int32Values[count++] = it.asInt(); + } + break; + case VehiclePropertyType::MIXED: + copyMixedValueJson(rawEventValue, value); + if (isDiagnosticProperty(event.prop)) { + value.byteValues = generateDiagnosticBytes(value); + } + break; + default: + ALOGE("%s: unsupported type for property: 0x%x", __func__, event.prop); + continue; + } + fakeVhalEvents.push_back(event); + } + return fakeVhalEvents; +} + +} // namespace + +JsonFakeValueGenerator::JsonFakeValueGenerator(const std::string& path) + : JsonFakeValueGenerator(path, /*iteration=*/1) {} + +JsonFakeValueGenerator::JsonFakeValueGenerator(const std::string& path, int32_t iteration) { + initWithPath(path, iteration); +} + +JsonFakeValueGenerator::JsonFakeValueGenerator(const VehiclePropValue& request) { + const auto& v = request.value; + // Iterate infinitely if iteration number is not provided + int32_t numOfIterations = v.int32Values.size() < 2 ? -1 : v.int32Values[1]; + + initWithPath(v.stringValue, numOfIterations); +} + +JsonFakeValueGenerator::JsonFakeValueGenerator([[maybe_unused]] bool unused, + const std::string& content, int32_t iteration) { + std::istringstream iss(content); + initWithStream(iss, iteration); +} + +void JsonFakeValueGenerator::initWithPath(const std::string& path, int32_t iteration) { + std::ifstream ifs(path); + if (!ifs) { + ALOGE("%s: couldn't open %s for parsing.", __func__, path.c_str()); + return; + } + initWithStream(ifs, iteration); +} + +void JsonFakeValueGenerator::initWithStream(std::istream& is, int32_t iteration) { + mEvents = parseFakeValueJson(is); + mNumOfIterations = iteration; +} + +const std::vector& JsonFakeValueGenerator::getAllEvents() { + return mEvents; +} + +std::optional JsonFakeValueGenerator::nextEvent() { + if (mNumOfIterations == 0 || mEvents.size() == 0) { + return std::nullopt; + } + + VehiclePropValue generatedValue = mEvents[mEventIndex]; + + if (mLastEventTimestamp == 0) { + mLastEventTimestamp = elapsedRealtimeNano(); + } else { + int64_t nextEventTime = 0; + if (mEventIndex > 0) { + // All events (start from 2nd one) are supposed to happen in the future with a delay + // equals to the duration between previous and current event. + nextEventTime = mLastEventTimestamp + + (mEvents[mEventIndex].timestamp - mEvents[mEventIndex - 1].timestamp); + } else { + // We are starting another iteration, immediately send the next event after 1ms. + nextEventTime = mLastEventTimestamp + 1000000; + } + // Prevent overflow. + assert(nextEventTime > mLastEventTimestamp); + mLastEventTimestamp = nextEventTime; + } + + mEventIndex++; + if (mEventIndex == mEvents.size()) { + mEventIndex = 0; + if (mNumOfIterations > 0) { + mNumOfIterations--; + } + } + generatedValue.timestamp = mLastEventTimestamp; + + return generatedValue; +} + +bool JsonFakeValueGenerator::hasNext() { + return mNumOfIterations != 0 && mEvents.size() > 0; +} + +} // namespace fake +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/src/LinearFakeValueGenerator.cpp b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/src/LinearFakeValueGenerator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fe08dcf335795d1f0a596f8ad77dda256b335a13 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/src/LinearFakeValueGenerator.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "LinearFakeValueGenerator" + +#include "LinearFakeValueGenerator.h" + +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace fake { + +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; + +LinearFakeValueGenerator::LinearFakeValueGenerator(int32_t propId, float middleValue, + float initValue, float dispersion, + float increment, int64_t interval) { + initGenCfg(propId, middleValue, initValue, dispersion, increment, interval); +} + +LinearFakeValueGenerator::LinearFakeValueGenerator(const VehiclePropValue& request) { + const auto& v = request.value; + initGenCfg(v.int32Values[1], v.floatValues[0], v.floatValues[0], v.floatValues[1], + v.floatValues[2], v.int64Values[0]); +} + +void LinearFakeValueGenerator::initGenCfg(int32_t propId, float middleValue, float initValue, + float dispersion, float increment, int64_t interval) { + // Other types are not supported. + assert(getPropType(propId) == VehicleProperty::INT32 || + getPropType(propId) == VehicleProperty::INT64 || + getPropType(propId) == VehicleProperty::FLOAT); + + if (initValue < middleValue - dispersion || initValue >= middleValue + dispersion) { + ALOGW("%s: invalid initValue: %f, out of range, default to %f", __func__, initValue, + middleValue); + initValue = middleValue; + } + mGenCfg = GeneratorCfg{ + .propId = propId, + .middleValue = middleValue, + .currentValue = initValue, + .dispersion = dispersion, + .increment = increment, + .interval = interval, + }; +} + +std::optional LinearFakeValueGenerator::nextEvent() { + VehiclePropValue event = { + .prop = mGenCfg.propId, + }; + auto& value = event.value; + switch (getPropType(event.prop)) { + case VehiclePropertyType::INT32: + value.int32Values = {static_cast(mGenCfg.currentValue)}; + break; + case VehiclePropertyType::INT64: + value.int64Values = {static_cast(mGenCfg.currentValue)}; + break; + case VehiclePropertyType::FLOAT: + value.floatValues = {mGenCfg.currentValue}; + break; + default: + ALOGE("%s: unsupported property type for 0x%x", __func__, event.prop); + } + if (mGenCfg.lastEventTimestamp == 0) { + mGenCfg.lastEventTimestamp = elapsedRealtimeNano(); + } else { + int64_t nextEventTime = mGenCfg.lastEventTimestamp + mGenCfg.interval; + // Prevent overflow. + assert(nextEventTime > mGenCfg.lastEventTimestamp); + mGenCfg.lastEventTimestamp = nextEventTime; + } + event.timestamp = mGenCfg.lastEventTimestamp; + + mGenCfg.currentValue += mGenCfg.increment; + if (mGenCfg.currentValue >= mGenCfg.middleValue + mGenCfg.dispersion) { + // Wrap around, (i - d) + c - (i + d) = c - 2 * d + mGenCfg.currentValue = mGenCfg.currentValue - 2 * mGenCfg.dispersion; + } + return event; +} + +} // namespace fake +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/Android.bp b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/test/Android.bp similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/Android.bp rename to automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/test/Android.bp diff --git a/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/test/FakeVehicleHalValueGeneratorsTest.cpp b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/test/FakeVehicleHalValueGeneratorsTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cdfa8b20318e2f3a071c2147fa0a470850437bb1 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/test/FakeVehicleHalValueGeneratorsTest.cpp @@ -0,0 +1,483 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace fake { + +using ::aidl::android::hardware::automotive::vehicle::VehicleProperty; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; +using ::android::base::ScopedLockAssertion; + +using std::literals::chrono_literals::operator""s; + +class FakeVehicleHalValueGeneratorsTest : public ::testing::Test { + protected: + void SetUp() override { + mHub = std::make_unique( + [this](const VehiclePropValue& event) { return onHalEvent(event); }); + } + + GeneratorHub* getHub() { return mHub.get(); } + + std::vector getEvents() { + std::scoped_lock lockGuard(mEventsLock); + return mEvents; + } + + void clearEvents() { + std::scoped_lock lockGuard(mEventsLock); + mEvents.clear(); + } + + void waitForEvents(size_t count) { + std::unique_lock uniqueLock(mEventsLock); + bool result = mCv.wait_for(uniqueLock, 10s, [this, count] { + ScopedLockAssertion lockAssertion(mEventsLock); + return mEvents.size() >= count; + }); + + ASSERT_TRUE(result) << "didn't receive enough events"; + } + + void TearDown() override { + // Generator callback uses mEvents, must stop generator before destroying mEvents. + mHub.reset(); + } + + static std::string getTestFilePath(const char* filename) { + static std::string baseDir = android::base::GetExecutableDirectory(); + return baseDir + "/" + filename; + } + + private: + void onHalEvent(const VehiclePropValue& event) { + VehiclePropValue eventCopy = event; + { + std::scoped_lock lockGuard(mEventsLock); + mEvents.push_back(std::move(eventCopy)); + } + mCv.notify_all(); + } + + std::unique_ptr mHub; + std::mutex mEventsLock; + std::condition_variable mCv; + std::vector mEvents GUARDED_BY(mEventsLock); +}; + +class TestFakeValueGenerator : public FakeValueGenerator { + public: + void setEvents(const std::vector& events) { + mEvents = events; + mEventIndex = 0; + } + + std::optional<::aidl::android::hardware::automotive::vehicle::VehiclePropValue> nextEvent() + override { + if (mEventIndex == mEvents.size()) { + return std::nullopt; + } + return mEvents[mEventIndex++]; + } + + private: + std::vector mEvents; + size_t mEventIndex = 0; +}; + +TEST_F(FakeVehicleHalValueGeneratorsTest, testRegisterTestFakeValueGenerator) { + auto generator = std::make_unique(); + std::vector events; + size_t eventCount = 10; + int64_t timestamp = elapsedRealtimeNano(); + for (size_t i = 0; i < eventCount; i++) { + events.push_back(VehiclePropValue{ + .prop = static_cast(i), + // Generate 1 event every 1ms. + .timestamp = timestamp + static_cast(1000000 * i), + }); + } + generator->setEvents(events); + + getHub()->registerGenerator(0, std::move(generator)); + + waitForEvents(events.size()); + + ASSERT_EQ(getEvents(), events); + + getHub()->unregisterGenerator(0); +} + +TEST_F(FakeVehicleHalValueGeneratorsTest, testUnregisterGeneratorStopGeneration) { + auto generator = std::make_unique(); + std::vector events; + size_t eventCount = 10; + int64_t timestamp = elapsedRealtimeNano(); + for (size_t i = 0; i < eventCount; i++) { + events.push_back(VehiclePropValue{ + .prop = static_cast(i), + // Generate 1 event every 1ms. + .timestamp = timestamp + static_cast(1000000 * i), + }); + } + generator->setEvents(events); + + getHub()->registerGenerator(0, std::move(generator)); + + waitForEvents(1); + + getHub()->unregisterGenerator(0); + clearEvents(); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + // It is possible that one last event would be generated after unregistering. + ASSERT_LE(getEvents().size(), 1u) + << "Must stop generating event after generator is unregistered"; +} + +TEST_F(FakeVehicleHalValueGeneratorsTest, testLinerFakeValueGeneratorFloat) { + std::unique_ptr generator = + std::make_unique(toInt(VehicleProperty::PERF_VEHICLE_SPEED), + /*middleValue=*/50.0, + /*initValue=*/30.0, + /*dispersion=*/50.0, + /*increment=*/20.0, + /*interval=*/10000000); + getHub()->registerGenerator(0, std::move(generator)); + + waitForEvents(10); + auto events = getEvents(); + + int value = 30; + for (size_t i = 0; i < 10; i++) { + EXPECT_EQ(std::vector({static_cast(value)}), events[i].value.floatValues); + value = (value + 20) % 100; + } +} + +TEST_F(FakeVehicleHalValueGeneratorsTest, testLinerFakeValueGeneratorInt32) { + std::unique_ptr generator = + std::make_unique(toInt(VehicleProperty::INFO_MODEL_YEAR), + /*middleValue=*/50.0, + /*initValue=*/30.0, + /*dispersion=*/50.0, + /*increment=*/20.0, + /*interval=*/10000000); + getHub()->registerGenerator(0, std::move(generator)); + + waitForEvents(10); + auto events = getEvents(); + + int value = 30; + for (size_t i = 0; i < 10; i++) { + EXPECT_EQ(std::vector({value}), events[i].value.int32Values); + value = (value + 20) % 100; + } +} + +TEST_F(FakeVehicleHalValueGeneratorsTest, testLinerFakeValueGeneratorInt64) { + std::unique_ptr generator = + std::make_unique(toInt(VehicleProperty::ANDROID_EPOCH_TIME), + /*middleValue=*/50.0, + /*initValue=*/30.0, + /*dispersion=*/50.0, + /*increment=*/20.0, + /*interval=*/10000000); + getHub()->registerGenerator(0, std::move(generator)); + + waitForEvents(10); + auto events = getEvents(); + + int value = 30; + for (size_t i = 0; i < 10; i++) { + EXPECT_EQ(std::vector({value}), events[i].value.int64Values); + value = (value + 20) % 100; + } +} + +TEST_F(FakeVehicleHalValueGeneratorsTest, testLinerFakeValueGeneratorUsingRequest) { + VehiclePropValue request; + request.value.int32Values = {0, toInt(VehicleProperty::PERF_VEHICLE_SPEED)}; + request.value.floatValues = {/*middleValue=*/50.0, /*dispersion=*/50.0, /*increment=*/20.0}; + request.value.int64Values = {/*interval=*/10000000}; + + std::unique_ptr generator = + std::make_unique(request); + getHub()->registerGenerator(0, std::move(generator)); + + waitForEvents(10); + auto events = getEvents(); + + int value = 50; + for (size_t i = 0; i < 10; i++) { + EXPECT_EQ(std::vector({static_cast(value)}), events[i].value.floatValues); + value = (value + 20) % 100; + } +} + +TEST_F(FakeVehicleHalValueGeneratorsTest, testLinerFakeValueGeneratorInvalidInitValue) { + std::unique_ptr generator = + std::make_unique(toInt(VehicleProperty::PERF_VEHICLE_SPEED), + /*middleValue=*/50.0, + // Out of range + /*initValue=*/110.0, + /*dispersion=*/50.0, + /*increment=*/20.0, + /*interval=*/10000000); + getHub()->registerGenerator(0, std::move(generator)); + + waitForEvents(10); + auto events = getEvents(); + + // Init value would be set to middleValue if given initValue is not valid. + int value = 50; + for (size_t i = 0; i < 10; i++) { + EXPECT_EQ(std::vector({static_cast(value)}), events[i].value.floatValues); + value = (value + 20) % 100; + } +} + +TEST_F(FakeVehicleHalValueGeneratorsTest, testJsonFakeValueGenerator) { + int64_t currentTime = elapsedRealtimeNano(); + + std::unique_ptr generator = + std::make_unique(getTestFilePath("prop.json"), 2); + getHub()->registerGenerator(0, std::move(generator)); + + std::vector expectedValues = { + VehiclePropValue{ + .areaId = 0, + .value.int32Values = {8}, + .prop = 289408000, + }, + VehiclePropValue{ + .areaId = 0, + .value.int32Values = {4}, + .prop = 289408000, + }, + VehiclePropValue{ + .areaId = 0, + .value.int32Values = {16}, + .prop = 289408000, + }, + VehiclePropValue{ + .areaId = 0, + .value.int32Values = {10}, + .prop = 289408000, + }, + }; + + // We have two iterations. + for (size_t i = 0; i < 4; i++) { + expectedValues.push_back(expectedValues[i]); + } + + waitForEvents(expectedValues.size()); + auto events = getEvents(); + + int64_t lastEventTime = currentTime; + for (auto& event : events) { + EXPECT_GT(event.timestamp, lastEventTime); + lastEventTime = event.timestamp; + event.timestamp = 0; + } + + EXPECT_EQ(events, expectedValues); +} + +TEST_F(FakeVehicleHalValueGeneratorsTest, testJsonFakeValueGeneratorIterateIndefinitely) { + std::unique_ptr generator = + std::make_unique(getTestFilePath("prop.json"), -1); + getHub()->registerGenerator(0, std::move(generator)); + + waitForEvents(40); +} + +TEST_F(FakeVehicleHalValueGeneratorsTest, testJsonFakeValueGeneratorUsingRequest) { + int64_t currentTime = elapsedRealtimeNano(); + + VehiclePropValue request = {.value = { + .stringValue = getTestFilePath("prop.json"), + .int32Values = {0, 2}, + }}; + + std::unique_ptr generator = + std::make_unique(request); + getHub()->registerGenerator(0, std::move(generator)); + + std::vector expectedValues = { + VehiclePropValue{ + .areaId = 0, + .value.int32Values = {8}, + .prop = 289408000, + }, + VehiclePropValue{ + .areaId = 0, + .value.int32Values = {4}, + .prop = 289408000, + }, + VehiclePropValue{ + .areaId = 0, + .value.int32Values = {16}, + .prop = 289408000, + }, + VehiclePropValue{ + .areaId = 0, + .value.int32Values = {10}, + .prop = 289408000, + }, + }; + + // We have two iterations. + for (size_t i = 0; i < 4; i++) { + expectedValues.push_back(expectedValues[i]); + } + + waitForEvents(expectedValues.size()); + auto events = getEvents(); + + int64_t lastEventTime = currentTime; + for (auto& event : events) { + EXPECT_GT(event.timestamp, lastEventTime); + lastEventTime = event.timestamp; + event.timestamp = 0; + } + + EXPECT_EQ(events, expectedValues); +} + +TEST_F(FakeVehicleHalValueGeneratorsTest, testJsonFakeValueGeneratorInvalidFile) { + VehiclePropValue request = {.value = { + .stringValue = getTestFilePath("prop_invalid.json"), + .int32Values = {0, 2}, + }}; + + std::unique_ptr generator = + std::make_unique(request); + getHub()->registerGenerator(0, std::move(generator)); + + ASSERT_TRUE(getEvents().empty()); +} + +TEST_F(FakeVehicleHalValueGeneratorsTest, testJsonFakeValueGeneratorNonExistingFile) { + VehiclePropValue request = {.value = { + .stringValue = "non_existing_file", + .int32Values = {0, 2}, + }}; + + std::unique_ptr generator = + std::make_unique(request); + getHub()->registerGenerator(0, std::move(generator)); + + ASSERT_TRUE(getEvents().empty()); +} + +TEST_F(FakeVehicleHalValueGeneratorsTest, testJsonFakeValueGeneratorDifferentTypes) { + std::unique_ptr generator = std::make_unique( + getTestFilePath("prop_different_types.json"), 1); + getHub()->registerGenerator(0, std::move(generator)); + + std::vector expectedValues = { + VehiclePropValue{ + .areaId = 0, + .value.int32Values = {1}, + .prop = 287310600, + }, + VehiclePropValue{ + .areaId = 0, + .value.int32Values = {2}, + .prop = 289408000, + }, + VehiclePropValue{ + .areaId = 0, + .value.floatValues = {3.3}, + .prop = 291504905, + }, + VehiclePropValue{ + .areaId = 0, + .value.int64Values = {4}, + .prop = 290457096, + }, + VehiclePropValue{ + .areaId = 0, + .value.stringValue = "test", + .prop = 286265094, + }, + VehiclePropValue{ + .areaId = 0, + .value.int32Values = {1, 2}, + .prop = 289476368, + }, + VehiclePropValue{ + .areaId = 0, + .value = + { + .int32Values = {1, 2}, + .int64Values = {3, 4}, + .floatValues = {5.5, 6.6}, + .stringValue = "test", + }, + .prop = 299896626, + }, + VehiclePropValue{ + .areaId = 0, + .value = + { + .int32Values = {1}, + .floatValues = {1.0}, + .byteValues = {0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}, + }, + .prop = 299896064, + }, + }; + + waitForEvents(expectedValues.size()); + auto events = getEvents(); + + for (auto& event : events) { + event.timestamp = 0; + } + + EXPECT_EQ(events, expectedValues); +} + +} // namespace fake +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/test/prop.json b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/test/prop.json new file mode 100644 index 0000000000000000000000000000000000000000..7123a002cc3656e640e9bdec7d6ca726ac6edc8f --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/test/prop.json @@ -0,0 +1,26 @@ +[ + { + "timestamp": 1000000, + "areaId": 0, + "value": 8, + "prop": 289408000 + }, + { + "timestamp": 2000000, + "areaId": 0, + "value": 4, + "prop": 289408000 + }, + { + "timestamp": 3000000, + "areaId": 0, + "value": 16, + "prop": 289408000 + }, + { + "timestamp": 4000000, + "areaId": 0, + "value": 10, + "prop": 289408000 + } +] diff --git a/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/test/prop_different_types.json b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/test/prop_different_types.json new file mode 100644 index 0000000000000000000000000000000000000000..38cd86b53a889eb961383c047cddab5591f44c6d --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/test/prop_different_types.json @@ -0,0 +1,74 @@ +[ + { + "timestamp": 1000000, + "areaId": 0, + "value": 1, + "prop": 287310600 + }, + { + "timestamp": 1000000, + "areaId": 0, + "value": 2, + "prop": 289408000 + }, + { + "timestamp": 1000000, + "areaId": 0, + "value": 3.3, + "prop": 291504905 + }, + { + "timestamp": 1000000, + "areaId": 0, + "value": 4, + "prop": 290457096 + }, + { + "timestamp": 1000000, + "areaId": 0, + "value": "test", + "prop": 286265094 + }, + { + "timestamp": 1000000, + "areaId": 0, + "value": [ + 1, + 2 + ], + "prop": 289476368 + }, + { + "timestamp": 1000000, + "areaId": 0, + "value": { + "int32Values": [ + 1, + 2 + ], + "int64Values": [ + 3, + 4 + ], + "floatValues": [ + 5.5, + 6.6 + ], + "stringValue": "test" + }, + "prop": 299896626 + }, + { + "timestamp": 1000000, + "areaId": 0, + "value": { + "int32Values": [ + 1 + ], + "floatValues": [ + 1 + ] + }, + "prop": 299896064 + } +] \ No newline at end of file diff --git a/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/test/prop_invalid.json b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/test/prop_invalid.json new file mode 100644 index 0000000000000000000000000000000000000000..98232c64fce9360c79f119cf6de8f670f69f1c44 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/test/prop_invalid.json @@ -0,0 +1 @@ +{ diff --git a/automotive/vehicle/aidl/impl/fake_impl/README.md b/automotive/vehicle/aidl/impl/current/fake_impl/README.md similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/README.md rename to automotive/vehicle/aidl/impl/current/fake_impl/README.md diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/Android.bp b/automotive/vehicle/aidl/impl/current/fake_impl/hardware/Android.bp similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/hardware/Android.bp rename to automotive/vehicle/aidl/impl/current/fake_impl/hardware/Android.bp diff --git a/automotive/vehicle/aidl/impl/current/fake_impl/hardware/include/FakeVehicleHardware.h b/automotive/vehicle/aidl/impl/current/fake_impl/hardware/include/FakeVehicleHardware.h new file mode 100644 index 0000000000000000000000000000000000000000..5916307a53b9cbb96a8051d221d735082ff47569 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/fake_impl/hardware/include/FakeVehicleHardware.h @@ -0,0 +1,347 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_aidl_impl_fake_impl_hardware_include_FakeVehicleHardware_H_ +#define android_hardware_automotive_vehicle_aidl_impl_fake_impl_hardware_include_FakeVehicleHardware_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace fake { + +class FakeVehicleHardware : public IVehicleHardware { + public: + using ValueResultType = VhalResult; + + FakeVehicleHardware(); + + FakeVehicleHardware(std::string defaultConfigDir, std::string overrideConfigDir, + bool forceOverride); + + // s2rS2dConfig is the config for whether S2R or S2D is supported, must be a bit flag combining + // values from VehicleApPowerStateConfigFlag. + // The default implementation is reading this from system property: + // "ro.vendor.fake_vhal.ap_power_state_req.config". + FakeVehicleHardware(std::string defaultConfigDir, std::string overrideConfigDir, + bool forceOverride, int32_t s2rS2dConfig); + + ~FakeVehicleHardware(); + + // Get all the property configs. + std::vector + getAllPropertyConfigs() const override; + + // Set property values asynchronously. Server could return before the property set requests + // are sent to vehicle bus or before property set confirmation is received. The callback is + // safe to be called after the function returns and is safe to be called in a different thread. + aidl::android::hardware::automotive::vehicle::StatusCode setValues( + std::shared_ptr callback, + const std::vector& + requests) override; + + // Get property values asynchronously. Server could return before the property values are ready. + // The callback is safe to be called after the function returns and is safe to be called in a + // different thread. + aidl::android::hardware::automotive::vehicle::StatusCode getValues( + std::shared_ptr callback, + const std::vector& + requests) const override; + + // Dump debug information in the server. + DumpResult dump(const std::vector& options) override; + + // Check whether the system is healthy, return {@code StatusCode::OK} for healthy. + aidl::android::hardware::automotive::vehicle::StatusCode checkHealth() override; + + // Register a callback that would be called when there is a property change event from vehicle. + void registerOnPropertyChangeEvent( + std::unique_ptr callback) override; + + // Register a callback that would be called when there is a property set error event from + // vehicle. + void registerOnPropertySetErrorEvent( + std::unique_ptr callback) override; + + // Subscribe to a new [propId, areaId] or change the update rate. + aidl::android::hardware::automotive::vehicle::StatusCode subscribe( + aidl::android::hardware::automotive::vehicle::SubscribeOptions options) override; + + // Unsubscribe to a [propId, areaId]. + aidl::android::hardware::automotive::vehicle::StatusCode unsubscribe(int32_t propId, + int32_t areaId) override; + + protected: + // mValuePool is also used in mServerSidePropStore. + const std::shared_ptr mValuePool; + const std::shared_ptr mServerSidePropStore; + + const std::string mDefaultConfigDir; + const std::string mOverrideConfigDir; + + ValueResultType getValue( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const; + + VhalResult setValue( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value); + + bool UseOverrideConfigDir(); + + private: + // Expose private methods to unit test. + friend class FakeVehicleHardwareTestHelper; + + template + struct RequestWithCallback { + RequestType request; + std::shared_ptr callback; + }; + + template + class PendingRequestHandler { + public: + PendingRequestHandler(FakeVehicleHardware* hardware); + + void addRequest(RequestType request, std::shared_ptr callback); + + void stop(); + + private: + FakeVehicleHardware* mHardware; + std::thread mThread; + ConcurrentQueue> mRequests; + + void handleRequestsOnce(); + }; + + struct RefreshInfo { + VehiclePropertyStore::EventMode eventMode; + int64_t intervalInNanos; + }; + + struct ActionForInterval { + std::unordered_set propIdAreaIdsToRefresh; + std::shared_ptr recurrentAction; + }; + + const std::unique_ptr mFakeObd2Frame; + const std::unique_ptr mFakeUserHal; + // RecurrentTimer is thread-safe. + std::unique_ptr mRecurrentTimer; + // GeneratorHub is thread-safe. + std::unique_ptr mGeneratorHub; + + // Only allowed to set once. + std::unique_ptr mOnPropertyChangeCallback; + std::unique_ptr mOnPropertySetErrorCallback; + + std::mutex mLock; + std::unordered_map mRefreshInfoByPropIdAreaId + GUARDED_BY(mLock); + std::unordered_map mActionByIntervalInNanos GUARDED_BY(mLock); + std::unordered_map + mSavedProps GUARDED_BY(mLock); + std::unordered_set mSubOnChangePropIdAreaIds GUARDED_BY(mLock); + // PendingRequestHandler is thread-safe. + mutable PendingRequestHandler + mPendingGetValueRequests; + mutable PendingRequestHandler + mPendingSetValueRequests; + + // Set of HVAC properties dependent on HVAC_POWER_ON + std::unordered_set hvacPowerDependentProps; + + const bool mForceOverride; + bool mAddExtraTestVendorConfigs = false; + + // Only used during initialization. + JsonConfigLoader mLoader; + + // Only used during initialization. If not empty, points to an external grpc server that + // provides power controlling related properties. + std::string mPowerControllerServiceAddress = ""; + + void init(int32_t s2rS2dConfig); + // Stores the initial value to property store. + void storePropInitialValue(const ConfigDeclaration& config); + // The callback that would be called when a vehicle property value change happens. + void onValueChangeCallback( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) + EXCLUDES(mLock); + // The callback that would be called when multiple vehicle property value changes happen. + void onValuesChangeCallback( + std::vector values) + EXCLUDES(mLock); + // Load the config files in format '*.json' from the directory and parse the config files + // into a map from property ID to ConfigDeclarations. + bool loadPropConfigsFromDir(const std::string& dirPath, + std::unordered_map* configs); + // Function to be called when a value change event comes from vehicle bus. In our fake + // implementation, this function is only called during "--inject-event" dump command. + void eventFromVehicleBus( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value); + + int getHvacTempNumIncrements(int requestedTemp, int minTemp, int maxTemp, int increment); + void updateHvacTemperatureValueSuggestionInput( + const std::vector& hvacTemperatureSetConfigArray, + std::vector* hvacTemperatureValueSuggestionInput); + VhalResult setHvacTemperatureValueSuggestion( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& + hvacTemperatureValueSuggestion); + VhalResult maybeSetSpecialValue( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value, + bool* isSpecialValue); + VhalResult isCruiseControlTypeStandard() const; + ValueResultType maybeGetSpecialValue( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value, + bool* isSpecialValue) const; + VhalResult setApPowerStateReport( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value); + VhalResult setApPowerStateReqShutdown( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value); + VehiclePropValuePool::RecyclableType createApPowerStateReq( + aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq state); + VehiclePropValuePool::RecyclableType createAdasStateReq(int32_t propertyId, int32_t areaId, + int32_t state); + VhalResult setUserHalProp( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value); + ValueResultType getUserHalProp( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const; + ValueResultType getEchoReverseBytes( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const; + bool isHvacPropAndHvacNotAvailable(int32_t propId, int32_t areaId) const; + VhalResult isAdasPropertyAvailable(int32_t adasStatePropertyId) const; + VhalResult synchronizeHvacTemp(int32_t hvacDualOnAreaId, + std::optional newTempC) const; + std::optional getSyncedAreaIdIfHvacDualOn(int32_t hvacTemperatureSetAreaId) const; + ValueResultType getPowerPropFromExternalService(int32_t propId) const; + ValueResultType getVehicleInUse( + android::hardware::automotive::remoteaccess::PowerController::Stub* clientStub) const; + ValueResultType getApPowerBootupReason( + android::hardware::automotive::remoteaccess::PowerController::Stub* clientStub) const; + + std::unordered_map loadConfigDeclarations(); + + std::string dumpAllProperties(); + std::string dumpOnePropertyByConfig( + int rowNumber, + const aidl::android::hardware::automotive::vehicle::VehiclePropConfig& config); + std::string dumpOnePropertyById(int32_t propId, int32_t areaId); + std::string dumpHelp(); + std::string dumpListProperties(); + std::string dumpSpecificProperty(const std::vector& options); + std::string dumpSetProperties(const std::vector& options); + std::string dumpGetPropertyWithArg(const std::vector& options); + std::string dumpSaveProperty(const std::vector& options); + std::string dumpRestoreProperty(const std::vector& options); + std::string dumpInjectEvent(const std::vector& options); + std::string dumpSubscriptions(); + + std::vector getOptionValues(const std::vector& options, + size_t* index); + android::base::Result + parsePropOptions(const std::vector& options); + android::base::Result> parseHexString(const std::string& s); + + android::base::Result checkArgumentsSize(const std::vector& options, + size_t minSize); + aidl::android::hardware::automotive::vehicle::GetValueResult handleGetValueRequest( + const aidl::android::hardware::automotive::vehicle::GetValueRequest& request); + aidl::android::hardware::automotive::vehicle::SetValueResult handleSetValueRequest( + const aidl::android::hardware::automotive::vehicle::SetValueRequest& request); + + std::string genFakeDataCommand(const std::vector& options); + void sendHvacPropertiesCurrentValues(int32_t areaId, int32_t hvacPowerOnVal); + void sendAdasPropertiesState(int32_t propertyId, int32_t state); + void generateVendorConfigs( + std::vector&) const; + + aidl::android::hardware::automotive::vehicle::StatusCode subscribePropIdAreaIdLocked( + int32_t propId, int32_t areaId, float sampleRateHz, bool enableVariableUpdateRate, + const aidl::android::hardware::automotive::vehicle::VehiclePropConfig& + vehiclePropConfig) REQUIRES(mLock); + + void registerRefreshLocked(PropIdAreaId propIdAreaId, VehiclePropertyStore::EventMode eventMode, + float sampleRateHz) REQUIRES(mLock); + void unregisterRefreshLocked(PropIdAreaId propIdAreaId) REQUIRES(mLock); + void refreshTimestampForInterval(int64_t intervalInNanos) EXCLUDES(mLock); + + static aidl::android::hardware::automotive::vehicle::VehiclePropValue createHwInputKeyProp( + aidl::android::hardware::automotive::vehicle::VehicleHwKeyInputAction action, + int32_t keyCode, int32_t targetDisplay); + static aidl::android::hardware::automotive::vehicle::VehiclePropValue createHwKeyInputV2Prop( + int32_t area, int32_t targetDisplay, int32_t keyCode, int32_t action, + int32_t repeatCount); + static aidl::android::hardware::automotive::vehicle::VehiclePropValue createHwMotionInputProp( + int32_t area, int32_t display, int32_t inputType, int32_t action, int32_t buttonState, + int32_t pointerCount, int32_t pointerId[], int32_t toolType[], float xData[], + float yData[], float pressure[], float size[]); + + static std::string genFakeDataHelp(); + static std::string parseErrMsg(std::string fieldName, std::string value, std::string type); + static bool isVariableUpdateRateSupported( + const aidl::android::hardware::automotive::vehicle::VehiclePropConfig& + vehiclePropConfig, + int32_t areaId); + template + static android::base::Result safelyParseInt(int index, const std::string& s) { + T out; + if (!::android::base::ParseInt(s, &out)) { + return android::base::Error() << android::base::StringPrintf( + "non-integer argument at index %d: %s\n", index, s.c_str()); + } + return out; + } + static android::base::Result safelyParseFloat(int index, const std::string& s); + static android::base::Result parsePropId(const std::vector& options, + size_t index); + static android::base::Result parseAreaId(const std::vector& options, + size_t index, int32_t propId); +}; + +} // namespace fake +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_aidl_impl_fake_impl_hardware_include_FakeVehicleHardware_H_ diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp b/automotive/vehicle/aidl/impl/current/fake_impl/hardware/src/FakeVehicleHardware.cpp similarity index 99% rename from automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp rename to automotive/vehicle/aidl/impl/current/fake_impl/hardware/src/FakeVehicleHardware.cpp index a6247a70b7b8110f74c4eb505580d33728fa4c9c..52daf682b1c39c3a7f95a82589719bac18a0d05e 100644 --- a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp +++ b/automotive/vehicle/aidl/impl/current/fake_impl/hardware/src/FakeVehicleHardware.cpp @@ -928,8 +928,8 @@ FakeVehicleHardware::ValueResultType FakeVehicleHardware::getVehicleInUse( grpc::ClientContext context; auto status = clientStub->IsVehicleInUse(&context, request, &response); if (!status.ok()) { - return StatusError(StatusCode::TRY_AGAIN) << "Cannot connect to GRPC service " - << ", error: " << status.error_message(); + return StatusError(StatusCode::TRY_AGAIN) + << "Cannot connect to GRPC service " << ", error: " << status.error_message(); } auto result = mValuePool->obtainBoolean(response.isvehicleinuse()); result->prop = toInt(VehicleProperty::VEHICLE_IN_USE); @@ -946,8 +946,8 @@ FakeVehicleHardware::ValueResultType FakeVehicleHardware::getApPowerBootupReason grpc::ClientContext context; auto status = clientStub->GetApPowerBootupReason(&context, request, &response); if (!status.ok()) { - return StatusError(StatusCode::TRY_AGAIN) << "Cannot connect to GRPC service " - << ", error: " << status.error_message(); + return StatusError(StatusCode::TRY_AGAIN) + << "Cannot connect to GRPC service " << ", error: " << status.error_message(); } auto result = mValuePool->obtainInt32(response.bootupreason()); result->prop = toInt(VehicleProperty::AP_POWER_BOOTUP_REASON); diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/Android.bp b/automotive/vehicle/aidl/impl/current/fake_impl/hardware/test/Android.bp similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/hardware/test/Android.bp rename to automotive/vehicle/aidl/impl/current/fake_impl/hardware/test/Android.bp diff --git a/automotive/vehicle/aidl/impl/current/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp b/automotive/vehicle/aidl/impl/current/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0dd5e9f11980a2f14735c89862ec06b6a3f89ee2 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp @@ -0,0 +1,3893 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace aidl { +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +void PrintTo(const VehiclePropValue& value, std::ostream* os) { + *os << "\n( " << value.toString() << " )\n"; +} + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android +} // namespace aidl + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace fake { +namespace { + +using ::aidl::android::hardware::automotive::vehicle::CruiseControlCommand; +using ::aidl::android::hardware::automotive::vehicle::CruiseControlType; +using ::aidl::android::hardware::automotive::vehicle::ErrorState; +using ::aidl::android::hardware::automotive::vehicle::GetValueRequest; +using ::aidl::android::hardware::automotive::vehicle::GetValueResult; +using ::aidl::android::hardware::automotive::vehicle::RawPropValues; +using ::aidl::android::hardware::automotive::vehicle::SetValueRequest; +using ::aidl::android::hardware::automotive::vehicle::SetValueResult; +using ::aidl::android::hardware::automotive::vehicle::StatusCode; +using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions; +using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateConfigFlag; +using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReport; +using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq; +using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateShutdownParam; +using ::aidl::android::hardware::automotive::vehicle::VehicleAreaMirror; +using ::aidl::android::hardware::automotive::vehicle::VehicleAreaSeat; +using ::aidl::android::hardware::automotive::vehicle::VehicleHwKeyInputAction; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig; +using ::aidl::android::hardware::automotive::vehicle::VehicleProperty; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; +using ::aidl::android::hardware::automotive::vehicle::VehicleUnit; +using ::android::base::expected; +using ::android::base::ScopedLockAssertion; +using ::android::base::StringPrintf; +using ::android::base::unexpected; +using ::testing::AnyOfArray; +using ::testing::ContainerEq; +using ::testing::ContainsRegex; +using ::testing::Eq; +using ::testing::HasSubstr; +using ::testing::IsSubsetOf; +using ::testing::UnorderedElementsAre; +using ::testing::WhenSortedBy; + +using std::chrono::milliseconds; + +constexpr int INVALID_PROP_ID = 0; +constexpr char CAR_MAKE[] = "Default Car"; + +} // namespace + +// A helper class to access private methods for FakeVehicleHardware. +class FakeVehicleHardwareTestHelper { + public: + FakeVehicleHardwareTestHelper(FakeVehicleHardware* hardware) { mHardware = hardware; } + + std::unordered_map loadConfigDeclarations() { + return mHardware->loadConfigDeclarations(); + } + + std::unordered_set getHvacPowerDependentProps() { + return mHardware->hvacPowerDependentProps; + } + + private: + FakeVehicleHardware* mHardware; +}; + +class FakeVehicleHardwareTest : public ::testing::Test { + protected: + void SetUp() override { + mHardware = std::make_unique(android::base::GetExecutableDirectory(), + /*overrideConfigDir=*/"", + /*forceOverride=*/false); + auto callback = std::make_unique( + [this](const std::vector& values) { + onPropertyChangeEvent(values); + }); + getHardware()->registerOnPropertyChangeEvent(std::move(callback)); + mSetValuesCallback = std::make_shared( + [this](std::vector results) { onSetValues(results); }); + mGetValuesCallback = std::make_shared( + [this](std::vector results) { onGetValues(results); }); + } + + void TearDown() override { + // mHardware uses callback which contains reference to 'this', so it has to be destroyed + // before 'this'. + mHardware.reset(); + } + + FakeVehicleHardware* getHardware() { return mHardware.get(); } + + void setHardware(std::unique_ptr hardware) { + mHardware = std::move(hardware); + } + + static SubscribeOptions newSubscribeOptions(int32_t propId, int32_t areaId, + float sampleRateHz) { + SubscribeOptions options; + options.areaIds = {areaId}; + options.propId = propId; + options.sampleRate = sampleRateHz; + return options; + } + + StatusCode setValues(const std::vector& requests) { + { + std::scoped_lock lockGuard(mLock); + for (const auto& request : requests) { + mPendingSetValueRequests.insert(request.requestId); + } + } + if (StatusCode status = getHardware()->setValues(mSetValuesCallback, requests); + status != StatusCode::OK) { + return status; + } + std::unique_lock lk(mLock); + // Wait for the onSetValueResults. + bool result = mCv.wait_for(lk, milliseconds(1000), [this] { + ScopedLockAssertion lockAssertion(mLock); + return mPendingSetValueRequests.size() == 0; + }); + if (!result) { + ALOGE("wait for callbacks for setValues timed-out"); + return StatusCode::INTERNAL_ERROR; + } + return StatusCode::OK; + } + + StatusCode getValues(const std::vector& requests) { + { + std::scoped_lock lockGuard(mLock); + for (const auto& request : requests) { + mPendingGetValueRequests.insert(request.requestId); + } + } + if (StatusCode status = getHardware()->getValues(mGetValuesCallback, requests); + status != StatusCode::OK) { + return status; + } + std::unique_lock lk(mLock); + // Wait for the onGetValueResults. + bool result = mCv.wait_for(lk, milliseconds(1000), [this] { + ScopedLockAssertion lockAssertion(mLock); + return mPendingGetValueRequests.size() == 0; + }); + if (!result) { + ALOGE("wait for callbacks for getValues timed-out"); + return StatusCode::INTERNAL_ERROR; + } + return StatusCode::OK; + } + + StatusCode setValue(const VehiclePropValue& value) { + std::vector requests = { + SetValueRequest{ + .requestId = 0, + .value = value, + }, + }; + + if (StatusCode status = setValues(requests); status != StatusCode::OK) { + return status; + } + + std::vector resultVector = getSetValueResults(); + const SetValueResult& result = resultVector.back(); + + if (result.requestId != 0) { + ALOGE("request ID mismatch, got %" PRId64 ", expect 0", result.requestId); + return StatusCode::INTERNAL_ERROR; + } + + return result.status; + } + + expected getValue(const VehiclePropValue& value) { + std::vector requests = { + GetValueRequest{ + .requestId = 0, + .prop = value, + }, + }; + + if (StatusCode status = getValues(requests); status != StatusCode::OK) { + return unexpected(status); + } + + std::vector resultVector = getGetValueResults(); + const GetValueResult& result = resultVector.back(); + if (result.requestId != 0) { + ALOGE("request ID mismatch, got %" PRId64 ", expect 0", result.requestId); + return unexpected(StatusCode::INTERNAL_ERROR); + } + + if (result.status != StatusCode::OK) { + return unexpected(result.status); + } + + if (!result.prop.has_value()) { + ALOGE("%s", "result property is empty"); + return unexpected(StatusCode::INTERNAL_ERROR); + } + + return result.prop.value(); + } + + template + int getStatus(expected result) { + return toInt(result.error()); + } + + void onSetValues(std::vector results) { + std::scoped_lock lockGuard(mLock); + for (auto& result : results) { + mSetValueResults.push_back(result); + mPendingSetValueRequests.erase(result.requestId); + } + mCv.notify_all(); + } + + std::vector getSetValueResults() { + std::scoped_lock lockGuard(mLock); + return mSetValueResults; + } + + void onGetValues(std::vector results) { + std::scoped_lock lockGuard(mLock); + for (auto& result : results) { + mGetValueResults.push_back(result); + mPendingGetValueRequests.erase(result.requestId); + } + mCv.notify_all(); + } + + std::vector getGetValueResults() { + std::scoped_lock lockGuard(mLock); + return mGetValueResults; + } + + void onPropertyChangeEvent(std::vector values) { + std::scoped_lock lockGuard(mLock); + for (auto& value : values) { + mChangedProperties.push_back(value); + PropIdAreaId propIdAreaId{ + .propId = value.prop, + .areaId = value.areaId, + }; + mEventCount[propIdAreaId]++; + } + mCv.notify_all(); + } + + std::vector getChangedProperties() { + std::scoped_lock lockGuard(mLock); + return mChangedProperties; + } + + bool waitForChangedProperties(size_t count, milliseconds timeout) { + std::unique_lock lk(mLock); + return mCv.wait_for(lk, timeout, [this, count] { + ScopedLockAssertion lockAssertion(mLock); + return mChangedProperties.size() >= count; + }); + } + + bool waitForChangedProperties(int32_t propId, int32_t areaId, size_t count, + milliseconds timeout) { + PropIdAreaId propIdAreaId{ + .propId = propId, + .areaId = areaId, + }; + std::unique_lock lk(mLock); + return mCv.wait_for(lk, timeout, [this, propIdAreaId, count] { + ScopedLockAssertion lockAssertion(mLock); + return mEventCount[propIdAreaId] >= count; + }); + } + + void clearChangedProperties() { + std::scoped_lock lockGuard(mLock); + mEventCount.clear(); + mChangedProperties.clear(); + } + + size_t getEventCount(int32_t propId, int32_t areaId) { + PropIdAreaId propIdAreaId{ + .propId = propId, + .areaId = areaId, + }; + std::scoped_lock lockGuard(mLock); + return mEventCount[propIdAreaId]; + } + + void subscribe(int32_t propId, int32_t areaId, float sampleRateHz) { + ASSERT_EQ(StatusCode::OK, + getHardware()->subscribe(newSubscribeOptions(propId, areaId, sampleRateHz))) + << "failed to subscribe to propId: " << propId << "areaId: " << areaId + << ", sampleRateHz: " << sampleRateHz; + } + + static void addSetValueRequest(std::vector& requests, + std::vector& expectedResults, int64_t requestId, + const VehiclePropValue& value, StatusCode expectedStatus) { + SetValueRequest request; + request.requestId = requestId; + request.value = value; + request.value.timestamp = elapsedRealtimeNano(); + requests.push_back(std::move(request)); + + SetValueResult result; + result.requestId = requestId; + result.status = expectedStatus; + expectedResults.push_back(std::move(result)); + } + + static void addGetValueRequest(std::vector& requests, + std::vector& expectedResults, int64_t requestId, + const VehiclePropValue& value, StatusCode expectedStatus) { + GetValueRequest request; + request.requestId = requestId; + request.prop.prop = value.prop; + request.prop.areaId = value.areaId; + requests.push_back(std::move(request)); + + GetValueResult result; + result.requestId = requestId; + result.status = expectedStatus; + if (expectedStatus == StatusCode::OK) { + result.prop = value; + } + expectedResults.push_back(std::move(result)); + } + + std::vector getTestPropValues() { + VehiclePropValue oilLevel = { + .prop = toInt(VehicleProperty::ENGINE_OIL_LEVEL), + .value = {.int32Values = {1}}, + }; + + VehiclePropValue leftHvacTemp = { + .prop = toInt(VehicleProperty::HVAC_TEMPERATURE_CURRENT), + .value = {.floatValues = {170.0}}, + .areaId = SEAT_1_LEFT, + }; + + VehiclePropValue rightHvacTemp = { + .prop = toInt(VehicleProperty::HVAC_TEMPERATURE_CURRENT), + .value = {.floatValues = {180.0}}, + .areaId = SEAT_1_RIGHT, + }; + + return {oilLevel, leftHvacTemp, rightHvacTemp}; + } + + struct PropValueCmp { + bool operator()(const VehiclePropValue& a, const VehiclePropValue& b) const { + return (a.prop < b.prop) || ((a.prop == b.prop) && (a.value < b.value)) || + ((a.prop == b.prop) && (a.value == b.value) && (a.areaId < b.areaId)); + } + } mPropValueCmp; + + std::unique_ptr getVehiclePropConfig(int32_t propertyId) { + auto configs = mHardware->getAllPropertyConfigs(); + for (auto& config : configs) { + if (config.prop == propertyId) { + auto ptr = std::make_unique(); + ptr->prop = config.prop; + ptr->access = config.access; + ptr->changeMode = config.changeMode; + ptr->areaConfigs = config.areaConfigs; + ptr->configArray = config.configArray; + ptr->configString = config.configString; + ptr->minSampleRate = config.minSampleRate; + ptr->maxSampleRate = config.maxSampleRate; + return ptr; + } + } + return std::unique_ptr(nullptr); + } + + private: + std::unique_ptr mHardware; + std::shared_ptr mSetValuesCallback; + std::shared_ptr mGetValuesCallback; + std::condition_variable mCv; + std::mutex mLock; + std::unordered_map mEventCount GUARDED_BY(mLock); + std::vector mSetValueResults GUARDED_BY(mLock); + std::vector mGetValueResults GUARDED_BY(mLock); + std::vector mChangedProperties GUARDED_BY(mLock); + std::unordered_set mPendingSetValueRequests GUARDED_BY(mLock); + std::unordered_set mPendingGetValueRequests GUARDED_BY(mLock); +}; + +TEST_F(FakeVehicleHardwareTest, testGetAllPropertyConfigs) { + std::vector configs = getHardware()->getAllPropertyConfigs(); + + FakeVehicleHardwareTestHelper helper(getHardware()); + ASSERT_EQ(configs.size(), helper.loadConfigDeclarations().size()); +} + +TEST_F(FakeVehicleHardwareTest, testGetAllPropertyConfigs_defaultSupportVUR) { + std::vector configs = getHardware()->getAllPropertyConfigs(); + + for (const auto& config : configs) { + bool expectedSupportVUR = true; + if (config.prop == toInt(VehicleProperty::VHAL_HEARTBEAT) || + config.prop == toInt(VehicleProperty::CLUSTER_HEARTBEAT)) { + expectedSupportVUR = false; + } + EXPECT_GE(config.areaConfigs.size(), 1u) + << "expect at least one area config, including global area config, propId: " + << config.prop; + if (config.areaConfigs.size() == 0) { + continue; + } + for (const auto& areaConfig : config.areaConfigs) { + EXPECT_EQ(areaConfig.supportVariableUpdateRate, expectedSupportVUR) + << "unexpected supportVariableUpdateRate for propId: " << config.prop + << ", areaId: " << areaConfig.areaId; + } + } +} + +TEST_F(FakeVehicleHardwareTest, testGetDefaultValues) { + std::vector getValueRequests; + std::vector expectedGetValueResults; + int64_t requestId = 1; + + FakeVehicleHardwareTestHelper helper(getHardware()); + for (auto& [propId, config] : helper.loadConfigDeclarations()) { + if (obd2frame::FakeObd2Frame::isDiagnosticProperty(config.config)) { + // Ignore storing default value for diagnostic property. They have special get/set + // logic. + continue; + } + + if (FakeUserHal::isSupported(config.config.prop)) { + // Ignore fake user HAL properties, they have special logic for getting values. + continue; + } + + if (propId == toInt(TestVendorProperty::ECHO_REVERSE_BYTES)) { + // Ignore ECHO_REVERSE_BYTES, it has special logic. + continue; + } + + if (propId == toInt(TestVendorProperty::VENDOR_PROPERTY_FOR_ERROR_CODE_TESTING)) { + // Ignore VENDOR_PROPERTY_FOR_ERROR_CODE_TESTING, it has special logic. + continue; + } + + if (propId == toInt(VehicleProperty::VEHICLE_IN_USE) || + propId == toInt(VehicleProperty::AP_POWER_BOOTUP_REASON)) { + // These may be controller by an external power control unit. + continue; + } + + if (isGlobalProp(propId)) { + if (config.initialValue == RawPropValues{}) { + addGetValueRequest(getValueRequests, expectedGetValueResults, requestId++, + VehiclePropValue{.prop = propId}, StatusCode::NOT_AVAILABLE); + continue; + } + addGetValueRequest(getValueRequests, expectedGetValueResults, requestId++, + VehiclePropValue{ + .prop = propId, + .value = config.initialValue, + }, + StatusCode::OK); + continue; + } + for (auto areaConfig : config.config.areaConfigs) { + StatusCode status = StatusCode::OK; + VehiclePropValue propValue{ + .prop = propId, + .areaId = areaConfig.areaId, + }; + if (config.initialAreaValues.empty()) { + if (config.initialValue == RawPropValues{}) { + status = StatusCode::NOT_AVAILABLE; + } else { + propValue.value = config.initialValue; + } + } else if (auto valueForAreaIt = config.initialAreaValues.find(areaConfig.areaId); + valueForAreaIt != config.initialAreaValues.end()) { + propValue.value = valueForAreaIt->second; + } else { + status = StatusCode::NOT_AVAILABLE; + } + addGetValueRequest(getValueRequests, expectedGetValueResults, requestId++, propValue, + status); + } + } + + // In our implementation, this would finish immediately. + StatusCode status = getValues(getValueRequests); + + ASSERT_EQ(status, StatusCode::OK); + + std::vector getValueResultsWithNoTimestamp; + for (auto& result : getGetValueResults()) { + GetValueResult resultCopy = result; + resultCopy.prop->timestamp = 0; + getValueResultsWithNoTimestamp.push_back(std::move(resultCopy)); + } + ASSERT_THAT(getValueResultsWithNoTimestamp, ContainerEq(expectedGetValueResults)); +} + +TEST_F(FakeVehicleHardwareTest, testSetValues) { + std::vector requests; + std::vector expectedResults; + + int64_t requestId = 1; + for (auto& value : getTestPropValues()) { + addSetValueRequest(requests, expectedResults, requestId++, value, StatusCode::OK); + } + + StatusCode status = setValues(requests); + + ASSERT_EQ(status, StatusCode::OK); + + // Although callback might be called asynchronously, in our implementation, the callback would + // be called before setValues returns. + ASSERT_THAT(getSetValueResults(), ContainerEq(expectedResults)); +} + +TEST_F(FakeVehicleHardwareTest, testSetValuesError) { + std::vector requests; + std::vector expectedResults; + + int64_t requestId = 1; + + VehiclePropValue invalidProp = { + .prop = INVALID_PROP_ID, + }; + addSetValueRequest(requests, expectedResults, requestId++, invalidProp, + StatusCode::INVALID_ARG); + + for (auto& value : getTestPropValues()) { + addSetValueRequest(requests, expectedResults, requestId++, value, StatusCode::OK); + } + + StatusCode status = setValues(requests); + + ASSERT_EQ(status, StatusCode::OK); + + // Although callback might be called asynchronously, in our implementation, the callback would + // be called before setValues returns. + ASSERT_THAT(getSetValueResults(), ContainerEq(expectedResults)); +} + +TEST_F(FakeVehicleHardwareTest, testSetValues_getUpdateEvents) { + auto testValues = getTestPropValues(); + std::vector requests; + std::vector expectedResults; + int64_t requestId = 1; + for (auto& value : testValues) { + subscribe(value.prop, value.areaId, /*sampleRateHz=*/0); + addSetValueRequest(requests, expectedResults, requestId++, value, StatusCode::OK); + } + int64_t timestamp = elapsedRealtimeNano(); + + StatusCode status = setValues(requests); + + ASSERT_EQ(status, StatusCode::OK); + + auto updatedValues = getChangedProperties(); + std::vector updatedValuesWithNoTimestamp; + for (auto& value : updatedValues) { + ASSERT_GE(value.timestamp, timestamp); + VehiclePropValue valueCopy = value; + valueCopy.timestamp = 0; + updatedValuesWithNoTimestamp.push_back(std::move(valueCopy)); + } + + ASSERT_THAT(updatedValuesWithNoTimestamp, WhenSortedBy(mPropValueCmp, Eq(testValues))); +} + +TEST_F(FakeVehicleHardwareTest, testReadValues) { + std::vector setValueRequests; + std::vector expectedSetValueResults; + + int64_t requestId = 1; + for (auto& value : getTestPropValues()) { + addSetValueRequest(setValueRequests, expectedSetValueResults, requestId++, value, + StatusCode::OK); + } + int64_t timestamp = elapsedRealtimeNano(); + + // In our implementation, this would finish immediately. + StatusCode status = setValues(setValueRequests); + + ASSERT_EQ(status, StatusCode::OK); + + std::vector getValueRequests; + std::vector expectedGetValueResults; + for (auto& value : getTestPropValues()) { + addGetValueRequest(getValueRequests, expectedGetValueResults, requestId++, value, + StatusCode::OK); + } + + // In our implementation, this would finish immediately. + status = getValues(getValueRequests); + + ASSERT_EQ(status, StatusCode::OK); + + std::vector getValueResultsWithNoTimestamp; + for (auto& result : getGetValueResults()) { + ASSERT_GE(result.prop->timestamp, timestamp); + GetValueResult resultCopy = result; + resultCopy.prop->timestamp = 0; + getValueResultsWithNoTimestamp.push_back(std::move(resultCopy)); + } + ASSERT_THAT(getValueResultsWithNoTimestamp, ContainerEq(expectedGetValueResults)); +} + +TEST_F(FakeVehicleHardwareTest, testReadValuesErrorInvalidProp) { + std::vector setValueRequests; + std::vector expectedSetValueResults; + + int64_t requestId = 1; + for (auto& value : getTestPropValues()) { + addSetValueRequest(setValueRequests, expectedSetValueResults, requestId++, value, + StatusCode::OK); + } + + // In our implementation, this would finish immediately. + StatusCode status = setValues(setValueRequests); + + ASSERT_EQ(status, StatusCode::OK); + + std::vector getValueRequests; + std::vector expectedGetValueResults; + VehiclePropValue invalidProp = { + .prop = INVALID_PROP_ID, + }; + addGetValueRequest(getValueRequests, expectedGetValueResults, requestId++, invalidProp, + StatusCode::INVALID_ARG); + + // In our implementation, this would finish immediately. + status = getValues(getValueRequests); + + ASSERT_EQ(status, StatusCode::OK); + ASSERT_THAT(getGetValueResults(), ContainerEq(expectedGetValueResults)); +} + +TEST_F(FakeVehicleHardwareTest, testReadValuesErrorNotAvailable) { + std::vector getValueRequests; + std::vector expectedGetValueResults; + // VEHICLE_MAP_SERVICE does not have initial value, 'get' must always return + // StatusCode::NOT_AVAILABLE. + addGetValueRequest(getValueRequests, expectedGetValueResults, 0, + VehiclePropValue{ + .prop = VEHICLE_MAP_SERVICE, + }, + StatusCode::NOT_AVAILABLE); + + // In our implementation, this would finish immediately. + StatusCode status = getValues(getValueRequests); + + ASSERT_EQ(status, StatusCode::OK); + ASSERT_THAT(getGetValueResults(), ContainerEq(expectedGetValueResults)); +} + +TEST_F(FakeVehicleHardwareTest, testSetStatusMustIgnore) { + VehiclePropValue testValue = getTestPropValues()[0]; + testValue.status = VehiclePropertyStatus::UNAVAILABLE; + + std::vector setValueRequests; + std::vector expectedSetValueResults; + + int64_t requestId = 1; + addSetValueRequest(setValueRequests, expectedSetValueResults, requestId++, testValue, + StatusCode::OK); + + // In our implementation, this would finish immediately. + StatusCode status = setValues(setValueRequests); + + ASSERT_EQ(status, StatusCode::OK); + ASSERT_THAT(getSetValueResults(), ContainerEq(expectedSetValueResults)); + + std::vector getValueRequests; + getValueRequests.push_back(GetValueRequest{ + .requestId = requestId++, + .prop = testValue, + }); + + // In our implementation, this would finish immediately. + status = getValues(getValueRequests); + + ASSERT_EQ(status, StatusCode::OK); + ASSERT_EQ(getGetValueResults().size(), static_cast(1)); + ASSERT_EQ(getGetValueResults()[0].status, StatusCode::OK); + // The status should be by-default AVAILABLE for new status. + ASSERT_EQ(getGetValueResults()[0].prop->status, VehiclePropertyStatus::AVAILABLE); + + // Try to set the property again. The status should not be overwritten. + status = setValues(setValueRequests); + + ASSERT_EQ(status, StatusCode::OK); + + status = getValues(getValueRequests); + + ASSERT_EQ(status, StatusCode::OK); + ASSERT_EQ(getGetValueResults().size(), static_cast(2)); + ASSERT_EQ(getGetValueResults()[1].status, StatusCode::OK); + ASSERT_EQ(getGetValueResults()[1].prop->status, VehiclePropertyStatus::AVAILABLE); +} + +TEST_F(FakeVehicleHardwareTest, testVendorOverrideProperties) { + std::string currentDir = android::base::GetExecutableDirectory(); + std::string overrideDir = currentDir + "/override/"; + // Set vendor override directory. + std::unique_ptr hardware = + std::make_unique(currentDir, overrideDir, /*forceOverride=*/true); + setHardware(std::move(hardware)); + + // This is the same as the prop in 'gear_selection.json'. + int gearProp = toInt(VehicleProperty::GEAR_SELECTION); + + auto result = getValue(VehiclePropValue{ + .prop = gearProp, + }); + + ASSERT_TRUE(result.ok()) << "expect to get the overridden property ok: " << getStatus(result); + ASSERT_EQ(static_cast(1), result.value().value.int32Values.size()); + ASSERT_EQ(8, result.value().value.int32Values[0]); + + // If we set the value, it should update despite the override. + ASSERT_EQ(setValue(VehiclePropValue{ + .prop = gearProp, + .value = + { + .int32Values = {5}, + }, + .timestamp = elapsedRealtimeNano(), + }), + StatusCode::OK) + << "expect to set the overridden property ok"; + + result = getValue(VehiclePropValue{ + .prop = gearProp, + }); + + ASSERT_TRUE(result.ok()) << "expect to get the overridden property after setting value ok"; + ASSERT_EQ(static_cast(1), result.value().value.int32Values.size()); + ASSERT_EQ(5, result.value().value.int32Values[0]); +} + +TEST_F(FakeVehicleHardwareTest, testVendorOverridePropertiesMultipleAreas) { + std::string currentDir = android::base::GetExecutableDirectory(); + std::string overrideDir = currentDir + "/override/"; + // Set vendor override directory. + std::unique_ptr hardware = + std::make_unique(currentDir, overrideDir, /*forceOverride=*/true); + setHardware(std::move(hardware)); + + // This is the same as the prop in 'hvac_temperature_set.json'. + int hvacProp = toInt(VehicleProperty::HVAC_TEMPERATURE_SET); + + auto result = getValue(VehiclePropValue{ + .prop = hvacProp, + .areaId = HVAC_LEFT, + }); + + ASSERT_TRUE(result.ok()) << "expect to get the overridden property ok: " << getStatus(result); + ASSERT_EQ(static_cast(1), result.value().value.floatValues.size()); + ASSERT_EQ(30.0f, result.value().value.floatValues[0]); +} + +TEST_F(FakeVehicleHardwareTest, testVendorOverridePropertiesDirDoesNotExist) { + std::string currentDir = android::base::GetExecutableDirectory(); + std::string overrideDir = currentDir + "/override/"; + // Set vendor override directory to a non-existing dir. + std::unique_ptr hardware = + std::make_unique(currentDir, "1234", /*forceOverride=*/true); + setHardware(std::move(hardware)); + + auto result = getValue(VehiclePropValue{ + .prop = toInt(VehicleProperty::GEAR_SELECTION), + }); + + ASSERT_TRUE(result.ok()) << "expect to get the default property ok: " << getStatus(result); + ASSERT_EQ(static_cast(1), result.value().value.int32Values.size()); + ASSERT_EQ(4, result.value().value.int32Values[0]); +} + +struct SetSpecialValueTestCase { + std::string name; + std::vector valuesToSet; + std::vector expectedValuesToGet; +}; + +std::vector setSpecialValueTestCases() { + return { + SetSpecialValueTestCase{ + .name = "set_ap_power_state_report_deep_sleep_exit", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT), + .value.int32Values = {toInt( + VehicleApPowerStateReport::DEEP_SLEEP_EXIT)}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt(VehicleProperty::AP_POWER_STATE_REQ), + .status = VehiclePropertyStatus::AVAILABLE, + .value.int32Values = {toInt(VehicleApPowerStateReq::ON), + 0}, + }, + VehiclePropValue{ + .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT), + .value.int32Values = {toInt( + VehicleApPowerStateReport::DEEP_SLEEP_EXIT)}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "set_ap_power_state_report_hibernation_exit", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT), + .value.int32Values = {toInt( + VehicleApPowerStateReport::HIBERNATION_EXIT)}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt(VehicleProperty::AP_POWER_STATE_REQ), + .status = VehiclePropertyStatus::AVAILABLE, + .value.int32Values = {toInt(VehicleApPowerStateReq::ON), + 0}, + }, + VehiclePropValue{ + .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT), + .value.int32Values = {toInt( + VehicleApPowerStateReport::HIBERNATION_EXIT)}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "set_ap_power_state_report_shutdown_cancelled", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT), + .value.int32Values = {toInt( + VehicleApPowerStateReport::SHUTDOWN_CANCELLED)}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt(VehicleProperty::AP_POWER_STATE_REQ), + .status = VehiclePropertyStatus::AVAILABLE, + .value.int32Values = {toInt(VehicleApPowerStateReq::ON), + 0}, + }, + VehiclePropValue{ + .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT), + .value.int32Values = {toInt( + VehicleApPowerStateReport::SHUTDOWN_CANCELLED)}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "set_ap_power_state_report_wait_for_vhal", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT), + .value.int32Values = {toInt( + VehicleApPowerStateReport::WAIT_FOR_VHAL)}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt(VehicleProperty::AP_POWER_STATE_REQ), + .status = VehiclePropertyStatus::AVAILABLE, + .value.int32Values = {toInt(VehicleApPowerStateReq::ON), + 0}, + }, + VehiclePropValue{ + .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT), + .value.int32Values = {toInt( + VehicleApPowerStateReport::WAIT_FOR_VHAL)}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "set_ap_power_state_report_deep_sleep_entry", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT), + .value.int32Values = {toInt( + VehicleApPowerStateReport::DEEP_SLEEP_ENTRY)}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt(VehicleProperty::AP_POWER_STATE_REQ), + .status = VehiclePropertyStatus::AVAILABLE, + .value.int32Values = + {toInt(VehicleApPowerStateReq::FINISHED), 0}, + }, + VehiclePropValue{ + .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT), + .value.int32Values = {toInt( + VehicleApPowerStateReport::DEEP_SLEEP_ENTRY)}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "set_ap_power_state_report_hibernation_entry", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT), + .value.int32Values = {toInt( + VehicleApPowerStateReport::HIBERNATION_ENTRY)}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt(VehicleProperty::AP_POWER_STATE_REQ), + .status = VehiclePropertyStatus::AVAILABLE, + .value.int32Values = + {toInt(VehicleApPowerStateReq::FINISHED), 0}, + }, + VehiclePropValue{ + .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT), + .value.int32Values = {toInt( + VehicleApPowerStateReport::HIBERNATION_ENTRY)}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "set_ap_power_state_report_shutdown_start", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT), + .value.int32Values = {toInt( + VehicleApPowerStateReport::SHUTDOWN_START)}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt(VehicleProperty::AP_POWER_STATE_REQ), + .status = VehiclePropertyStatus::AVAILABLE, + .value.int32Values = + {toInt(VehicleApPowerStateReq::FINISHED), 0}, + }, + VehiclePropValue{ + .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT), + .value.int32Values = {toInt( + VehicleApPowerStateReport::SHUTDOWN_START)}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "cluster_report_state_to_vendor", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt(VehicleProperty::CLUSTER_REPORT_STATE), + .value.int32Values = {1}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt(TestVendorProperty:: + VENDOR_CLUSTER_REPORT_STATE), + .value.int32Values = {1}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "cluster_request_display_to_vendor", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt(VehicleProperty::CLUSTER_REQUEST_DISPLAY), + .value.int32Values = {1}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt(TestVendorProperty:: + VENDOR_CLUSTER_REQUEST_DISPLAY), + .value.int32Values = {1}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "cluster_navigation_state_to_vendor", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty::CLUSTER_NAVIGATION_STATE), + .value.byteValues = {0x1}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt(TestVendorProperty:: + VENDOR_CLUSTER_NAVIGATION_STATE), + .value.byteValues = {0x1}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "vendor_cluster_switch_ui_to_system", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt( + TestVendorProperty::VENDOR_CLUSTER_SWITCH_UI), + .value.int32Values = {1}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt(VehicleProperty::CLUSTER_SWITCH_UI), + .value.int32Values = {1}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "vendor_cluster_display_state_to_system", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt(TestVendorProperty:: + VENDOR_CLUSTER_DISPLAY_STATE), + .value.int32Values = {1, 2}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt(VehicleProperty::CLUSTER_DISPLAY_STATE), + .value.int32Values = {1, 2}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "set_automatic_emergency_braking_enabled_false", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty:: + AUTOMATIC_EMERGENCY_BRAKING_ENABLED), + .value.int32Values = {0}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty:: + AUTOMATIC_EMERGENCY_BRAKING_ENABLED), + .value.int32Values = {0}, + }, + VehiclePropValue{ + .prop = toInt( + VehicleProperty:: + AUTOMATIC_EMERGENCY_BRAKING_STATE), + .value.int32Values = {toInt( + ErrorState::NOT_AVAILABLE_DISABLED)}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "set_automatic_emergency_braking_enabled_true", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty:: + AUTOMATIC_EMERGENCY_BRAKING_ENABLED), + .value.int32Values = {1}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty:: + AUTOMATIC_EMERGENCY_BRAKING_ENABLED), + .value.int32Values = {1}, + }, + VehiclePropValue{ + .prop = toInt( + VehicleProperty:: + AUTOMATIC_EMERGENCY_BRAKING_STATE), + .value.int32Values = {1}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "set_forward_collision_warning_enabled_false", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty:: + FORWARD_COLLISION_WARNING_ENABLED), + .value.int32Values = {0}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty:: + FORWARD_COLLISION_WARNING_ENABLED), + .value.int32Values = {0}, + }, + VehiclePropValue{ + .prop = toInt(VehicleProperty:: + FORWARD_COLLISION_WARNING_STATE), + .value.int32Values = {toInt( + ErrorState::NOT_AVAILABLE_DISABLED)}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "set_forward_collision_warning_enabled_true", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty:: + FORWARD_COLLISION_WARNING_ENABLED), + .value.int32Values = {1}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty:: + FORWARD_COLLISION_WARNING_ENABLED), + .value.int32Values = {1}, + }, + VehiclePropValue{ + .prop = toInt(VehicleProperty:: + FORWARD_COLLISION_WARNING_STATE), + .value.int32Values = {1}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "set_blind_spot_warning_enabled_false", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty::BLIND_SPOT_WARNING_ENABLED), + .value.int32Values = {0}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty::BLIND_SPOT_WARNING_ENABLED), + .value.int32Values = {0}, + }, + VehiclePropValue{ + .prop = toInt( + VehicleProperty::BLIND_SPOT_WARNING_STATE), + .areaId = toInt(VehicleAreaMirror::DRIVER_LEFT), + .value.int32Values = {toInt( + ErrorState::NOT_AVAILABLE_DISABLED)}, + }, + VehiclePropValue{ + .prop = toInt( + VehicleProperty::BLIND_SPOT_WARNING_STATE), + .areaId = toInt(VehicleAreaMirror::DRIVER_RIGHT), + .value.int32Values = {toInt( + ErrorState::NOT_AVAILABLE_DISABLED)}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "set_blind_spot_warning_enabled_true", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty::BLIND_SPOT_WARNING_ENABLED), + .value.int32Values = {1}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty::BLIND_SPOT_WARNING_ENABLED), + .value.int32Values = {1}, + }, + VehiclePropValue{ + .prop = toInt( + VehicleProperty::BLIND_SPOT_WARNING_STATE), + .areaId = toInt(VehicleAreaMirror::DRIVER_LEFT), + .value.int32Values = {1}, + }, + VehiclePropValue{ + .prop = toInt( + VehicleProperty::BLIND_SPOT_WARNING_STATE), + .areaId = toInt(VehicleAreaMirror::DRIVER_RIGHT), + .value.int32Values = {1}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "set_lane_departure_warning_enabled_false", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt(VehicleProperty:: + LANE_DEPARTURE_WARNING_ENABLED), + .value.int32Values = {0}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt(VehicleProperty:: + LANE_DEPARTURE_WARNING_ENABLED), + .value.int32Values = {0}, + }, + VehiclePropValue{ + .prop = toInt( + VehicleProperty::LANE_DEPARTURE_WARNING_STATE), + .value.int32Values = {toInt( + ErrorState::NOT_AVAILABLE_DISABLED)}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "set_lane_departure_warning_enabled_true", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt(VehicleProperty:: + LANE_DEPARTURE_WARNING_ENABLED), + .value.int32Values = {1}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt(VehicleProperty:: + LANE_DEPARTURE_WARNING_ENABLED), + .value.int32Values = {1}, + }, + VehiclePropValue{ + .prop = toInt( + VehicleProperty::LANE_DEPARTURE_WARNING_STATE), + .value.int32Values = {1}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "set_lane_keep_assist_enabled_false", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty::LANE_KEEP_ASSIST_ENABLED), + .value.int32Values = {0}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty::LANE_KEEP_ASSIST_ENABLED), + .value.int32Values = {0}, + }, + VehiclePropValue{ + .prop = toInt(VehicleProperty::LANE_KEEP_ASSIST_STATE), + .value.int32Values = {toInt( + ErrorState::NOT_AVAILABLE_DISABLED)}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "set_lane_keep_assist_enabled_true", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty::LANE_KEEP_ASSIST_ENABLED), + .value.int32Values = {1}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty::LANE_KEEP_ASSIST_ENABLED), + .value.int32Values = {1}, + }, + VehiclePropValue{ + .prop = toInt(VehicleProperty::LANE_KEEP_ASSIST_STATE), + .value.int32Values = {1}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "set_lane_centering_assist_enabled_false", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty::LANE_CENTERING_ASSIST_ENABLED), + .value.int32Values = {0}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty::LANE_CENTERING_ASSIST_ENABLED), + .value.int32Values = {0}, + }, + VehiclePropValue{ + .prop = toInt( + VehicleProperty::LANE_CENTERING_ASSIST_STATE), + .value.int32Values = {toInt( + ErrorState::NOT_AVAILABLE_DISABLED)}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "set_lane_centering_assist_enabled_true", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty::LANE_CENTERING_ASSIST_ENABLED), + .value.int32Values = {1}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty::LANE_CENTERING_ASSIST_ENABLED), + .value.int32Values = {1}, + }, + VehiclePropValue{ + .prop = toInt( + VehicleProperty::LANE_CENTERING_ASSIST_STATE), + .value.int32Values = {1}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "set_emergency_lane_keep_assist_enabled_false", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty:: + EMERGENCY_LANE_KEEP_ASSIST_ENABLED), + .value.int32Values = {0}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty:: + EMERGENCY_LANE_KEEP_ASSIST_ENABLED), + .value.int32Values = {0}, + }, + VehiclePropValue{ + .prop = toInt(VehicleProperty:: + EMERGENCY_LANE_KEEP_ASSIST_STATE), + .value.int32Values = {toInt( + ErrorState::NOT_AVAILABLE_DISABLED)}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "set_emergency_lane_keep_assist_enabled_true", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty:: + EMERGENCY_LANE_KEEP_ASSIST_ENABLED), + .value.int32Values = {1}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty:: + EMERGENCY_LANE_KEEP_ASSIST_ENABLED), + .value.int32Values = {1}, + }, + VehiclePropValue{ + .prop = toInt(VehicleProperty:: + EMERGENCY_LANE_KEEP_ASSIST_STATE), + .value.int32Values = {1}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "set_cruise_control_enabled_false", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt(VehicleProperty::CRUISE_CONTROL_ENABLED), + .value.int32Values = {0}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt(VehicleProperty::CRUISE_CONTROL_ENABLED), + .value.int32Values = {0}, + }, + VehiclePropValue{ + .prop = toInt(VehicleProperty::CRUISE_CONTROL_TYPE), + .value.int32Values = {toInt( + ErrorState::NOT_AVAILABLE_DISABLED)}, + }, + VehiclePropValue{ + .prop = toInt(VehicleProperty::CRUISE_CONTROL_STATE), + .value.int32Values = {toInt( + ErrorState::NOT_AVAILABLE_DISABLED)}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "set_cruise_control_enabled_true", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt(VehicleProperty::CRUISE_CONTROL_ENABLED), + .value.int32Values = {1}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt(VehicleProperty::CRUISE_CONTROL_ENABLED), + .value.int32Values = {1}, + }, + VehiclePropValue{ + .prop = toInt(VehicleProperty::CRUISE_CONTROL_TYPE), + .value.int32Values = {2}, + }, + VehiclePropValue{ + .prop = toInt(VehicleProperty::CRUISE_CONTROL_STATE), + .value.int32Values = {1}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "set_hands_on_detection_enabled_false", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty::HANDS_ON_DETECTION_ENABLED), + .value.int32Values = {0}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty::HANDS_ON_DETECTION_ENABLED), + .value.int32Values = {0}, + }, + VehiclePropValue{ + .prop = toInt(VehicleProperty:: + HANDS_ON_DETECTION_DRIVER_STATE), + .value.int32Values = {toInt( + ErrorState::NOT_AVAILABLE_DISABLED)}, + }, + VehiclePropValue{ + .prop = toInt( + VehicleProperty::HANDS_ON_DETECTION_WARNING), + .value.int32Values = {toInt( + ErrorState::NOT_AVAILABLE_DISABLED)}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "set_hands_on_detection_enabled_true", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty::HANDS_ON_DETECTION_ENABLED), + .value.int32Values = {1}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty::HANDS_ON_DETECTION_ENABLED), + .value.int32Values = {1}, + }, + VehiclePropValue{ + .prop = toInt(VehicleProperty:: + HANDS_ON_DETECTION_DRIVER_STATE), + .value.int32Values = {1}, + }, + VehiclePropValue{ + .prop = toInt( + VehicleProperty::HANDS_ON_DETECTION_WARNING), + .value.int32Values = {1}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "set_low_speed_collision_warning_enabled_false", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty:: + LOW_SPEED_COLLISION_WARNING_ENABLED), + .value.int32Values = {0}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty:: + LOW_SPEED_COLLISION_WARNING_ENABLED), + .value.int32Values = {0}, + }, + VehiclePropValue{ + .prop = toInt( + VehicleProperty:: + LOW_SPEED_COLLISION_WARNING_STATE), + .value.int32Values = {toInt( + ErrorState::NOT_AVAILABLE_DISABLED)}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "set_low_speed_collision_warning_enabled_true", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty:: + LOW_SPEED_COLLISION_WARNING_ENABLED), + .value.int32Values = {1}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty:: + LOW_SPEED_COLLISION_WARNING_ENABLED), + .value.int32Values = {1}, + }, + VehiclePropValue{ + .prop = toInt( + VehicleProperty:: + LOW_SPEED_COLLISION_WARNING_STATE), + .value.int32Values = {1}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "set_electronic_stability_control_enabled_false", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty:: + ELECTRONIC_STABILITY_CONTROL_ENABLED), + .value.int32Values = {0}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty:: + ELECTRONIC_STABILITY_CONTROL_ENABLED), + .value.int32Values = {0}, + }, + VehiclePropValue{ + .prop = toInt( + VehicleProperty:: + ELECTRONIC_STABILITY_CONTROL_STATE), + .value.int32Values = {toInt( + ErrorState::NOT_AVAILABLE_DISABLED)}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "set_electronic_stability_control_enabled_true", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty:: + ELECTRONIC_STABILITY_CONTROL_ENABLED), + .value.int32Values = {1}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt( + VehicleProperty:: + ELECTRONIC_STABILITY_CONTROL_ENABLED), + .value.int32Values = {1}, + }, + VehiclePropValue{ + .prop = toInt( + VehicleProperty:: + ELECTRONIC_STABILITY_CONTROL_STATE), + .value.int32Values = {1}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "set_shutdown_request", + .valuesToSet = + { + VehiclePropValue{ + .prop = toInt(VehicleProperty::SHUTDOWN_REQUEST), + .value.int32Values = + { + toInt(VehicleApPowerStateShutdownParam:: + SHUTDOWN_ONLY), + }, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = toInt(VehicleProperty::AP_POWER_STATE_REQ), + .value.int32Values = + { + toInt(VehicleApPowerStateReq:: + SHUTDOWN_PREPARE), + toInt(VehicleApPowerStateShutdownParam:: + SHUTDOWN_ONLY), + }, + }, + }, + }, + }; +} + +class FakeVehicleHardwareSpecialValuesTest + : public FakeVehicleHardwareTest, + public testing::WithParamInterface {}; + +TEST_P(FakeVehicleHardwareSpecialValuesTest, testSetSpecialProperties) { + const SetSpecialValueTestCase& tc = GetParam(); + + for (const auto& value : tc.valuesToSet) { + ASSERT_EQ(setValue(value), StatusCode::OK) << "failed to set property " << value.prop; + } + + std::vector gotValues; + + for (const auto& value : tc.expectedValuesToGet) { + auto result = getValue(VehiclePropValue{.prop = value.prop, .areaId = value.areaId}); + + ASSERT_TRUE(result.ok()) << "failed to get property " << value.prop + << " status:" << getStatus(result); + + gotValues.push_back(result.value()); + VehiclePropValue valueWithNoTimestamp = result.value(); + valueWithNoTimestamp.timestamp = 0; + + ASSERT_EQ(valueWithNoTimestamp, value); + } + + // Some of the updated properties might be the same as default config, thus not causing + // a property change event. So the changed properties should be a subset of all the updated + // properties. + ASSERT_THAT(getChangedProperties(), IsSubsetOf(gotValues)); +} + +INSTANTIATE_TEST_SUITE_P( + SpecialValuesTests, FakeVehicleHardwareSpecialValuesTest, + testing::ValuesIn(setSpecialValueTestCases()), + [](const testing::TestParamInfo& info) { + return info.param.name; + }); + +TEST_F(FakeVehicleHardwareTest, testSetWaitForVhal_alwaysTriggerEvents) { + int32_t powerReq = toInt(VehicleProperty::AP_POWER_STATE_REQ); + subscribe(powerReq, /*areaId*/ 0, /*sampleRateHz*/ 0); + + int32_t powerReport = toInt(VehicleProperty::AP_POWER_STATE_REPORT); + VehiclePropValue request = VehiclePropValue{ + .prop = powerReport, + .value.int32Values = {toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL)}, + }; + ASSERT_EQ(setValue(request), StatusCode::OK) << "failed to set property " << powerReport; + + // Clear existing events. + clearChangedProperties(); + + // Simulate a Car Service crash, Car Service would restart and send the message again. + ASSERT_EQ(setValue(request), StatusCode::OK) << "failed to set property " << powerReport; + + std::vector events = getChangedProperties(); + // Even though the state is already ON, we should receive another ON event. + ASSERT_EQ(events.size(), 1u) << "failed to receive on-change events AP_POWER_STATE_REQ ON"; + // Erase the timestamp for comparison. + events[0].timestamp = 0; + auto expectedValue = VehiclePropValue{ + .prop = powerReq, + .status = VehiclePropertyStatus::AVAILABLE, + .value.int32Values = {toInt(VehicleApPowerStateReq::ON), 0}, + }; + ASSERT_EQ(events[0], expectedValue); +} + +TEST_F(FakeVehicleHardwareTest, testGetObd2FreezeFrame) { + int64_t timestamp = elapsedRealtimeNano(); + + auto result = getValue(VehiclePropValue{.prop = OBD2_FREEZE_FRAME_INFO}); + + ASSERT_TRUE(result.ok()); + + auto propValue = result.value(); + ASSERT_GE(propValue.timestamp, timestamp); + ASSERT_EQ(propValue.value.int64Values.size(), static_cast(3)) + << "expect 3 obd2 freeze frames stored"; + + for (int64_t timestamp : propValue.value.int64Values) { + auto freezeFrameResult = getValue(VehiclePropValue{ + .prop = OBD2_FREEZE_FRAME, + .value.int64Values = {timestamp}, + }); + + EXPECT_TRUE(result.ok()) << "expect to get freeze frame for timestamp " << timestamp + << " ok"; + EXPECT_GE(freezeFrameResult.value().timestamp, timestamp); + } +} + +TEST_F(FakeVehicleHardwareTest, testClearObd2FreezeFrame) { + int64_t timestamp = elapsedRealtimeNano(); + + auto getValueResult = getValue(VehiclePropValue{.prop = OBD2_FREEZE_FRAME_INFO}); + + ASSERT_TRUE(getValueResult.ok()); + + auto propValue = getValueResult.value(); + ASSERT_GE(propValue.timestamp, timestamp); + ASSERT_EQ(propValue.value.int64Values.size(), static_cast(3)) + << "expect 3 obd2 freeze frames stored"; + + // No int64Values should clear all freeze frames. + StatusCode status = setValue(VehiclePropValue{.prop = OBD2_FREEZE_FRAME_CLEAR}); + + ASSERT_EQ(status, StatusCode::OK); + + getValueResult = getValue(VehiclePropValue{.prop = OBD2_FREEZE_FRAME_INFO}); + + ASSERT_TRUE(getValueResult.ok()); + ASSERT_EQ(getValueResult.value().value.int64Values.size(), static_cast(0)) + << "expect 0 obd2 freeze frames after cleared"; +} + +TEST_F(FakeVehicleHardwareTest, testSetVehicleMapService) { + StatusCode status = + setValue(VehiclePropValue{.prop = toInt(VehicleProperty::VEHICLE_MAP_SERVICE)}); + + EXPECT_EQ(status, StatusCode::OK); + + auto getValueResult = + getValue(VehiclePropValue{.prop = toInt(VehicleProperty::VEHICLE_MAP_SERVICE)}); + + EXPECT_FALSE(getValueResult.ok()); + EXPECT_EQ(getValueResult.error(), StatusCode::NOT_AVAILABLE); +} + +TEST_F(FakeVehicleHardwareTest, testGetHvacPropNotAvailable) { + FakeVehicleHardwareTestHelper helper(getHardware()); + auto hvacPowerOnConfig = getVehiclePropConfig(toInt(VehicleProperty::HVAC_POWER_ON)); + EXPECT_NE(hvacPowerOnConfig, nullptr); + for (auto& hvacPowerOnAreaConfig : hvacPowerOnConfig->areaConfigs) { + int hvacPowerAreaId = hvacPowerOnAreaConfig.areaId; + // Turn off HVAC_POWER_ON for only 1 area ID + StatusCode status = setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_POWER_ON), + .areaId = hvacPowerAreaId, + .value.int32Values = {0}}); + EXPECT_EQ(status, StatusCode::OK); + + for (auto& powerPropId : helper.getHvacPowerDependentProps()) { + auto powerPropConfig = getVehiclePropConfig(powerPropId); + EXPECT_NE(powerPropConfig, nullptr); + if (powerPropConfig->access == VehiclePropertyAccess::WRITE) { + continue; + } + // Try getting a value at each area ID supported by the power dependent property + for (auto& powerPropAreaConfig : powerPropConfig->areaConfigs) { + int powerDependentAreaId = powerPropAreaConfig.areaId; + auto getValueResult = getValue(VehiclePropValue{ + .prop = powerPropId, + .areaId = powerDependentAreaId, + }); + + // If the current area ID is contained within the HVAC_POWER_ON area ID + // turned off, then getValue should fail and a StatusCode error should be + // returned. Otherwise, a value should be returned. + if ((hvacPowerAreaId & powerDependentAreaId) == powerDependentAreaId) { + EXPECT_FALSE(getValueResult.ok()); + EXPECT_EQ(getValueResult.error(), StatusCode::NOT_AVAILABLE_DISABLED); + } else { + EXPECT_TRUE(getValueResult.ok()); + } + } + } + + // Resetting HVAC_POWER_ON at areaId back to ON state to ensure that there's no dependence + // on this value from any power dependent property values other than those with the same + // areaId. + setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_POWER_ON), + .areaId = hvacPowerAreaId, + .value.int32Values = {1}}); + } +} + +TEST_F(FakeVehicleHardwareTest, testSetHvacPropNotAvailable) { + FakeVehicleHardwareTestHelper helper(getHardware()); + auto hvacPowerOnConfig = getVehiclePropConfig(toInt(VehicleProperty::HVAC_POWER_ON)); + EXPECT_NE(hvacPowerOnConfig, nullptr); + for (auto& hvacPowerOnAreaConfig : hvacPowerOnConfig->areaConfigs) { + int hvacPowerAreaId = hvacPowerOnAreaConfig.areaId; + // Turn off HVAC_POWER_ON for only 1 area ID + StatusCode status = setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_POWER_ON), + .areaId = hvacPowerAreaId, + .value.int32Values = {0}}); + EXPECT_EQ(status, StatusCode::OK); + + for (auto& powerPropId : helper.getHvacPowerDependentProps()) { + auto powerPropConfig = getVehiclePropConfig(powerPropId); + EXPECT_NE(powerPropConfig, nullptr); + if (powerPropConfig->access == VehiclePropertyAccess::READ) { + continue; + } + auto propType = getPropType(powerPropId); + // Try setting a value at each area ID supported by the power dependent property + for (auto& powerPropAreaConfig : powerPropConfig->areaConfigs) { + int powerDependentAreaId = powerPropAreaConfig.areaId; + auto val = VehiclePropValue{.prop = powerPropId, .areaId = powerDependentAreaId}; + if (propType == VehiclePropertyType::FLOAT) { + val.value.floatValues.emplace_back(20); + } else { + val.value.int32Values.emplace_back(1); + } + status = setValue(val); + + // If the current area ID is contained within the HVAC_POWER_ON area ID + // turned off, then setValue should fail and a StatusCode error should be + // returned. Otherwise, an ok StatusCode should be returned. + if ((hvacPowerAreaId & powerDependentAreaId) == powerDependentAreaId) { + EXPECT_EQ(status, StatusCode::NOT_AVAILABLE_DISABLED); + } else { + EXPECT_EQ(status, StatusCode::OK); + } + } + } + + // Resetting HVAC_POWER_ON at areaId back to ON state to ensure that there's no dependence + // on this value from any power dependent property values other than those with the same + // areaId. + setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_POWER_ON), + .areaId = hvacPowerAreaId, + .value.int32Values = {1}}); + } +} + +TEST_F(FakeVehicleHardwareTest, testHvacPowerOnSendCurrentHvacPropValues) { + FakeVehicleHardwareTestHelper helper(getHardware()); + auto hvacPowerOnConfig = getVehiclePropConfig(toInt(VehicleProperty::HVAC_POWER_ON)); + EXPECT_NE(hvacPowerOnConfig, nullptr); + for (auto& hvacPowerOnAreaConfig : hvacPowerOnConfig->areaConfigs) { + int hvacPowerAreaId = hvacPowerOnAreaConfig.areaId; + StatusCode status = setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_POWER_ON), + .areaId = hvacPowerAreaId, + .value.int32Values = {0}}); + EXPECT_EQ(status, StatusCode::OK); + auto events = getChangedProperties(); + for (const auto& event : events) { + // Ignore HVAC_POWER_ON event + if (event.prop == toInt(VehicleProperty::HVAC_POWER_ON)) { + continue; + } + EXPECT_THAT(event.prop, AnyOfArray(helper.getHvacPowerDependentProps())); + EXPECT_EQ((hvacPowerAreaId & event.areaId), hvacPowerAreaId); + EXPECT_EQ(event.status, VehiclePropertyStatus::UNAVAILABLE); + } + clearChangedProperties(); + + status = setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_POWER_ON), + .areaId = hvacPowerAreaId, + .value.int32Values = {1}}); + EXPECT_EQ(status, StatusCode::OK); + events = getChangedProperties(); + for (const auto& event : events) { + // Ignore HVAC_POWER_ON event + if (event.prop == toInt(VehicleProperty::HVAC_POWER_ON)) { + continue; + } + EXPECT_THAT(event.prop, AnyOfArray(helper.getHvacPowerDependentProps())); + EXPECT_EQ((hvacPowerAreaId & event.areaId), hvacPowerAreaId); + EXPECT_EQ(event.status, VehiclePropertyStatus::AVAILABLE); + } + clearChangedProperties(); + } +} + +TEST_F(FakeVehicleHardwareTest, testHvacDualOnSynchronizesTemp) { + auto hvacDualOnConfig = getVehiclePropConfig(toInt(VehicleProperty::HVAC_DUAL_ON)); + auto hvacTemperatureSetConfig = + getVehiclePropConfig(toInt(VehicleProperty::HVAC_TEMPERATURE_SET)); + EXPECT_NE(hvacDualOnConfig, nullptr); + EXPECT_NE(hvacTemperatureSetConfig, nullptr); + for (auto& hvacTemperatureSetConfig : hvacTemperatureSetConfig->areaConfigs) { + int32_t hvacTemperatureSetAreaId = hvacTemperatureSetConfig.areaId; + subscribe(toInt(VehicleProperty::HVAC_TEMPERATURE_SET), hvacTemperatureSetAreaId, + /*sampleRateHz*/ 0); + } + for (auto& hvacDualOnConfig : hvacDualOnConfig->areaConfigs) { + int32_t hvacDualOnAreaId = hvacDualOnConfig.areaId; + subscribe(toInt(VehicleProperty::HVAC_DUAL_ON), hvacDualOnAreaId, /*sampleRateHz*/ 0); + StatusCode status = setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_DUAL_ON), + .areaId = hvacDualOnAreaId, + .value.int32Values = {1}}); + EXPECT_EQ(status, StatusCode::OK); + + // Verify there's an event for all HVAC_TEMPERATURE_SET + // area IDs covered by the HVAC_DUAL_ON area ID + auto events = getChangedProperties(); + std::unordered_set temperatureValues; + for (const auto& event : events) { + // Ignore HVAC_DUAL_ON event + if (event.prop == toInt(VehicleProperty::HVAC_DUAL_ON)) { + continue; + } + EXPECT_EQ(event.prop, toInt(VehicleProperty::HVAC_TEMPERATURE_SET)); + EXPECT_EQ((hvacDualOnAreaId & event.areaId), event.areaId); + EXPECT_EQ(1u, event.value.floatValues.size()); + temperatureValues.insert(event.value.floatValues[0]); + } + // Verify that the temperature value is the same for all events + // Ie the temperature in all area IDs are synchronized + EXPECT_EQ(1u, temperatureValues.size()); + clearChangedProperties(); + + // Verify when any HVAC_TEMPERATURE_SET area ID is changed all + // area IDs covered by the HVAC_DUAL_ON area ID are also changed + for (auto& hvacTemperatureSetConfig : hvacTemperatureSetConfig->areaConfigs) { + int32_t hvacTemperatureSetAreaId = hvacTemperatureSetConfig.areaId; + if ((hvacDualOnAreaId & hvacTemperatureSetAreaId) != hvacTemperatureSetAreaId) { + continue; + } + float expectedValue = 25; + status = setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET), + .areaId = hvacTemperatureSetAreaId, + .value.floatValues = {expectedValue}}); + EXPECT_EQ(status, StatusCode::OK); + events = getChangedProperties(); + for (const auto& event : events) { + EXPECT_EQ(event.prop, toInt(VehicleProperty::HVAC_TEMPERATURE_SET)); + EXPECT_EQ(1u, event.value.floatValues.size()); + EXPECT_EQ(expectedValue, event.value.floatValues[0]); + } + clearChangedProperties(); + } + + status = setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_DUAL_ON), + .areaId = hvacDualOnAreaId, + .value.int32Values = {0}}); + EXPECT_EQ(status, StatusCode::OK); + + // When HVAC_DUAL_ON is disabled, there should be no events created + // for HVAC_TEMPERATURE_SET ie no temperature synchronization. + events = getChangedProperties(); + EXPECT_EQ(1u, events.size()); + EXPECT_EQ(events[0].prop, toInt(VehicleProperty::HVAC_DUAL_ON)); + EXPECT_EQ(events[0].areaId, hvacDualOnAreaId); + clearChangedProperties(); + + // Verify when any HVAC_TEMPERATURE_SET area ID is + // changed other area IDs do not change. + for (auto& hvacTemperatureSetConfig : hvacTemperatureSetConfig->areaConfigs) { + int32_t hvacTemperatureSetAreaId = hvacTemperatureSetConfig.areaId; + if ((hvacDualOnAreaId & hvacTemperatureSetAreaId) != hvacTemperatureSetAreaId) { + continue; + } + float expectedValue = 24; + status = setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET), + .areaId = hvacTemperatureSetAreaId, + .value.floatValues = {expectedValue}}); + EXPECT_EQ(status, StatusCode::OK); + events = getChangedProperties(); + EXPECT_EQ(1u, events.size()); + EXPECT_EQ(events[0].prop, toInt(VehicleProperty::HVAC_TEMPERATURE_SET)); + EXPECT_EQ(events[0].areaId, hvacTemperatureSetAreaId); + EXPECT_EQ(1u, events[0].value.floatValues.size()); + EXPECT_EQ(expectedValue, events[0].value.floatValues[0]); + clearChangedProperties(); + } + } +} + +TEST_F(FakeVehicleHardwareTest, testGetAdasPropNotAvailable) { + std::unordered_map> adasEnabledPropToDependentProps = { + { + toInt(VehicleProperty::CRUISE_CONTROL_ENABLED), + { + toInt(VehicleProperty::CRUISE_CONTROL_TARGET_SPEED), + toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP), + toInt(VehicleProperty:: + ADAPTIVE_CRUISE_CONTROL_LEAD_VEHICLE_MEASURED_DISTANCE), + }, + }, + }; + for (auto& enabledToDependents : adasEnabledPropToDependentProps) { + int32_t adasEnabledPropertyId = enabledToDependents.first; + StatusCode status = + setValue(VehiclePropValue{.prop = adasEnabledPropertyId, .value.int32Values = {0}}); + EXPECT_EQ(status, StatusCode::OK); + + auto& dependentProps = enabledToDependents.second; + for (auto dependentProp : dependentProps) { + auto getValueResult = getValue(VehiclePropValue{.prop = dependentProp}); + EXPECT_FALSE(getValueResult.ok()); + EXPECT_EQ(getValueResult.error(), StatusCode::NOT_AVAILABLE_DISABLED); + } + } +} + +TEST_F(FakeVehicleHardwareTest, testSetAdasPropNotAvailable) { + std::unordered_map> adasEnabledPropToDependentProps = { + { + toInt(VehicleProperty::LANE_CENTERING_ASSIST_ENABLED), + { + toInt(VehicleProperty::LANE_CENTERING_ASSIST_COMMAND), + }, + }, + { + toInt(VehicleProperty::CRUISE_CONTROL_ENABLED), + { + toInt(VehicleProperty::CRUISE_CONTROL_COMMAND), + toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP), + }, + }, + }; + for (auto& enabledToDependents : adasEnabledPropToDependentProps) { + int32_t adasEnabledPropertyId = enabledToDependents.first; + StatusCode status = + setValue(VehiclePropValue{.prop = adasEnabledPropertyId, .value.int32Values = {0}}); + EXPECT_EQ(status, StatusCode::OK); + + auto& dependentProps = enabledToDependents.second; + for (auto dependentProp : dependentProps) { + StatusCode status = setValue(VehiclePropValue{.prop = dependentProp}); + EXPECT_EQ(status, StatusCode::NOT_AVAILABLE_DISABLED); + } + } +} + +TEST_F(FakeVehicleHardwareTest, testGetAccPropertiesOnStandardCc) { + std::vector ccTypeDependentProperties = { + toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP), + toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_LEAD_VEHICLE_MEASURED_DISTANCE), + }; + + StatusCode status = + setValue(VehiclePropValue{.prop = toInt(VehicleProperty::CRUISE_CONTROL_TYPE), + .value.int32Values = {toInt(CruiseControlType::STANDARD)}}); + EXPECT_EQ(status, StatusCode::OK); + + for (int32_t dependentProp : ccTypeDependentProperties) { + auto getValueResult = getValue(VehiclePropValue{.prop = dependentProp}); + EXPECT_FALSE(getValueResult.ok()); + EXPECT_EQ(getValueResult.error(), StatusCode::NOT_AVAILABLE_DISABLED); + } +} + +TEST_F(FakeVehicleHardwareTest, testSetAccPropertiesOnStandardCc) { + std::vector testVehiclePropValues = { + VehiclePropValue{ + .prop = toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP), + .value.int32Values = {3}}, + VehiclePropValue{ + .prop = toInt(VehicleProperty::CRUISE_CONTROL_COMMAND), + .value.int32Values = {toInt(CruiseControlCommand::INCREASE_TARGET_TIME_GAP)}}, + VehiclePropValue{ + .prop = toInt(VehicleProperty::CRUISE_CONTROL_COMMAND), + .value.int32Values = {toInt(CruiseControlCommand::DECREASE_TARGET_TIME_GAP)}}}; + + StatusCode status = + setValue(VehiclePropValue{.prop = toInt(VehicleProperty::CRUISE_CONTROL_TYPE), + .value.int32Values = {toInt(CruiseControlType::STANDARD)}}); + EXPECT_EQ(status, StatusCode::OK); + + for (auto value : testVehiclePropValues) { + status = setValue(value); + EXPECT_EQ(status, StatusCode::NOT_AVAILABLE_DISABLED); + } +} + +TEST_F(FakeVehicleHardwareTest, testSendAdasPropertiesState) { + std::unordered_map> adasEnabledPropToAdasPropWithErrorState = { + // AEB + { + toInt(VehicleProperty::AUTOMATIC_EMERGENCY_BRAKING_ENABLED), + { + toInt(VehicleProperty::AUTOMATIC_EMERGENCY_BRAKING_STATE), + }, + }, + // FCW + { + toInt(VehicleProperty::FORWARD_COLLISION_WARNING_ENABLED), + { + toInt(VehicleProperty::FORWARD_COLLISION_WARNING_STATE), + }, + }, + // BSW + { + toInt(VehicleProperty::BLIND_SPOT_WARNING_ENABLED), + { + toInt(VehicleProperty::BLIND_SPOT_WARNING_STATE), + }, + }, + // LDW + { + toInt(VehicleProperty::LANE_DEPARTURE_WARNING_ENABLED), + { + toInt(VehicleProperty::LANE_DEPARTURE_WARNING_STATE), + }, + }, + // LKA + { + toInt(VehicleProperty::LANE_KEEP_ASSIST_ENABLED), + { + toInt(VehicleProperty::LANE_KEEP_ASSIST_STATE), + }, + }, + // LCA + { + toInt(VehicleProperty::LANE_CENTERING_ASSIST_ENABLED), + { + toInt(VehicleProperty::LANE_CENTERING_ASSIST_STATE), + }, + }, + // ELKA + { + toInt(VehicleProperty::EMERGENCY_LANE_KEEP_ASSIST_ENABLED), + { + toInt(VehicleProperty::EMERGENCY_LANE_KEEP_ASSIST_STATE), + }, + }, + // CC + { + toInt(VehicleProperty::CRUISE_CONTROL_ENABLED), + { + toInt(VehicleProperty::CRUISE_CONTROL_TYPE), + toInt(VehicleProperty::CRUISE_CONTROL_STATE), + }, + }, + // HOD + { + toInt(VehicleProperty::HANDS_ON_DETECTION_ENABLED), + { + toInt(VehicleProperty::HANDS_ON_DETECTION_DRIVER_STATE), + toInt(VehicleProperty::HANDS_ON_DETECTION_WARNING), + }, + }, + // LSCW + { + toInt(VehicleProperty::LOW_SPEED_COLLISION_WARNING_ENABLED), + { + toInt(VehicleProperty::LOW_SPEED_COLLISION_WARNING_STATE), + }, + }, + // ESC + { + toInt(VehicleProperty::ELECTRONIC_STABILITY_CONTROL_ENABLED), + { + toInt(VehicleProperty::ELECTRONIC_STABILITY_CONTROL_STATE), + }, + }, + }; + + // First subscribe to all the properties that we will change. + for (auto& enabledToErrorStateProps : adasEnabledPropToAdasPropWithErrorState) { + std::unordered_set expectedChangedPropIds(enabledToErrorStateProps.second.begin(), + enabledToErrorStateProps.second.end()); + expectedChangedPropIds.insert(enabledToErrorStateProps.first); + + for (int32_t propId : expectedChangedPropIds) { + int32_t areaId = 0; + if (propId == toInt(VehicleProperty::BLIND_SPOT_WARNING_STATE)) { + areaId = toInt(VehicleAreaMirror::DRIVER_LEFT); + } + subscribe(propId, areaId, /*sampleRateHz*/ 0); + } + } + + for (auto& enabledToErrorStateProps : adasEnabledPropToAdasPropWithErrorState) { + int32_t adasEnabledPropertyId = enabledToErrorStateProps.first; + StatusCode status = + setValue(VehiclePropValue{.prop = adasEnabledPropertyId, .value.int32Values = {0}}); + EXPECT_EQ(status, StatusCode::OK); + + clearChangedProperties(); + status = + setValue(VehiclePropValue{.prop = adasEnabledPropertyId, .value.int32Values = {1}}); + EXPECT_EQ(status, StatusCode::OK); + + // If we enable the ADAS feature, we expect to receive one property event for every ADAS + // state property plus one event for enabling the feature. + std::unordered_set expectedChangedPropIds(enabledToErrorStateProps.second.begin(), + enabledToErrorStateProps.second.end()); + expectedChangedPropIds.insert(adasEnabledPropertyId); + + std::unordered_set changedPropIds; + auto events = getChangedProperties(); + for (const auto& event : events) { + changedPropIds.insert(event.prop); + } + EXPECT_EQ(changedPropIds, expectedChangedPropIds); + } +} + +TEST_F(FakeVehicleHardwareTest, testGetUserPropertySetOnly) { + for (VehicleProperty prop : std::vector({ + VehicleProperty::INITIAL_USER_INFO, + VehicleProperty::SWITCH_USER, + VehicleProperty::CREATE_USER, + VehicleProperty::REMOVE_USER, + })) { + auto result = getValue(VehiclePropValue{.prop = toInt(prop)}); + + EXPECT_FALSE(result.ok()); + if (!result.ok()) { + EXPECT_EQ(result.error(), StatusCode::INVALID_ARG); + } + } +} + +TEST_F(FakeVehicleHardwareTest, testGetUserIdAssoc) { + int32_t userIdAssocProp = toInt(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION); + + auto result = getValue(VehiclePropValue{.prop = userIdAssocProp}); + + // Default returns NOT_AVAILABLE. + ASSERT_FALSE(result.ok()); + ASSERT_EQ(result.error(), StatusCode::NOT_AVAILABLE); + + // This is the same example as used in User HAL Emulation doc. + VehiclePropValue valueToSet = { + .prop = toInt(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION), + .areaId = 1, + .value.int32Values = {666, 1, 1, 2}, + }; + + StatusCode status = setValue(valueToSet); + + ASSERT_EQ(status, StatusCode::OK); + + result = getValue(VehiclePropValue{ + .prop = userIdAssocProp, + // Request ID + .value.int32Values = {1}, + }); + + ASSERT_TRUE(result.ok()); + + auto& gotValue = result.value(); + gotValue.timestamp = 0; + + // Expect to get the same request ID. + valueToSet.value.int32Values[0] = 1; + + ASSERT_EQ(gotValue, valueToSet); +} + +TEST_F(FakeVehicleHardwareTest, testSwitchUser) { + SubscribeOptions options; + int32_t propSwitchUser = toInt(VehicleProperty::SWITCH_USER); + options.propId = propSwitchUser; + options.areaIds = {0, 1}; + ASSERT_EQ(StatusCode::OK, getHardware()->subscribe(options)) + << "failed to subscribe to propId: " << propSwitchUser; + + // This is the same example as used in User HAL Emulation doc. + VehiclePropValue valueToSet = { + .prop = propSwitchUser, + .areaId = 1, + .value.int32Values = {666, 3, 2}, + }; + + StatusCode status = setValue(valueToSet); + + ASSERT_EQ(status, StatusCode::OK); + + // Simulate a request from Android side. + VehiclePropValue switchUserRequest = { + .prop = propSwitchUser, + .areaId = 0, + .value.int32Values = {666, 3}, + }; + // Clear existing events. + clearChangedProperties(); + + status = setValue(switchUserRequest); + + ASSERT_EQ(status, StatusCode::OK); + + // Should generate an event for user hal response. + auto events = getChangedProperties(); + ASSERT_EQ(events.size(), static_cast(1)); + + events[0].timestamp = 0; + // The returned event will have area ID 0. + valueToSet.areaId = 0; + ASSERT_EQ(events[0], valueToSet); + + // Try to get switch_user again, should return default value. + clearChangedProperties(); + status = setValue(switchUserRequest); + ASSERT_EQ(status, StatusCode::OK); + + events = getChangedProperties(); + ASSERT_EQ(events.size(), static_cast(1)); + events[0].timestamp = 0; + auto expectedValue = VehiclePropValue{ + .areaId = 0, + .prop = propSwitchUser, + .value.int32Values = + { + // Request ID + 666, + // VEHICLE_RESPONSE + 3, + // SUCCESS + 1, + }, + }; + ASSERT_EQ(events[0], expectedValue); +} + +TEST_F(FakeVehicleHardwareTest, testCreateUser) { + SubscribeOptions options; + int32_t propCreateUser = toInt(VehicleProperty::CREATE_USER); + options.propId = propCreateUser; + options.areaIds = {0, 1}; + ASSERT_EQ(StatusCode::OK, getHardware()->subscribe(options)) + << "failed to subscribe to propId: " << propCreateUser; + + // This is the same example as used in User HAL Emulation doc. + VehiclePropValue valueToSet = { + .prop = toInt(VehicleProperty::CREATE_USER), + .areaId = 1, + .value.int32Values = {666, 2}, + }; + + StatusCode status = setValue(valueToSet); + + ASSERT_EQ(status, StatusCode::OK); + + // Simulate a request from Android side. + VehiclePropValue createUserRequest = { + .prop = propCreateUser, + .areaId = 0, + .value.int32Values = {666}, + }; + // Clear existing events. + clearChangedProperties(); + + status = setValue(createUserRequest); + + ASSERT_EQ(status, StatusCode::OK); + + // Should generate an event for user hal response. + auto events = getChangedProperties(); + ASSERT_EQ(events.size(), static_cast(1)); + events[0].timestamp = 0; + // The returned event will have area ID 0. + valueToSet.areaId = 0; + EXPECT_EQ(events[0], valueToSet); + + // Try to get create_user again, should return default value. + clearChangedProperties(); + status = setValue(createUserRequest); + ASSERT_EQ(status, StatusCode::OK); + + events = getChangedProperties(); + ASSERT_EQ(events.size(), static_cast(1)); + events[0].timestamp = 0; + auto expectedValue = VehiclePropValue{ + .areaId = 0, + .prop = propCreateUser, + .value.int32Values = + { + // Request ID + 666, + // SUCCESS + 1, + }, + }; + ASSERT_EQ(events[0], expectedValue); +} + +TEST_F(FakeVehicleHardwareTest, testInitialUserInfo) { + SubscribeOptions options; + int32_t propInitialUserInfo = toInt(VehicleProperty::INITIAL_USER_INFO); + options.propId = propInitialUserInfo; + options.areaIds = {0, 1}; + ASSERT_EQ(StatusCode::OK, getHardware()->subscribe(options)) + << "failed to subscribe to propId: " << propInitialUserInfo; + + // This is the same example as used in User HAL Emulation doc. + VehiclePropValue valueToSet = { + .prop = propInitialUserInfo, + .areaId = 1, + .value.int32Values = {666, 1, 11}, + }; + + StatusCode status = setValue(valueToSet); + + ASSERT_EQ(status, StatusCode::OK); + + // Simulate a request from Android side. + VehiclePropValue initialUserInfoRequest = { + .prop = propInitialUserInfo, + .areaId = 0, + .value.int32Values = {3}, + }; + // Clear existing events. + clearChangedProperties(); + + status = setValue(initialUserInfoRequest); + + ASSERT_EQ(status, StatusCode::OK); + + // Should generate an event for user hal response. + auto events = getChangedProperties(); + ASSERT_EQ(events.size(), static_cast(1)); + events[0].timestamp = 0; + auto expectedValue = VehiclePropValue{ + .areaId = 0, + .prop = propInitialUserInfo, + .value.int32Values = {3, 1, 11}, + }; + EXPECT_EQ(events[0], expectedValue); + + // Try to get create_user again, should return default value. + clearChangedProperties(); + status = setValue(initialUserInfoRequest); + ASSERT_EQ(status, StatusCode::OK); + + events = getChangedProperties(); + ASSERT_EQ(events.size(), static_cast(1)); + events[0].timestamp = 0; + expectedValue = VehiclePropValue{ + .areaId = 0, + .prop = propInitialUserInfo, + .value.int32Values = + { + // Request ID + 3, + // ACTION: DEFAULT + 0, + // User id: 0 + 0, + // Flags: 0 + 0, + }, + .value.stringValue = "||", + }; + EXPECT_EQ(events[0], expectedValue); +} + +TEST_F(FakeVehicleHardwareTest, testDumpAllProperties) { + std::vector options; + DumpResult result = getHardware()->dump(options); + ASSERT_TRUE(result.callerShouldDumpState); + ASSERT_NE(result.buffer, ""); + ASSERT_THAT(result.buffer, ContainsRegex("dumping .+ properties")); +} + +TEST_F(FakeVehicleHardwareTest, testDumpHelp) { + std::vector options; + options.push_back("--help"); + DumpResult result = getHardware()->dump(options); + ASSERT_FALSE(result.callerShouldDumpState); + ASSERT_NE(result.buffer, ""); + ASSERT_THAT(result.buffer, ContainsRegex("Usage: ")); +} + +TEST_F(FakeVehicleHardwareTest, testDumpListProperties) { + std::vector options; + options.push_back("--list"); + DumpResult result = getHardware()->dump(options); + ASSERT_FALSE(result.callerShouldDumpState); + ASSERT_NE(result.buffer, ""); + ASSERT_THAT(result.buffer, ContainsRegex("listing .+ properties")); +} + +TEST_F(FakeVehicleHardwareTest, testDumpSpecificProperties) { + std::vector options; + options.push_back("--get"); + std::string prop1 = std::to_string(toInt(VehicleProperty::INFO_FUEL_CAPACITY)); + std::string prop2 = std::to_string(toInt(VehicleProperty::TIRE_PRESSURE)); + options.push_back(prop1); + options.push_back(prop2); + DumpResult result = getHardware()->dump(options); + ASSERT_FALSE(result.callerShouldDumpState); + ASSERT_NE(result.buffer, ""); + ASSERT_THAT(result.buffer, + ContainsRegex(StringPrintf("1:.*prop: %s.*\n2-0:.*prop: %s.*\n2-1:.*prop: %s.*\n", + prop1.c_str(), prop2.c_str(), prop2.c_str()))); +} + +TEST_F(FakeVehicleHardwareTest, testDumpSpecificPropertiesWithName) { + std::vector options; + options.push_back("--get"); + std::string prop1 = "INFO_FUEL_CAPACITY"; + std::string prop2 = "TIRE_PRESSURE"; + int prop1Int = toInt(VehicleProperty::INFO_FUEL_CAPACITY); + int prop2Int = toInt(VehicleProperty::TIRE_PRESSURE); + options.push_back(prop1); + options.push_back(prop2); + DumpResult result = getHardware()->dump(options); + ASSERT_FALSE(result.callerShouldDumpState); + ASSERT_NE(result.buffer, ""); + ASSERT_THAT(result.buffer, + ContainsRegex(StringPrintf("1:.*prop: %d.*\n2-0:.*prop: %d.*\n2-1:.*prop: %d.*\n", + prop1Int, prop2Int, prop2Int))); +} + +TEST_F(FakeVehicleHardwareTest, testDumpSpecificPropertiesInvalidProp) { + std::vector options; + options.push_back("--get"); + std::string prop1 = std::to_string(toInt(VehicleProperty::INFO_FUEL_CAPACITY)); + std::string prop2 = std::to_string(INVALID_PROP_ID); + options.push_back(prop1); + options.push_back(prop2); + DumpResult result = getHardware()->dump(options); + ASSERT_FALSE(result.callerShouldDumpState); + ASSERT_NE(result.buffer, ""); + ASSERT_THAT(result.buffer, ContainsRegex(StringPrintf("1:.*prop: %s.*\nNo property INVALID\n", + prop1.c_str()))); +} + +TEST_F(FakeVehicleHardwareTest, testDumpSpecificPropertiesNoArg) { + std::vector options; + options.push_back("--get"); + + // No arguments. + DumpResult result = getHardware()->dump(options); + ASSERT_FALSE(result.callerShouldDumpState); + ASSERT_NE(result.buffer, ""); + ASSERT_THAT(result.buffer, ContainsRegex("Invalid number of arguments")); +} + +TEST_F(FakeVehicleHardwareTest, testDumpSpecificPropertyWithArg) { + auto getValueResult = getValue(VehiclePropValue{.prop = OBD2_FREEZE_FRAME_INFO}); + ASSERT_TRUE(getValueResult.ok()); + auto propValue = getValueResult.value(); + ASSERT_EQ(propValue.value.int64Values.size(), static_cast(3)) + << "expect 3 obd2 freeze frames stored"; + + std::string propIdStr = StringPrintf("%d", OBD2_FREEZE_FRAME); + DumpResult result; + for (int64_t timestamp : propValue.value.int64Values) { + result = getHardware()->dump( + {"--getWithArg", propIdStr, "-i64", StringPrintf("%" PRId64, timestamp)}); + + ASSERT_FALSE(result.callerShouldDumpState); + ASSERT_NE(result.buffer, ""); + ASSERT_THAT(result.buffer, ContainsRegex("Get property result:")); + } + + // Set the timestamp argument to 0. + result = getHardware()->dump({"--getWithArg", propIdStr, "-i64", "0"}); + + ASSERT_FALSE(result.callerShouldDumpState); + // There is no freeze obd2 frame at timestamp 0. + ASSERT_THAT(result.buffer, ContainsRegex("failed to read property value")); +} + +TEST_F(FakeVehicleHardwareTest, testSaveRestoreProp) { + int32_t prop = toInt(VehicleProperty::TIRE_PRESSURE); + std::string propIdStr = std::to_string(prop); + std::string areaIdStr = std::to_string(WHEEL_FRONT_LEFT); + + DumpResult result = getHardware()->dump({"--save-prop", propIdStr, "-a", areaIdStr}); + + ASSERT_FALSE(result.callerShouldDumpState); + ASSERT_THAT(result.buffer, ContainsRegex("saved")); + + ASSERT_EQ(setValue(VehiclePropValue{ + .prop = prop, + .areaId = WHEEL_FRONT_LEFT, + .value = + { + .floatValues = {210.0}, + }, + }), + StatusCode::OK); + + result = getHardware()->dump({"--restore-prop", propIdStr, "-a", areaIdStr}); + + ASSERT_FALSE(result.callerShouldDumpState); + ASSERT_THAT(result.buffer, ContainsRegex("restored")); + + auto getResult = getValue(VehiclePropValue{.prop = prop, .areaId = WHEEL_FRONT_LEFT}); + + ASSERT_TRUE(getResult.ok()); + // The default value is 200.0. + ASSERT_EQ(getResult.value().value.floatValues, std::vector{200.0}); +} + +TEST_F(FakeVehicleHardwareTest, testDumpInjectEvent) { + int32_t prop = toInt(VehicleProperty::ENGINE_OIL_LEVEL); + std::string propIdStr = std::to_string(prop); + + subscribe(prop, /*areaId*/ 0, /*sampleRateHz*/ 0); + + int64_t timestamp = elapsedRealtimeNano(); + DumpResult result = getHardware()->dump( + {"--inject-event", propIdStr, "-i", "1234", "-t", std::to_string(timestamp)}); + + ASSERT_FALSE(result.callerShouldDumpState); + ASSERT_THAT(result.buffer, ContainsRegex("Event for property: ENGINE_OIL_LEVEL injected")); + ASSERT_TRUE(waitForChangedProperties(prop, 0, /*count=*/1, milliseconds(1000))) + << "No changed event received for injected event from vehicle bus"; + auto events = getChangedProperties(); + ASSERT_EQ(events.size(), 1u); + auto event = events[0]; + ASSERT_EQ(event.timestamp, timestamp); + ASSERT_EQ(event.value.int32Values, std::vector({1234})); +} + +TEST_F(FakeVehicleHardwareTest, testDumpInvalidOptions) { + std::vector options; + options.push_back("--invalid"); + + DumpResult result = getHardware()->dump(options); + ASSERT_FALSE(result.callerShouldDumpState); + ASSERT_NE(result.buffer, ""); + ASSERT_THAT(result.buffer, ContainsRegex("Invalid option: --invalid")); +} + +TEST_F(FakeVehicleHardwareTest, testDumpFakeUserHal) { + std::vector options; + options.push_back("--user-hal"); + + DumpResult result = getHardware()->dump(options); + ASSERT_FALSE(result.callerShouldDumpState); + ASSERT_NE(result.buffer, ""); + ASSERT_THAT(result.buffer, + ContainsRegex("No InitialUserInfo response\nNo SwitchUser response\nNo CreateUser " + "response\nNo SetUserIdentificationAssociation response\n")); +} + +struct SetPropTestCase { + std::string test_name; + std::vector options; + bool success; + std::string errorMsg = ""; +}; + +class FakeVehicleHardwareSetPropTest : public FakeVehicleHardwareTest, + public testing::WithParamInterface {}; + +TEST_P(FakeVehicleHardwareSetPropTest, cmdSetOneProperty) { + const SetPropTestCase& tc = GetParam(); + + DumpResult result = getHardware()->dump(tc.options); + ASSERT_FALSE(result.callerShouldDumpState); + ASSERT_NE(result.buffer, ""); + if (tc.success) { + ASSERT_THAT(result.buffer, ContainsRegex("Set property:")); + } else { + ASSERT_THAT(result.buffer, ContainsRegex(tc.errorMsg)); + } +} + +std::vector GenSetPropParams() { + std::string infoMakeProperty = std::to_string(toInt(VehicleProperty::INFO_MAKE)); + std::string testVendorProperty = + std::to_string(toInt(TestVendorProperty::VENDOR_EXTENSION_FLOAT_PROPERTY)); + return { + {"success_set_string", {"--set", infoMakeProperty, "-s", CAR_MAKE}, true}, + {"success_set_with_name", {"--set", "INFO_MAKE", "-s", CAR_MAKE}, true}, + {"success_set_bytes", {"--set", infoMakeProperty, "-b", "0xdeadbeef"}, true}, + {"success_set_bytes_caps", {"--set", infoMakeProperty, "-b", "0xDEADBEEF"}, true}, + {"success_set_int", {"--set", infoMakeProperty, "-i", "2147483647"}, true}, + {"success_set_ints", + {"--set", infoMakeProperty, "-i", "2147483647", "0", "-2147483648"}, + true}, + {"success_set_int64", + {"--set", infoMakeProperty, "-i64", "-9223372036854775808"}, + true}, + {"success_set_int64s", + {"--set", infoMakeProperty, "-i64", "-9223372036854775808", "0", + "9223372036854775807"}, + true}, + {"success_set_float", {"--set", infoMakeProperty, "-f", "1.175494351E-38"}, true}, + {"success_set_floats", + {"--set", infoMakeProperty, "-f", "-3.402823466E+38", "0", "3.402823466E+38"}, + true}, + {"success_set_area", {"--set", infoMakeProperty, "-a", "2147483647"}, true}, + {"fail_no_options", {"--set", infoMakeProperty}, false, "Invalid number of arguments"}, + {"fail_less_than_4_options", + {"--set", infoMakeProperty, "-i"}, + false, + "No values specified"}, + {"fail_unknown_options", {"--set", infoMakeProperty, "-abcd"}, false, "Unknown option"}, + {"fail_invalid_property", {"--set", "not_valid", "-s", CAR_MAKE}, false, "not valid"}, + {"fail_duplicate_string", + {"--set", infoMakeProperty, "-s", CAR_MAKE, "-s", CAR_MAKE}, + false, + "Duplicate \"-s\" options"}, + {"fail_multiple_strings", + {"--set", infoMakeProperty, "-s", CAR_MAKE, CAR_MAKE}, + false, + "Expect exact one value"}, + {"fail_no_string_value", + {"--set", infoMakeProperty, "-s", "-a", "1234"}, + false, + "Expect exact one value"}, + {"fail_duplicate_bytes", + {"--set", infoMakeProperty, "-b", "0xdeadbeef", "-b", "0xdeadbeef"}, + false, + "Duplicate \"-b\" options"}, + {"fail_multiple_bytes", + {"--set", infoMakeProperty, "-b", "0xdeadbeef", "0xdeadbeef"}, + false, + "Expect exact one value"}, + {"fail_invalid_bytes", + {"--set", infoMakeProperty, "-b", "0xgood"}, + false, + "not a valid hex string"}, + {"fail_invalid_bytes_no_prefix", + {"--set", infoMakeProperty, "-b", "deadbeef"}, + false, + "not a valid hex string"}, + {"fail_invalid_int", + {"--set", infoMakeProperty, "-i", "abc"}, + false, + "not a valid int"}, + {"fail_int_out_of_range", + {"--set", infoMakeProperty, "-i", "2147483648"}, + false, + "not a valid int"}, + {"fail_no_int_value", + {"--set", infoMakeProperty, "-i", "-s", CAR_MAKE}, + false, + "No values specified"}, + {"fail_invalid_int64", + {"--set", infoMakeProperty, "-i64", "abc"}, + false, + "not a valid int64"}, + {"fail_int64_out_of_range", + {"--set", infoMakeProperty, "-i64", "-9223372036854775809"}, + false, + "not a valid int64"}, + {"fail_no_int64_value", + {"--set", infoMakeProperty, "-i64", "-s", CAR_MAKE}, + false, + "No values specified"}, + {"fail_invalid_float", + {"--set", infoMakeProperty, "-f", "abc"}, + false, + "not a valid float"}, + {"fail_float_out_of_range", + {"--set", infoMakeProperty, "-f", "-3.402823466E+39"}, + false, + "not a valid float"}, + {"fail_no_float_value", + {"--set", infoMakeProperty, "-f", "-s", CAR_MAKE}, + false, + "No values specified"}, + {"fail_multiple_areas", + {"--set", infoMakeProperty, "-a", "2147483648", "0"}, + false, + "Expect exact one value"}, + {"fail_invalid_area", + {"--set", infoMakeProperty, "-a", "abc"}, + false, + "not a valid int"}, + {"fail_area_out_of_range", + {"--set", infoMakeProperty, "-a", "2147483648"}, + false, + "not a valid int"}, + {"fail_no_area_value", + {"--set", infoMakeProperty, "-a", "-s", CAR_MAKE}, + false, + "Expect exact one value"}, + {"fail_invalid_area_name", + {"--set", testVendorProperty, "-a", "ROW_1_LEFT|NO_SUCH_AREA", "-f", "1.234"}, + false, + "not a valid int or one or more area names"}, + {"fail_invalid_area_format", + {"--set", testVendorProperty, "-a", "ROW_1_LEFT|||ROW_2_LEFT", "-f", "1.234"}, + false, + "not a valid int or one or more area names"}, + }; +} + +INSTANTIATE_TEST_SUITE_P( + FakeVehicleHardwareSetPropTests, FakeVehicleHardwareSetPropTest, + testing::ValuesIn(GenSetPropParams()), + [](const testing::TestParamInfo& info) { + return info.param.test_name; + }); + +TEST_F(FakeVehicleHardwareTest, SetComplexPropTest) { + std::string infoMakeProperty = std::to_string(toInt(VehicleProperty::INFO_MAKE)); + getHardware()->dump({"--set", infoMakeProperty, "-s", CAR_MAKE, + "-b", "0xdeadbeef", "-i", "2147483647", + "0", "-2147483648", "-i64", "-9223372036854775808", + "0", "9223372036854775807", "-f", "-3.402823466E+38", + "0", "3.402823466E+38", "-a", "123"}); + VehiclePropValue requestProp; + requestProp.prop = toInt(VehicleProperty::INFO_MAKE); + requestProp.areaId = 123; + auto result = getValue(requestProp); + ASSERT_TRUE(result.ok()); + VehiclePropValue value = result.value(); + ASSERT_EQ(value.prop, toInt(VehicleProperty::INFO_MAKE)); + ASSERT_EQ(value.areaId, 123); + ASSERT_STREQ(CAR_MAKE, value.value.stringValue.c_str()); + uint8_t bytes[] = {0xde, 0xad, 0xbe, 0xef}; + ASSERT_FALSE(memcmp(bytes, value.value.byteValues.data(), sizeof(bytes))); + ASSERT_EQ(3u, value.value.int32Values.size()); + ASSERT_EQ(2147483647, value.value.int32Values[0]); + ASSERT_EQ(0, value.value.int32Values[1]); + ASSERT_EQ(-2147483648, value.value.int32Values[2]); + ASSERT_EQ(3u, value.value.int64Values.size()); + // -9223372036854775808 is not a valid literal since '-' and '9223372036854775808' would be two + // tokens and the later does not fit in unsigned long long. + ASSERT_EQ(-9223372036854775807 - 1, value.value.int64Values[0]); + ASSERT_EQ(0, value.value.int64Values[1]); + ASSERT_EQ(9223372036854775807, value.value.int64Values[2]); + ASSERT_EQ(3u, value.value.floatValues.size()); + ASSERT_EQ(-3.402823466E+38f, value.value.floatValues[0]); + ASSERT_EQ(0.0f, value.value.floatValues[1]); + ASSERT_EQ(3.402823466E+38f, value.value.floatValues[2]); +} + +TEST_F(FakeVehicleHardwareTest, SetPropertyWithPropertyNameAreaId) { + int32_t areaId = toInt(VehicleAreaSeat::ROW_1_LEFT); + getHardware()->dump( + {"--set", "HVAC_TEMPERATURE_SET", "-a", std::to_string(areaId), "-f", "22.345"}); + + VehiclePropValue requestProp; + requestProp.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET); + requestProp.areaId = areaId; + auto result = getValue(requestProp); + + ASSERT_TRUE(result.ok()); + VehiclePropValue value = result.value(); + ASSERT_EQ(value.prop, toInt(VehicleProperty::HVAC_TEMPERATURE_SET)); + ASSERT_EQ(value.areaId, areaId); + ASSERT_EQ(1u, value.value.floatValues.size()); + ASSERT_EQ(22.345f, value.value.floatValues[0]); +} + +TEST_F(FakeVehicleHardwareTest, SetPropertyWithPropertyNameAreaName) { + int32_t areaId = toInt(VehicleAreaSeat::ROW_1_LEFT); + getHardware()->dump({"--set", "HVAC_TEMPERATURE_SET", "-a", "ROW_1_LEFT", "-f", "22.345"}); + + VehiclePropValue requestProp; + requestProp.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET); + requestProp.areaId = areaId; + auto result = getValue(requestProp); + + ASSERT_TRUE(result.ok()); + VehiclePropValue value = result.value(); + ASSERT_EQ(value.prop, toInt(VehicleProperty::HVAC_TEMPERATURE_SET)); + ASSERT_EQ(value.areaId, areaId); + ASSERT_EQ(1u, value.value.floatValues.size()); + ASSERT_EQ(22.345f, value.value.floatValues[0]); +} + +TEST_F(FakeVehicleHardwareTest, GetPropertyWithPropertyNameAreaName) { + auto result = getHardware()->dump({"--get", "HVAC_TEMPERATURE_SET", "-a", "ROW_1_LEFT"}); + + // Default value is 17 + ASSERT_THAT(result.buffer, ContainsRegex("17")); + + getHardware()->dump({"--set", "HVAC_TEMPERATURE_SET", "-a", "ROW_1_LEFT", "-f", "22"}); + result = getHardware()->dump({"--get", "HVAC_TEMPERATURE_SET", "-a", "ROW_1_LEFT"}); + + ASSERT_THAT(result.buffer, ContainsRegex("22")); +} + +TEST_F(FakeVehicleHardwareTest, SetPropertyWithPropertyNameTwoAreasInOneId) { + int32_t propId = toInt(TestVendorProperty::VENDOR_EXTENSION_FLOAT_PROPERTY); + std::string testVendorProperty = std::to_string(propId); + getHardware()->dump({"--set", testVendorProperty, "-a", "ROW_1_LEFT|ROW_2_LEFT|ROW_2_CENTER", + "-f", "1.234"}); + + VehiclePropValue requestProp; + requestProp.prop = propId; + int32_t areaId = toInt(VehicleAreaSeat::ROW_1_LEFT) | toInt(VehicleAreaSeat::ROW_2_LEFT) | + toInt(VehicleAreaSeat::ROW_2_CENTER); + requestProp.areaId = areaId; + auto result = getValue(requestProp); + + ASSERT_TRUE(result.ok()); + VehiclePropValue value = result.value(); + ASSERT_EQ(value.prop, propId); + ASSERT_EQ(value.areaId, areaId); + ASSERT_EQ(1u, value.value.floatValues.size()); + ASSERT_EQ(1.234f, value.value.floatValues[0]); + + // Ignore space between two areas. + getHardware()->dump({"--set", testVendorProperty, "-a", + "ROW_1_LEFT | ROW_2_LEFT | ROW_2_CENTER", "-f", "2.345"}); + result = getValue(requestProp); + + ASSERT_TRUE(result.ok()); + value = result.value(); + ASSERT_EQ(value.prop, propId); + ASSERT_EQ(value.areaId, areaId); + ASSERT_EQ(1u, value.value.floatValues.size()); + ASSERT_EQ(2.345f, value.value.floatValues[0]); +} + +struct OptionsTestCase { + std::string name; + std::vector options; + std::string expectMsg; +}; + +class FakeVehicleHardwareOptionsTest : public FakeVehicleHardwareTest, + public testing::WithParamInterface {}; + +std::vector GenInvalidOptions() { + return {{"unknown_command", {"--unknown"}, "Invalid option: --unknown"}, + {"help", {"--help"}, "Usage:"}, + {"genfakedata_no_subcommand", + {"--genfakedata"}, + "No subcommand specified for genfakedata"}, + {"genfakedata_unknown_subcommand", + {"--genfakedata", "--unknown"}, + "Unknown command: \"--unknown\""}, + {"genfakedata_start_linear_no_args", + {"--genfakedata", "--startlinear"}, + "incorrect argument count"}, + {"genfakedata_start_linear_invalid_propId", + {"--genfakedata", "--startlinear", "abcd", "0.1", "0.1", "0.1", "0.1", "100000000"}, + "failed to parse propId as int: \"abcd\""}, + {"genfakedata_start_linear_invalid_middleValue", + {"--genfakedata", "--startlinear", "1", "abcd", "0.1", "0.1", "0.1", "100000000"}, + "failed to parse middleValue as float: \"abcd\""}, + {"genfakedata_start_linear_invalid_currentValue", + {"--genfakedata", "--startlinear", "1", "0.1", "abcd", "0.1", "0.1", "100000000"}, + "failed to parse currentValue as float: \"abcd\""}, + {"genfakedata_start_linear_invalid_dispersion", + {"--genfakedata", "--startlinear", "1", "0.1", "0.1", "abcd", "0.1", "100000000"}, + "failed to parse dispersion as float: \"abcd\""}, + {"genfakedata_start_linear_invalid_increment", + {"--genfakedata", "--startlinear", "1", "0.1", "0.1", "0.1", "abcd", "100000000"}, + "failed to parse increment as float: \"abcd\""}, + {"genfakedata_start_linear_invalid_interval", + {"--genfakedata", "--startlinear", "1", "0.1", "0.1", "0.1", "0.1", "0.1"}, + "failed to parse interval as int: \"0.1\""}, + {"genfakedata_stop_linear_no_args", + {"--genfakedata", "--stoplinear"}, + "incorrect argument count"}, + {"genfakedata_stop_linear_invalid_propId", + {"--genfakedata", "--stoplinear", "abcd"}, + "failed to parse propId as int: \"abcd\""}, + {"genfakedata_startjson_no_args", + {"--genfakedata", "--startjson"}, + "incorrect argument count"}, + {"genfakedata_startjson_invalid_repetition", + {"--genfakedata", "--startjson", "--path", "file", "0.1"}, + "failed to parse repetition as int: \"0.1\""}, + {"genfakedata_startjson_invalid_json_file", + {"--genfakedata", "--startjson", "--path", "file", "1"}, + "invalid JSON file"}, + {"genfakedata_stopjson_no_args", + {"--genfakedata", "--stopjson"}, + "incorrect argument count"}, + {"genfakedata_keypress_no_args", + {"--genfakedata", "--keypress"}, + "incorrect argument count"}, + {"genfakedata_keypress_invalid_keyCode", + {"--genfakedata", "--keypress", "0.1", "1"}, + "failed to parse keyCode as int: \"0.1\""}, + {"genfakedata_keypress_invalid_display", + {"--genfakedata", "--keypress", "1", "0.1"}, + "failed to parse display as int: \"0.1\""}, + {"genfakedata_keyinputv2_incorrect_arguments", + {"--genfakedata", "--keyinputv2", "1", "1"}, + "incorrect argument count, need 7 arguments for --genfakedata --keyinputv2\n"}, + {"genfakedata_keyinputv2_invalid_area", + {"--genfakedata", "--keyinputv2", "0.1", "1", "1", "1", "1"}, + "failed to parse area as int: \"0.1\""}, + {"genfakedata_keyinputv2_invalid_display", + {"--genfakedata", "--keyinputv2", "1", "0.1", "1", "1", "1"}, + "failed to parse display as int: \"0.1\""}, + {"genfakedata_keyinputv2_invalid_keycode", + {"--genfakedata", "--keyinputv2", "1", "1", "0.1", "1", "1"}, + "failed to parse keyCode as int: \"0.1\""}, + {"genfakedata_keyinputv2_invalid_action", + {"--genfakedata", "--keyinputv2", "1", "1", "1", "0.1", "1"}, + "failed to parse action as int: \"0.1\""}, + {"genfakedata_keyinputv2_invalid_repeatcount", + {"--genfakedata", "--keyinputv2", "1", "1", "1", "1", "0.1"}, + "failed to parse repeatCount as int: \"0.1\""}, + {"genfakedata_motioninput_invalid_argument_count", + {"--genfakedata", "--motioninput", "1", "1", "1", "1", "1"}, + "incorrect argument count, need at least 14 arguments for --genfakedata " + "--motioninput including at least 1 --pointer\n"}, + {"genfakedata_motioninput_pointer_invalid_argument_count", + {"--genfakedata", "--motioninput", "1", "1", "1", "1", "1", "--pointer", "1", "1", "1", + "1", "1", "1", "--pointer"}, + "incorrect argument count, need 6 arguments for every --pointer\n"}, + {"genfakedata_motioninput_invalid_area", + {"--genfakedata", "--motioninput", "0.1", "1", "1", "1", "1", "--pointer", "1", "1", + "1", "1", "1", "1"}, + "failed to parse area as int: \"0.1\""}, + {"genfakedata_motioninput_invalid_display", + {"--genfakedata", "--motioninput", "1", "0.1", "1", "1", "1", "--pointer", "1", "1", + "1", "1", "1", "1"}, + "failed to parse display as int: \"0.1\""}, + {"genfakedata_motioninput_invalid_inputtype", + {"--genfakedata", "--motioninput", "1", "1", "0.1", "1", "1", "--pointer", "1", "1", + "1", "1", "1", "1"}, + "failed to parse inputType as int: \"0.1\""}, + {"genfakedata_motioninput_invalid_action", + {"--genfakedata", "--motioninput", "1", "1", "1", "0.1", "1", "--pointer", "1", "1", + "1", "1", "1", "1"}, + "failed to parse action as int: \"0.1\""}, + {"genfakedata_motioninput_invalid_buttonstate", + {"--genfakedata", "--motioninput", "1", "1", "1", "1", "0.1", "--pointer", "1", "1", + "1.2", "1.2", "1.2", "1.2"}, + "failed to parse buttonState as int: \"0.1\""}, + {"genfakedata_motioninput_invalid_pointerid", + {"--genfakedata", "--motioninput", "1", "1", "1", "1", "1", "--pointer", "0.1", "1", + "1.2", "1", "1", "1"}, + "failed to parse pointerId as int: \"0.1\""}, + {"genfakedata_motioninput_invalid_tooltype", + {"--genfakedata", "--motioninput", "1", "1", "1", "1", "1", "--pointer", "1", "0.1", + "1.2", "1", "1", "1"}, + "failed to parse toolType as int: \"0.1\""}}; +} + +TEST_P(FakeVehicleHardwareOptionsTest, testInvalidOptions) { + auto tc = GetParam(); + + DumpResult result = getHardware()->dump(tc.options); + + EXPECT_FALSE(result.callerShouldDumpState); + EXPECT_THAT(result.buffer, HasSubstr(tc.expectMsg)); +} + +INSTANTIATE_TEST_SUITE_P( + FakeVehicleHardwareOptionsTests, FakeVehicleHardwareOptionsTest, + testing::ValuesIn(GenInvalidOptions()), + [](const testing::TestParamInfo& info) { + return info.param.name; + }); + +TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataLinear) { + // Start a fake linear data generator for engine oil level at 0.1s interval. + // range: 0 - 100, current value: 30, step: 20. + int32_t prop = toInt(VehicleProperty::ENGINE_OIL_LEVEL); + + subscribe(prop, /*areaId*/ 0, /*sampleRateHz*/ 0); + + std::string propIdString = StringPrintf("%d", prop); + std::vector options = {"--genfakedata", "--startlinear", propIdString, + /*middleValue=*/"50", + /*currentValue=*/"30", + /*dispersion=*/"50", + /*increment=*/"20", + /*interval=*/"100000000"}; + + DumpResult result = getHardware()->dump(options); + + ASSERT_FALSE(result.callerShouldDumpState); + ASSERT_THAT(result.buffer, HasSubstr("successfully")); + + ASSERT_TRUE(waitForChangedProperties(prop, 0, /*count=*/5, milliseconds(1000))) + << "not enough events generated for linear data generator"; + + int32_t value = 30; + auto events = getChangedProperties(); + for (size_t i = 0; i < 5; i++) { + ASSERT_EQ(1u, events[i].value.int32Values.size()); + EXPECT_EQ(value, events[i].value.int32Values[0]); + value = (value + 20) % 100; + } + + // Stop the linear generator. + options = {"--genfakedata", "--stoplinear", propIdString}; + + result = getHardware()->dump(options); + + ASSERT_FALSE(result.callerShouldDumpState); + ASSERT_THAT(result.buffer, HasSubstr("successfully")); + + clearChangedProperties(); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + + // There should be no new events generated. + EXPECT_EQ(0u, getEventCount(prop, 0)); +} + +std::string getTestFilePath(const char* filename) { + static std::string baseDir = android::base::GetExecutableDirectory(); + return baseDir + "/fakedata/" + filename; +} + +TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJson) { + subscribe(toInt(VehicleProperty::GEAR_SELECTION), /*areaId*/ 0, /*sampleRateHz*/ 0); + + std::vector options = {"--genfakedata", "--startjson", "--path", + getTestFilePath("prop.json"), "2"}; + + DumpResult result = getHardware()->dump(options); + + ASSERT_FALSE(result.callerShouldDumpState); + ASSERT_THAT(result.buffer, HasSubstr("successfully")); + + ASSERT_TRUE(waitForChangedProperties(/*count=*/8, milliseconds(1000))) + << "not enough events generated for JSON data generator"; + + auto events = getChangedProperties(); + ASSERT_EQ(8u, events.size()); + // First set of events, we test 1st and the last. + EXPECT_EQ(1u, events[0].value.int32Values.size()); + EXPECT_EQ(8, events[0].value.int32Values[0]); + EXPECT_EQ(1u, events[3].value.int32Values.size()); + EXPECT_EQ(10, events[3].value.int32Values[0]); + // Second set of the same events. + EXPECT_EQ(1u, events[4].value.int32Values.size()); + EXPECT_EQ(8, events[4].value.int32Values[0]); + EXPECT_EQ(1u, events[7].value.int32Values.size()); + EXPECT_EQ(10, events[7].value.int32Values[0]); +} + +TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJsonByContent) { + subscribe(toInt(VehicleProperty::GEAR_SELECTION), /*areaId*/ 0, /*sampleRateHz*/ 0); + + std::vector options = { + "--genfakedata", "--startjson", "--content", + "[{\"timestamp\":1000000,\"areaId\":0,\"value\":8,\"prop\":289408000}]", "1"}; + + DumpResult result = getHardware()->dump(options); + + ASSERT_FALSE(result.callerShouldDumpState); + ASSERT_THAT(result.buffer, HasSubstr("successfully")); + + ASSERT_TRUE(waitForChangedProperties(/*count=*/1, milliseconds(1000))) + << "not enough events generated for JSON data generator"; + + auto events = getChangedProperties(); + ASSERT_EQ(1u, events.size()); + EXPECT_EQ(1u, events[0].value.int32Values.size()); + EXPECT_EQ(8, events[0].value.int32Values[0]); +} + +TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJsonInvalidContent) { + std::vector options = {"--genfakedata", "--startjson", "--content", "[{", "2"}; + + DumpResult result = getHardware()->dump(options); + + ASSERT_FALSE(result.callerShouldDumpState); + ASSERT_THAT(result.buffer, HasSubstr("invalid JSON content")); +} + +TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJsonInvalidFile) { + std::vector options = {"--genfakedata", "--startjson", "--path", + getTestFilePath("blahblah.json"), "2"}; + + DumpResult result = getHardware()->dump(options); + + ASSERT_FALSE(result.callerShouldDumpState); + ASSERT_THAT(result.buffer, HasSubstr("invalid JSON file")); +} + +TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJsonStop) { + // No iteration number provided, would loop indefinitely. + std::vector options = {"--genfakedata", "--startjson", "--path", + getTestFilePath("prop.json")}; + + DumpResult result = getHardware()->dump(options); + + ASSERT_FALSE(result.callerShouldDumpState); + ASSERT_THAT(result.buffer, HasSubstr("successfully")); + + std::string id = result.buffer.substr(result.buffer.find("ID: ") + 4); + + result = getHardware()->dump({"--genfakedata", "--stopjson", id}); + + ASSERT_FALSE(result.callerShouldDumpState); + ASSERT_THAT(result.buffer, HasSubstr("successfully")); +} + +TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJsonStopInvalidFile) { + // No iteration number provided, would loop indefinitely. + std::vector options = {"--genfakedata", "--startjson", "--path", + getTestFilePath("prop.json")}; + + DumpResult result = getHardware()->dump(options); + + ASSERT_FALSE(result.callerShouldDumpState); + ASSERT_THAT(result.buffer, HasSubstr("successfully")); + + result = getHardware()->dump({"--genfakedata", "--stopjson", "1234"}); + + ASSERT_FALSE(result.callerShouldDumpState); + ASSERT_THAT(result.buffer, HasSubstr("No JSON event generator found")); + + // TearDown function should destroy the generator which stops the iteration. +} + +TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataKeyPress) { + int32_t propHwKeyInput = toInt(VehicleProperty::HW_KEY_INPUT); + std::vector options = {"--genfakedata", "--keypress", "1", "2"}; + + subscribe(propHwKeyInput, /*areaId*/ 0, /*sampleRateHz*/ 0); + + DumpResult result = getHardware()->dump(options); + + ASSERT_FALSE(result.callerShouldDumpState); + ASSERT_THAT(result.buffer, HasSubstr("successfully")); + + auto events = getChangedProperties(); + ASSERT_EQ(2u, events.size()); + EXPECT_EQ(propHwKeyInput, events[0].prop); + EXPECT_EQ(propHwKeyInput, events[1].prop); + ASSERT_EQ(3u, events[0].value.int32Values.size()); + ASSERT_EQ(3u, events[1].value.int32Values.size()); + EXPECT_EQ(toInt(VehicleHwKeyInputAction::ACTION_DOWN), events[0].value.int32Values[0]); + EXPECT_EQ(1, events[0].value.int32Values[1]); + EXPECT_EQ(2, events[0].value.int32Values[2]); + EXPECT_EQ(toInt(VehicleHwKeyInputAction::ACTION_UP), events[1].value.int32Values[0]); + EXPECT_EQ(1, events[1].value.int32Values[1]); + EXPECT_EQ(2, events[1].value.int32Values[2]); +} + +TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataKeyInputV2) { + int32_t propHwKeyInputV2 = toInt(VehicleProperty::HW_KEY_INPUT_V2); + std::vector options = {"--genfakedata", "--keyinputv2", "1", "2", "3", "4", "5"}; + + subscribe(propHwKeyInputV2, /*areaId*/ 1, /*sampleRateHz*/ 0); + + DumpResult result = getHardware()->dump(options); + + ASSERT_FALSE(result.callerShouldDumpState); + ASSERT_THAT(result.buffer, HasSubstr("successfully")); + + auto events = getChangedProperties(); + ASSERT_EQ(1u, events.size()); + EXPECT_EQ(toInt(VehicleProperty::HW_KEY_INPUT_V2), events[0].prop); + ASSERT_EQ(4u, events[0].value.int32Values.size()); + EXPECT_EQ(2, events[0].value.int32Values[0]); + EXPECT_EQ(3, events[0].value.int32Values[1]); + EXPECT_EQ(4, events[0].value.int32Values[2]); + EXPECT_EQ(5, events[0].value.int32Values[3]); + ASSERT_EQ(1u, events[0].value.int64Values.size()); +} + +TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataMotionInput) { + int32_t propHwMotionInput = toInt(VehicleProperty::HW_MOTION_INPUT); + std::vector options = {"--genfakedata", + "--motioninput", + "1", + "2", + "3", + "4", + "5", + "--pointer", + "11", + "22", + "33.3", + "44.4", + "55.5", + "66.6", + "--pointer", + "21", + "32", + "43.3", + "54.4", + "65.5", + "76.6"}; + + subscribe(propHwMotionInput, /*areaId*/ 1, /*sampleRateHz*/ 0); + + DumpResult result = getHardware()->dump(options); + + ASSERT_FALSE(result.callerShouldDumpState); + ASSERT_THAT(result.buffer, HasSubstr("successfully")); + + auto events = getChangedProperties(); + ASSERT_EQ(1u, events.size()); + EXPECT_EQ(propHwMotionInput, events[0].prop); + ASSERT_EQ(9u, events[0].value.int32Values.size()); + EXPECT_EQ(2, events[0].value.int32Values[0]); + EXPECT_EQ(3, events[0].value.int32Values[1]); + EXPECT_EQ(4, events[0].value.int32Values[2]); + EXPECT_EQ(5, events[0].value.int32Values[3]); + EXPECT_EQ(2, events[0].value.int32Values[4]); + EXPECT_EQ(11, events[0].value.int32Values[5]); + EXPECT_EQ(21, events[0].value.int32Values[6]); + EXPECT_EQ(22, events[0].value.int32Values[7]); + EXPECT_EQ(32, events[0].value.int32Values[8]); + ASSERT_EQ(8u, events[0].value.floatValues.size()); + EXPECT_FLOAT_EQ(33.3, events[0].value.floatValues[0]); + EXPECT_FLOAT_EQ(43.3, events[0].value.floatValues[1]); + EXPECT_FLOAT_EQ(44.4, events[0].value.floatValues[2]); + EXPECT_FLOAT_EQ(54.4, events[0].value.floatValues[3]); + EXPECT_FLOAT_EQ(55.5, events[0].value.floatValues[4]); + EXPECT_FLOAT_EQ(65.5, events[0].value.floatValues[5]); + EXPECT_FLOAT_EQ(66.6, events[0].value.floatValues[6]); + EXPECT_FLOAT_EQ(76.6, events[0].value.floatValues[7]); + ASSERT_EQ(1u, events[0].value.int64Values.size()); +} + +TEST_F(FakeVehicleHardwareTest, testGetEchoReverseBytes) { + ASSERT_EQ(setValue(VehiclePropValue{ + .prop = toInt(TestVendorProperty::ECHO_REVERSE_BYTES), + .value = + { + .byteValues = {0x01, 0x02, 0x03, 0x04}, + }, + }), + StatusCode::OK); + + auto result = getValue(VehiclePropValue{ + .prop = toInt(TestVendorProperty::ECHO_REVERSE_BYTES), + }); + + ASSERT_TRUE(result.ok()) << "failed to get ECHO_REVERSE_BYTES value: " << getStatus(result); + ASSERT_EQ(result.value().value.byteValues, std::vector({0x04, 0x03, 0x02, 0x01})); +} + +TEST_F(FakeVehicleHardwareTest, testSubscribeUnsubscribe_continuous) { + int32_t propSpeed = toInt(VehicleProperty::PERF_VEHICLE_SPEED); + int32_t propSteering = toInt(VehicleProperty::PERF_STEERING_ANGLE); + int32_t areaId = 0; + + auto status = getHardware()->subscribe(newSubscribeOptions(propSpeed, areaId, 5)); + ASSERT_EQ(status, StatusCode::OK) << "failed to subscribe"; + + ASSERT_TRUE(waitForChangedProperties(propSpeed, areaId, /*count=*/5, milliseconds(1500))) + << "not enough events generated for speed"; + + status = getHardware()->subscribe(newSubscribeOptions(propSteering, areaId, 10)); + ASSERT_EQ(status, StatusCode::OK) << "failed to subscribe"; + + ASSERT_TRUE(waitForChangedProperties(propSteering, areaId, /*count=*/10, milliseconds(1500))) + << "not enough events generated for steering"; + + int64_t timestamp = elapsedRealtimeNano(); + // Disable refreshing for propSpeed. + status = getHardware()->unsubscribe(propSpeed, areaId); + ASSERT_EQ(status, StatusCode::OK) << "failed to unsubscribe"; + clearChangedProperties(); + + ASSERT_TRUE(waitForChangedProperties(propSteering, areaId, /*count=*/5, milliseconds(1500))) + << "should still receive steering events after disable polling for speed"; + auto updatedValues = getChangedProperties(); + for (auto& value : updatedValues) { + ASSERT_GE(value.timestamp, timestamp); + ASSERT_EQ(value.prop, propSteering); + ASSERT_EQ(value.areaId, areaId); + } +} + +TEST_F(FakeVehicleHardwareTest, testSubscribe_enableVUR) { + int32_t propSpeed = toInt(VehicleProperty::PERF_VEHICLE_SPEED); + int32_t areaId = 0; + SubscribeOptions options; + options.propId = propSpeed; + options.areaIds = {areaId}; + options.enableVariableUpdateRate = true; + options.sampleRate = 5; + int64_t timestamp = elapsedRealtimeNano(); + + auto status = getHardware()->subscribe(options); + ASSERT_EQ(status, StatusCode::OK) << "failed to subscribe"; + + status = setValue({ + .prop = propSpeed, + .areaId = 0, + .value.floatValues = {1.1f}, + }); + ASSERT_EQ(status, StatusCode::OK) << "failed to set speed"; + + status = setValue({ + .prop = propSpeed, + .areaId = 0, + .value.floatValues = {1.2f}, + }); + ASSERT_EQ(status, StatusCode::OK) << "failed to set speed"; + + ASSERT_TRUE(waitForChangedProperties(propSpeed, areaId, /*count=*/2, milliseconds(100))) + << "not enough events generated for speed"; + auto updatedValues = getChangedProperties(); + std::unordered_set gotValues; + for (auto& value : updatedValues) { + EXPECT_GE(value.timestamp, timestamp) << "timestamp must be updated"; + EXPECT_EQ(value.prop, propSpeed) << "propId must be correct"; + EXPECT_EQ(value.areaId, areaId) << "areaId must be correct"; + gotValues.insert(value.value.floatValues[0]); + } + EXPECT_THAT(gotValues, UnorderedElementsAre(1.1f, 1.2f)) + << "must only receive property event for changed value"; +} + +TEST_F(FakeVehicleHardwareTest, testSubscribeUnusubscribe_onChange) { + int32_t propHvac = toInt(VehicleProperty::HVAC_TEMPERATURE_SET); + int32_t areaId = SEAT_1_LEFT; + + auto status = getHardware()->subscribe(newSubscribeOptions(propHvac, areaId, 0)); + ASSERT_EQ(status, StatusCode::OK) << "failed to subscribe"; + + status = setValue({ + .prop = propHvac, + .areaId = areaId, + .value.floatValues = {20.0f}, + }); + ASSERT_EQ(status, StatusCode::OK) << "failed to set hvac value"; + + ASSERT_TRUE(waitForChangedProperties(propHvac, areaId, /*count=*/1, milliseconds(100))) + << "not enough on change events generated for hvac"; + clearChangedProperties(); + + status = setValue({ + .prop = propHvac, + .areaId = areaId, + .value.floatValues = {21.0f}, + }); + ASSERT_EQ(status, StatusCode::OK) << "failed to set hvac value"; + + ASSERT_TRUE(waitForChangedProperties(propHvac, areaId, /*count=*/1, milliseconds(100))) + << "not enough on change events generated for hvac"; + clearChangedProperties(); + + status = getHardware()->unsubscribe(propHvac, areaId); + ASSERT_EQ(status, StatusCode::OK); + + status = setValue({ + .prop = propHvac, + .areaId = areaId, + .value.floatValues = {22.0f}, + }); + ASSERT_EQ(status, StatusCode::OK) << "failed to set hvac value"; + + ASSERT_FALSE(waitForChangedProperties(propHvac, areaId, /*count=*/1, milliseconds(100))) + << "must not receive on change events if the propId, areaId is unsubscribed"; +} + +TEST_F(FakeVehicleHardwareTest, testSubscribeContinuous_rate0_mustReturnInvalidArg) { + int32_t propSpeed = toInt(VehicleProperty::PERF_VEHICLE_SPEED); + int32_t areaId = 0; + auto status = getHardware()->subscribe(newSubscribeOptions(propSpeed, areaId, 0)); + + ASSERT_EQ(status, StatusCode::INVALID_ARG); +} + +TEST_F(FakeVehicleHardwareTest, testSetHvacTemperatureValueSuggestion) { + float CELSIUS = static_cast(toInt(VehicleUnit::CELSIUS)); + float FAHRENHEIT = static_cast(toInt(VehicleUnit::FAHRENHEIT)); + int32_t propHvacTempValueSuggest = toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION); + + subscribe(propHvacTempValueSuggest, HVAC_ALL, /*sampleRateHz*/ 0); + + VehiclePropValue floatArraySizeFour = { + .prop = propHvacTempValueSuggest, + .areaId = HVAC_ALL, + .value.floatValues = {0, CELSIUS, 0, 0}, + }; + StatusCode status = setValue(floatArraySizeFour); + EXPECT_EQ(status, StatusCode::OK); + + VehiclePropValue floatArraySizeZero = { + .prop = propHvacTempValueSuggest, + .areaId = HVAC_ALL, + }; + status = setValue(floatArraySizeZero); + EXPECT_EQ(status, StatusCode::INVALID_ARG); + + VehiclePropValue floatArraySizeFive = { + .prop = propHvacTempValueSuggest, + .areaId = HVAC_ALL, + .value.floatValues = {0, CELSIUS, 0, 0, 0}, + }; + status = setValue(floatArraySizeFive); + EXPECT_EQ(status, StatusCode::INVALID_ARG); + + VehiclePropValue invalidUnit = { + .prop = propHvacTempValueSuggest, + .areaId = HVAC_ALL, + .value.floatValues = {0, 0, 0, 0}, + }; + status = setValue(floatArraySizeFive); + EXPECT_EQ(status, StatusCode::INVALID_ARG); + clearChangedProperties(); + + // Config array values from HVAC_TEMPERATURE_SET in DefaultProperties.json + auto configs = getHardware()->getAllPropertyConfigs(); + auto hvacTemperatureSetConfig = + getVehiclePropConfig(toInt(VehicleProperty::HVAC_TEMPERATURE_SET)); + EXPECT_NE(hvacTemperatureSetConfig, nullptr); + + auto& hvacTemperatureSetConfigArray = hvacTemperatureSetConfig->configArray; + // The HVAC_TEMPERATURE_SET config array values are temperature values that have been multiplied + // by 10 and converted to integers. HVAC_TEMPERATURE_VALUE_SUGGESTION specifies the temperature + // values to be in the original floating point form so we divide by 10 and convert to float. + float minTempInCelsius = hvacTemperatureSetConfigArray[0] / 10.0f; + float maxTempInCelsius = hvacTemperatureSetConfigArray[1] / 10.0f; + float incrementInCelsius = hvacTemperatureSetConfigArray[2] / 10.0f; + float minTempInFahrenheit = hvacTemperatureSetConfigArray[3] / 10.0f; + float maxTempInFahrenheit = hvacTemperatureSetConfigArray[4] / 10.0f; + float incrementInFahrenheit = hvacTemperatureSetConfigArray[5] / 10.0f; + + auto testCases = { + SetSpecialValueTestCase{ + .name = "min_celsius_temperature", + .valuesToSet = + { + VehiclePropValue{ + .prop = propHvacTempValueSuggest, + .areaId = HVAC_ALL, + .value.floatValues = {minTempInCelsius, CELSIUS, 0, 0}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = propHvacTempValueSuggest, + .areaId = HVAC_ALL, + .value.floatValues = {minTempInCelsius, CELSIUS, + minTempInCelsius, + minTempInFahrenheit}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "min_fahrenheit_temperature", + .valuesToSet = + { + VehiclePropValue{ + .prop = propHvacTempValueSuggest, + .areaId = HVAC_ALL, + .value.floatValues = {minTempInFahrenheit, FAHRENHEIT, + 0, 0}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = propHvacTempValueSuggest, + .areaId = HVAC_ALL, + .value.floatValues = {minTempInFahrenheit, FAHRENHEIT, + minTempInCelsius, + minTempInFahrenheit}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "max_celsius_temperature", + .valuesToSet = + { + VehiclePropValue{ + .prop = propHvacTempValueSuggest, + .areaId = HVAC_ALL, + .value.floatValues = {maxTempInCelsius, CELSIUS, 0, 0}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = propHvacTempValueSuggest, + .areaId = HVAC_ALL, + .value.floatValues = {maxTempInCelsius, CELSIUS, + maxTempInCelsius, + maxTempInFahrenheit}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "max_fahrenheit_temperature", + .valuesToSet = + { + VehiclePropValue{ + .prop = propHvacTempValueSuggest, + .areaId = HVAC_ALL, + .value.floatValues = {maxTempInFahrenheit, FAHRENHEIT, + 0, 0}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = propHvacTempValueSuggest, + .areaId = HVAC_ALL, + .value.floatValues = {maxTempInFahrenheit, FAHRENHEIT, + maxTempInCelsius, + maxTempInFahrenheit}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "below_min_celsius_temperature", + .valuesToSet = + { + VehiclePropValue{ + .prop = propHvacTempValueSuggest, + .areaId = HVAC_ALL, + .value.floatValues = {minTempInCelsius - 1, CELSIUS, 0, + 0}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = propHvacTempValueSuggest, + .areaId = HVAC_ALL, + .value.floatValues = {minTempInCelsius - 1, CELSIUS, + minTempInCelsius, + minTempInFahrenheit}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "below_min_fahrenheit_temperature", + .valuesToSet = + { + VehiclePropValue{ + .prop = propHvacTempValueSuggest, + .areaId = HVAC_ALL, + .value.floatValues = {minTempInFahrenheit - 1, + FAHRENHEIT, 0, 0}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = propHvacTempValueSuggest, + .areaId = HVAC_ALL, + .value.floatValues = {minTempInFahrenheit - 1, + FAHRENHEIT, minTempInCelsius, + minTempInFahrenheit}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "above_max_celsius_temperature", + .valuesToSet = + { + VehiclePropValue{ + .prop = propHvacTempValueSuggest, + .areaId = HVAC_ALL, + .value.floatValues = {maxTempInCelsius + 1, CELSIUS, 0, + 0}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = propHvacTempValueSuggest, + .areaId = HVAC_ALL, + .value.floatValues = {maxTempInCelsius + 1, CELSIUS, + maxTempInCelsius, + maxTempInFahrenheit}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "above_max_fahrenheit_temperature", + .valuesToSet = + { + VehiclePropValue{ + .prop = propHvacTempValueSuggest, + .areaId = HVAC_ALL, + .value.floatValues = {maxTempInFahrenheit + 1, + FAHRENHEIT, 0, 0}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = propHvacTempValueSuggest, + .areaId = HVAC_ALL, + .value.floatValues = {maxTempInFahrenheit + 1, + FAHRENHEIT, maxTempInCelsius, + maxTempInFahrenheit}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "inbetween_value_celsius", + .valuesToSet = + { + VehiclePropValue{ + .prop = propHvacTempValueSuggest, + .areaId = HVAC_ALL, + .value.floatValues = {minTempInCelsius + + incrementInCelsius * 2.5f, + CELSIUS, 0, 0}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = propHvacTempValueSuggest, + .areaId = HVAC_ALL, + .value.floatValues = + {minTempInCelsius + incrementInCelsius * 2.5f, + CELSIUS, + minTempInCelsius + incrementInCelsius * 2, + minTempInFahrenheit + + incrementInFahrenheit * 2}, + }, + }, + }, + SetSpecialValueTestCase{ + .name = "inbetween_value_fahrenheit", + .valuesToSet = + { + VehiclePropValue{ + .prop = propHvacTempValueSuggest, + .areaId = HVAC_ALL, + .value.floatValues = {minTempInFahrenheit + + incrementInFahrenheit * + 2.5f, + FAHRENHEIT, 0, 0}, + }, + }, + .expectedValuesToGet = + { + VehiclePropValue{ + .prop = propHvacTempValueSuggest, + .areaId = HVAC_ALL, + .value.floatValues = + {minTempInFahrenheit + + incrementInFahrenheit * 2.5f, + FAHRENHEIT, + minTempInCelsius + incrementInCelsius * 2, + minTempInFahrenheit + + incrementInFahrenheit * 2}, + }, + }, + }, + }; + + for (auto& tc : testCases) { + StatusCode status = setValue(tc.valuesToSet[0]); + EXPECT_EQ(status, StatusCode::OK); + + auto events = getChangedProperties(); + EXPECT_EQ(events.size(), static_cast(1)); + events[0].timestamp = 0; + + EXPECT_EQ(events[0], tc.expectedValuesToGet[0]); + clearChangedProperties(); + } +} + +TEST_F(FakeVehicleHardwareTest, testOverrideApPowerStateReqConfig) { + auto hardware = std::make_unique( + android::base::GetExecutableDirectory(), + /*overrideConfigDir=*/"", + /*forceOverride=*/false, + toInt(VehicleApPowerStateConfigFlag::ENABLE_DEEP_SLEEP_FLAG) | + toInt(VehicleApPowerStateConfigFlag::ENABLE_HIBERNATION_FLAG)); + + std::vector configs = hardware->getAllPropertyConfigs(); + + for (const auto& config : configs) { + if (config.prop != toInt(VehicleProperty::AP_POWER_STATE_REQ)) { + continue; + } + ASSERT_EQ(config.configArray[0], 0x5); + break; + } +} + +} // namespace fake +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/current/fake_impl/hardware/test/fakedata/prop.json b/automotive/vehicle/aidl/impl/current/fake_impl/hardware/test/fakedata/prop.json new file mode 100644 index 0000000000000000000000000000000000000000..7123a002cc3656e640e9bdec7d6ca726ac6edc8f --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/fake_impl/hardware/test/fakedata/prop.json @@ -0,0 +1,26 @@ +[ + { + "timestamp": 1000000, + "areaId": 0, + "value": 8, + "prop": 289408000 + }, + { + "timestamp": 2000000, + "areaId": 0, + "value": 4, + "prop": 289408000 + }, + { + "timestamp": 3000000, + "areaId": 0, + "value": 16, + "prop": 289408000 + }, + { + "timestamp": 4000000, + "areaId": 0, + "value": 10, + "prop": 289408000 + } +] diff --git a/automotive/vehicle/aidl/impl/current/fake_impl/hardware/test/override/gear_selection.json b/automotive/vehicle/aidl/impl/current/fake_impl/hardware/test/override/gear_selection.json new file mode 100644 index 0000000000000000000000000000000000000000..693f1e2ae56effddf16b3c6a1c739a2d6b985f91 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/fake_impl/hardware/test/override/gear_selection.json @@ -0,0 +1,13 @@ +{ + "apiVersion": 1, + "properties": [ + { + "property": "VehicleProperty::GEAR_SELECTION", + "defaultValue": { + "int32Values": [ + 8 + ] + } + } + ] +} diff --git a/automotive/vehicle/aidl/impl/current/fake_impl/hardware/test/override/hvac_temperature_set.json b/automotive/vehicle/aidl/impl/current/fake_impl/hardware/test/override/hvac_temperature_set.json new file mode 100644 index 0000000000000000000000000000000000000000..07cfebba107cb02ec3b6629ab3ac2434d14f4486 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/fake_impl/hardware/test/override/hvac_temperature_set.json @@ -0,0 +1,20 @@ +{ + "apiVersion": 1, + "properties": [ + { + "property": "VehicleProperty::HVAC_TEMPERATURE_SET", + "areas": [ + { + "defaultValue": { + "floatValues": [ + 30.0 + ] + }, + "areaId": 49, + "minFloatValue": 16.0, + "maxFloatValue": 32.0 + } + ] + } + ] +} diff --git a/automotive/vehicle/aidl/impl/fake_impl/obd2frame/Android.bp b/automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/Android.bp similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/obd2frame/Android.bp rename to automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/Android.bp diff --git a/automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/include/FakeObd2Frame.h b/automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/include/FakeObd2Frame.h new file mode 100644 index 0000000000000000000000000000000000000000..4d2ffd049b140abfda9dd9418a13d04e620c4dbc --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/include/FakeObd2Frame.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef android_hardware_automotive_vehicle_aidl_impl_fake_impl_obd2frame_include_FakeObd2Frame_H_ +#define android_hardware_automotive_vehicle_aidl_impl_fake_impl_obd2frame_include_FakeObd2Frame_H_ + +#include +#include +#include + +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace fake { +namespace obd2frame { + +class FakeObd2Frame final { + public: + explicit FakeObd2Frame(std::shared_ptr propStore) + : mPropStore(propStore) {} + + void initObd2LiveFrame( + const aidl::android::hardware::automotive::vehicle::VehiclePropConfig& propConfig); + void initObd2FreezeFrame( + const aidl::android::hardware::automotive::vehicle::VehiclePropConfig& propConfig); + VhalResult getObd2FreezeFrame( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& + requestedPropValue) const; + VhalResult getObd2DtcInfo() const; + VhalResult clearObd2FreezeFrames( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue); + static bool isDiagnosticProperty( + const aidl::android::hardware::automotive::vehicle::VehiclePropConfig& propConfig); + + private: + std::shared_ptr mPropStore; + + std::unique_ptr fillDefaultObd2Frame(size_t numVendorIntegerSensors, + size_t numVendorFloatSensors); +}; + +} // namespace obd2frame +} // namespace fake +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_aidl_impl_fake_impl_obd2frame_include_FakeObd2Frame_H_ diff --git a/automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/include/Obd2SensorStore.h b/automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/include/Obd2SensorStore.h new file mode 100644 index 0000000000000000000000000000000000000000..1395eae3e19658b742aff1b5299903bb33aa162d --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/include/Obd2SensorStore.h @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_aidl_impl_fake_impl_obd2frame_include_Obd2SensorStore_H_ +#define android_hardware_automotive_vehicle_aidl_impl_fake_impl_obd2frame_include_Obd2SensorStore_H_ + +#include +#include +#include + +#include + +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace fake { +namespace obd2frame { + +// This class wraps all the logic required to create an OBD2 frame. +// It allows storing sensor values, setting appropriate bitmasks as needed, and returning +// appropriately laid out storage of sensor values suitable for being returned via a VehicleHal +// implementation. +class Obd2SensorStore final { + public: + // Creates a sensor storage with a given number of vendor-specific sensors. + Obd2SensorStore(std::shared_ptr valuePool, size_t numVendorIntegerSensors, + size_t numVendorFloatSensors); + + template + static int getLastIndex() { + auto range = ndk::enum_range(); + auto it = range.begin(); + while (std::next(it) != range.end()) { + it++; + } + return toInt(*it); + } + + // Stores an integer-valued sensor. + aidl::android::hardware::automotive::vehicle::StatusCode setIntegerSensor( + aidl::android::hardware::automotive::vehicle::DiagnosticIntegerSensorIndex index, + int32_t value); + // Stores an integer-valued sensor. + aidl::android::hardware::automotive::vehicle::StatusCode setIntegerSensor(size_t index, + int32_t value); + // Stores a float-valued sensor. + aidl::android::hardware::automotive::vehicle::StatusCode setFloatSensor( + aidl::android::hardware::automotive::vehicle::DiagnosticFloatSensorIndex index, + float value); + // Stores a float-valued sensor. + aidl::android::hardware::automotive::vehicle::StatusCode setFloatSensor(size_t index, + float value); + + // Returns a sensor property value using the given DTC. + VehiclePropValuePool::RecyclableType getSensorProperty(const std::string& dtc) const; + + private: + class BitmaskInVector final { + public: + explicit BitmaskInVector(size_t numBits = 0); + void resize(size_t numBits); + android::base::Result get(size_t index) const; + android::base::Result set(size_t index, bool value); + + const std::vector& getBitmask() const; + + private: + std::vector mStorage; + size_t mNumBits; + }; + + std::vector mIntegerSensors; + std::vector mFloatSensors; + BitmaskInVector mSensorsBitmask; + std::shared_ptr mValuePool; + + // Returns a vector that contains all integer sensors stored. + const std::vector& getIntegerSensors() const; + // Returns a vector that contains all float sensors stored. + const std::vector& getFloatSensors() const; + // Returns a vector that contains a bitmask for all stored sensors. + const std::vector& getSensorsBitmask() const; +}; + +} // namespace obd2frame +} // namespace fake +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_aidl_impl_fake_impl_obd2frame_include_Obd2SensorStore_H_ diff --git a/automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/src/FakeObd2Frame.cpp b/automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/src/FakeObd2Frame.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5f9f2174f098b97d04bd1cb2a00b43b7ec54b189 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/src/FakeObd2Frame.cpp @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2021 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 "FakeObd2Frame.h" +#include "Obd2SensorStore.h" + +#include +#include +#include +#include + +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace fake { +namespace obd2frame { + +using ::aidl::android::hardware::automotive::vehicle::DiagnosticFloatSensorIndex; +using ::aidl::android::hardware::automotive::vehicle::DiagnosticIntegerSensorIndex; +using ::aidl::android::hardware::automotive::vehicle::Obd2CommonIgnitionMonitors; +using ::aidl::android::hardware::automotive::vehicle::Obd2FuelSystemStatus; +using ::aidl::android::hardware::automotive::vehicle::Obd2FuelType; +using ::aidl::android::hardware::automotive::vehicle::Obd2IgnitionMonitorKind; +using ::aidl::android::hardware::automotive::vehicle::Obd2SecondaryAirStatus; +using ::aidl::android::hardware::automotive::vehicle::Obd2SparkIgnitionMonitors; +using ::aidl::android::hardware::automotive::vehicle::StatusCode; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; +using ::android::base::Result; + +std::unique_ptr FakeObd2Frame::fillDefaultObd2Frame(size_t numVendorIntegerSensors, + size_t numVendorFloatSensors) { + std::unique_ptr sensorStore(new Obd2SensorStore( + mPropStore->getValuePool(), numVendorIntegerSensors, numVendorFloatSensors)); + + sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::FUEL_SYSTEM_STATUS, + toInt(Obd2FuelSystemStatus::CLOSED_LOOP)); + sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::MALFUNCTION_INDICATOR_LIGHT_ON, 0); + sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::IGNITION_MONITORS_SUPPORTED, + toInt(Obd2IgnitionMonitorKind::SPARK)); + sensorStore->setIntegerSensor( + DiagnosticIntegerSensorIndex::IGNITION_SPECIFIC_MONITORS, + toInt(Obd2CommonIgnitionMonitors::COMPONENTS_AVAILABLE) | + toInt(Obd2CommonIgnitionMonitors::MISFIRE_AVAILABLE) | + toInt(Obd2SparkIgnitionMonitors::AC_REFRIGERANT_AVAILABLE) | + toInt(Obd2SparkIgnitionMonitors::EVAPORATIVE_SYSTEM_AVAILABLE)); + sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::INTAKE_AIR_TEMPERATURE, 35); + sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::COMMANDED_SECONDARY_AIR_STATUS, + toInt(Obd2SecondaryAirStatus::FROM_OUTSIDE_OR_OFF)); + sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::NUM_OXYGEN_SENSORS_PRESENT, 1); + sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::RUNTIME_SINCE_ENGINE_START, 500); + sensorStore->setIntegerSensor( + DiagnosticIntegerSensorIndex::DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON, 0); + sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::WARMUPS_SINCE_CODES_CLEARED, 51); + sensorStore->setIntegerSensor( + DiagnosticIntegerSensorIndex::DISTANCE_TRAVELED_SINCE_CODES_CLEARED, 365); + sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::ABSOLUTE_BAROMETRIC_PRESSURE, 30); + sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::CONTROL_MODULE_VOLTAGE, 12); + sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::AMBIENT_AIR_TEMPERATURE, 18); + sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::MAX_FUEL_AIR_EQUIVALENCE_RATIO, 1); + sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::FUEL_TYPE, + toInt(Obd2FuelType::GASOLINE)); + sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::CALCULATED_ENGINE_LOAD, 0.153); + sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK1, -0.16); + sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK1, -0.16); + sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK2, -0.16); + sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK2, -0.16); + sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::INTAKE_MANIFOLD_ABSOLUTE_PRESSURE, 7.5); + sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ENGINE_RPM, 1250.); + sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::VEHICLE_SPEED, 40.); + sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::TIMING_ADVANCE, 2.5); + sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::THROTTLE_POSITION, 19.75); + sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::OXYGEN_SENSOR1_VOLTAGE, 0.265); + sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::FUEL_TANK_LEVEL_INPUT, 0.824); + sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::EVAPORATION_SYSTEM_VAPOR_PRESSURE, + -0.373); + sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::CATALYST_TEMPERATURE_BANK1_SENSOR1, + 190.); + sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::RELATIVE_THROTTLE_POSITION, 3.); + sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ABSOLUTE_THROTTLE_POSITION_B, 0.306); + sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ACCELERATOR_PEDAL_POSITION_D, 0.188); + sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ACCELERATOR_PEDAL_POSITION_E, 0.094); + sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::COMMANDED_THROTTLE_ACTUATOR, 0.024); + + return sensorStore; +} + +void FakeObd2Frame::initObd2LiveFrame(const VehiclePropConfig& propConfig) { + auto sensorStore = fillDefaultObd2Frame(static_cast(propConfig.configArray[0]), + static_cast(propConfig.configArray[1])); + auto liveObd2Frame = sensorStore->getSensorProperty(""); + liveObd2Frame->prop = OBD2_LIVE_FRAME; + + mPropStore->writeValue(std::move(liveObd2Frame), /*updateStatus=*/true); +} + +void FakeObd2Frame::initObd2FreezeFrame(const VehiclePropConfig& propConfig) { + auto sensorStore = fillDefaultObd2Frame(static_cast(propConfig.configArray[0]), + static_cast(propConfig.configArray[1])); + + static std::vector sampleDtcs = {"P0070", "P0102", "P0123"}; + for (auto&& dtc : sampleDtcs) { + auto freezeFrame = sensorStore->getSensorProperty(dtc); + freezeFrame->prop = OBD2_FREEZE_FRAME; + + mPropStore->writeValue(std::move(freezeFrame), /*updateStatus=*/true); + } +} + +VhalResult FakeObd2Frame::getObd2FreezeFrame( + const VehiclePropValue& requestedPropValue) const { + if (requestedPropValue.value.int64Values.size() != 1) { + return StatusError(StatusCode::INVALID_ARG) + << "asked for OBD2_FREEZE_FRAME without valid timestamp"; + } + auto readValuesResult = mPropStore->readValuesForProperty(OBD2_FREEZE_FRAME); + if (!readValuesResult.ok()) { + return StatusError(StatusCode::INTERNAL_ERROR) + << "failed to read OBD2_FREEZE_FRAME property: " + << readValuesResult.error().message(); + } + if (readValuesResult.value().size() == 0) { + // Should no freeze frame be available at the given timestamp, a response of NOT_AVAILABLE + // must be returned by the implementation + return StatusError(StatusCode::NOT_AVAILABLE); + } + auto timestamp = requestedPropValue.value.int64Values[0]; + auto readValueResult = mPropStore->readValue(OBD2_FREEZE_FRAME, /*area=*/0, timestamp); + if (!readValueResult.ok()) { + return StatusError(StatusCode::INVALID_ARG) + << "asked for OBD2_FREEZE_FRAME at invalid timestamp"; + } + return readValueResult; +} + +VhalResult FakeObd2Frame::getObd2DtcInfo() const { + std::vector timestamps; + auto result = mPropStore->readValuesForProperty(OBD2_FREEZE_FRAME); + if (!result.ok()) { + return StatusError(StatusCode::INTERNAL_ERROR) + << "failed to read OBD2_FREEZE_FRAME property: " << result.error().message(); + } + for (const auto& freezeFrame : result.value()) { + timestamps.push_back(freezeFrame->timestamp); + } + auto outValue = + mPropStore->getValuePool()->obtain(VehiclePropertyType::INT64_VEC, timestamps.size()); + outValue->value.int64Values = timestamps; + outValue->prop = OBD2_FREEZE_FRAME_INFO; + return outValue; +} + +VhalResult FakeObd2Frame::clearObd2FreezeFrames(const VehiclePropValue& propValue) { + if (propValue.value.int64Values.size() == 0) { + mPropStore->removeValuesForProperty(OBD2_FREEZE_FRAME); + return {}; + } + for (int64_t timestamp : propValue.value.int64Values) { + auto result = mPropStore->readValue(OBD2_FREEZE_FRAME, 0, timestamp); + if (!result.ok()) { + return StatusError(StatusCode::INVALID_ARG) + << "asked for OBD2_FREEZE_FRAME at invalid timestamp, error: %s" + << result.error().message(); + } + mPropStore->removeValue(*result.value()); + } + return {}; +} + +bool FakeObd2Frame::isDiagnosticProperty(const VehiclePropConfig& propConfig) { + return (propConfig.prop == OBD2_LIVE_FRAME || propConfig.prop == OBD2_FREEZE_FRAME || + propConfig.prop == OBD2_FREEZE_FRAME_CLEAR || + propConfig.prop == OBD2_FREEZE_FRAME_INFO); +} + +} // namespace obd2frame +} // namespace fake +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/src/Obd2SensorStore.cpp b/automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/src/Obd2SensorStore.cpp new file mode 100644 index 0000000000000000000000000000000000000000..405061499c54f59d210773c1e373fee759860b57 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/src/Obd2SensorStore.cpp @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2021 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 "Obd2SensorStore.h" + +#include + +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace fake { +namespace obd2frame { + +using ::aidl::android::hardware::automotive::vehicle::DiagnosticFloatSensorIndex; +using ::aidl::android::hardware::automotive::vehicle::DiagnosticIntegerSensorIndex; +using ::aidl::android::hardware::automotive::vehicle::StatusCode; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType; +using ::android::base::Error; +using ::android::base::Result; + +Obd2SensorStore::BitmaskInVector::BitmaskInVector(size_t numBits) { + mNumBits = numBits; + resize(numBits); +} + +void Obd2SensorStore::BitmaskInVector::resize(size_t numBits) { + mNumBits = numBits; + mStorage = std::vector((numBits + 7) / 8, 0); +} + +Result Obd2SensorStore::BitmaskInVector::set(size_t index, bool value) { + const size_t byteIndex = index / 8; + const size_t bitIndex = index % 8; + if (index >= mNumBits) { + return Error() << "out of bound"; + } + const uint8_t byte = mStorage[byteIndex]; + uint8_t newValue = value ? (byte | (1 << bitIndex)) : (byte & ~(1 << bitIndex)); + mStorage[byteIndex] = newValue; + return {}; +} + +Result Obd2SensorStore::BitmaskInVector::get(size_t index) const { + const size_t byteIndex = index / 8; + const size_t bitIndex = index % 8; + if (index >= mNumBits) { + return Error() << "out of bound"; + } + const uint8_t byte = mStorage[byteIndex]; + return (byte & (1 << bitIndex)) != 0; +} + +const std::vector& Obd2SensorStore::BitmaskInVector::getBitmask() const { + return mStorage; +} + +Obd2SensorStore::Obd2SensorStore(std::shared_ptr valuePool, + size_t numVendorIntegerSensors, size_t numVendorFloatSensors) + : mValuePool(valuePool) { + const size_t numSystemIntegerSensors = getLastIndex() + 1; + const size_t numSystemFloatSensors = getLastIndex() + 1; + mIntegerSensors = std::vector(numSystemIntegerSensors + numVendorIntegerSensors, 0); + mFloatSensors = std::vector(numSystemFloatSensors + numVendorFloatSensors, 0); + mSensorsBitmask.resize(mIntegerSensors.size() + mFloatSensors.size()); +} + +StatusCode Obd2SensorStore::setIntegerSensor(DiagnosticIntegerSensorIndex index, int32_t value) { + return setIntegerSensor(toInt(index), value); +} +StatusCode Obd2SensorStore::setFloatSensor(DiagnosticFloatSensorIndex index, float value) { + return setFloatSensor(toInt(index), value); +} + +StatusCode Obd2SensorStore::setIntegerSensor(size_t index, int32_t value) { + if (index >= mIntegerSensors.size()) { + ALOGE("failed to set integer sensor: OOB"); + return StatusCode::INVALID_ARG; + } + mIntegerSensors[index] = value; + if (auto result = mSensorsBitmask.set(index, true); !result.ok()) { + ALOGE("failed to set integer sensor: %s", result.error().message().c_str()); + return StatusCode::INVALID_ARG; + } + return StatusCode::OK; +} + +StatusCode Obd2SensorStore::setFloatSensor(size_t index, float value) { + if (index >= mFloatSensors.size()) { + ALOGE("failed to set integer sensor: OOB"); + return StatusCode::INVALID_ARG; + } + mFloatSensors[index] = value; + if (auto result = mSensorsBitmask.set(index + mIntegerSensors.size(), true); !result.ok()) { + ALOGE("failed to set float sensor: %s", result.error().message().c_str()); + return StatusCode::INVALID_ARG; + } + return StatusCode::OK; +} + +const std::vector& Obd2SensorStore::getIntegerSensors() const { + return mIntegerSensors; +} + +const std::vector& Obd2SensorStore::getFloatSensors() const { + return mFloatSensors; +} + +const std::vector& Obd2SensorStore::getSensorsBitmask() const { + return mSensorsBitmask.getBitmask(); +} + +VehiclePropValuePool::RecyclableType Obd2SensorStore::getSensorProperty( + const std::string& dtc) const { + auto propValue = mValuePool->obtain(VehiclePropertyType::MIXED); + propValue->timestamp = elapsedRealtimeNano(); + propValue->value.int32Values = getIntegerSensors(); + propValue->value.floatValues = getFloatSensors(); + propValue->value.byteValues = getSensorsBitmask(); + propValue->value.stringValue = dtc; + return propValue; +} + +} // namespace obd2frame +} // namespace fake +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/fake_impl/obd2frame/test/Android.bp b/automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/test/Android.bp similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/obd2frame/test/Android.bp rename to automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/test/Android.bp diff --git a/automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/test/FakeObd2FrameTest.cpp b/automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/test/FakeObd2FrameTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..54ec1b2e4abb6f8b66d280d9c61d340e80d09f4c --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/test/FakeObd2FrameTest.cpp @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2021 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 "FakeObd2Frame.h" + +#include +#include +#include +#include +#include + +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace fake { +namespace obd2frame { + +using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig; +using ::aidl::android::hardware::automotive::vehicle::VehicleProperty; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyChangeMode; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; + +class FakeObd2FrameTest : public ::testing::Test { + protected: + void SetUp() override { + std::shared_ptr valuePool = std::make_shared(); + mPropertyStore = std::make_shared(valuePool); + mObd2Frame = std::make_unique(mPropertyStore); + + mPropertyStore->registerProperty(getObd2LiveFrameConfig()); + mPropertyStore->registerProperty( + getObd2FreezeFrameConfig(), + [](const VehiclePropValue& propValue) { return propValue.timestamp; }); + mPropertyStore->registerProperty(getObd2FreezeFrameInfoConfig()); + } + + VehiclePropConfig getObd2LiveFrameConfig() { + return VehiclePropConfig{.prop = OBD2_LIVE_FRAME, + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .configArray = {1, 1}}; + } + + VehiclePropConfig getObd2FreezeFrameConfig() { + return VehiclePropConfig{.prop = OBD2_FREEZE_FRAME, + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .configArray = {0, 0}}; + } + + VehiclePropConfig getObd2FreezeFrameInfoConfig() { + return VehiclePropConfig{.prop = OBD2_FREEZE_FRAME_INFO, + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE}; + } + + FakeObd2Frame* getFakeObd2Frame() { return mObd2Frame.get(); } + + VehiclePropertyStore* getPropertyStore() { return mPropertyStore.get(); } + + private: + std::unique_ptr mObd2Frame; + std::shared_ptr mPropertyStore; +}; + +TEST_F(FakeObd2FrameTest, testIsDiagnosticPropertyTrue) { + for (auto prop : std::vector({ + OBD2_LIVE_FRAME, + OBD2_FREEZE_FRAME, + OBD2_FREEZE_FRAME_CLEAR, + OBD2_FREEZE_FRAME_INFO, + })) { + EXPECT_TRUE(FakeObd2Frame::isDiagnosticProperty(VehiclePropConfig{ + .prop = prop, + })); + } +} + +TEST_F(FakeObd2FrameTest, testIsDiagnosticPropertyFalse) { + ASSERT_FALSE(FakeObd2Frame::isDiagnosticProperty(VehiclePropConfig{ + .prop = toInt(VehicleProperty::INFO_VIN), + })); +} + +TEST_F(FakeObd2FrameTest, testInitObd2LiveFrame) { + int64_t timestamp = elapsedRealtimeNano(); + + getFakeObd2Frame()->initObd2LiveFrame(getObd2LiveFrameConfig()); + + auto result = getPropertyStore()->readValue(OBD2_LIVE_FRAME); + + ASSERT_TRUE(result.ok()); + auto& value = result.value(); + + EXPECT_GE(value->timestamp, timestamp); + EXPECT_EQ(value->value.stringValue, ""); + EXPECT_EQ(value->value.int32Values.size(), static_cast(33)); + EXPECT_EQ(value->value.floatValues.size(), static_cast(72)); +} + +TEST_F(FakeObd2FrameTest, testInitFreezeFrame) { + getFakeObd2Frame()->initObd2FreezeFrame(getObd2FreezeFrameConfig()); + + auto result = getPropertyStore()->readValuesForProperty(OBD2_FREEZE_FRAME); + + ASSERT_TRUE(result.ok()); + ASSERT_EQ(result.value().size(), static_cast(3)); +} + +TEST_F(FakeObd2FrameTest, testGetObd2DtcInfo) { + getFakeObd2Frame()->initObd2FreezeFrame(getObd2FreezeFrameConfig()); + + auto result = getFakeObd2Frame()->getObd2DtcInfo(); + + ASSERT_TRUE(result.ok()); + EXPECT_EQ(result.value()->prop, OBD2_FREEZE_FRAME_INFO); + EXPECT_EQ(result.value()->value.int64Values.size(), static_cast(3)); +} + +TEST_F(FakeObd2FrameTest, testGetObd2FreezeFrame) { + getFakeObd2Frame()->initObd2FreezeFrame(getObd2FreezeFrameConfig()); + + auto result = getFakeObd2Frame()->getObd2DtcInfo(); + + ASSERT_TRUE(result.ok()); + ASSERT_EQ(result.value()->prop, OBD2_FREEZE_FRAME_INFO); + ASSERT_EQ(result.value()->value.int64Values.size(), static_cast(3)); + + std::set dtcs; + + for (int64_t timestamp : result.value()->value.int64Values) { + auto freezeFrameResult = getFakeObd2Frame()->getObd2FreezeFrame(VehiclePropValue{ + .value.int64Values = {timestamp}, + }); + + ASSERT_TRUE(freezeFrameResult.ok()); + + dtcs.insert(freezeFrameResult.value()->value.stringValue); + } + + ASSERT_EQ(dtcs, std::set({"P0070", "P0102", "P0123"})); +} + +TEST_F(FakeObd2FrameTest, testClearObd2FreezeFrameAll) { + getFakeObd2Frame()->initObd2FreezeFrame(getObd2FreezeFrameConfig()); + + auto result = getFakeObd2Frame()->getObd2DtcInfo(); + + ASSERT_TRUE(result.ok()); + ASSERT_EQ(result.value()->prop, OBD2_FREEZE_FRAME_INFO); + ASSERT_EQ(result.value()->value.int64Values.size(), static_cast(3)); + + ASSERT_TRUE(getFakeObd2Frame()->clearObd2FreezeFrames(VehiclePropValue{}).ok()); + + result = getFakeObd2Frame()->getObd2DtcInfo(); + + ASSERT_TRUE(result.ok()); + EXPECT_EQ(result.value()->prop, OBD2_FREEZE_FRAME_INFO); + EXPECT_EQ(result.value()->value.int64Values.size(), static_cast(0)); +} + +TEST_F(FakeObd2FrameTest, testClearObd2FreezeFrameByTimestamp) { + getFakeObd2Frame()->initObd2FreezeFrame(getObd2FreezeFrameConfig()); + + auto result = getFakeObd2Frame()->getObd2DtcInfo(); + + ASSERT_TRUE(result.ok()); + ASSERT_EQ(result.value()->prop, OBD2_FREEZE_FRAME_INFO); + ASSERT_EQ(result.value()->value.int64Values.size(), static_cast(3)); + + ASSERT_TRUE(getFakeObd2Frame() + ->clearObd2FreezeFrames(VehiclePropValue{ + .value.int64Values = {result.value()->value.int64Values[0], + result.value()->value.int64Values[1]}}) + .ok()); + + result = getFakeObd2Frame()->getObd2DtcInfo(); + + ASSERT_TRUE(result.ok()); + EXPECT_EQ(result.value()->prop, OBD2_FREEZE_FRAME_INFO); + EXPECT_EQ(result.value()->value.int64Values.size(), static_cast(1)); +} + +} // namespace obd2frame +} // namespace fake +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/test/Obd2SensorStoreTest.cpp b/automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/test/Obd2SensorStoreTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..23ea51d7bc5c90af6d2be18af4d94ad599d22a97 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/test/Obd2SensorStoreTest.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2021 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 "Obd2SensorStore.h" + +#include + +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace fake { +namespace obd2frame { + +using ::aidl::android::hardware::automotive::vehicle::DiagnosticFloatSensorIndex; +using ::aidl::android::hardware::automotive::vehicle::DiagnosticIntegerSensorIndex; +using ::aidl::android::hardware::automotive::vehicle::StatusCode; + +TEST(Obd2SensorStoreTest, testObd2SensorStore) { + int64_t timestamp = elapsedRealtimeNano(); + std::shared_ptr valuePool = std::make_shared(); + Obd2SensorStore sensorStore(valuePool, 1, 1); + + DiagnosticIntegerSensorIndex systemIntSensorIndex = + DiagnosticIntegerSensorIndex::IGNITION_MONITORS_SUPPORTED; + size_t vendorIntSensorIndex = Obd2SensorStore::getLastIndex() + 1; + DiagnosticFloatSensorIndex systemFloatSensorIndex = + DiagnosticFloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK1; + size_t vendorFloatSensorIndex = Obd2SensorStore::getLastIndex() + 1; + // Four 1s in all the bits. + std::vector bitMask = {0x4, 0x0, 0x0, 0x0, 0x9, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1}; + + ASSERT_EQ(sensorStore.setIntegerSensor(systemIntSensorIndex, 1), StatusCode::OK); + ASSERT_EQ(sensorStore.setIntegerSensor(vendorIntSensorIndex, 2), StatusCode::OK); + ASSERT_EQ(sensorStore.setFloatSensor(systemFloatSensorIndex, 3.0), StatusCode::OK); + ASSERT_EQ(sensorStore.setFloatSensor(vendorFloatSensorIndex, 4.0), StatusCode::OK); + + std::string dtc = "dtc"; + auto propValue = sensorStore.getSensorProperty(dtc); + + ASSERT_GE(propValue->timestamp, timestamp); + ASSERT_EQ(propValue->value.int32Values[toInt(systemIntSensorIndex)], 1); + ASSERT_EQ(propValue->value.int32Values[vendorIntSensorIndex], 2); + ASSERT_EQ(propValue->value.floatValues[toInt(systemFloatSensorIndex)], 3.0); + ASSERT_EQ(propValue->value.floatValues[vendorFloatSensorIndex], 4.0); + ASSERT_EQ(propValue->value.byteValues, bitMask); + ASSERT_EQ(propValue->value.stringValue, dtc); +} + +TEST(Obd2SensorStoreTest, testIndexOOB) { + std::shared_ptr valuePool = std::make_shared(); + Obd2SensorStore sensorStore(valuePool, 1, 1); + + EXPECT_EQ(sensorStore.setIntegerSensor( + Obd2SensorStore::getLastIndex() + 2, 1), + StatusCode::INVALID_ARG); + EXPECT_EQ(sensorStore.setIntegerSensor(static_cast(-1), 1), StatusCode::INVALID_ARG); + EXPECT_EQ(sensorStore.setFloatSensor( + Obd2SensorStore::getLastIndex() + 2, 1.0), + StatusCode::INVALID_ARG); + EXPECT_EQ(sensorStore.setFloatSensor(static_cast(-1), 1.0), StatusCode::INVALID_ARG); +} + +} // namespace obd2frame +} // namespace fake +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/fake_impl/userhal/Android.bp b/automotive/vehicle/aidl/impl/current/fake_impl/userhal/Android.bp similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/userhal/Android.bp rename to automotive/vehicle/aidl/impl/current/fake_impl/userhal/Android.bp diff --git a/automotive/vehicle/aidl/impl/current/fake_impl/userhal/include/FakeUserHal.h b/automotive/vehicle/aidl/impl/current/fake_impl/userhal/include/FakeUserHal.h new file mode 100644 index 0000000000000000000000000000000000000000..fcbe8fddea6c8a570f05300174c642bdd44729c8 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/fake_impl/userhal/include/FakeUserHal.h @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_aidl_impl_fake_impl_userhal_include_FakeUserHal_H_ +#define android_hardware_automotive_vehicle_aidl_impl_fake_impl_userhal_include_FakeUserHal_H_ + +#include +#include +#include + +#include +#include +#include + +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace fake { + +constexpr char kUserHalDumpOption[] = "--user-hal"; + +// Class used to emulate a real User HAL behavior through lshal debug requests. +class FakeUserHal final { + public: + using ValueResultType = VhalResult; + + explicit FakeUserHal(std::shared_ptr valuePool) : mValuePool(valuePool) {} + + ~FakeUserHal() = default; + + // Checks if the emulator can handle the property. + static bool isSupported(int32_t prop); + + // Lets the emulator set the property. + // + // @return updated property and StatusCode + ValueResultType onSetProperty( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value); + + // Gets the property value from the emulator. + // + // @return property value and StatusCode + ValueResultType onGetProperty( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const; + + // Shows the User HAL emulation help. + std::string showDumpHelp() const; + + // Dump its contents. + std::string dump() const; + + private: + const std::shared_ptr mValuePool; + mutable std::mutex mLock; + VehiclePropValuePool::RecyclableType mInitialUserResponseFromCmd GUARDED_BY(mLock); + VehiclePropValuePool::RecyclableType mSwitchUserResponseFromCmd GUARDED_BY(mLock); + VehiclePropValuePool::RecyclableType mCreateUserResponseFromCmd GUARDED_BY(mLock); + VehiclePropValuePool::RecyclableType mSetUserIdentificationAssociationResponseFromCmd + GUARDED_BY(mLock); + + // INITIAL_USER_INFO is called by Android when it starts, and it's expecting a property change + // indicating what the initial user should be. + // + // During normal circumstances, the emulator will reply right away, passing a response if + // InitialUserInfoResponseAction::DEFAULT (so Android could use its own logic to decide which + // user to boot). + // + // But during development / testing, the behavior can be changed using lshal dump, which must + // use the areaId to indicate what should happen next. + // + // So, the behavior of set(INITIAL_USER_INFO) is: + // + // - if it has an areaId, store the property into mInitialUserResponseFromCmd (as it was called + // by lshal). + // - else if mInitialUserResponseFromCmd is not set, return a response with the same request id + // and InitialUserInfoResponseAction::DEFAULT + // - else the behavior is defined by the areaId on mInitialUserResponseFromCmd: + // - if it's 1, reply with mInitialUserResponseFromCmd and the right request id + // - if it's 2, reply with mInitialUserResponseFromCmd but a wrong request id (so Android can + // test this error scenario) + // - if it's 3, then don't send a property change (so Android can emulate a timeout) + ValueResultType onSetInitialUserInfoResponse( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value); + + // Used to emulate SWITCH_USER - see onSetInitialUserInfoResponse() for usage. + ValueResultType onSetSwitchUserResponse( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value); + + // Used to emulate CREATE_USER - see onSetInitialUserInfoResponse() for usage. + ValueResultType onSetCreateUserResponse( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value); + + // Used to emulate set USER_IDENTIFICATION_ASSOCIATION - see onSetInitialUserInfoResponse() for + // usage. + ValueResultType onSetUserIdentificationAssociation( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value); + + // Used to emulate get USER_IDENTIFICATION_ASSOCIATION - see onSetInitialUserInfoResponse() for + // usage. + ValueResultType onGetUserIdentificationAssociation( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const; + + // Creates a default USER_IDENTIFICATION_ASSOCIATION when it was not set by lshal. + static ValueResultType defaultUserIdentificationAssociation( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& request); + + ValueResultType sendUserHalResponse(VehiclePropValuePool::RecyclableType response, + int32_t requestId); +}; + +} // namespace fake +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_aidl_impl_fake_impl_userhal_include_FakeUserHal_H_ diff --git a/automotive/vehicle/aidl/impl/current/fake_impl/userhal/include/UserHalHelper.h b/automotive/vehicle/aidl/impl/current/fake_impl/userhal/include/UserHalHelper.h new file mode 100644 index 0000000000000000000000000000000000000000..104876c4309ac873ad6e205bc440fa37cfa53d52 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/fake_impl/userhal/include/UserHalHelper.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_aidl_impl_fake_impl_userhal_include_UserHalHelper_H_ +#define android_hardware_automotive_vehicle_aidl_impl_fake_impl_userhal_include_UserHalHelper_H_ + +#include +#include +#include +#include + +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace fake { +namespace user_hal_helper { + +// Verify whether the |value| can be casted to the type |T| and return the casted value on success. +// Otherwise, return the error. +template +android::base::Result verifyAndCast(int32_t value); + +// Below functions parse VehiclePropValues to the respective User HAL request structs. On success, +// these functions return the User HAL struct. Otherwise, they return the error. +android::base::Result +toInitialUserInfoRequest( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue); +android::base::Result +toSwitchUserRequest( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue); +android::base::Result +toCreateUserRequest( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue); +android::base::Result +toRemoveUserRequest( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue); +android::base::Result +toUserIdentificationGetRequest( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue); +android::base::Result +toUserIdentificationSetRequest( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue); + +// Below functions convert the User HAL structs to VehiclePropValues. On success, these functions +// return the pointer to VehiclePropValue. Otherwise, they return the error. +android::base::Result toVehiclePropValue( + VehiclePropValuePool& pool, + const aidl::android::hardware::automotive::vehicle::SwitchUserRequest& request); +VehiclePropValuePool::RecyclableType toVehiclePropValue( + VehiclePropValuePool& pool, + const aidl::android::hardware::automotive::vehicle::InitialUserInfoResponse& response); +VehiclePropValuePool::RecyclableType toVehiclePropValue( + VehiclePropValuePool& pool, + const aidl::android::hardware::automotive::vehicle::SwitchUserResponse& response); +VehiclePropValuePool::RecyclableType toVehiclePropValue( + VehiclePropValuePool& pool, + const aidl::android::hardware::automotive::vehicle::CreateUserResponse& response); +VehiclePropValuePool::RecyclableType toVehiclePropValue( + VehiclePropValuePool& pool, + const aidl::android::hardware::automotive::vehicle::UserIdentificationResponse& response); + +} // namespace user_hal_helper +} // namespace fake +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_aidl_impl_fake_impl_userhal_include_UserHalHelper_H_ diff --git a/automotive/vehicle/aidl/impl/current/fake_impl/userhal/include/UserHalTypes.h b/automotive/vehicle/aidl/impl/current/fake_impl/userhal/include/UserHalTypes.h new file mode 100644 index 0000000000000000000000000000000000000000..b5e17b31718120293a359e1538dbc12f057fd73e --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/fake_impl/userhal/include/UserHalTypes.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_aidl_impl_fake_impl_userhal_include_UserHalTypes_H_ +#define android_hardware_automotive_vehicle_aidl_impl_fake_impl_userhal_include_UserHalTypes_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // android_hardware_automotive_vehicle_aidl_impl_fake_impl_userhal_include_UserHalTypes_H_ diff --git a/automotive/vehicle/aidl/impl/current/fake_impl/userhal/src/FakeUserHal.cpp b/automotive/vehicle/aidl/impl/current/fake_impl/userhal/src/FakeUserHal.cpp new file mode 100644 index 0000000000000000000000000000000000000000..878c2e7da06caf651fe22e4d40376b4be0b59423 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/fake_impl/userhal/src/FakeUserHal.cpp @@ -0,0 +1,375 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "FakeUserHal" + +#include "FakeUserHal.h" + +#include "UserHalHelper.h" + +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace fake { + +namespace { + +using ::aidl::android::hardware::automotive::vehicle::CreateUserResponse; +using ::aidl::android::hardware::automotive::vehicle::CreateUserStatus; +using ::aidl::android::hardware::automotive::vehicle::InitialUserInfoResponse; +using ::aidl::android::hardware::automotive::vehicle::InitialUserInfoResponseAction; +using ::aidl::android::hardware::automotive::vehicle::StatusCode; +using ::aidl::android::hardware::automotive::vehicle::SwitchUserMessageType; +using ::aidl::android::hardware::automotive::vehicle::SwitchUserResponse; +using ::aidl::android::hardware::automotive::vehicle::SwitchUserStatus; +using ::aidl::android::hardware::automotive::vehicle::VehicleProperty; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; +using ::android::base::Error; +using ::android::base::Result; + +constexpr int32_t INITIAL_USER_INFO = toInt(VehicleProperty::INITIAL_USER_INFO); +constexpr int32_t SWITCH_USER = toInt(VehicleProperty::SWITCH_USER); +constexpr int32_t CREATE_USER = toInt(VehicleProperty::CREATE_USER); +constexpr int32_t REMOVE_USER = toInt(VehicleProperty::REMOVE_USER); +constexpr int32_t USER_IDENTIFICATION_ASSOCIATION = + toInt(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION); + +VhalResult getRequestId(const VehiclePropValue& value) { + if (value.value.int32Values.size() < 1) { + return StatusError(StatusCode::INVALID_ARG) + << "no int32Values on property: " << value.toString(); + } + return value.value.int32Values[0]; +} + +VhalResult getSwitchUserMessageType(const VehiclePropValue& value) { + if (value.value.int32Values.size() < 2) { + return StatusError(StatusCode::INVALID_ARG) + << "missing switch user message type on property: " << value.toString(); + } + auto result = user_hal_helper::verifyAndCast(value.value.int32Values[1]); + if (!result.ok()) { + return StatusError(StatusCode::INVALID_ARG) << result.error().message(); + } + return result.value(); +} + +} // namespace + +bool FakeUserHal::isSupported(int32_t prop) { + switch (prop) { + case INITIAL_USER_INFO: + case SWITCH_USER: + case CREATE_USER: + case REMOVE_USER: + case USER_IDENTIFICATION_ASSOCIATION: + return true; + default: + return false; + } +} + +FakeUserHal::ValueResultType FakeUserHal::onSetProperty(const VehiclePropValue& value) { + ALOGV("onSetProperty(): %s", value.toString().c_str()); + + switch (value.prop) { + case INITIAL_USER_INFO: + return onSetInitialUserInfoResponse(value); + case SWITCH_USER: + return onSetSwitchUserResponse(value); + case CREATE_USER: + return onSetCreateUserResponse(value); + case REMOVE_USER: + ALOGI("REMOVE_USER is FYI only, nothing to do..."); + return nullptr; + case USER_IDENTIFICATION_ASSOCIATION: + return onSetUserIdentificationAssociation(value); + default: + return StatusError(StatusCode::INVALID_ARG) + << "Unsupported property: " << value.toString(); + } +} + +FakeUserHal::ValueResultType FakeUserHal::onGetProperty(const VehiclePropValue& value) const { + ALOGV("onGetProperty(%s)", value.toString().c_str()); + switch (value.prop) { + case INITIAL_USER_INFO: + case SWITCH_USER: + case CREATE_USER: + case REMOVE_USER: + ALOGE("onGetProperty(): %d is only supported on SET", value.prop); + return StatusError(StatusCode::INVALID_ARG) << "only supported on SET"; + case USER_IDENTIFICATION_ASSOCIATION: + return onGetUserIdentificationAssociation(value); + default: + ALOGE("onGetProperty(): %d is not supported", value.prop); + return StatusError(StatusCode::INVALID_ARG) << "not supported by User HAL"; + } +} + +FakeUserHal::ValueResultType FakeUserHal::onGetUserIdentificationAssociation( + const VehiclePropValue& value) const { + std::scoped_lock lockGuard(mLock); + + if (mSetUserIdentificationAssociationResponseFromCmd == nullptr) { + return defaultUserIdentificationAssociation(value); + } + ALOGI("get(USER_IDENTIFICATION_ASSOCIATION): returning %s", + mSetUserIdentificationAssociationResponseFromCmd->toString().c_str()); + auto newValue = mValuePool->obtain(*mSetUserIdentificationAssociationResponseFromCmd); + auto requestId = getRequestId(value); + if (requestId.ok()) { + // Must use the same requestId + newValue->value.int32Values[0] = *requestId; + } else { + ALOGE("get(USER_IDENTIFICATION_ASSOCIATION): no requestId on %s", value.toString().c_str()); + return requestId.error(); + } + return newValue; +} + +FakeUserHal::ValueResultType FakeUserHal::onSetInitialUserInfoResponse( + const VehiclePropValue& value) { + std::scoped_lock lockGuard(mLock); + + auto requestId = getRequestId(value); + if (!requestId.ok()) { + ALOGE("Failed to get requestId on set(INITIAL_USER_INFO): %s", + requestId.error().message().c_str()); + return requestId.error(); + } + + if (value.areaId != 0) { + ALOGD("set(INITIAL_USER_INFO) called from lshal; storing it: %s", value.toString().c_str()); + mInitialUserResponseFromCmd = mValuePool->obtain(value); + return nullptr; + } + + ALOGD("set(INITIAL_USER_INFO) called from Android: %s", value.toString().c_str()); + if (mInitialUserResponseFromCmd != nullptr) { + ALOGI("replying INITIAL_USER_INFO with lshal value: %s", + mInitialUserResponseFromCmd->toString().c_str()); + return sendUserHalResponse(std::move(mInitialUserResponseFromCmd), *requestId); + } + + // Returns default response + auto updatedValue = user_hal_helper::toVehiclePropValue( + *mValuePool, InitialUserInfoResponse{ + .requestId = *requestId, + .action = InitialUserInfoResponseAction::DEFAULT, + }); + ALOGI("no lshal response; replying with InitialUserInfoResponseAction::DEFAULT: %s", + updatedValue->toString().c_str()); + return updatedValue; +} + +FakeUserHal::ValueResultType FakeUserHal::onSetSwitchUserResponse(const VehiclePropValue& value) { + std::scoped_lock lockGuard(mLock); + + auto requestId = getRequestId(value); + if (!requestId.ok()) { + ALOGE("Failed to get requestId on set(SWITCH_USER): %s", + requestId.error().message().c_str()); + return requestId.error(); + } + + auto messageType = getSwitchUserMessageType(value); + if (!messageType.ok()) { + ALOGE("Failed to get messageType on set(SWITCH_USER): %s", + messageType.error().message().c_str()); + return messageType.error(); + } + + if (value.areaId != 0) { + if (*messageType == SwitchUserMessageType::VEHICLE_REQUEST) { + // User HAL can also request a user switch, so we need to check it first + ALOGD("set(SWITCH_USER) called from lshal to emulate a vehicle request: %s", + value.toString().c_str()); + return mValuePool->obtain(value); + } + // Otherwise, we store it + ALOGD("set(SWITCH_USER) called from lshal; storing it: %s", value.toString().c_str()); + mSwitchUserResponseFromCmd = mValuePool->obtain(value); + return nullptr; + } + ALOGD("set(SWITCH_USER) called from Android: %s", value.toString().c_str()); + + if (mSwitchUserResponseFromCmd != nullptr) { + ALOGI("replying SWITCH_USER with lshal value: %s", + mSwitchUserResponseFromCmd->toString().c_str()); + return sendUserHalResponse(std::move(mSwitchUserResponseFromCmd), *requestId); + } + + if (*messageType == SwitchUserMessageType::LEGACY_ANDROID_SWITCH || + *messageType == SwitchUserMessageType::ANDROID_POST_SWITCH) { + ALOGI("request is %s; ignoring it", toString(*messageType).c_str()); + return nullptr; + } + + // Returns default response + auto updatedValue = user_hal_helper::toVehiclePropValue( + *mValuePool, SwitchUserResponse{ + .requestId = *requestId, + .messageType = SwitchUserMessageType::VEHICLE_RESPONSE, + .status = SwitchUserStatus::SUCCESS, + }); + ALOGI("no lshal response; replying with VEHICLE_RESPONSE / SUCCESS: %s", + updatedValue->toString().c_str()); + return updatedValue; +} + +FakeUserHal::ValueResultType FakeUserHal::onSetCreateUserResponse(const VehiclePropValue& value) { + std::scoped_lock lockGuard(mLock); + + auto requestId = getRequestId(value); + if (!requestId.ok()) { + ALOGE("Failed to get requestId on set(CREATE_USER): %s", + requestId.error().message().c_str()); + return requestId.error(); + } + + if (value.areaId != 0) { + ALOGD("set(CREATE_USER) called from lshal; storing it: %s", value.toString().c_str()); + mCreateUserResponseFromCmd = mValuePool->obtain(value); + return nullptr; + } + ALOGD("set(CREATE_USER) called from Android: %s", value.toString().c_str()); + + if (mCreateUserResponseFromCmd != nullptr) { + ALOGI("replying CREATE_USER with lshal value: %s", + mCreateUserResponseFromCmd->toString().c_str()); + return sendUserHalResponse(std::move(mCreateUserResponseFromCmd), *requestId); + } + + // Returns default response + auto updatedValue = user_hal_helper::toVehiclePropValue( + *mValuePool, CreateUserResponse{ + .requestId = *requestId, + .status = CreateUserStatus::SUCCESS, + }); + ALOGI("no lshal response; replying with SUCCESS: %s", updatedValue->toString().c_str()); + return updatedValue; +} + +FakeUserHal::ValueResultType FakeUserHal::onSetUserIdentificationAssociation( + const VehiclePropValue& value) { + std::scoped_lock lockGuard(mLock); + + auto requestId = getRequestId(value); + if (!requestId.ok()) { + ALOGE("Failed to get requestId on set(USER_IDENTIFICATION_ASSOCIATION): %s", + requestId.error().message().c_str()); + return requestId.error(); + } + + if (value.areaId != 0) { + ALOGD("set(USER_IDENTIFICATION_ASSOCIATION) called from lshal; storing it: %s", + value.toString().c_str()); + mSetUserIdentificationAssociationResponseFromCmd = mValuePool->obtain(value); + return nullptr; + } + ALOGD("set(USER_IDENTIFICATION_ASSOCIATION) called from Android: %s", value.toString().c_str()); + + if (mSetUserIdentificationAssociationResponseFromCmd != nullptr) { + ALOGI("replying USER_IDENTIFICATION_ASSOCIATION with lshal value: %s", + mSetUserIdentificationAssociationResponseFromCmd->toString().c_str()); + // Not moving response so it can be used on GET requests + auto copy = mValuePool->obtain(*mSetUserIdentificationAssociationResponseFromCmd); + return sendUserHalResponse(std::move(copy), *requestId); + } + // Returns default response + return defaultUserIdentificationAssociation(value); +} + +FakeUserHal::ValueResultType FakeUserHal::defaultUserIdentificationAssociation( + const VehiclePropValue& request) { + // TODO(b/159498909): return a response with NOT_ASSOCIATED_ANY_USER for all requested types + ALOGE("no lshal response for %s; replying with NOT_AVAILABLE", request.toString().c_str()); + return StatusError(StatusCode::NOT_AVAILABLE) << "not set by lshal"; +} + +FakeUserHal::ValueResultType FakeUserHal::sendUserHalResponse( + VehiclePropValuePool::RecyclableType response, int32_t requestId) { + switch (response->areaId) { + case 1: + ALOGD("returning response with right request id"); + response->value.int32Values[0] = requestId; + break; + case 2: + ALOGD("returning response with wrong request id"); + response->value.int32Values[0] = -requestId; + break; + case 3: + ALOGD("not generating a property change event because of lshal prop: %s", + response->toString().c_str()); + return StatusError(StatusCode::NOT_AVAILABLE) + << "not generating a property change event because of lshal prop: " + << response->toString(); + default: + ALOGE("invalid action on lshal response: %s", response->toString().c_str()); + return StatusError(StatusCode::INTERNAL_ERROR) + << "invalid action on lshal response: " << response->toString(); + } + + // Update area ID to 0 since this is a global property (and the area ID was only set to emulate + // the request id behavior). + response->areaId = 0; + ALOGD("updating property to: %s", response->toString().c_str()); + return response; +} + +std::string FakeUserHal::showDumpHelp() const { + return fmt::format("{}: dumps state used for user management\n", kUserHalDumpOption); +} + +std::string FakeUserHal::dump() const { + std::scoped_lock lockGuard(mLock); + + std::string info; + if (mInitialUserResponseFromCmd != nullptr) { + info += fmt::format("InitialUserInfo response: {}\n", + mInitialUserResponseFromCmd->toString()); + } else { + info += "No InitialUserInfo response\n"; + } + if (mSwitchUserResponseFromCmd != nullptr) { + info += fmt::format("SwitchUser response: {}\n", mSwitchUserResponseFromCmd->toString()); + } else { + info += "No SwitchUser response\n"; + } + if (mCreateUserResponseFromCmd != nullptr) { + info += fmt::format("CreateUser response: {}\n", mCreateUserResponseFromCmd->toString()); + } else { + info += "No CreateUser response\n"; + } + if (mSetUserIdentificationAssociationResponseFromCmd != nullptr) { + info += fmt::format("SetUserIdentificationAssociation response: {}\n", + mSetUserIdentificationAssociationResponseFromCmd->toString()); + } else { + info += "No SetUserIdentificationAssociation response\n"; + } + return info; +} + +} // namespace fake +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/current/fake_impl/userhal/src/UserHalHelper.cpp b/automotive/vehicle/aidl/impl/current/fake_impl/userhal/src/UserHalHelper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4fd93ae24b2d81b97eb04d7362d67ac468f911f4 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/fake_impl/userhal/src/UserHalHelper.cpp @@ -0,0 +1,403 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "UserHalHelper" + +#include "UserHalHelper.h" + +#include +#include +#include + +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace fake { +namespace user_hal_helper { + +namespace { + +using ::aidl::android::hardware::automotive::vehicle::CreateUserRequest; +using ::aidl::android::hardware::automotive::vehicle::CreateUserResponse; +using ::aidl::android::hardware::automotive::vehicle::CreateUserStatus; +using ::aidl::android::hardware::automotive::vehicle::InitialUserInfoRequest; +using ::aidl::android::hardware::automotive::vehicle::InitialUserInfoRequestType; +using ::aidl::android::hardware::automotive::vehicle::InitialUserInfoResponse; +using ::aidl::android::hardware::automotive::vehicle::RemoveUserRequest; +using ::aidl::android::hardware::automotive::vehicle::SwitchUserMessageType; +using ::aidl::android::hardware::automotive::vehicle::SwitchUserRequest; +using ::aidl::android::hardware::automotive::vehicle::SwitchUserResponse; +using ::aidl::android::hardware::automotive::vehicle::SwitchUserStatus; +using ::aidl::android::hardware::automotive::vehicle::UserIdentificationAssociationSetValue; +using ::aidl::android::hardware::automotive::vehicle::UserIdentificationAssociationType; +using ::aidl::android::hardware::automotive::vehicle::UserIdentificationGetRequest; +using ::aidl::android::hardware::automotive::vehicle::UserIdentificationResponse; +using ::aidl::android::hardware::automotive::vehicle::UserIdentificationSetAssociation; +using ::aidl::android::hardware::automotive::vehicle::UserIdentificationSetRequest; +using ::aidl::android::hardware::automotive::vehicle::UserInfo; +using ::aidl::android::hardware::automotive::vehicle::UsersInfo; +using ::aidl::android::hardware::automotive::vehicle::VehicleProperty; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; +using ::android::base::Error; +using ::android::base::Result; + +constexpr const char kSeparator[] = "||"; +constexpr size_t kNumFieldsPerUserInfo = 2; +constexpr size_t kNumFieldsPerSetAssociation = 2; + +Result verifyPropValue(const VehiclePropValue& propValue, VehicleProperty vehicleProperty, + size_t minInt32Values) { + auto prop = verifyAndCast(propValue.prop); + if (!prop.ok()) { + return Error() << "Invalid vehicle property: " << prop.error(); + } + if (*prop != vehicleProperty) { + return Error() << "Mismatching " << toString(vehicleProperty) << " request, received " + << toString(*prop) << " property"; + } + if (propValue.value.int32Values.size() < minInt32Values) { + return Error() << "Int32Values must have at least " << minInt32Values + << " values, received " << propValue.value.int32Values.size(); + } + return {}; +} + +Result parseUserInfo(const std::vector& int32Values, size_t startPos, + UserInfo* userInfo) { + if (int32Values.size() < startPos + kNumFieldsPerUserInfo) { + return Error() << "Int32Values must have at least " << startPos + 2 << " values, received " + << int32Values.size(); + } + userInfo->userId = int32Values[startPos]; + int32_t intUserFlags = int32Values[startPos + 1]; + const int32_t combinedFlags = UserInfo::USER_FLAG_SYSTEM | UserInfo::USER_FLAG_GUEST | + UserInfo::USER_FLAG_EPHEMERAL | UserInfo::USER_FLAG_ADMIN | + UserInfo::USER_FLAG_DISABLED | UserInfo::USER_FLAG_PROFILE; + + if ((intUserFlags & ~combinedFlags) != 0) { + return Error() << "Invalid user flags: " << intUserFlags << ", must be '|' of UserFlags"; + } + userInfo->flags = intUserFlags; + return {}; +} + +Result parseUsersInfo(const std::vector& int32Values, size_t startPos, + UsersInfo* usersInfo) { + if (int32Values.size() < startPos + 3) { + return Error() << "Int32Values must have at least " << startPos + 3 << " values, received " + << int32Values.size(); + } + auto ret = parseUserInfo(int32Values, startPos, &usersInfo->currentUser); + if (!ret.ok()) { + return ret; + } + usersInfo->numberUsers = int32Values[startPos + 2]; + usersInfo->existingUsers.resize(usersInfo->numberUsers); + for (size_t i = 0; i < static_cast(usersInfo->numberUsers); ++i) { + ret = parseUserInfo(int32Values, startPos + 3 + (kNumFieldsPerUserInfo * i), + &usersInfo->existingUsers[i]); + if (!ret.ok()) { + return Error() << "Failed to parse existing user '" << i << "' info: " << ret.error(); + } + } + return {}; +} + +Result parseUserAssociationTypes( + const std::vector& int32Values, size_t startPos, size_t numberAssociationTypes, + std::vector* associationTypes) { + size_t minInt32Values = startPos + numberAssociationTypes; + if (int32Values.size() < minInt32Values) { + return Error() << "Int32Values must have at least " << minInt32Values + << " values, received " << int32Values.size(); + } + associationTypes->resize(numberAssociationTypes); + for (size_t i = 0; i < static_cast(numberAssociationTypes); ++i) { + size_t pos = startPos + i; + auto type = verifyAndCast(int32Values[pos]); + if (!type.ok()) { + return Error() << "Invalid association type in query '" << i << "': " << type.error(); + } + (*associationTypes)[i] = *type; + } + return {}; +} + +Result parseUserAssociations(const std::vector& int32Values, size_t startPos, + size_t numberAssociations, + std::vector* associations) { + size_t minInt32Values = startPos + (numberAssociations * kNumFieldsPerSetAssociation); + if (int32Values.size() < minInt32Values) { + return Error() << "Int32Values must have at least " << minInt32Values + << " values, received " << int32Values.size(); + } + associations->resize(numberAssociations); + for (size_t i = 0; i < static_cast(numberAssociations); ++i) { + size_t pos = startPos + (kNumFieldsPerSetAssociation * i); + auto type = verifyAndCast(int32Values[pos]); + if (!type.ok()) { + return Error() << "Invalid association type in request '" << i << "': " << type.error(); + } + (*associations)[i].type = *type; + auto value = verifyAndCast(int32Values[pos + 1]); + if (!value.ok()) { + return Error() << "Invalid association set value in request '" << i + << "': " << value.error(); + } + (*associations)[i].value = *value; + } + return {}; +} + +} // namespace + +template +Result verifyAndCast(int32_t value) { + T castValue = static_cast(value); + for (const auto& v : ::ndk::enum_range()) { + if (castValue == v) { + return castValue; + } + } + + return Error() << "Value " << value << " not in enum values"; +} + +Result toInitialUserInfoRequest(const VehiclePropValue& propValue) { + auto ret = verifyPropValue(propValue, VehicleProperty::INITIAL_USER_INFO, /*minInt32Values=*/2); + if (!ret.ok()) { + return ret.error(); + } + InitialUserInfoRequest request; + request.requestId = propValue.value.int32Values[0]; + auto requestType = verifyAndCast(propValue.value.int32Values[1]); + if (!requestType.ok()) { + return Error() << "Invalid InitialUserInfoRequestType: " << requestType.error(); + } + request.requestType = *requestType; + ret = parseUsersInfo(propValue.value.int32Values, 2, &request.usersInfo); + if (!ret.ok()) { + return Error() << "Failed to parse users info: " << ret.error(); + } + return request; +} + +Result toSwitchUserRequest(const VehiclePropValue& propValue) { + auto ret = verifyPropValue(propValue, VehicleProperty::SWITCH_USER, /*minInt32Values=*/2); + if (!ret.ok()) { + return ret.error(); + } + SwitchUserRequest request; + auto messageType = verifyAndCast(propValue.value.int32Values[1]); + if (!messageType.ok()) { + return Error() << "Invalid SwitchUserMessageType: " << messageType.error(); + } + if (*messageType != SwitchUserMessageType::LEGACY_ANDROID_SWITCH && + *messageType != SwitchUserMessageType::ANDROID_SWITCH && + *messageType != SwitchUserMessageType::ANDROID_POST_SWITCH) { + return Error() << "Invalid " << toString(*messageType) + << " message type from Android System"; + } + request.requestId = propValue.value.int32Values[0]; + request.messageType = *messageType; + ret = parseUserInfo(propValue.value.int32Values, /*startPos=*/2, &request.targetUser); + if (!ret.ok()) { + return Error() << "Failed to parse target user info: " << ret.error(); + } + ret = parseUsersInfo(propValue.value.int32Values, /*startPos=*/4, &request.usersInfo); + if (!ret.ok()) { + return Error() << "Failed to parse users info: " << ret.error(); + } + return request; +} + +Result toCreateUserRequest(const VehiclePropValue& propValue) { + auto ret = verifyPropValue(propValue, VehicleProperty::CREATE_USER, /*minInt32Values=*/1); + if (!ret.ok()) { + return ret.error(); + } + CreateUserRequest request; + request.requestId = propValue.value.int32Values[0]; + ret = parseUserInfo(propValue.value.int32Values, /*startPos=*/1, &request.newUserInfo); + if (!ret.ok()) { + return Error() << "Failed to parse new user info: " << ret.error(); + } + request.newUserName = propValue.value.stringValue; + ret = parseUsersInfo(propValue.value.int32Values, /*startPos=*/3, &request.usersInfo); + if (!ret.ok()) { + return Error() << "Failed to parse users info: " << ret.error(); + } + return request; +} + +Result toRemoveUserRequest(const VehiclePropValue& propValue) { + auto ret = verifyPropValue(propValue, VehicleProperty::REMOVE_USER, /*minInt32Values=*/1); + if (!ret.ok()) { + return ret.error(); + } + RemoveUserRequest request; + request.requestId = propValue.value.int32Values[0]; + ret = parseUserInfo(propValue.value.int32Values, /*startPos=*/1, &request.removedUserInfo); + if (!ret.ok()) { + return Error() << "Failed to parse removed user info: " << ret.error(); + } + ret = parseUsersInfo(propValue.value.int32Values, /*startPos=*/3, &request.usersInfo); + if (!ret.ok()) { + return Error() << "Failed to parse users info: " << ret.error(); + } + return request; +} + +Result toUserIdentificationGetRequest( + const VehiclePropValue& propValue) { + auto ret = verifyPropValue(propValue, VehicleProperty::USER_IDENTIFICATION_ASSOCIATION, + /*minInt32Values=*/4); + if (!ret.ok()) { + return ret.error(); + } + UserIdentificationGetRequest request; + request.requestId = propValue.value.int32Values[0]; + ret = parseUserInfo(propValue.value.int32Values, /*startPos=*/1, &request.userInfo); + if (!ret.ok()) { + return Error() << "Failed to parse user info: " << ret.error(); + } + request.numberAssociationTypes = propValue.value.int32Values[3]; + ret = parseUserAssociationTypes(propValue.value.int32Values, 4, request.numberAssociationTypes, + &request.associationTypes); + if (!ret.ok()) { + return Error() << "Failed to parse UserIdentificationAssociationType: " << ret.error(); + } + return request; +} + +Result toUserIdentificationSetRequest( + const VehiclePropValue& propValue) { + auto ret = verifyPropValue(propValue, VehicleProperty::USER_IDENTIFICATION_ASSOCIATION, + /*minInt32Values=*/4); + if (!ret.ok()) { + return ret.error(); + } + UserIdentificationSetRequest request; + request.requestId = propValue.value.int32Values[0]; + ret = parseUserInfo(propValue.value.int32Values, /*startPos=*/1, &request.userInfo); + if (!ret.ok()) { + return Error() << "Failed to parse user info: " << ret.error(); + } + request.numberAssociations = propValue.value.int32Values[3]; + ret = parseUserAssociations(propValue.value.int32Values, 4, request.numberAssociations, + &request.associations); + if (!ret.ok()) { + return Error() << "Failed to parse UserIdentificationSetAssociation: " << ret.error(); + } + return request; +} + +Result toVehiclePropValue(VehiclePropValuePool& pool, + const SwitchUserRequest& request) { + if (request.messageType != SwitchUserMessageType::VEHICLE_REQUEST) { + return Errorf("Invalid %s message type %s from HAL", + toString(VehicleProperty::SWITCH_USER).c_str(), + toString(request.messageType).c_str()); + } + int32_t switchUserProp = toInt(VehicleProperty::SWITCH_USER); + auto propValue = pool.obtain(getPropType(switchUserProp)); + propValue->prop = switchUserProp; + propValue->timestamp = elapsedRealtimeNano(); + propValue->value.int32Values.resize(3); + propValue->value.int32Values[0] = static_cast(request.requestId); + propValue->value.int32Values[1] = static_cast(request.messageType); + propValue->value.int32Values[2] = static_cast(request.targetUser.userId); + return propValue; +} + +VehiclePropValuePool::RecyclableType toVehiclePropValue(VehiclePropValuePool& pool, + const InitialUserInfoResponse& response) { + int32_t initialUserInfoProp = toInt(VehicleProperty::INITIAL_USER_INFO); + auto propValue = pool.obtain(getPropType(initialUserInfoProp)); + propValue->prop = initialUserInfoProp; + propValue->timestamp = elapsedRealtimeNano(); + propValue->value.int32Values.resize(4); + propValue->value.int32Values[0] = static_cast(response.requestId); + propValue->value.int32Values[1] = static_cast(response.action); + propValue->value.int32Values[2] = static_cast(response.userToSwitchOrCreate.userId); + propValue->value.int32Values[3] = response.userToSwitchOrCreate.flags; + propValue->value.stringValue = std::string(response.userLocales) + std::string(kSeparator) + + std::string(response.userNameToCreate); + return propValue; +} + +VehiclePropValuePool::RecyclableType toVehiclePropValue(VehiclePropValuePool& pool, + const SwitchUserResponse& response) { + int32_t switchUserProp = toInt(VehicleProperty::SWITCH_USER); + auto propValue = pool.obtain(getPropType(switchUserProp)); + propValue->prop = switchUserProp; + propValue->timestamp = elapsedRealtimeNano(); + propValue->value.int32Values.resize(3); + propValue->value.int32Values[0] = static_cast(response.requestId); + propValue->value.int32Values[1] = static_cast(response.messageType); + propValue->value.int32Values[2] = static_cast(response.status); + if (response.status == SwitchUserStatus::FAILURE) { + propValue->value.stringValue = response.errorMessage; + } + return propValue; +} + +VehiclePropValuePool::RecyclableType toVehiclePropValue(VehiclePropValuePool& pool, + const CreateUserResponse& response) { + int32_t createUserProp = toInt(VehicleProperty::CREATE_USER); + auto propValue = pool.obtain(getPropType(createUserProp)); + propValue->prop = createUserProp; + propValue->timestamp = elapsedRealtimeNano(); + propValue->value.int32Values.resize(2); + propValue->value.int32Values[0] = static_cast(response.requestId); + propValue->value.int32Values[1] = static_cast(response.status); + if (response.status == CreateUserStatus::FAILURE) { + propValue->value.stringValue = response.errorMessage; + } + return propValue; +} + +VehiclePropValuePool::RecyclableType toVehiclePropValue( + VehiclePropValuePool& pool, const UserIdentificationResponse& response) { + int32_t userIdAssocProp = toInt(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION); + auto propValue = pool.obtain(getPropType(userIdAssocProp)); + propValue->prop = userIdAssocProp; + propValue->timestamp = elapsedRealtimeNano(); + propValue->value.int32Values.resize(2 + (response.numberAssociation * 2)); + propValue->value.int32Values[0] = static_cast(response.requestId); + propValue->value.int32Values[1] = static_cast(response.numberAssociation); + for (size_t i = 0; i < static_cast(response.numberAssociation); ++i) { + size_t int32ValuesPos = 2 + (2 * i); + propValue->value.int32Values[int32ValuesPos] = + static_cast(response.associations[i].type); + propValue->value.int32Values[int32ValuesPos + 1] = + static_cast(response.associations[i].value); + } + if (!response.errorMessage.empty()) { + propValue->value.stringValue = response.errorMessage; + } + return propValue; +} + +} // namespace user_hal_helper +} // namespace fake +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/fake_impl/userhal/test/Android.bp b/automotive/vehicle/aidl/impl/current/fake_impl/userhal/test/Android.bp similarity index 100% rename from automotive/vehicle/aidl/impl/fake_impl/userhal/test/Android.bp rename to automotive/vehicle/aidl/impl/current/fake_impl/userhal/test/Android.bp diff --git a/automotive/vehicle/aidl/impl/current/fake_impl/userhal/test/UserHalHelper_test.cpp b/automotive/vehicle/aidl/impl/current/fake_impl/userhal/test/UserHalHelper_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2afb2e3b2e37480a5ebeda4ecc359bfe6d08cfe0 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/fake_impl/userhal/test/UserHalHelper_test.cpp @@ -0,0 +1,715 @@ +/* + * Copyright (C) 2021 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 "UserHalHelper.h" + +#include +#include +#include +#include + +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace fake { +namespace user_hal_helper { + +namespace { + +using ::testing::Eq; +using ::testing::Gt; +using ::testing::IsNull; +using ::testing::NotNull; +using ::testing::Pointee; + +using ::aidl::android::hardware::automotive::vehicle::CreateUserRequest; +using ::aidl::android::hardware::automotive::vehicle::CreateUserResponse; +using ::aidl::android::hardware::automotive::vehicle::CreateUserStatus; +using ::aidl::android::hardware::automotive::vehicle::InitialUserInfoRequest; +using ::aidl::android::hardware::automotive::vehicle::InitialUserInfoRequestType; +using ::aidl::android::hardware::automotive::vehicle::InitialUserInfoResponse; +using ::aidl::android::hardware::automotive::vehicle::InitialUserInfoResponseAction; +using ::aidl::android::hardware::automotive::vehicle::RemoveUserRequest; +using ::aidl::android::hardware::automotive::vehicle::SwitchUserMessageType; +using ::aidl::android::hardware::automotive::vehicle::SwitchUserRequest; +using ::aidl::android::hardware::automotive::vehicle::SwitchUserResponse; +using ::aidl::android::hardware::automotive::vehicle::SwitchUserStatus; +using ::aidl::android::hardware::automotive::vehicle::UserIdentificationAssociationSetValue; +using ::aidl::android::hardware::automotive::vehicle::UserIdentificationAssociationType; +using ::aidl::android::hardware::automotive::vehicle::UserIdentificationAssociationValue; +using ::aidl::android::hardware::automotive::vehicle::UserIdentificationGetRequest; +using ::aidl::android::hardware::automotive::vehicle::UserIdentificationResponse; +using ::aidl::android::hardware::automotive::vehicle::UserIdentificationSetRequest; +using ::aidl::android::hardware::automotive::vehicle::UserInfo; +using ::aidl::android::hardware::automotive::vehicle::VehicleProperty; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; + +constexpr int32_t INITIAL_USER_INFO = toInt(VehicleProperty::INITIAL_USER_INFO); +constexpr int32_t SWITCH_USER = toInt(VehicleProperty::SWITCH_USER); +constexpr int32_t CREATE_USER = toInt(VehicleProperty::CREATE_USER); +constexpr int32_t REMOVE_USER = toInt(VehicleProperty::REMOVE_USER); +constexpr int32_t USER_IDENTIFICATION_ASSOCIATION = + toInt(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION); + +constexpr int32_t FIRST_BOOT_AFTER_OTA = toInt(InitialUserInfoRequestType::FIRST_BOOT_AFTER_OTA); +constexpr int32_t LEGACY_ANDROID_SWITCH = toInt(SwitchUserMessageType::LEGACY_ANDROID_SWITCH); +constexpr int32_t VEHICLE_REQUEST = toInt(SwitchUserMessageType::VEHICLE_REQUEST); + +constexpr int32_t NONE_USER = 0; +constexpr int32_t GUEST_USER = toInt(UserInfo::USER_FLAG_GUEST); +constexpr int32_t SYSTEM_USER = toInt(UserInfo::USER_FLAG_SYSTEM); +constexpr int32_t SYSTEM_ADMIN_USER = SYSTEM_USER | toInt(UserInfo::USER_FLAG_ADMIN); +// 0x1111 is not a valid UserFlags combination. +constexpr int32_t INVALID_USER_FLAG = 0x1111; + +constexpr int32_t USER_ID_ASSOC_KEY_FOB = toInt(UserIdentificationAssociationType::KEY_FOB); +constexpr int32_t USER_ID_ASSOC_CUSTOM_1 = toInt(UserIdentificationAssociationType::CUSTOM_1); + +constexpr int32_t USER_ID_ASSOC_SET_CURRENT_USER = + toInt(UserIdentificationAssociationSetValue::ASSOCIATE_CURRENT_USER); +constexpr int32_t USER_ID_ASSOC_UNSET_CURRENT_USER = + toInt(UserIdentificationAssociationSetValue::DISASSOCIATE_CURRENT_USER); + +constexpr int32_t USER_ID_ASSOC_CURRENT_USER = + toInt(UserIdentificationAssociationValue::ASSOCIATED_CURRENT_USER); +constexpr int32_t USER_ID_ASSOC_NO_USER = + toInt(UserIdentificationAssociationValue::NOT_ASSOCIATED_ANY_USER); + +} // namespace + +TEST(UserHalHelperTest, TestToInitialUserInfoRequest) { + VehiclePropValue propValue{ + .prop = INITIAL_USER_INFO, + .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0, SYSTEM_USER, + 10, NONE_USER}}, + }; + InitialUserInfoRequest expected{ + .requestId = 23, + .requestType = InitialUserInfoRequestType::FIRST_BOOT_AFTER_OTA, + .usersInfo = {{10, 0}, 2, {{0, SYSTEM_USER}, {10, 0}}}, + }; + + auto actual = toInitialUserInfoRequest(propValue); + + ASSERT_TRUE(actual.ok()) << actual.error().message(); + EXPECT_THAT(actual.value(), Eq(expected)); +} + +TEST(UserHalHelperTest, TestToInitialUserInfoRequestUserFlagsBitCombination) { + // SYSTEM_ADMIN_USER is two UserFlags combined. + VehiclePropValue propValue{ + .prop = INITIAL_USER_INFO, + .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0, + SYSTEM_ADMIN_USER, 10, NONE_USER}}, + }; + InitialUserInfoRequest expected{ + .requestId = 23, + .requestType = InitialUserInfoRequestType::FIRST_BOOT_AFTER_OTA, + .usersInfo = {{10, 0}, 2, {{0, SYSTEM_ADMIN_USER}, {10, 0}}}, + }; + + auto actual = toInitialUserInfoRequest(propValue); + + ASSERT_TRUE(actual.ok()) << actual.error().message(); + EXPECT_THAT(actual.value(), Eq(expected)); +} + +TEST(UserHalHelperTest, TestToInitialUserInfoRequestUserInvalidUserFlag) { + VehiclePropValue propValue{ + .prop = INITIAL_USER_INFO, + .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0, + INVALID_USER_FLAG, 10, NONE_USER}}, + }; + + auto actual = toInitialUserInfoRequest(propValue); + + EXPECT_FALSE(actual.ok()) << "No error returned on invalid user flags"; +} + +TEST(UserHalHelperTest, TestFailsToInitialUserInfoRequestWithMismatchingPropType) { + VehiclePropValue propValue{ + .prop = INT32_MAX, + .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0, SYSTEM_USER, + 10, NONE_USER}}, + }; + + auto actual = toInitialUserInfoRequest(propValue); + + EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type"; +} + +TEST(UserHalHelperTest, TestFailsToInitialUserInfoRequestWithInvalidRequestType) { + VehiclePropValue propValue{ + .prop = INITIAL_USER_INFO, + .value = {.int32Values = {23, INT32_MAX, 10, NONE_USER, 2, 0, SYSTEM_USER, 10, + NONE_USER}}, + }; + + auto actual = toInitialUserInfoRequest(propValue); + + EXPECT_FALSE(actual.ok()) << "No error returned on invalid request type"; +} + +TEST(UserHalHelperTest, TestFailsToInitialUserInfoRequestWithInvalidUserFlag) { + VehiclePropValue propValue{ + .prop = INITIAL_USER_INFO, + .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0, SYSTEM_USER, + 10, INT32_MAX}}, + }; + + auto actual = toInitialUserInfoRequest(propValue); + + EXPECT_FALSE(actual.ok()) << "No error returned on invalid user flags"; +} + +TEST(UserHalHelperTest, TestFailsToInitialUserInfoRequestWithIncompleteUsersInfo) { + VehiclePropValue propValueMissingSecondUserInfo{ + .prop = INITIAL_USER_INFO, + .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0, + SYSTEM_USER /*Missing 2nd UserInfo*/}}, + }; + + auto actual = toInitialUserInfoRequest(propValueMissingSecondUserInfo); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing second user info"; + + VehiclePropValue propValueMissingUsersInfo{ + .prop = INITIAL_USER_INFO, + .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, /*Missing UsersInfo*/}}, + }; + + actual = toInitialUserInfoRequest(propValueMissingUsersInfo); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing users info"; +} + +TEST(UserHalHelperTest, TestToSwitchUserRequest) { + VehiclePropValue propValue{ + .prop = SWITCH_USER, + .value = {.int32Values = {23, LEGACY_ANDROID_SWITCH, 0, SYSTEM_USER, 10, NONE_USER, 2, + 0, SYSTEM_USER, 10, NONE_USER}}, + }; + SwitchUserRequest expected{ + .requestId = 23, + .messageType = SwitchUserMessageType::LEGACY_ANDROID_SWITCH, + .targetUser = {0, SYSTEM_USER}, + .usersInfo = {{10, 0}, 2, {{0, SYSTEM_USER}, {10, 0}}}, + }; + + auto actual = toSwitchUserRequest(propValue); + + ASSERT_TRUE(actual.ok()) << actual.error().message(); + EXPECT_THAT(actual.value(), Eq(expected)); +} + +TEST(UserHalHelperTest, TestFailsToSwitchUserRequestWithMismatchingPropType) { + VehiclePropValue propValue{ + .prop = INITIAL_USER_INFO, + .value = {.int32Values = {23, LEGACY_ANDROID_SWITCH, 0, SYSTEM_USER, 10, NONE_USER, 2, + 0, SYSTEM_USER, 10, NONE_USER}}, + }; + + auto actual = toSwitchUserRequest(propValue); + + EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type"; +} + +TEST(UserHalHelperTest, TestFailsToSwitchUserRequestWithInvalidMessageType) { + VehiclePropValue propValueIncompatibleMessageType{ + .prop = SWITCH_USER, + .value = {.int32Values = {23, VEHICLE_REQUEST, 0, SYSTEM_USER, 10, NONE_USER, 2, 0, + SYSTEM_USER, 10, NONE_USER}}, + }; + + auto actual = toSwitchUserRequest(propValueIncompatibleMessageType); + + EXPECT_FALSE(actual.ok()) << "No error returned on incompatible message type"; + + VehiclePropValue propValueInvalidMessageType{ + .prop = SWITCH_USER, + .value = {.int32Values = {23, INT32_MAX, 0, SYSTEM_USER, 10, NONE_USER, 2, 0, + SYSTEM_USER, 10, NONE_USER}}, + }; + + actual = toSwitchUserRequest(propValueInvalidMessageType); + + EXPECT_FALSE(actual.ok()) << "No error returned on invalid message type"; +} + +TEST(UserHalHelperTest, TestFailsToSwitchUserRequestWithIncompleteUsersInfo) { + VehiclePropValue propValueMissingSecondUserInfo{ + .prop = SWITCH_USER, + .value = {.int32Values = {23, LEGACY_ANDROID_SWITCH, 0, SYSTEM_USER, 10, NONE_USER, 2, + 0, SYSTEM_USER, + /*Missing 2nd UserInfo*/}}, + }; + + auto actual = toSwitchUserRequest(propValueMissingSecondUserInfo); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing second user info"; + + VehiclePropValue propValueMissingUsersInfo{ + .prop = SWITCH_USER, + .value = {.int32Values = {23, LEGACY_ANDROID_SWITCH, 0, SYSTEM_USER, + /*Missing UsersInfo*/}}, + }; + + actual = toSwitchUserRequest(propValueMissingUsersInfo); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing users info"; + + VehiclePropValue propValueMissingTargetUser{ + .prop = SWITCH_USER, + .value = {.int32Values = {23, LEGACY_ANDROID_SWITCH, /*Missing target UserInfo*/}}, + }; + + actual = toSwitchUserRequest(propValueMissingTargetUser); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing target user info"; +} + +TEST(UserHalHelperTest, TestToCreateUserRequest) { + VehiclePropValue propValue{ + .prop = CREATE_USER, + .value = {.int32Values = {23, 11, GUEST_USER, 10, NONE_USER, 2, 0, SYSTEM_USER, 10, + NONE_USER}, + .stringValue = "Guest11"}, + }; + CreateUserRequest expected{ + .requestId = 23, + .newUserInfo = {11, GUEST_USER}, + .newUserName = "Guest11", + .usersInfo = {{10, 0}, 2, {{0, SYSTEM_USER}, {10, 0}}}, + }; + + auto actual = toCreateUserRequest(propValue); + + ASSERT_TRUE(actual.ok()) << actual.error().message(); + EXPECT_THAT(actual.value(), Eq(expected)); +} + +TEST(UserHalHelperTest, TestFailsToCreateUserRequestWithMismatchingPropType) { + VehiclePropValue propValue{ + .prop = INITIAL_USER_INFO, + .value = {.int32Values = {23, 11, GUEST_USER, 10, NONE_USER, 2, 0, SYSTEM_USER, 10, + NONE_USER}, + .stringValue = "Guest11"}, + }; + + auto actual = toCreateUserRequest(propValue); + + EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type"; +} + +TEST(UserHalHelperTest, TestFailsToCreateUserRequestWithIncompleteUsersInfo) { + VehiclePropValue propValueMissingSecondUserInfo{ + .prop = CREATE_USER, + .value = {.int32Values = {23, 11, GUEST_USER, 10, NONE_USER, 2, 0, + SYSTEM_USER /*Missing 2nd UserInfo*/}, + .stringValue = "Guest11"}, + }; + + auto actual = toCreateUserRequest(propValueMissingSecondUserInfo); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing second user info"; + + VehiclePropValue propValueMissingUsersInfo{ + .prop = CREATE_USER, + .value = {.int32Values = {23, 11, GUEST_USER, /*Missing UsersInfo*/}, + .stringValue = "Guest11"}, + }; + + actual = toCreateUserRequest(propValueMissingUsersInfo); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing users info"; + + VehiclePropValue propValueMissingCreateUserInfo{ + .prop = CREATE_USER, + .value = {.int32Values = {23, /*Missing create UserInfo*/}, .stringValue = "Guest11"}, + }; + + actual = toCreateUserRequest(propValueMissingCreateUserInfo); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing create user info"; +} + +TEST(UserHalHelperTest, TestToRemoveUserRequest) { + VehiclePropValue propValue{ + .prop = REMOVE_USER, + .value = {.int32Values = {23, 10, NONE_USER, 10, NONE_USER, 2, 0, SYSTEM_USER, 10, + NONE_USER}}, + }; + RemoveUserRequest expected{ + .requestId = 23, + .removedUserInfo = {10, 0}, + .usersInfo = {{10, 0}, 2, {{0, SYSTEM_USER}, {10, 0}}}, + }; + + auto actual = toRemoveUserRequest(propValue); + + ASSERT_TRUE(actual.ok()) << actual.error().message(); + EXPECT_THAT(actual.value(), Eq(expected)); +} + +TEST(UserHalHelperTest, TestFailsToRemoveUserRequestWithMismatchingPropType) { + VehiclePropValue propValue{ + .prop = INITIAL_USER_INFO, + .value = {.int32Values = {23, 10, NONE_USER, 10, NONE_USER, 2, 0, SYSTEM_USER, 10, + NONE_USER}}, + }; + + auto actual = toRemoveUserRequest(propValue); + + EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type"; +} + +TEST(UserHalHelperTest, TestFailsToRemoveUserRequestWithIncompleteUsersInfo) { + VehiclePropValue propValueMissingSecondUserInfo{ + .prop = REMOVE_USER, + .value = {.int32Values = {23, 10, NONE_USER, 10, NONE_USER, 2, 0, + SYSTEM_USER /*Missing 2nd UserInfo*/}}, + }; + + auto actual = toRemoveUserRequest(propValueMissingSecondUserInfo); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing second user info"; + + VehiclePropValue propValueMissingUsersInfo{ + .prop = REMOVE_USER, + .value = {.int32Values = {23, 10, NONE_USER, /*Missing UsersInfo*/}}, + }; + + actual = toRemoveUserRequest(propValueMissingUsersInfo); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing users info"; + + VehiclePropValue propValueMissingRemoveUserInfo{ + .prop = REMOVE_USER, + .value = {.int32Values = {23, /*Missing remove UserInfo*/}}, + }; + + actual = toRemoveUserRequest(propValueMissingRemoveUserInfo); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing remove user info"; +} + +TEST(UserHalHelperTest, TestFailsToUserIdentificationGetRequest) { + VehiclePropValue propValue{ + .prop = USER_IDENTIFICATION_ASSOCIATION, + .value = {.int32Values = {23, 10, NONE_USER, 2, USER_ID_ASSOC_KEY_FOB, + USER_ID_ASSOC_CUSTOM_1}}, + }; + UserIdentificationGetRequest expected{ + .requestId = 23, + .userInfo = {10, 0}, + .numberAssociationTypes = 2, + .associationTypes = {UserIdentificationAssociationType::KEY_FOB, + UserIdentificationAssociationType::CUSTOM_1}, + }; + + auto actual = toUserIdentificationGetRequest(propValue); + + ASSERT_TRUE(actual.ok()) << actual.error().message(); + EXPECT_THAT(actual.value(), Eq(expected)); +} + +TEST(UserHalHelperTest, TestFailsToUserIdentificationGetRequestWithMismatchingPropType) { + VehiclePropValue propValue{ + .prop = INITIAL_USER_INFO, + .value = {.int32Values = {23, 10, NONE_USER, 2, USER_ID_ASSOC_KEY_FOB, + USER_ID_ASSOC_CUSTOM_1}}, + }; + + auto actual = toUserIdentificationGetRequest(propValue); + + EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type"; +} + +TEST(UserHalHelperTest, TestFailsToUserIdentificationGetRequestWithInvalidAssociationTypes) { + VehiclePropValue propValue{ + .prop = USER_IDENTIFICATION_ASSOCIATION, + .value = {.int32Values = {23, 10, NONE_USER, 1, INT32_MAX}}, + }; + + auto actual = toUserIdentificationGetRequest(propValue); + + EXPECT_FALSE(actual.ok()) << "No error returned on invalid association type"; +} + +TEST(UserHalHelperTest, TestFailsToUserIdentificationGetRequestWithIncompleteAssociationTypes) { + VehiclePropValue propValueMissingSecondAssociationType{ + .prop = USER_IDENTIFICATION_ASSOCIATION, + .value = {.int32Values = {23, 10, NONE_USER, 2, + USER_ID_ASSOC_KEY_FOB /*Missing 2nd association type*/}}, + }; + + auto actual = toUserIdentificationGetRequest(propValueMissingSecondAssociationType); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing second association type"; + + VehiclePropValue propValueMissingNumberAssociationTypes{ + .prop = USER_IDENTIFICATION_ASSOCIATION, + .value = {.int32Values = {23, 10, NONE_USER, /*Missing number association types*/}}, + }; + + actual = toUserIdentificationGetRequest(propValueMissingNumberAssociationTypes); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing number association types"; +} + +TEST(UserHalHelperTest, TestFailsToUserIdentificationGetRequestWithMissingUserInfo) { + VehiclePropValue propValue{ + .prop = USER_IDENTIFICATION_ASSOCIATION, + .value = {.int32Values = {23, /*Missing user info*/}}, + }; + + auto actual = toUserIdentificationGetRequest(propValue); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing UserInfo"; +} + +TEST(UserHalHelperTest, TestToUserIdentificationSetRequest) { + VehiclePropValue propValue{ + .prop = USER_IDENTIFICATION_ASSOCIATION, + .value = {.int32Values = {23, 10, NONE_USER, 2, USER_ID_ASSOC_KEY_FOB, + USER_ID_ASSOC_SET_CURRENT_USER, USER_ID_ASSOC_CUSTOM_1, + USER_ID_ASSOC_UNSET_CURRENT_USER}}, + }; + UserIdentificationSetRequest expected{ + .requestId = 23, + .userInfo = {10, 0}, + .numberAssociations = 2, + .associations = {{UserIdentificationAssociationType::KEY_FOB, + UserIdentificationAssociationSetValue::ASSOCIATE_CURRENT_USER}, + {UserIdentificationAssociationType::CUSTOM_1, + UserIdentificationAssociationSetValue::DISASSOCIATE_CURRENT_USER}}, + }; + + auto actual = toUserIdentificationSetRequest(propValue); + + ASSERT_TRUE(actual.ok()) << actual.error().message(); + EXPECT_THAT(actual.value(), Eq(expected)); +} + +TEST(UserHalHelperTest, TestFailsToUserIdentificationSetRequestWithMismatchingPropType) { + VehiclePropValue propValue{ + .prop = INITIAL_USER_INFO, + .value = {.int32Values = {23, 10, NONE_USER, 2, USER_ID_ASSOC_KEY_FOB, + USER_ID_ASSOC_SET_CURRENT_USER, USER_ID_ASSOC_CUSTOM_1, + USER_ID_ASSOC_UNSET_CURRENT_USER}}, + }; + + auto actual = toUserIdentificationSetRequest(propValue); + + EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type"; +} + +TEST(UserHalHelperTest, TestFailsToUserIdentificationSetRequestWithInvalidAssociations) { + VehiclePropValue propValueInvalidAssociationType{ + .prop = USER_IDENTIFICATION_ASSOCIATION, + .value = {.int32Values = {23, 10, NONE_USER, 1, INT32_MAX, + USER_ID_ASSOC_SET_CURRENT_USER}}, + }; + + auto actual = toUserIdentificationSetRequest(propValueInvalidAssociationType); + + EXPECT_FALSE(actual.ok()) << "No error returned on invalid association type"; + + VehiclePropValue propValueInvalidAssociationValue{ + .prop = USER_IDENTIFICATION_ASSOCIATION, + .value = {.int32Values = {23, 10, NONE_USER, USER_ID_ASSOC_KEY_FOB, INT32_MAX}}, + }; + + actual = toUserIdentificationSetRequest(propValueInvalidAssociationValue); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing number association types"; +} + +TEST(UserHalHelperTest, TestFailsToUserIdentificationSetRequestWithIncompleteAssociations) { + VehiclePropValue propValueMissingSecondAssociationType{ + .prop = USER_IDENTIFICATION_ASSOCIATION, + .value = {.int32Values = {23, 10, NONE_USER, 2, USER_ID_ASSOC_KEY_FOB, + USER_ID_ASSOC_SET_CURRENT_USER, + /*Missing 2nd association*/}}, + }; + + auto actual = toUserIdentificationSetRequest(propValueMissingSecondAssociationType); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing second association type"; + + VehiclePropValue propValueMissingNumberAssociationTypes{ + .prop = USER_IDENTIFICATION_ASSOCIATION, + .value = {.int32Values = {23, 10, NONE_USER, /*Missing number associations*/}}, + }; + + actual = toUserIdentificationSetRequest(propValueMissingNumberAssociationTypes); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing number association types"; +} + +TEST(UserHalHelperTest, TestFailsToUserIdentificationSetRequestWithMissingUserInfo) { + VehiclePropValue propValue{ + .prop = USER_IDENTIFICATION_ASSOCIATION, + .value = {.int32Values = {23, /*Missing user info*/}}, + }; + + auto actual = toUserIdentificationSetRequest(propValue); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing UserInfo"; +} + +TEST(UserHalHelperTest, TestSwitchUserRequestToVehiclePropValue) { + SwitchUserRequest request{ + .requestId = 23, + .messageType = SwitchUserMessageType::VEHICLE_REQUEST, + .targetUser = {11, GUEST_USER}, + }; + VehiclePropValue expected{ + .prop = SWITCH_USER, + .value = {.int32Values = {23, + static_cast(SwitchUserMessageType::VEHICLE_REQUEST), + 11}}, + }; + + VehiclePropValuePool pool; + auto result = toVehiclePropValue(pool, request); + + ASSERT_TRUE(result.ok()); + EXPECT_THAT(result.value()->timestamp, Gt(0)); + // Don't rely on real timestamp in tests as the expected and actual objects won't have the same + // timestamps. Thus remove the timestamps before comparing them. + result.value()->timestamp = 0; + EXPECT_THAT(result.value(), Pointee(Eq(expected))); +} + +TEST(UserHalHelperTest, TestFailsSwitchUserRequestToVehiclePropValueWithIncompatibleMessageType) { + SwitchUserRequest request{ + .requestId = 23, + .messageType = SwitchUserMessageType::VEHICLE_RESPONSE, + .targetUser = {11, GUEST_USER}, + }; + + VehiclePropValuePool pool; + auto result = toVehiclePropValue(pool, request); + + EXPECT_FALSE(result.ok()); +} + +TEST(UserHalHelperTest, TestInitialUserInfoResponseToVehiclePropValue) { + InitialUserInfoResponse response{ + .requestId = 23, + .action = InitialUserInfoResponseAction::CREATE, + .userToSwitchOrCreate = {11, GUEST_USER}, + .userLocales = "en-US,pt-BR", + .userNameToCreate = "Owner", + }; + VehiclePropValue expected{ + .prop = INITIAL_USER_INFO, + .value = {.int32Values = {23, + static_cast(InitialUserInfoResponseAction::CREATE), + 11, GUEST_USER}, + .stringValue = "en-US,pt-BR||Owner"}, + }; + + VehiclePropValuePool pool; + auto actual = toVehiclePropValue(pool, response); + + ASSERT_THAT(actual, NotNull()); + EXPECT_THAT(actual->timestamp, Gt(0)); + actual->timestamp = 0; + EXPECT_THAT(actual, Pointee(Eq(expected))); +} + +TEST(UserHalHelperTest, TestSwitchUserResponseToVehiclePropValue) { + SwitchUserResponse response{ + .requestId = 23, + .messageType = SwitchUserMessageType::VEHICLE_RESPONSE, + .status = SwitchUserStatus::FAILURE, + .errorMessage = "random error", + }; + VehiclePropValue expected{ + .prop = SWITCH_USER, + .value = {.int32Values = {23, + static_cast(SwitchUserMessageType::VEHICLE_RESPONSE), + static_cast(SwitchUserStatus::FAILURE)}, + .stringValue = "random error"}, + }; + + VehiclePropValuePool pool; + auto actual = toVehiclePropValue(pool, response); + + ASSERT_THAT(actual, NotNull()); + EXPECT_THAT(actual->timestamp, Gt(0)); + actual->timestamp = 0; + EXPECT_THAT(actual, Pointee(Eq(expected))); +} + +TEST(UserHalHelperTest, TestCreateUserResponseToVehiclePropValue) { + CreateUserResponse response{ + .requestId = 23, + .status = CreateUserStatus::FAILURE, + .errorMessage = "random error", + }; + VehiclePropValue expected{ + .prop = CREATE_USER, + .value = {.int32Values = {23, static_cast(CreateUserStatus::FAILURE)}, + .stringValue = "random error"}, + }; + + VehiclePropValuePool pool; + auto actual = toVehiclePropValue(pool, response); + + ASSERT_THAT(actual, NotNull()); + EXPECT_THAT(actual->timestamp, Gt(0)); + actual->timestamp = 0; + EXPECT_THAT(actual, Pointee(Eq(expected))); +} + +TEST(UserHalHelperTest, TestUserIdentificationResponseToVehiclePropValue) { + UserIdentificationResponse response{ + .requestId = 23, + .numberAssociation = 2, + .associations = {{UserIdentificationAssociationType::KEY_FOB, + UserIdentificationAssociationValue::ASSOCIATED_CURRENT_USER}, + {UserIdentificationAssociationType::CUSTOM_1, + UserIdentificationAssociationValue::NOT_ASSOCIATED_ANY_USER}}, + .errorMessage = "random error", + }; + VehiclePropValue expected{ + .prop = USER_IDENTIFICATION_ASSOCIATION, + .value = {.int32Values = {23, 2, USER_ID_ASSOC_KEY_FOB, USER_ID_ASSOC_CURRENT_USER, + USER_ID_ASSOC_CUSTOM_1, USER_ID_ASSOC_NO_USER}, + .stringValue = "random error"}, + }; + + VehiclePropValuePool pool; + auto actual = toVehiclePropValue(pool, response); + + ASSERT_THAT(actual, NotNull()); + EXPECT_THAT(actual->timestamp, Gt(0)); + actual->timestamp = 0; + EXPECT_THAT(actual, Pointee(Eq(expected))); +} + +} // namespace user_hal_helper +} // namespace fake +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/grpc/Android.bp b/automotive/vehicle/aidl/impl/current/grpc/Android.bp similarity index 89% rename from automotive/vehicle/aidl/impl/grpc/Android.bp rename to automotive/vehicle/aidl/impl/current/grpc/Android.bp index 7a8da5907424d349eb0ca61625137eebc0cfd00f..f798b722748b89decb86b89bfc2a19efa40199ed 100644 --- a/automotive/vehicle/aidl/impl/grpc/Android.bp +++ b/automotive/vehicle/aidl/impl/current/grpc/Android.bp @@ -22,7 +22,7 @@ genrule { "aprotoc", "protoc-gen-grpc-cpp-plugin", ], - cmd: "$(location aprotoc) -I$$(dirname $(location proto/VehicleServer.proto)) -Ihardware/interfaces/automotive/vehicle/aidl/impl/proto -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(location proto/VehicleServer.proto) --grpc_opt=generate_mock_code=true --grpc_out=$(genDir) --cpp_out=$(genDir)", + cmd: "$(location aprotoc) -I$$(dirname $(location proto/VehicleServer.proto)) -Ihardware/interfaces/automotive/vehicle/aidl/impl/current/proto -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(location proto/VehicleServer.proto) --grpc_opt=generate_mock_code=true --grpc_out=$(genDir) --cpp_out=$(genDir)", srcs: [ "proto/VehicleServer.proto", ":libprotobuf-internal-protos", @@ -42,7 +42,7 @@ genrule { "aprotoc", "protoc-gen-grpc-cpp-plugin", ], - cmd: "$(location aprotoc) -I$$(dirname $(location proto/VehicleServer.proto)) -Ihardware/interfaces/automotive/vehicle/aidl/impl/proto -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(location proto/VehicleServer.proto) --grpc_out=$(genDir) --cpp_out=$(genDir)", + cmd: "$(location aprotoc) -I$$(dirname $(location proto/VehicleServer.proto)) -Ihardware/interfaces/automotive/vehicle/aidl/impl/current/proto -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(location proto/VehicleServer.proto) --grpc_out=$(genDir) --cpp_out=$(genDir)", srcs: [ "proto/VehicleServer.proto", ":libprotobuf-internal-protos", diff --git a/automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleHardware.cpp b/automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleHardware.cpp new file mode 100644 index 0000000000000000000000000000000000000000..875037524df7c2e8bff0e393f665febacc71992a --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleHardware.cpp @@ -0,0 +1,411 @@ +/* + * Copyright (C) 2023 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 "ProtoMessageConverter.h" + +#include +#include +#include + +#include +#include +#include +#include + +namespace android::hardware::automotive::vehicle::virtualization { + +namespace { + +constexpr size_t MAX_RETRY_COUNT = 5; + +std::shared_ptr<::grpc::ChannelCredentials> getChannelCredentials() { + return ::grpc::InsecureChannelCredentials(); +} + +} // namespace + +GRPCVehicleHardware::GRPCVehicleHardware(std::string service_addr) + : mServiceAddr(std::move(service_addr)), + mGrpcChannel(::grpc::CreateChannel(mServiceAddr, getChannelCredentials())), + mGrpcStub(proto::VehicleServer::NewStub(mGrpcChannel)), + mValuePollingThread([this] { ValuePollingLoop(); }) {} + +// Only used for unit testing. +GRPCVehicleHardware::GRPCVehicleHardware(std::unique_ptr stub, + bool startValuePollingLoop) + : mServiceAddr(""), mGrpcChannel(nullptr), mGrpcStub(std::move(stub)) { + if (startValuePollingLoop) { + mValuePollingThread = std::thread([this] { ValuePollingLoop(); }); + } +} + +GRPCVehicleHardware::~GRPCVehicleHardware() { + { + std::lock_guard lck(mShutdownMutex); + mShuttingDownFlag.store(true); + } + mShutdownCV.notify_all(); + if (mValuePollingThread.joinable()) { + mValuePollingThread.join(); + } +} + +std::vector GRPCVehicleHardware::getAllPropertyConfigs() const { + std::vector configs; + ::grpc::ClientContext context; + auto config_stream = mGrpcStub->GetAllPropertyConfig(&context, ::google::protobuf::Empty()); + proto::VehiclePropConfig protoConfig; + while (config_stream->Read(&protoConfig)) { + aidlvhal::VehiclePropConfig config; + proto_msg_converter::protoToAidl(protoConfig, &config); + configs.push_back(std::move(config)); + } + auto grpc_status = config_stream->Finish(); + if (!grpc_status.ok()) { + LOG(ERROR) << __func__ + << ": GRPC GetAllPropertyConfig Failed: " << grpc_status.error_message(); + } + return configs; +} + +std::optional GRPCVehicleHardware::getPropertyConfig( + int32_t propId) const { + // TODO(b/354055835): Use GRPC call to get one config instead of getting all the configs. + for (const auto& config : getAllPropertyConfigs()) { + if (config.prop == propId) { + return config; + } + } + return std::nullopt; +} + +aidlvhal::StatusCode GRPCVehicleHardware::setValues( + std::shared_ptr callback, + const std::vector& requests) { + ::grpc::ClientContext context; + proto::VehiclePropValueRequests protoRequests; + proto::SetValueResults protoResults; + for (const auto& request : requests) { + auto& protoRequest = *protoRequests.add_requests(); + protoRequest.set_request_id(request.requestId); + proto_msg_converter::aidlToProto(request.value, protoRequest.mutable_value()); + } + // TODO(chenhaosjtuacm): Make it Async. + auto grpc_status = mGrpcStub->SetValues(&context, protoRequests, &protoResults); + if (!grpc_status.ok()) { + LOG(ERROR) << __func__ << ": GRPC SetValues Failed: " << grpc_status.error_message(); + { + std::shared_lock lck(mCallbackMutex); + // TODO(chenhaosjtuacm): call on-set-error callback. + } + return aidlvhal::StatusCode::INTERNAL_ERROR; + } + std::vector results; + for (const auto& protoResult : protoResults.results()) { + auto& result = results.emplace_back(); + result.requestId = protoResult.request_id(); + result.status = static_cast(protoResult.status()); + // TODO(chenhaosjtuacm): call on-set-error callback. + } + (*callback)(std::move(results)); + + return aidlvhal::StatusCode::OK; +} + +aidlvhal::StatusCode GRPCVehicleHardware::getValues( + std::shared_ptr callback, + const std::vector& requests) const { + std::vector results; + auto status = getValuesWithRetry(requests, &results, /*retryCount=*/0); + if (status != aidlvhal::StatusCode::OK) { + return status; + } + if (!results.empty()) { + (*callback)(std::move(results)); + } + return status; +} + +aidlvhal::StatusCode GRPCVehicleHardware::getValuesWithRetry( + const std::vector& requests, + std::vector* results, size_t retryCount) const { + if (retryCount == MAX_RETRY_COUNT) { + LOG(ERROR) << __func__ << ": GRPC GetValues Failed, failed to get the latest value after " + << retryCount << " retries"; + return aidlvhal::StatusCode::TRY_AGAIN; + } + + proto::VehiclePropValueRequests protoRequests; + std::unordered_map requestById; + for (const auto& request : requests) { + auto& protoRequest = *protoRequests.add_requests(); + protoRequest.set_request_id(request.requestId); + proto_msg_converter::aidlToProto(request.prop, protoRequest.mutable_value()); + requestById[request.requestId] = &request; + } + + // TODO(chenhaosjtuacm): Make it Async. + ::grpc::ClientContext context; + proto::GetValueResults protoResults; + auto grpc_status = mGrpcStub->GetValues(&context, protoRequests, &protoResults); + if (!grpc_status.ok()) { + LOG(ERROR) << __func__ << ": GRPC GetValues Failed: " << grpc_status.error_message(); + return aidlvhal::StatusCode::INTERNAL_ERROR; + } + + std::vector retryRequests; + for (const auto& protoResult : protoResults.results()) { + int64_t requestId = protoResult.request_id(); + auto it = requestById.find(requestId); + if (it == requestById.end()) { + LOG(ERROR) << __func__ + << "Invalid getValue request with unknown request ID: " << requestId + << ", ignore"; + continue; + } + + if (!protoResult.has_value()) { + auto& result = results->emplace_back(); + result.requestId = requestId; + result.status = static_cast(protoResult.status()); + continue; + } + + aidlvhal::VehiclePropValue value; + proto_msg_converter::protoToAidl(protoResult.value(), &value); + + // VHAL proxy server uses a different timestamp then AAOS timestamp, so we have to reset + // the timestamp. + // TODO(b/350822044): Remove this once we use timestamp from proxy server. + if (!setAndroidTimestamp(&value)) { + // This is a rare case when we receive a property update event reflecting a new value + // for the property before we receive the get value result. This means that the result + // is already outdated, hence we should retry getting the latest value again. + LOG(WARNING) << __func__ << "getValue result for propId: " << value.prop + << " areaId: " << value.areaId << " is oudated, retry"; + retryRequests.push_back(*(it->second)); + continue; + } + + auto& result = results->emplace_back(); + result.requestId = requestId; + result.status = static_cast(protoResult.status()); + result.prop = std::move(value); + } + + if (retryRequests.size() != 0) { + return getValuesWithRetry(retryRequests, results, retryCount++); + } + + return aidlvhal::StatusCode::OK; +} + +bool GRPCVehicleHardware::setAndroidTimestamp(aidlvhal::VehiclePropValue* propValue) const { + PropIdAreaId propIdAreaId = { + .propId = propValue->prop, + .areaId = propValue->areaId, + }; + int64_t now = elapsedRealtimeNano(); + int64_t externalTimestamp = propValue->timestamp; + + { + std::lock_guard lck(mLatestUpdateTimestampsMutex); + auto it = mLatestUpdateTimestamps.find(propIdAreaId); + if (it == mLatestUpdateTimestamps.end() || externalTimestamp > (it->second).first) { + mLatestUpdateTimestamps[propIdAreaId].first = externalTimestamp; + mLatestUpdateTimestamps[propIdAreaId].second = now; + propValue->timestamp = now; + return true; + } + if (externalTimestamp == (it->second).first) { + propValue->timestamp = (it->second).second; + return true; + } + } + // externalTimestamp < (it->second).first, the value is outdated. + return false; +} + +void GRPCVehicleHardware::registerOnPropertyChangeEvent( + std::unique_ptr callback) { + std::lock_guard lck(mCallbackMutex); + if (mOnPropChange) { + LOG(ERROR) << __func__ << " must only be called once."; + return; + } + mOnPropChange = std::move(callback); +} + +void GRPCVehicleHardware::registerOnPropertySetErrorEvent( + std::unique_ptr callback) { + std::lock_guard lck(mCallbackMutex); + if (mOnSetErr) { + LOG(ERROR) << __func__ << " must only be called once."; + return; + } + mOnSetErr = std::move(callback); +} + +DumpResult GRPCVehicleHardware::dump(const std::vector& options) { + ::grpc::ClientContext context; + proto::DumpOptions protoDumpOptions; + proto::DumpResult protoDumpResult; + for (const auto& option : options) { + protoDumpOptions.add_options(option); + } + auto grpc_status = mGrpcStub->Dump(&context, protoDumpOptions, &protoDumpResult); + if (!grpc_status.ok()) { + LOG(ERROR) << __func__ << ": GRPC Dump Failed: " << grpc_status.error_message(); + return {}; + } + return { + .callerShouldDumpState = protoDumpResult.caller_should_dump_state(), + .buffer = protoDumpResult.buffer(), + .refreshPropertyConfigs = protoDumpResult.refresh_property_configs(), + }; +} + +aidlvhal::StatusCode GRPCVehicleHardware::checkHealth() { + ::grpc::ClientContext context; + proto::VehicleHalCallStatus protoStatus; + auto grpc_status = mGrpcStub->CheckHealth(&context, ::google::protobuf::Empty(), &protoStatus); + if (!grpc_status.ok()) { + LOG(ERROR) << __func__ << ": GRPC CheckHealth Failed: " << grpc_status.error_message(); + return aidlvhal::StatusCode::INTERNAL_ERROR; + } + return static_cast(protoStatus.status_code()); +} + +aidlvhal::StatusCode GRPCVehicleHardware::subscribe(aidlvhal::SubscribeOptions options) { + proto::SubscribeRequest request; + ::grpc::ClientContext context; + proto::VehicleHalCallStatus protoStatus; + proto_msg_converter::aidlToProto(options, request.mutable_options()); + auto grpc_status = mGrpcStub->Subscribe(&context, request, &protoStatus); + if (!grpc_status.ok()) { + if (grpc_status.error_code() == ::grpc::StatusCode::UNIMPLEMENTED) { + // This is a legacy sever. It should handle updateSampleRate. + LOG(INFO) << __func__ << ": GRPC Subscribe is not supported by the server"; + return aidlvhal::StatusCode::OK; + } + LOG(ERROR) << __func__ << ": GRPC Subscribe Failed: " << grpc_status.error_message(); + return aidlvhal::StatusCode::INTERNAL_ERROR; + } + return static_cast(protoStatus.status_code()); +} + +aidlvhal::StatusCode GRPCVehicleHardware::unsubscribe(int32_t propId, int32_t areaId) { + proto::UnsubscribeRequest request; + ::grpc::ClientContext context; + proto::VehicleHalCallStatus protoStatus; + request.set_prop_id(propId); + request.set_area_id(areaId); + auto grpc_status = mGrpcStub->Unsubscribe(&context, request, &protoStatus); + if (!grpc_status.ok()) { + if (grpc_status.error_code() == ::grpc::StatusCode::UNIMPLEMENTED) { + // This is a legacy sever. Ignore unsubscribe request. + LOG(INFO) << __func__ << ": GRPC Unsubscribe is not supported by the server"; + return aidlvhal::StatusCode::OK; + } + LOG(ERROR) << __func__ << ": GRPC Unsubscribe Failed: " << grpc_status.error_message(); + return aidlvhal::StatusCode::INTERNAL_ERROR; + } + return static_cast(protoStatus.status_code()); +} + +aidlvhal::StatusCode GRPCVehicleHardware::updateSampleRate(int32_t propId, int32_t areaId, + float sampleRate) { + ::grpc::ClientContext context; + proto::UpdateSampleRateRequest request; + proto::VehicleHalCallStatus protoStatus; + request.set_prop(propId); + request.set_area_id(areaId); + request.set_sample_rate(sampleRate); + auto grpc_status = mGrpcStub->UpdateSampleRate(&context, request, &protoStatus); + if (!grpc_status.ok()) { + LOG(ERROR) << __func__ << ": GRPC UpdateSampleRate Failed: " << grpc_status.error_message(); + return aidlvhal::StatusCode::INTERNAL_ERROR; + } + return static_cast(protoStatus.status_code()); +} + +bool GRPCVehicleHardware::waitForConnected(std::chrono::milliseconds waitTime) { + return mGrpcChannel->WaitForConnected(gpr_time_add( + gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_millis(waitTime.count(), GPR_TIMESPAN))); +} + +void GRPCVehicleHardware::ValuePollingLoop() { + while (!mShuttingDownFlag.load()) { + pollValue(); + // try to reconnect + } +} + +void GRPCVehicleHardware::pollValue() { + ::grpc::ClientContext context; + + bool rpc_stopped{false}; + std::thread shuttingdown_watcher([this, &rpc_stopped, &context]() { + std::unique_lock lck(mShutdownMutex); + mShutdownCV.wait( + lck, [this, &rpc_stopped]() { return rpc_stopped || mShuttingDownFlag.load(); }); + context.TryCancel(); + }); + + auto value_stream = mGrpcStub->StartPropertyValuesStream(&context, ::google::protobuf::Empty()); + LOG(INFO) << __func__ << ": GRPC Value Streaming Started"; + proto::VehiclePropValues protoValues; + while (!mShuttingDownFlag.load() && value_stream->Read(&protoValues)) { + std::vector values; + for (const auto protoValue : protoValues.values()) { + aidlvhal::VehiclePropValue aidlValue = {}; + proto_msg_converter::protoToAidl(protoValue, &aidlValue); + + // VHAL proxy server uses a different timestamp then AAOS timestamp, so we have to + // reset the timestamp. + // TODO(b/350822044): Remove this once we use timestamp from proxy server. + if (!setAndroidTimestamp(&aidlValue)) { + LOG(WARNING) << __func__ << ": property event for propId: " << aidlValue.prop + << " areaId: " << aidlValue.areaId << " is outdated, ignore"; + continue; + } + + values.push_back(std::move(aidlValue)); + } + if (values.empty()) { + continue; + } + std::shared_lock lck(mCallbackMutex); + if (mOnPropChange) { + (*mOnPropChange)(values); + } + } + + { + std::lock_guard lck(mShutdownMutex); + rpc_stopped = true; + } + mShutdownCV.notify_all(); + shuttingdown_watcher.join(); + + auto grpc_status = value_stream->Finish(); + // never reach here until connection lost + LOG(ERROR) << __func__ << ": GRPC Value Streaming Failed: " << grpc_status.error_message(); +} + +} // namespace android::hardware::automotive::vehicle::virtualization diff --git a/automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleHardware.h b/automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleHardware.h new file mode 100644 index 0000000000000000000000000000000000000000..ad2f5121869aa9660983bb75ab3f9917afcbdb0d --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleHardware.h @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2023 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. + */ + +#pragma once + +#include +#include +#include +#include +#include + +#include "VehicleServer.grpc.pb.h" +#include "VehicleServer.pb.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android::hardware::automotive::vehicle::virtualization { + +namespace aidlvhal = ::aidl::android::hardware::automotive::vehicle; + +class GRPCVehicleHardware : public IVehicleHardware { + public: + explicit GRPCVehicleHardware(std::string service_addr); + + ~GRPCVehicleHardware(); + + // Get all the property configs. + std::vector getAllPropertyConfigs() const override; + + // Get the config for the specified propId. + std::optional + getPropertyConfig(int32_t propId) const override; + + // Set property values asynchronously. Server could return before the property set requests + // are sent to vehicle bus or before property set confirmation is received. The callback is + // safe to be called after the function returns and is safe to be called in a different thread. + aidlvhal::StatusCode setValues(std::shared_ptr callback, + const std::vector& requests) override; + + // Get property values asynchronously. Server could return before the property values are ready. + // The callback is safe to be called after the function returns and is safe to be called in a + // different thread. + aidlvhal::StatusCode getValues( + std::shared_ptr callback, + const std::vector& requests) const override; + + // Dump debug information in the server. + DumpResult dump(const std::vector& options) override; + + // Check whether the system is healthy, return {@code StatusCode::OK} for healthy. + aidlvhal::StatusCode checkHealth() override; + + // Register a callback that would be called when there is a property change event from vehicle. + void registerOnPropertyChangeEvent( + std::unique_ptr callback) override; + + // Register a callback that would be called when there is a property set error event from + // vehicle. + void registerOnPropertySetErrorEvent( + std::unique_ptr callback) override; + + // Update the sample rate for the [propId, areaId] pair. + aidlvhal::StatusCode updateSampleRate(int32_t propId, int32_t areaId, + float sampleRate) override; + + aidlvhal::StatusCode subscribe(aidlvhal::SubscribeOptions options) override; + + aidlvhal::StatusCode unsubscribe(int32_t propId, int32_t areaId) override; + + bool waitForConnected(std::chrono::milliseconds waitTime); + + protected: + std::shared_mutex mCallbackMutex; + std::unique_ptr mOnPropChange; + + private: + friend class GRPCVehicleHardwareUnitTest; + + std::string mServiceAddr; + std::shared_ptr<::grpc::Channel> mGrpcChannel; + std::unique_ptr mGrpcStub; + std::thread mValuePollingThread; + + std::unique_ptr mOnSetErr; + + std::mutex mShutdownMutex; + std::condition_variable mShutdownCV; + std::atomic mShuttingDownFlag{false}; + + mutable std::mutex mLatestUpdateTimestampsMutex; + + // A map from [propId, areaId] to the latest timestamp this property is updated. + // The key is a tuple, the first element is the external timestamp (timestamp set by VHAL + // server), the second element is the Android timestamp (elapsedRealtimeNano). + mutable std::unordered_map, PropIdAreaIdHash> + mLatestUpdateTimestamps GUARDED_BY(mLatestUpdateTimestampsMutex); + + // Only used for unit testing. + GRPCVehicleHardware(std::unique_ptr stub, + bool startValuePollingLoop); + + void ValuePollingLoop(); + void pollValue(); + + aidlvhal::StatusCode getValuesWithRetry(const std::vector& requests, + std::vector* results, + size_t retryCount) const; + + // Check the external timestamp of propValue against the latest updated external timestamp, if + // this is an outdated value, return false. Otherwise, update the external timestamp to the + // Android timestamp and return true. + bool setAndroidTimestamp(aidlvhal::VehiclePropValue* propValue) const; +}; + +} // namespace android::hardware::automotive::vehicle::virtualization diff --git a/automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleProxyServer.cpp b/automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleProxyServer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..927a5955e7bab4b5ca2841c5225a453f0f89fa12 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleProxyServer.cpp @@ -0,0 +1,346 @@ +/* + * Copyright (C) 2023 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 "GRPCVehicleProxyServer.h" + +#include "ProtoMessageConverter.h" + +#include + +#include + +#include +#include +#include +#include +#include +#include + +namespace android::hardware::automotive::vehicle::virtualization { + +std::atomic GrpcVehicleProxyServer::ConnectionDescriptor::connection_id_counter_{0}; + +static std::shared_ptr<::grpc::ServerCredentials> getServerCredentials() { + // TODO(chenhaosjtuacm): get secured credentials here + return ::grpc::InsecureServerCredentials(); +} + +GrpcVehicleProxyServer::GrpcVehicleProxyServer(std::string serverAddr, + std::unique_ptr&& hardware) + : GrpcVehicleProxyServer(std::vector({serverAddr}), std::move(hardware)) {}; + +GrpcVehicleProxyServer::GrpcVehicleProxyServer(std::vector serverAddrs, + std::unique_ptr&& hardware) + : mServiceAddrs(std::move(serverAddrs)), mHardware(std::move(hardware)) { + mHardware->registerOnPropertyChangeEvent( + std::make_unique( + [this](std::vector values) { + OnVehiclePropChange(values); + })); +} + +::grpc::Status GrpcVehicleProxyServer::GetAllPropertyConfig( + ::grpc::ServerContext* context, const ::google::protobuf::Empty* request, + ::grpc::ServerWriter* stream) { + for (const auto& config : mHardware->getAllPropertyConfigs()) { + proto::VehiclePropConfig protoConfig; + proto_msg_converter::aidlToProto(config, &protoConfig); + if (!stream->Write(protoConfig)) { + return ::grpc::Status(::grpc::StatusCode::ABORTED, "Connection lost."); + } + } + return ::grpc::Status::OK; +} + +::grpc::Status GrpcVehicleProxyServer::SetValues(::grpc::ServerContext* context, + const proto::VehiclePropValueRequests* requests, + proto::SetValueResults* results) { + std::vector aidlRequests; + std::unordered_set requestIds; + for (const auto& protoRequest : requests->requests()) { + auto& aidlRequest = aidlRequests.emplace_back(); + int64_t requestId = protoRequest.request_id(); + aidlRequest.requestId = requestId; + proto_msg_converter::protoToAidl(protoRequest.value(), &aidlRequest.value); + requestIds.insert(requestId); + } + auto waitMtx = std::make_shared(); + auto waitCV = std::make_shared(); + auto complete = std::make_shared(false); + auto tmpResults = std::make_shared(); + auto aidlStatus = mHardware->setValues( + std::make_shared( + [waitMtx, waitCV, complete, tmpResults, + &requestIds](std::vector setValueResults) { + bool receivedAllResults = false; + { + std::lock_guard lck(*waitMtx); + for (const auto& aidlResult : setValueResults) { + auto& protoResult = *tmpResults->add_results(); + int64_t requestIdForResult = aidlResult.requestId; + protoResult.set_request_id(requestIdForResult); + protoResult.set_status( + static_cast(aidlResult.status)); + requestIds.erase(requestIdForResult); + } + if (requestIds.empty()) { + receivedAllResults = true; + *complete = true; + } + } + if (receivedAllResults) { + waitCV->notify_all(); + } + }), + aidlRequests); + if (aidlStatus != aidlvhal::StatusCode::OK) { + return ::grpc::Status(::grpc::StatusCode::INTERNAL, + "The underlying hardware fails to set values, VHAL status: " + + toString(aidlStatus)); + } + std::unique_lock lck(*waitMtx); + bool success = waitCV->wait_for(lck, kHardwareOpTimeout, [complete] { return *complete; }); + if (!success) { + return ::grpc::Status(::grpc::StatusCode::INTERNAL, + "The underlying hardware set values timeout."); + } + *results = std::move(*tmpResults); + return ::grpc::Status::OK; +} + +::grpc::Status GrpcVehicleProxyServer::GetValues(::grpc::ServerContext* context, + const proto::VehiclePropValueRequests* requests, + proto::GetValueResults* results) { + std::vector aidlRequests; + std::unordered_set requestIds; + for (const auto& protoRequest : requests->requests()) { + auto& aidlRequest = aidlRequests.emplace_back(); + int64_t requestId = protoRequest.request_id(); + aidlRequest.requestId = requestId; + proto_msg_converter::protoToAidl(protoRequest.value(), &aidlRequest.prop); + requestIds.insert(requestId); + } + auto waitMtx = std::make_shared(); + auto waitCV = std::make_shared(); + auto complete = std::make_shared(false); + auto tmpResults = std::make_shared(); + auto aidlStatus = mHardware->getValues( + std::make_shared( + [waitMtx, waitCV, complete, tmpResults, + &requestIds](std::vector getValueResults) { + bool receivedAllResults = false; + { + std::lock_guard lck(*waitMtx); + for (const auto& aidlResult : getValueResults) { + auto& protoResult = *tmpResults->add_results(); + int64_t requestIdForResult = aidlResult.requestId; + protoResult.set_request_id(requestIdForResult); + protoResult.set_status( + static_cast(aidlResult.status)); + if (aidlResult.prop) { + auto* valuePtr = protoResult.mutable_value(); + proto_msg_converter::aidlToProto(*aidlResult.prop, valuePtr); + } + requestIds.erase(requestIdForResult); + } + if (requestIds.empty()) { + receivedAllResults = true; + *complete = true; + } + } + if (receivedAllResults) { + waitCV->notify_all(); + } + }), + aidlRequests); + if (aidlStatus != aidlvhal::StatusCode::OK) { + return ::grpc::Status(::grpc::StatusCode::INTERNAL, + "The underlying hardware fails to get values, VHAL status: " + + toString(aidlStatus)); + } + std::unique_lock lck(*waitMtx); + bool success = waitCV->wait_for(lck, kHardwareOpTimeout, [complete] { return *complete; }); + if (!success) { + return ::grpc::Status(::grpc::StatusCode::INTERNAL, + "The underlying hardware get values timeout."); + } + *results = std::move(*tmpResults); + return ::grpc::Status::OK; +} + +::grpc::Status GrpcVehicleProxyServer::UpdateSampleRate( + ::grpc::ServerContext* context, const proto::UpdateSampleRateRequest* request, + proto::VehicleHalCallStatus* status) { + const auto status_code = mHardware->updateSampleRate(request->prop(), request->area_id(), + request->sample_rate()); + status->set_status_code(static_cast(status_code)); + return ::grpc::Status::OK; +} + +::grpc::Status GrpcVehicleProxyServer::Subscribe(::grpc::ServerContext* context, + const proto::SubscribeRequest* request, + proto::VehicleHalCallStatus* status) { + const auto& protoSubscribeOptions = request->options(); + aidlvhal::SubscribeOptions aidlSubscribeOptions = {}; + proto_msg_converter::protoToAidl(protoSubscribeOptions, &aidlSubscribeOptions); + const auto status_code = mHardware->subscribe(aidlSubscribeOptions); + status->set_status_code(static_cast(status_code)); + return ::grpc::Status::OK; +} + +::grpc::Status GrpcVehicleProxyServer::Unsubscribe(::grpc::ServerContext* context, + const proto::UnsubscribeRequest* request, + proto::VehicleHalCallStatus* status) { + int32_t propId = request->prop_id(); + int32_t areaId = request->area_id(); + const auto status_code = mHardware->unsubscribe(propId, areaId); + status->set_status_code(static_cast(status_code)); + return ::grpc::Status::OK; +} + +::grpc::Status GrpcVehicleProxyServer::CheckHealth(::grpc::ServerContext* context, + const ::google::protobuf::Empty*, + proto::VehicleHalCallStatus* status) { + status->set_status_code(static_cast(mHardware->checkHealth())); + return ::grpc::Status::OK; +} + +::grpc::Status GrpcVehicleProxyServer::Dump(::grpc::ServerContext* context, + const proto::DumpOptions* options, + proto::DumpResult* result) { + std::vector dumpOptionStrings(options->options().begin(), + options->options().end()); + auto dumpResult = mHardware->dump(dumpOptionStrings); + result->set_caller_should_dump_state(dumpResult.callerShouldDumpState); + result->set_buffer(dumpResult.buffer); + result->set_refresh_property_configs(dumpResult.refreshPropertyConfigs); + return ::grpc::Status::OK; +} + +::grpc::Status GrpcVehicleProxyServer::StartPropertyValuesStream( + ::grpc::ServerContext* context, const ::google::protobuf::Empty* request, + ::grpc::ServerWriter* stream) { + auto conn = std::make_shared(stream); + { + std::lock_guard lck(mConnectionMutex); + mValueStreamingConnections.push_back(conn); + } + conn->Wait(); + LOG(ERROR) << __func__ << ": Stream lost, ID : " << conn->ID(); + return ::grpc::Status(::grpc::StatusCode::ABORTED, "Connection lost."); +} + +void GrpcVehicleProxyServer::OnVehiclePropChange( + const std::vector& values) { + std::unordered_set brokenConn; + proto::VehiclePropValues protoValues; + for (const auto& value : values) { + auto* protoValuePtr = protoValues.add_values(); + proto_msg_converter::aidlToProto(value, protoValuePtr); + } + { + std::shared_lock read_lock(mConnectionMutex); + for (auto& connection : mValueStreamingConnections) { + auto writeOK = connection->Write(protoValues); + if (!writeOK) { + LOG(ERROR) << __func__ + << ": Server Write failed, connection lost. ID: " << connection->ID(); + brokenConn.insert(connection->ID()); + } + } + } + if (brokenConn.empty()) { + return; + } + std::unique_lock write_lock(mConnectionMutex); + mValueStreamingConnections.erase( + std::remove_if(mValueStreamingConnections.begin(), mValueStreamingConnections.end(), + [&brokenConn](const auto& conn) { + return brokenConn.find(conn->ID()) != brokenConn.end(); + }), + mValueStreamingConnections.end()); +} + +GrpcVehicleProxyServer& GrpcVehicleProxyServer::Start() { + if (mServer) { + LOG(WARNING) << __func__ << ": GrpcVehicleProxyServer has already started."; + return *this; + } + ::grpc::ServerBuilder builder; + builder.RegisterService(this); + for (const std::string& serviceAddr : mServiceAddrs) { + builder.AddListeningPort(serviceAddr, getServerCredentials()); + } + mServer = builder.BuildAndStart(); + CHECK(mServer) << __func__ << ": failed to create the GRPC server, " + << "please make sure the configuration and permissions are correct"; + return *this; +} + +GrpcVehicleProxyServer& GrpcVehicleProxyServer::Shutdown() { + std::shared_lock read_lock(mConnectionMutex); + for (auto& conn : mValueStreamingConnections) { + conn->Shutdown(); + } + if (mServer) { + mServer->Shutdown(); + } + return *this; +} + +void GrpcVehicleProxyServer::Wait() { + if (mServer) { + mServer->Wait(); + } + mServer.reset(); +} + +GrpcVehicleProxyServer::ConnectionDescriptor::~ConnectionDescriptor() { + Shutdown(); +} + +bool GrpcVehicleProxyServer::ConnectionDescriptor::Write(const proto::VehiclePropValues& values) { + if (!mStream) { + LOG(ERROR) << __func__ << ": Empty stream. ID: " << ID(); + Shutdown(); + return false; + } + { + std::lock_guard lck(*mMtx); + if (!mShutdownFlag && mStream->Write(values)) { + return true; + } else { + LOG(ERROR) << __func__ << ": Server Write failed, connection lost. ID: " << ID(); + } + } + Shutdown(); + return false; +} + +void GrpcVehicleProxyServer::ConnectionDescriptor::Wait() { + std::unique_lock lck(*mMtx); + mCV->wait(lck, [this] { return mShutdownFlag; }); +} + +void GrpcVehicleProxyServer::ConnectionDescriptor::Shutdown() { + { + std::lock_guard lck(*mMtx); + mShutdownFlag = true; + } + mCV->notify_all(); +} + +} // namespace android::hardware::automotive::vehicle::virtualization diff --git a/automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleProxyServer.h b/automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleProxyServer.h new file mode 100644 index 0000000000000000000000000000000000000000..5ffb531c7a23f908bc5c32cbddbf7b50f5c8574a --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleProxyServer.h @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2023 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. + */ + +#pragma once + +#include "IVehicleHardware.h" + +#include "VehicleServer.grpc.pb.h" +#include "VehicleServer.pb.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android::hardware::automotive::vehicle::virtualization { + +namespace aidlvhal = ::aidl::android::hardware::automotive::vehicle; + +// Connect other GRPC vehicle hardware(s) to the underlying vehicle hardware. +class GrpcVehicleProxyServer : public proto::VehicleServer::Service { + public: + GrpcVehicleProxyServer(std::string serverAddr, std::unique_ptr&& hardware); + + GrpcVehicleProxyServer(std::vector serverAddrs, + std::unique_ptr&& hardware); + + ::grpc::Status GetAllPropertyConfig( + ::grpc::ServerContext* context, const ::google::protobuf::Empty* request, + ::grpc::ServerWriter* stream) override; + + ::grpc::Status SetValues(::grpc::ServerContext* context, + const proto::VehiclePropValueRequests* requests, + proto::SetValueResults* results) override; + + ::grpc::Status GetValues(::grpc::ServerContext* context, + const proto::VehiclePropValueRequests* requests, + proto::GetValueResults* results) override; + + ::grpc::Status UpdateSampleRate(::grpc::ServerContext* context, + const proto::UpdateSampleRateRequest* request, + proto::VehicleHalCallStatus* status) override; + + ::grpc::Status Subscribe(::grpc::ServerContext* context, const proto::SubscribeRequest* request, + proto::VehicleHalCallStatus* status) override; + + ::grpc::Status Unsubscribe(::grpc::ServerContext* context, + const proto::UnsubscribeRequest* request, + proto::VehicleHalCallStatus* status) override; + + ::grpc::Status CheckHealth(::grpc::ServerContext* context, const ::google::protobuf::Empty*, + proto::VehicleHalCallStatus* status) override; + + ::grpc::Status Dump(::grpc::ServerContext* context, const proto::DumpOptions* options, + proto::DumpResult* result) override; + + ::grpc::Status StartPropertyValuesStream( + ::grpc::ServerContext* context, const ::google::protobuf::Empty* request, + ::grpc::ServerWriter* stream) override; + + GrpcVehicleProxyServer& Start(); + + GrpcVehicleProxyServer& Shutdown(); + + void Wait(); + + private: + void OnVehiclePropChange(const std::vector& values); + + // We keep long-lasting connection for streaming the prop values. + struct ConnectionDescriptor { + explicit ConnectionDescriptor(::grpc::ServerWriter* stream) + : mStream(stream), + mConnectionID(connection_id_counter_.fetch_add(1) + 1), + mMtx(std::make_unique()), + mCV(std::make_unique()) {} + + ConnectionDescriptor(const ConnectionDescriptor&) = delete; + ConnectionDescriptor(ConnectionDescriptor&& cd) = default; + ConnectionDescriptor& operator=(const ConnectionDescriptor&) = delete; + ConnectionDescriptor& operator=(ConnectionDescriptor&& cd) = default; + + ~ConnectionDescriptor(); + + uint64_t ID() const { return mConnectionID; } + + bool Write(const proto::VehiclePropValues& values); + + void Wait(); + + void Shutdown(); + + private: + ::grpc::ServerWriter* mStream; + uint64_t mConnectionID{0}; + std::unique_ptr mMtx; + std::unique_ptr mCV; + bool mShutdownFlag{false}; + + static std::atomic connection_id_counter_; + }; + + std::vector mServiceAddrs; + std::unique_ptr<::grpc::Server> mServer{nullptr}; + std::unique_ptr mHardware; + + std::shared_mutex mConnectionMutex; + std::vector> mValueStreamingConnections; + + static constexpr auto kHardwareOpTimeout = std::chrono::seconds(1); +}; + +} // namespace android::hardware::automotive::vehicle::virtualization diff --git a/automotive/vehicle/aidl/impl/current/grpc/proto/VehicleServer.proto b/automotive/vehicle/aidl/impl/current/grpc/proto/VehicleServer.proto new file mode 100644 index 0000000000000000000000000000000000000000..732957f9f1fcd61e2642ba5f97af268e3ae7f579 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/grpc/proto/VehicleServer.proto @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2023 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. + */ + +syntax = "proto3"; + +package android.hardware.automotive.vehicle.proto; + +import "android/hardware/automotive/vehicle/DumpOptions.proto"; +import "android/hardware/automotive/vehicle/DumpResult.proto"; +import "android/hardware/automotive/vehicle/SubscribeRequest.proto"; +import "android/hardware/automotive/vehicle/StatusCode.proto"; +import "android/hardware/automotive/vehicle/UnsubscribeRequest.proto"; +import "android/hardware/automotive/vehicle/VehiclePropConfig.proto"; +import "android/hardware/automotive/vehicle/VehiclePropValue.proto"; +import "android/hardware/automotive/vehicle/VehiclePropValueRequest.proto"; +import "google/protobuf/empty.proto"; + +service VehicleServer { + rpc GetAllPropertyConfig(google.protobuf.Empty) returns (stream VehiclePropConfig) {} + + rpc SetValues(VehiclePropValueRequests) returns (SetValueResults) {} + + rpc GetValues(VehiclePropValueRequests) returns (GetValueResults) {} + + rpc UpdateSampleRate(UpdateSampleRateRequest) returns (VehicleHalCallStatus) {} + + rpc CheckHealth(google.protobuf.Empty) returns (VehicleHalCallStatus) {} + + rpc Dump(DumpOptions) returns (DumpResult) {} + + rpc StartPropertyValuesStream(google.protobuf.Empty) returns (stream VehiclePropValues) {} + + rpc Subscribe(SubscribeRequest) returns (VehicleHalCallStatus) {} + + rpc Unsubscribe(UnsubscribeRequest) returns (VehicleHalCallStatus) {} +} diff --git a/automotive/vehicle/aidl/impl/grpc/test/Android.bp b/automotive/vehicle/aidl/impl/current/grpc/test/Android.bp similarity index 100% rename from automotive/vehicle/aidl/impl/grpc/test/Android.bp rename to automotive/vehicle/aidl/impl/current/grpc/test/Android.bp diff --git a/automotive/vehicle/aidl/impl/current/grpc/test/GRPCVehicleHardwareUnitTest.cpp b/automotive/vehicle/aidl/impl/current/grpc/test/GRPCVehicleHardwareUnitTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..20af2311bc0931df5208a76b97620b3986da6c8e --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/grpc/test/GRPCVehicleHardwareUnitTest.cpp @@ -0,0 +1,445 @@ +// Copyright (C) 2023 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 "GRPCVehicleHardware.h" +#include "VehicleServer.grpc.pb.h" +#include "VehicleServer.pb.h" +#include "VehicleServer_mock.grpc.pb.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace android::hardware::automotive::vehicle::virtualization { + +namespace aidlvhal = ::aidl::android::hardware::automotive::vehicle; + +using ::testing::_; +using ::testing::DoAll; +using ::testing::ElementsAre; +using ::testing::NiceMock; +using ::testing::Return; +using ::testing::SaveArg; +using ::testing::SetArgPointee; +using ::testing::SizeIs; + +using ::grpc::testing::MockClientReader; + +using proto::MockVehicleServerStub; + +class GRPCVehicleHardwareUnitTest : public ::testing::Test { + protected: + NiceMock* mGrpcStub; + std::unique_ptr mHardware; + + void SetUp() override { + auto stub = std::make_unique>(); + mGrpcStub = stub.get(); + // Cannot use make_unique here since the constructor is a private method. + mHardware = std::unique_ptr( + new GRPCVehicleHardware(std::move(stub), /*startValuePollingLoop=*/false)); + } + + void TearDown() override { mHardware.reset(); } + + // Access GRPCVehicleHardware private method. + void pollValue() { mHardware->pollValue(); } + + void startValuePollingLoop(std::unique_ptr stub) { + mHardware = std::unique_ptr( + new GRPCVehicleHardware(std::move(stub), /*startValuePollingLoop=*/true)); + } + + void generatePropertyUpdateEvent(int32_t propId, int64_t timestamp); +}; + +MATCHER_P(RepeatedInt32Eq, expected_values, "") { + return std::vector(arg.begin(), arg.end()) == expected_values; +} + +TEST_F(GRPCVehicleHardwareUnitTest, TestSubscribe) { + proto::VehicleHalCallStatus protoStatus; + protoStatus.set_status_code(proto::StatusCode::OK); + proto::SubscribeRequest actualRequest; + + EXPECT_CALL(*mGrpcStub, Subscribe(_, _, _)) + .WillOnce(DoAll(SaveArg<1>(&actualRequest), SetArgPointee<2>(protoStatus), + Return(::grpc::Status::OK))); + + aidlvhal::SubscribeOptions options = {.propId = 1, + .areaIds = {1, 2, 3, 4}, + .sampleRate = 1.234, + .resolution = 0.01, + .enableVariableUpdateRate = true}; + auto status = mHardware->subscribe(options); + + EXPECT_EQ(status, aidlvhal::StatusCode::OK); + const auto& protoOptions = actualRequest.options(); + EXPECT_EQ(protoOptions.prop_id(), 1); + EXPECT_THAT(protoOptions.area_ids(), RepeatedInt32Eq(std::vector({1, 2, 3, 4}))); + EXPECT_FLOAT_EQ(protoOptions.sample_rate(), 1.234); + EXPECT_FLOAT_EQ(protoOptions.resolution(), 0.01); + EXPECT_EQ(protoOptions.enable_variable_update_rate(), true); +} + +TEST_F(GRPCVehicleHardwareUnitTest, TestSubscribeLegacyServer) { + EXPECT_CALL(*mGrpcStub, Subscribe(_, _, _)) + .WillOnce(Return(::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""))); + + aidlvhal::SubscribeOptions options; + auto status = mHardware->subscribe(options); + + EXPECT_EQ(status, aidlvhal::StatusCode::OK); +} + +TEST_F(GRPCVehicleHardwareUnitTest, TestSubscribeGrpcFailure) { + EXPECT_CALL(*mGrpcStub, Subscribe(_, _, _)) + .WillOnce(Return(::grpc::Status(::grpc::StatusCode::INTERNAL, "GRPC Error"))); + + aidlvhal::SubscribeOptions options; + auto status = mHardware->subscribe(options); + + EXPECT_EQ(status, aidlvhal::StatusCode::INTERNAL_ERROR); +} + +TEST_F(GRPCVehicleHardwareUnitTest, TestSubscribeProtoFailure) { + proto::VehicleHalCallStatus protoStatus; + protoStatus.set_status_code(proto::StatusCode::NOT_AVAILABLE_SPEED_LOW); + + EXPECT_CALL(*mGrpcStub, Subscribe(_, _, _)) + .WillOnce(DoAll(SetArgPointee<2>(protoStatus), // Set the output status + Return(::grpc::Status::OK))); + + aidlvhal::SubscribeOptions options; + auto status = mHardware->subscribe(options); + + EXPECT_EQ(status, aidlvhal::StatusCode::NOT_AVAILABLE_SPEED_LOW); +} + +TEST_F(GRPCVehicleHardwareUnitTest, TestUnsubscribe) { + proto::VehicleHalCallStatus protoStatus; + protoStatus.set_status_code(proto::StatusCode::OK); + proto::UnsubscribeRequest actualRequest; + + EXPECT_CALL(*mGrpcStub, Unsubscribe(_, _, _)) + .WillOnce(DoAll(SaveArg<1>(&actualRequest), SetArgPointee<2>(protoStatus), + Return(::grpc::Status::OK))); + + int32_t propId = 1; + int32_t areaId = 2; + auto status = mHardware->unsubscribe(propId, areaId); + + EXPECT_EQ(status, aidlvhal::StatusCode::OK); + EXPECT_EQ(actualRequest.prop_id(), propId); + EXPECT_EQ(actualRequest.area_id(), areaId); +} + +TEST_F(GRPCVehicleHardwareUnitTest, TestUnsubscribeLegacyServer) { + EXPECT_CALL(*mGrpcStub, Unsubscribe(_, _, _)) + .WillOnce(Return(::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""))); + + auto status = mHardware->unsubscribe(1, 2); + + EXPECT_EQ(status, aidlvhal::StatusCode::OK); +} + +TEST_F(GRPCVehicleHardwareUnitTest, TestUnsubscribeGrpcFailure) { + EXPECT_CALL(*mGrpcStub, Unsubscribe(_, _, _)) + .WillOnce(Return(::grpc::Status(::grpc::StatusCode::INTERNAL, "GRPC Error"))); + + auto status = mHardware->unsubscribe(1, 2); + + EXPECT_EQ(status, aidlvhal::StatusCode::INTERNAL_ERROR); +} + +TEST_F(GRPCVehicleHardwareUnitTest, TestUnsubscribeProtoFailure) { + proto::VehicleHalCallStatus protoStatus; + protoStatus.set_status_code(proto::StatusCode::NOT_AVAILABLE_SPEED_LOW); + + EXPECT_CALL(*mGrpcStub, Unsubscribe(_, _, _)) + .WillOnce(DoAll(SetArgPointee<2>(protoStatus), // Set the output status + Return(::grpc::Status::OK))); + + auto status = mHardware->unsubscribe(1, 2); + + EXPECT_EQ(status, aidlvhal::StatusCode::NOT_AVAILABLE_SPEED_LOW); +} + +TEST_F(GRPCVehicleHardwareUnitTest, TestPollValue) { + int64_t testTimestamp = 12345; + int32_t testPropId = 54321; + int64_t startTimestamp = elapsedRealtimeNano(); + + // This will be converted to a unique_ptr in StartPropertyValuesStream. The ownership is passed + // there. + auto clientReader = new MockClientReader(); + EXPECT_CALL(*mGrpcStub, StartPropertyValuesStreamRaw(_, _)).WillOnce(Return(clientReader)); + EXPECT_CALL(*clientReader, Read(_)) + .WillOnce([testTimestamp, testPropId](proto::VehiclePropValues* values) { + values->Clear(); + auto value = values->add_values(); + value->set_timestamp(testTimestamp); + value->set_prop(testPropId); + return true; + }) + .WillOnce(Return(false)); + EXPECT_CALL(*clientReader, Finish()).WillOnce(Return(::grpc::Status::OK)); + + std::vector propertyEvents; + + mHardware->registerOnPropertyChangeEvent( + std::make_unique( + [&propertyEvents](const std::vector& events) { + for (const auto& event : events) { + propertyEvents.push_back(event); + } + })); + + pollValue(); + + ASSERT_THAT(propertyEvents, SizeIs(1)); + EXPECT_EQ(propertyEvents[0].prop, testPropId); + EXPECT_GT(propertyEvents[0].timestamp, startTimestamp) + << "Timestamp must be updated to Android timestamp"; + EXPECT_LT(propertyEvents[0].timestamp, elapsedRealtimeNano()) + << "Timestamp must be updated to Android timestamp"; +} + +TEST_F(GRPCVehicleHardwareUnitTest, TestPollValueIgnoreOutdatedValue) { + int64_t testTimestamp1 = 12345; + int32_t value1 = 1324; + int64_t testTimestamp2 = 12340; + int32_t value2 = 1423; + int32_t testPropId = 54321; + int64_t startTimestamp = elapsedRealtimeNano(); + + // This will be converted to a unique_ptr in StartPropertyValuesStream. The ownership is passed + // there. + auto clientReader = new MockClientReader(); + EXPECT_CALL(*mGrpcStub, StartPropertyValuesStreamRaw(_, _)).WillOnce(Return(clientReader)); + EXPECT_CALL(*clientReader, Read(_)) + .WillOnce([testTimestamp1, value1, testPropId](proto::VehiclePropValues* values) { + values->Clear(); + auto value = values->add_values(); + value->set_timestamp(testTimestamp1); + value->set_prop(testPropId); + value->add_int32_values(value1); + return true; + }) + .WillOnce([testTimestamp2, value2, testPropId](proto::VehiclePropValues* values) { + values->Clear(); + // This event is outdated, must be ignored. + auto value = values->add_values(); + value->set_timestamp(testTimestamp2); + value->set_prop(testPropId); + value->add_int32_values(value2); + return true; + }) + .WillOnce(Return(false)); + EXPECT_CALL(*clientReader, Finish()).WillOnce(Return(::grpc::Status::OK)); + + std::vector propertyEvents; + + mHardware->registerOnPropertyChangeEvent( + std::make_unique( + [&propertyEvents](const std::vector& events) { + for (const auto& event : events) { + propertyEvents.push_back(event); + } + })); + + pollValue(); + + ASSERT_THAT(propertyEvents, SizeIs(1)) << "Outdated event must be ignored"; + EXPECT_EQ(propertyEvents[0].prop, testPropId); + EXPECT_GT(propertyEvents[0].timestamp, startTimestamp); + EXPECT_LT(propertyEvents[0].timestamp, elapsedRealtimeNano()); + EXPECT_THAT(propertyEvents[0].value.int32Values, ElementsAre(value1)); +} + +TEST_F(GRPCVehicleHardwareUnitTest, TestValuePollingLoop) { + int64_t testTimestamp = 12345; + int32_t testPropId = 54321; + auto stub = std::make_unique>(); + + // This will be converted to a unique_ptr in StartPropertyValuesStream. The ownership is passed + // there. + auto clientReader = new MockClientReader(); + EXPECT_CALL(*stub, StartPropertyValuesStreamRaw(_, _)).WillOnce(Return(clientReader)); + EXPECT_CALL(*clientReader, Read(_)) + .WillRepeatedly([testTimestamp, testPropId](proto::VehiclePropValues* values) { + // Sleep for 10ms and always return the same property event. + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + values->Clear(); + auto value = values->add_values(); + value->set_timestamp(testTimestamp); + value->set_prop(testPropId); + return true; + }); + EXPECT_CALL(*clientReader, Finish()).WillOnce(Return(::grpc::Status::OK)); + + startValuePollingLoop(std::move(stub)); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + // This must stop the loop and wait for the thread to finish. + mHardware.reset(); +} + +TEST_F(GRPCVehicleHardwareUnitTest, TestGetValues) { + int64_t testRequestId = 1234; + int32_t testPropId = 4321; + int32_t testValue = 123456; + proto::VehiclePropValueRequests gotRequests; + EXPECT_CALL(*mGrpcStub, GetValues(_, _, _)) + .WillOnce([&gotRequests, testRequestId, testPropId, testValue]( + ::grpc::ClientContext* context, + const proto::VehiclePropValueRequests& request, + proto::GetValueResults* response) { + gotRequests = request; + response->Clear(); + auto* resultPtr = response->add_results(); + resultPtr->set_request_id(testRequestId); + resultPtr->set_status(proto::StatusCode::OK); + auto* valuePtr = resultPtr->mutable_value(); + valuePtr->set_prop(testPropId); + valuePtr->add_int32_values(testValue); + return ::grpc::Status::OK; + }); + + std::vector requests; + requests.push_back(aidlvhal::GetValueRequest{.requestId = testRequestId, + .prop = { + .prop = testPropId, + }}); + + std::vector gotResults; + + auto status = mHardware->getValues( + std::make_shared( + [&gotResults](std::vector results) { + for (const auto& result : results) { + gotResults.push_back(result); + } + }), + requests); + + ASSERT_EQ(status, aidlvhal::StatusCode::OK); + ASSERT_THAT(gotRequests.requests(), SizeIs(1)); + EXPECT_THAT(gotRequests.requests(0).request_id(), testRequestId); + EXPECT_THAT(gotRequests.requests(0).value().prop(), testPropId); + + ASSERT_THAT(gotResults, SizeIs(1)); + EXPECT_EQ(gotResults[0].requestId, testRequestId); + EXPECT_EQ(gotResults[0].status, aidlvhal::StatusCode::OK); + EXPECT_EQ(gotResults[0].prop->prop, testPropId); + EXPECT_THAT(gotResults[0].prop->value.int32Values, ElementsAre(testValue)); +} + +void GRPCVehicleHardwareUnitTest::generatePropertyUpdateEvent(int32_t propId, int64_t timestamp) { + // This will be converted to a unique_ptr in StartPropertyValuesStream. The ownership is passed + // there. + auto clientReader = new MockClientReader(); + EXPECT_CALL(*mGrpcStub, StartPropertyValuesStreamRaw(_, _)).WillOnce(Return(clientReader)); + EXPECT_CALL(*clientReader, Read(_)) + .WillOnce([timestamp, propId](proto::VehiclePropValues* values) { + values->Clear(); + auto value = values->add_values(); + value->set_timestamp(timestamp); + value->set_prop(propId); + return true; + }) + .WillOnce(Return(false)); + EXPECT_CALL(*clientReader, Finish()).WillOnce(Return(::grpc::Status::OK)); + + pollValue(); +} + +TEST_F(GRPCVehicleHardwareUnitTest, TestGetValuesOutdatedRetry) { + int64_t startTimestamp = elapsedRealtimeNano(); + int64_t testRequestId = 1234; + int32_t testPropId = 4321; + int32_t testValue1 = 123456; + int32_t testValue2 = 654321; + int32_t testTimestamp1 = 1000; + int32_t testTimestamp2 = 2000; + + // A property update event for testTimestamp2 happens before getValues returns. + generatePropertyUpdateEvent(testPropId, testTimestamp2); + + // GetValues first returns an outdated result, then an up-to-date result. + EXPECT_CALL(*mGrpcStub, GetValues(_, _, _)) + .WillOnce([testRequestId, testPropId, testValue1, testTimestamp1]( + ::grpc::ClientContext* context, + const proto::VehiclePropValueRequests& request, + proto::GetValueResults* response) { + response->Clear(); + auto* resultPtr = response->add_results(); + resultPtr->set_request_id(testRequestId); + resultPtr->set_status(proto::StatusCode::OK); + auto* valuePtr = resultPtr->mutable_value(); + valuePtr->set_prop(testPropId); + valuePtr->set_timestamp(testTimestamp1); + valuePtr->add_int32_values(testValue1); + return ::grpc::Status::OK; + }) + .WillOnce([testRequestId, testPropId, testValue2, testTimestamp2]( + ::grpc::ClientContext* context, + const proto::VehiclePropValueRequests& request, + proto::GetValueResults* response) { + response->Clear(); + auto* resultPtr = response->add_results(); + resultPtr->set_request_id(testRequestId); + resultPtr->set_status(proto::StatusCode::OK); + auto* valuePtr = resultPtr->mutable_value(); + valuePtr->set_prop(testPropId); + valuePtr->set_timestamp(testTimestamp2); + valuePtr->add_int32_values(testValue2); + return ::grpc::Status::OK; + }); + + std::vector requests; + requests.push_back(aidlvhal::GetValueRequest{.requestId = testRequestId, + .prop = { + .prop = testPropId, + }}); + + std::vector gotResults; + + auto status = mHardware->getValues( + std::make_shared( + [&gotResults](std::vector results) { + for (const auto& result : results) { + gotResults.push_back(result); + } + }), + requests); + + ASSERT_EQ(status, aidlvhal::StatusCode::OK); + ASSERT_THAT(gotResults, SizeIs(1)); + EXPECT_EQ(gotResults[0].requestId, testRequestId); + EXPECT_EQ(gotResults[0].status, aidlvhal::StatusCode::OK); + EXPECT_EQ(gotResults[0].prop->prop, testPropId); + EXPECT_THAT(gotResults[0].prop->value.int32Values, ElementsAre(testValue2)); + EXPECT_GT(gotResults[0].prop->timestamp, startTimestamp); + EXPECT_LT(gotResults[0].prop->timestamp, elapsedRealtimeNano()); +} + +} // namespace android::hardware::automotive::vehicle::virtualization diff --git a/automotive/vehicle/aidl/impl/current/grpc/test/GRPCVehicleProxyServerUnitTest.cpp b/automotive/vehicle/aidl/impl/current/grpc/test/GRPCVehicleProxyServerUnitTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ca5c2d5a2e176ff9863bd24eb985212ad04f0cca --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/grpc/test/GRPCVehicleProxyServerUnitTest.cpp @@ -0,0 +1,241 @@ +// Copyright (C) 2023 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 "GRPCVehicleHardware.h" +#include "GRPCVehicleProxyServer.h" +#include "IVehicleHardware.h" +#include "VehicleServer.grpc.pb.h" +#include "VehicleServer.pb.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace android::hardware::automotive::vehicle::virtualization { + +namespace aidlvhal = ::aidl::android::hardware::automotive::vehicle; + +using ::testing::_; +using ::testing::DoAll; +using ::testing::Return; +using ::testing::SaveArg; + +const std::string kFakeServerAddr = "0.0.0.0:54321"; + +class VehicleHardwareForTest : public IVehicleHardware { + public: + void registerOnPropertyChangeEvent( + std::unique_ptr callback) override { + mOnProp = std::move(callback); + } + + void onPropertyEvent(std::vector values) { + if (mOnProp) { + (*mOnProp)(std::move(values)); + } + } + + // Functions that we do not care. + std::vector getAllPropertyConfigs() const override { return {}; } + + aidlvhal::StatusCode setValues( + std::shared_ptr callback, + const std::vector& requests) override { + return aidlvhal::StatusCode::OK; + } + + aidlvhal::StatusCode getValues( + std::shared_ptr callback, + const std::vector& requests) const override { + return aidlvhal::StatusCode::OK; + } + + DumpResult dump(const std::vector& options) override { return {}; } + + aidlvhal::StatusCode checkHealth() override { return aidlvhal::StatusCode::OK; } + + void registerOnPropertySetErrorEvent( + std::unique_ptr callback) override {} + + private: + std::unique_ptr mOnProp; +}; + +class MockVehicleHardware : public IVehicleHardware { + public: + // Mock methods from IVehicleHardware + MOCK_METHOD(std::vector, getAllPropertyConfigs, (), + (const, override)); + + MOCK_METHOD((aidlvhal::StatusCode), setValues, + (std::shared_ptr callback, + const std::vector& requests), + (override)); + + MOCK_METHOD((aidlvhal::StatusCode), getValues, + (std::shared_ptr callback, + const std::vector& requests), + (const, override)); + + MOCK_METHOD(DumpResult, dump, (const std::vector& options), (override)); + MOCK_METHOD(aidlvhal::StatusCode, checkHealth, (), (override)); + MOCK_METHOD(void, registerOnPropertyChangeEvent, + (std::unique_ptr callback), (override)); + MOCK_METHOD(void, registerOnPropertySetErrorEvent, + (std::unique_ptr callback), (override)); + MOCK_METHOD(std::chrono::nanoseconds, getPropertyOnChangeEventBatchingWindow, (), (override)); + MOCK_METHOD(aidlvhal::StatusCode, subscribe, (aidlvhal::SubscribeOptions options), (override)); + MOCK_METHOD(aidlvhal::StatusCode, unsubscribe, (int32_t propId, int32_t areaId), (override)); + MOCK_METHOD(aidlvhal::StatusCode, updateSampleRate, + (int32_t propId, int32_t areaId, float sampleRate), (override)); +}; + +TEST(GRPCVehicleProxyServerUnitTest, ClientConnectDisconnect) { + auto testHardware = std::make_unique(); + // HACK: manipulate the underlying hardware via raw pointer for testing. + auto* testHardwareRaw = testHardware.get(); + auto vehicleServer = + std::make_unique(kFakeServerAddr, std::move(testHardware)); + vehicleServer->Start(); + + constexpr auto kWaitForConnectionMaxTime = std::chrono::seconds(5); + constexpr auto kWaitForStreamStartTime = std::chrono::seconds(1); + constexpr auto kWaitForUpdateDeliveryTime = std::chrono::milliseconds(100); + + auto updateReceived1 = std::make_shared(false); + auto vehicleHardware1 = std::make_unique(kFakeServerAddr); + vehicleHardware1->registerOnPropertyChangeEvent( + std::make_unique( + [updateReceived1](const auto&) { *updateReceived1 = true; })); + EXPECT_TRUE(vehicleHardware1->waitForConnected(kWaitForConnectionMaxTime)); + std::this_thread::sleep_for(kWaitForStreamStartTime); + + // Client hardware 1 received update from the server. + EXPECT_FALSE(*updateReceived1); + testHardwareRaw->onPropertyEvent({}); + // Wait for the update delivery. + std::this_thread::sleep_for(kWaitForUpdateDeliveryTime); + EXPECT_TRUE(*updateReceived1); + + // Reset. + *updateReceived1 = false; + + auto updateReceived2 = std::make_shared(false); + auto vehicleHardware2 = std::make_unique(kFakeServerAddr); + vehicleHardware2->registerOnPropertyChangeEvent( + std::make_unique( + [updateReceived2](const auto&) { *updateReceived2 = true; })); + EXPECT_TRUE(vehicleHardware2->waitForConnected(kWaitForConnectionMaxTime)); + std::this_thread::sleep_for(kWaitForStreamStartTime); + + // Both client hardware 1 and 2 received update from the server. + EXPECT_FALSE(*updateReceived1); + EXPECT_FALSE(*updateReceived2); + testHardwareRaw->onPropertyEvent({}); + // Wait for the update delivery. + std::this_thread::sleep_for(kWaitForUpdateDeliveryTime); + EXPECT_TRUE(*updateReceived1); + EXPECT_TRUE(*updateReceived2); + + // Reset. + *updateReceived1 = false; + *updateReceived2 = false; + + vehicleHardware1.reset(); + + // Client 1 exited, only client hardware 2 received update from the server. + EXPECT_FALSE(*updateReceived1); + EXPECT_FALSE(*updateReceived2); + testHardwareRaw->onPropertyEvent({}); + // Wait for the update delivery. + std::this_thread::sleep_for(kWaitForUpdateDeliveryTime); + EXPECT_FALSE(*updateReceived1); + EXPECT_TRUE(*updateReceived2); + + vehicleServer->Shutdown().Wait(); +} + +TEST(GRPCVehicleProxyServerUnitTest, Subscribe) { + auto mockHardware = std::make_unique(); + // We make sure this is alive inside the function scope. + MockVehicleHardware* mockHardwarePtr = mockHardware.get(); + GrpcVehicleProxyServer server = GrpcVehicleProxyServer("", std::move(mockHardware)); + ::grpc::ServerContext context; + proto::SubscribeRequest request; + proto::VehicleHalCallStatus returnStatus; + aidlvhal::SubscribeOptions aidlOptions; + request.mutable_options()->set_prop_id(1); + request.mutable_options()->add_area_ids(2); + request.mutable_options()->set_sample_rate(1.234); + request.mutable_options()->set_resolution(0.01); + request.mutable_options()->set_enable_variable_update_rate(true); + + EXPECT_CALL(*mockHardwarePtr, subscribe(_)) + .WillOnce(DoAll(SaveArg<0>(&aidlOptions), Return(aidlvhal::StatusCode::OK))); + + auto grpcStatus = server.Subscribe(&context, &request, &returnStatus); + + EXPECT_TRUE(grpcStatus.ok()); + EXPECT_EQ(returnStatus.status_code(), proto::StatusCode::OK); + EXPECT_EQ(aidlOptions.propId, 1); + EXPECT_EQ(aidlOptions.areaIds, std::vector{2}); + EXPECT_FLOAT_EQ(aidlOptions.sampleRate, 1.234); + EXPECT_FLOAT_EQ(aidlOptions.resolution, 0.01); + EXPECT_TRUE(aidlOptions.enableVariableUpdateRate); +} + +TEST(GRPCVehicleProxyServerUnitTest, SubscribeNotAvailable) { + auto mockHardware = std::make_unique(); + // We make sure this is alive inside the function scope. + MockVehicleHardware* mockHardwarePtr = mockHardware.get(); + GrpcVehicleProxyServer server = GrpcVehicleProxyServer("", std::move(mockHardware)); + ::grpc::ServerContext context; + proto::SubscribeRequest request; + proto::VehicleHalCallStatus returnStatus; + + EXPECT_CALL(*mockHardwarePtr, subscribe(_)) + .WillOnce(Return(aidlvhal::StatusCode::NOT_AVAILABLE)); + + auto grpcStatus = server.Subscribe(&context, &request, &returnStatus); + + EXPECT_TRUE(grpcStatus.ok()); + EXPECT_EQ(returnStatus.status_code(), proto::StatusCode::NOT_AVAILABLE); +} + +TEST(GRPCVehicleProxyServerUnitTest, Unsubscribe) { + auto mockHardware = std::make_unique(); + // We make sure this is alive inside the function scope. + MockVehicleHardware* mockHardwarePtr = mockHardware.get(); + GrpcVehicleProxyServer server = GrpcVehicleProxyServer("", std::move(mockHardware)); + ::grpc::ServerContext context; + proto::UnsubscribeRequest request; + proto::VehicleHalCallStatus returnStatus; + request.set_prop_id(1); + request.set_area_id(2); + + EXPECT_CALL(*mockHardwarePtr, unsubscribe(1, 2)).WillOnce(Return(aidlvhal::StatusCode::OK)); + + auto grpcStatus = server.Unsubscribe(&context, &request, &returnStatus); + + EXPECT_TRUE(grpcStatus.ok()); + EXPECT_EQ(returnStatus.status_code(), proto::StatusCode::OK); +} + +} // namespace android::hardware::automotive::vehicle::virtualization diff --git a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/Android.bp b/automotive/vehicle/aidl/impl/current/grpc/utils/proto_message_converter/Android.bp similarity index 100% rename from automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/Android.bp rename to automotive/vehicle/aidl/impl/current/grpc/utils/proto_message_converter/Android.bp diff --git a/automotive/vehicle/aidl/impl/current/grpc/utils/proto_message_converter/include/ProtoMessageConverter.h b/automotive/vehicle/aidl/impl/current/grpc/utils/proto_message_converter/include/ProtoMessageConverter.h new file mode 100644 index 0000000000000000000000000000000000000000..25c07ef2caee47a87b5aebebc0a0c5817ceccf47 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/grpc/utils/proto_message_converter/include/ProtoMessageConverter.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_aidl_impl_grpc_utils_proto_message_converter_include_ProtoMessageConverter_H_ +#define android_hardware_automotive_vehicle_aidl_impl_grpc_utils_proto_message_converter_include_ProtoMessageConverter_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace proto_msg_converter { + +// Convert AIDL VehiclePropConfig to Protobuf VehiclePropConfig. +void aidlToProto( + const ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig& inAidlConfig, + ::android::hardware::automotive::vehicle::proto::VehiclePropConfig* outProtoConfig); +// Convert Protobuf VehiclePropConfig to AIDL VehiclePropConfig. +void protoToAidl( + const ::android::hardware::automotive::vehicle::proto::VehiclePropConfig& inProtoConfig, + ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig* outAidlConfig); +// Convert AIDL VehiclePropValue to Protobuf VehiclePropValue. +void aidlToProto(const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& inAidlVal, + ::android::hardware::automotive::vehicle::proto::VehiclePropValue* outProtoVal); +// Convert Protobuf VehiclePropValue to AIDL VehiclePropValue. +void protoToAidl( + const ::android::hardware::automotive::vehicle::proto::VehiclePropValue& inProtoVal, + ::aidl::android::hardware::automotive::vehicle::VehiclePropValue* outAidlVal); +// Convert AIDL SubscribeOptions to Protobuf SubscribeOptions. +void aidlToProto(const ::aidl::android::hardware::automotive::vehicle::SubscribeOptions& in, + ::android::hardware::automotive::vehicle::proto::SubscribeOptions* out); +// Convert Protobuf SubscribeOptions to AIDL SubscribeOptions. +void protoToAidl(const ::android::hardware::automotive::vehicle::proto::SubscribeOptions& in, + ::aidl::android::hardware::automotive::vehicle::SubscribeOptions* out); + +} // namespace proto_msg_converter +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_aidl_impl_grpc_utils_proto_message_converter_include_ProtoMessageConverter_H_ diff --git a/automotive/vehicle/aidl/impl/current/grpc/utils/proto_message_converter/src/ProtoMessageConverter.cpp b/automotive/vehicle/aidl/impl/current/grpc/utils/proto_message_converter/src/ProtoMessageConverter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c40004a09608ad1e2b81b09bff32af02d8c8b2b6 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/grpc/utils/proto_message_converter/src/ProtoMessageConverter.cpp @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "ProtoMsgConverter" + +#include "ProtoMessageConverter.h" + +#include + +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace proto_msg_converter { + +namespace aidl_vehicle = ::aidl::android::hardware::automotive::vehicle; +namespace proto = ::android::hardware::automotive::vehicle::proto; + +// Copy the vector PROTO_VECNAME of protobuf class PROTO_VALUE to +// VHAL_TYPE_VALUE->VHAL_TYPE_VECNAME, every element of PROTO_VECNAME is casted by CAST. +#define CAST_COPY_PROTOBUF_VEC_TO_VHAL_TYPE(PROTO_VALUE, PROTO_VECNAME, VHAL_TYPE_VALUE, \ + VHAL_TYPE_VECNAME, CAST) \ + do { \ + (VHAL_TYPE_VALUE)->VHAL_TYPE_VECNAME.resize(PROTO_VALUE.PROTO_VECNAME##_size()); \ + size_t idx = 0; \ + for (auto& value : PROTO_VALUE.PROTO_VECNAME()) { \ + VHAL_TYPE_VALUE->VHAL_TYPE_VECNAME[idx++] = CAST(value); \ + } \ + } while (0) + +// Copying the vector PROTO_VECNAME of protobuf class PROTO_VALUE to +// VHAL_TYPE_VALUE->VHAL_TYPE_VECNAME. +#define COPY_PROTOBUF_VEC_TO_VHAL_TYPE(PROTO_VALUE, PROTO_VECNAME, VHAL_TYPE_VALUE, \ + VHAL_TYPE_VECNAME) \ + CAST_COPY_PROTOBUF_VEC_TO_VHAL_TYPE( \ + PROTO_VALUE, PROTO_VECNAME, VHAL_TYPE_VALUE, VHAL_TYPE_VECNAME, /*NO CAST*/) + +void aidlToProto(const aidl_vehicle::VehiclePropConfig& in, proto::VehiclePropConfig* out) { + out->set_prop(in.prop); + out->set_access(static_cast(toInt(in.access))); + out->set_change_mode(static_cast(toInt(in.changeMode))); + out->set_config_string(in.configString.c_str(), in.configString.size()); + out->set_min_sample_rate(in.minSampleRate); + out->set_max_sample_rate(in.maxSampleRate); + + for (auto& configElement : in.configArray) { + out->add_config_array(configElement); + } + + out->clear_area_configs(); + for (auto& areaConfig : in.areaConfigs) { + auto* protoACfg = out->add_area_configs(); + protoACfg->set_area_id(areaConfig.areaId); + protoACfg->set_access(static_cast(toInt(areaConfig.access))); + protoACfg->set_min_int64_value(areaConfig.minInt64Value); + protoACfg->set_max_int64_value(areaConfig.maxInt64Value); + protoACfg->set_min_float_value(areaConfig.minFloatValue); + protoACfg->set_max_float_value(areaConfig.maxFloatValue); + protoACfg->set_min_int32_value(areaConfig.minInt32Value); + protoACfg->set_max_int32_value(areaConfig.maxInt32Value); + if (areaConfig.supportedEnumValues.has_value()) { + for (auto& supportedEnumValue : areaConfig.supportedEnumValues.value()) { + protoACfg->add_supported_enum_values(supportedEnumValue); + } + } + protoACfg->set_support_variable_update_rate(areaConfig.supportVariableUpdateRate); + } +} + +void protoToAidl(const proto::VehiclePropConfig& in, aidl_vehicle::VehiclePropConfig* out) { + out->prop = in.prop(); + out->access = static_cast(in.access()); + out->changeMode = static_cast(in.change_mode()); + out->configString = in.config_string(); + out->minSampleRate = in.min_sample_rate(); + out->maxSampleRate = in.max_sample_rate(); + + COPY_PROTOBUF_VEC_TO_VHAL_TYPE(in, config_array, out, configArray); + + auto cast_to_acfg = [](const proto::VehicleAreaConfig& protoAcfg) { + auto vehicleAreaConfig = aidl_vehicle::VehicleAreaConfig{ + .areaId = protoAcfg.area_id(), + .access = static_cast(protoAcfg.access()), + .minInt32Value = protoAcfg.min_int32_value(), + .maxInt32Value = protoAcfg.max_int32_value(), + .minInt64Value = protoAcfg.min_int64_value(), + .maxInt64Value = protoAcfg.max_int64_value(), + .minFloatValue = protoAcfg.min_float_value(), + .maxFloatValue = protoAcfg.max_float_value(), + .supportVariableUpdateRate = protoAcfg.support_variable_update_rate(), + }; + if (protoAcfg.supported_enum_values().size() != 0) { + vehicleAreaConfig.supportedEnumValues = std::vector(); + COPY_PROTOBUF_VEC_TO_VHAL_TYPE(protoAcfg, supported_enum_values, (&vehicleAreaConfig), + supportedEnumValues.value()); + } + + return vehicleAreaConfig; + }; + CAST_COPY_PROTOBUF_VEC_TO_VHAL_TYPE(in, area_configs, out, areaConfigs, cast_to_acfg); +} + +void aidlToProto(const aidl_vehicle::VehiclePropValue& in, proto::VehiclePropValue* out) { + out->set_prop(in.prop); + out->set_timestamp(in.timestamp); + out->set_status(static_cast(in.status)); + out->set_area_id(in.areaId); + out->set_string_value(in.value.stringValue); + out->set_byte_values(in.value.byteValues.data(), in.value.byteValues.size()); + + for (auto& int32Value : in.value.int32Values) { + out->add_int32_values(int32Value); + } + + for (auto& int64Value : in.value.int64Values) { + out->add_int64_values(int64Value); + } + + for (auto& floatValue : in.value.floatValues) { + out->add_float_values(floatValue); + } +} + +void protoToAidl(const proto::VehiclePropValue& in, aidl_vehicle::VehiclePropValue* out) { + out->prop = in.prop(); + out->timestamp = in.timestamp(); + out->status = static_cast(in.status()); + out->areaId = in.area_id(); + out->value.stringValue = in.string_value(); + for (const char& byte : in.byte_values()) { + out->value.byteValues.push_back(byte); + } + + COPY_PROTOBUF_VEC_TO_VHAL_TYPE(in, int32_values, out, value.int32Values); + COPY_PROTOBUF_VEC_TO_VHAL_TYPE(in, int64_values, out, value.int64Values); + COPY_PROTOBUF_VEC_TO_VHAL_TYPE(in, float_values, out, value.floatValues); +} + +void aidlToProto(const aidl_vehicle::SubscribeOptions& in, proto::SubscribeOptions* out) { + out->set_prop_id(in.propId); + for (int areaId : in.areaIds) { + out->add_area_ids(areaId); + } + out->set_sample_rate(in.sampleRate); + out->set_resolution(in.resolution); + out->set_enable_variable_update_rate(in.enableVariableUpdateRate); +} + +void protoToAidl(const proto::SubscribeOptions& in, aidl_vehicle::SubscribeOptions* out) { + out->propId = in.prop_id(); + COPY_PROTOBUF_VEC_TO_VHAL_TYPE(in, area_ids, out, areaIds); + out->sampleRate = in.sample_rate(); + out->resolution = in.resolution(); + out->enableVariableUpdateRate = in.enable_variable_update_rate(); +} + +#undef COPY_PROTOBUF_VEC_TO_VHAL_TYPE +#undef CAST_COPY_PROTOBUF_VEC_TO_VHAL_TYPE + +} // namespace proto_msg_converter +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/current/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp b/automotive/vehicle/aidl/impl/current/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2efda5b69af83f4fcfb34d3d2fb6e727d688684f --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace proto_msg_converter { + +namespace { + +namespace proto = ::android::hardware::automotive::vehicle::proto; +namespace aidl_vehicle = ::aidl::android::hardware::automotive::vehicle; + +constexpr char DEFAULT_PROPERTIES_CONFIG[] = "DefaultProperties.json"; + +inline std::string getConfigPath(const std::string& name) { + return android::base::GetExecutableDirectory() + "/" + name; +} + +std::vector prepareTestConfigs() { + JsonConfigLoader loader; + auto result = loader.loadPropConfig(getConfigPath(DEFAULT_PROPERTIES_CONFIG)); + if (!result.ok()) { + return {}; + } + std::vector configs; + for (auto& [_, configDeclaration] : result.value()) { + configs.push_back(configDeclaration.config); + } + return configs; +} + +std::vector prepareTestValues() { + JsonConfigLoader loader; + auto result = loader.loadPropConfig(getConfigPath(DEFAULT_PROPERTIES_CONFIG)); + if (!result.ok()) { + return {}; + } + std::vector values; + int64_t timestamp = 1; + for (auto& [_, configDeclaration] : result.value()) { + values.push_back({ + .timestamp = timestamp, + .areaId = 123, + .prop = configDeclaration.config.prop, + .value = configDeclaration.initialValue, + .status = aidl_vehicle::VehiclePropertyStatus::ERROR, + }); + } + return values; +} + +class PropConfigConversionTest : public testing::TestWithParam {}; + +class PropValueConversionTest : public testing::TestWithParam {}; + +} // namespace + +TEST_P(PropConfigConversionTest, testConversion) { + proto::VehiclePropConfig protoCfg; + aidl_vehicle::VehiclePropConfig aidlCfg; + + aidlToProto(GetParam(), &protoCfg); + protoToAidl(protoCfg, &aidlCfg); + + EXPECT_EQ(aidlCfg, GetParam()); +} + +TEST_P(PropValueConversionTest, testConversion) { + proto::VehiclePropValue protoVal; + aidl_vehicle::VehiclePropValue aidlVal; + + aidlToProto(GetParam(), &protoVal); + protoToAidl(protoVal, &aidlVal); + + EXPECT_EQ(aidlVal, GetParam()); +} + +INSTANTIATE_TEST_SUITE_P(DefaultConfigs, PropConfigConversionTest, + ::testing::ValuesIn(prepareTestConfigs()), + [](const ::testing::TestParamInfo& info) { + return ::fmt::format("property_{:d}", info.param.prop); + }); + +INSTANTIATE_TEST_SUITE_P(TestValues, PropValueConversionTest, + ::testing::ValuesIn(prepareTestValues()), + [](const ::testing::TestParamInfo& info) { + return ::fmt::format("property_{:d}", info.param.prop); + }); + +TEST_F(PropValueConversionTest, testConvertSubscribeOption) { + proto::SubscribeOptions protoOptions; + aidl_vehicle::SubscribeOptions aidlOptions = {.propId = 1, + .areaIds = {1, 2}, + .sampleRate = 1.234, + .resolution = 0.01, + .enableVariableUpdateRate = true}; + aidl_vehicle::SubscribeOptions outputOptions; + + aidlToProto(aidlOptions, &protoOptions); + protoToAidl(protoOptions, &outputOptions); + + EXPECT_EQ(aidlOptions, outputOptions); +} + +} // namespace proto_msg_converter +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/hardware/Android.bp b/automotive/vehicle/aidl/impl/current/hardware/Android.bp similarity index 100% rename from automotive/vehicle/aidl/impl/hardware/Android.bp rename to automotive/vehicle/aidl/impl/current/hardware/Android.bp diff --git a/automotive/vehicle/aidl/impl/current/hardware/include/IVehicleHardware.h b/automotive/vehicle/aidl/impl/current/hardware/include/IVehicleHardware.h new file mode 100644 index 0000000000000000000000000000000000000000..06846553da76aa4a273f15e72f152f70653cce39 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/hardware/include/IVehicleHardware.h @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_aidl_impl_hardware_include_IVehicleHardware_H_ +#define android_hardware_automotive_vehicle_aidl_impl_hardware_include_IVehicleHardware_H_ + +#include + +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +// A structure used to return dumped information. +struct DumpResult { + // If callerShouldDumpState is true, caller would print the information in buffer and + // continue to dump its state, otherwise would just dump the buffer and skip its own + // dumping logic. + bool callerShouldDumpState; + // The dumped information for the caller to print. + std::string buffer; + // To pass if DefaultVehicleHal should refresh the property configs + bool refreshPropertyConfigs = false; +}; + +// A structure to represent a set value error event reported from vehicle. +struct SetValueErrorEvent { + aidl::android::hardware::automotive::vehicle::StatusCode errorCode; + int32_t propId; + int32_t areaId; +}; + +namespace aidlvhal = ::aidl::android::hardware::automotive::vehicle; + +// An abstract interface to access vehicle hardware. +// For virtualized VHAL, GrpcVehicleHardware would communicate with a VehicleHardware +// implementation in another VM through GRPC. For non-virtualzied VHAL, VHAL directly communicates +// with a VehicleHardware through this interface. +class IVehicleHardware { + public: + using SetValuesCallback = std::function)>; + using GetValuesCallback = std::function)>; + using PropertyChangeCallback = std::function)>; + using PropertySetErrorCallback = std::function)>; + + virtual ~IVehicleHardware() = default; + + // Get all the property configs. + virtual std::vector getAllPropertyConfigs() const = 0; + + // Get the property configs for the specified propId. This is used for early-boot + // native VHAL clients to access certain property configs when not all property configs are + // available. For example, a config discovery process might be required to determine the + // property config for HVAC. However, for early boot properties, e.g. VHAL_HEARTBEAT, it + // could return before the config discovery process. + // + // Currently Android system may try to access the following properties during early boot: + // STORAGE_ENCRYPTION_BINDING_SEED, WATCHDOG_ALIVE, WATCHDOG_TERMINATE_PROCESS, VHAL_HEARTBEAT, + // CURRENT_POWER_POLICY, POWER_POLICY_REQ, POWER_POLICY_GROUP_REQ. They should return + // quickly otherwise the whole bootup process might be blocked. + virtual std::optional getPropertyConfig(int32_t propId) const { + // The default implementation is to use getAllPropertyConfigs(). This should be + // overridden if getAllPropertyConfigs() takes a while to return for initial boot or + // relies on ethernet or other communication channel that is not available during early + // boot. + for (const auto& config : getAllPropertyConfigs()) { + if (config.prop == propId) { + return config; + } + } + return std::nullopt; + } + + // Set property values asynchronously. Server could return before the property set requests + // are sent to vehicle bus or before property set confirmation is received. The callback is + // safe to be called after the function returns and is safe to be called in a different thread. + virtual aidlvhal::StatusCode setValues( + std::shared_ptr callback, + const std::vector& requests) = 0; + + // Get property values asynchronously. Server could return before the property values are ready. + // The callback is safe to be called after the function returns and is safe to be called in a + // different thread. + virtual aidl::android::hardware::automotive::vehicle::StatusCode getValues( + std::shared_ptr callback, + const std::vector& + requests) const = 0; + + // Dump debug information in the server. + virtual DumpResult dump(const std::vector& options) = 0; + + // Check whether the system is healthy, return {@code StatusCode::OK} for healthy. + virtual aidlvhal::StatusCode checkHealth() = 0; + + // Register a callback that would be called when there is a property change event from vehicle. + // This function must only be called once during initialization. + virtual void registerOnPropertyChangeEvent( + std::unique_ptr callback) = 0; + + // Register a callback that would be called when there is a property set error event from + // vehicle. Must only be called once during initialization. + virtual void registerOnPropertySetErrorEvent( + std::unique_ptr callback) = 0; + + // Gets the batching window used by DefaultVehicleHal for property change events. + // + // In DefaultVehicleHal, all the property change events generated within the batching window + // will be delivered through one callback to the VHAL client. This affects the maximum supported + // subscription rate. For example, if this returns 10ms, then only one callback for property + // change events will be called per 10ms, meaining that the max subscription rate for all + // continuous properties would be 100hz. + // + // A higher batching window means less callbacks to the VHAL client, causing a better + // performance. However, it also means a longer average latency for every property change + // events. + // + // 0 means no batching should be enabled in DefaultVehicleHal. In this case, batching can + // be optionally implemented in IVehicleHardware layer. + virtual std::chrono::nanoseconds getPropertyOnChangeEventBatchingWindow() { + // By default batching is disabled. + return std::chrono::nanoseconds(0); + } + + // A [propId, areaId] is newly subscribed or the subscribe options are changed. + // + // The subscribe options contain sample rate in Hz or enable/disable variable update rate. + // + // For continuous properties: + // + // The sample rate is never 0 and indicates the desired polling rate for this property. The + // sample rate is guaranteed to be within supported {@code minSampleRate} and + // {@code maxSampleRate} as specified in {@code VehiclePropConfig}. + // + // If the specified sample rate is not supported, e.g. vehicle bus only supports 5hz and 10hz + // polling rate but the sample rate is 8hz, impl must choose the higher polling rate (10hz). + // + // Whether variable update rate is enabled is specified by {@code enableVariableUpdateRate} in + // {@code SubscribeOptions}. If variable update rate is not supported for the + // [propId, areaId], impl must ignore this option and always treat it as disabled. + // + // If variable update rate is disabled/not supported, impl must report all the property events + // for this [propId, areaId] through {@code propertyChangeCallback} according to the sample + // rate. E.g. a sample rate of 10hz must generate at least 10 property change events per second. + // + // If variable update rate is enabled AND supported, impl must only report property events + // when the [propId, areaId]'s value or status changes (a.k.a same as on-change property). + // The sample rate still guides the polling rate, but duplicate property events must be dropped + // and not reported via {@code propertyChangeCallback}. + // + // Async property set error events are not affected by variable update rate and must always + // be reported. + // + // If the impl is always polling at {@code maxSampleRate} for all continuous [propId, areaId]s, + // and do not support variable update rate for any [propId, areaId], then this function can be a + // no-op. + // + // For on-change properties: + // + // The sample rate is always 0 and must be ignored. If the impl is always subscribing to all + // on-change properties, then this function can be no-op. + // + // For all properties: + // + // It is recommended to only deliver the subscribed property events to DefaultVehicleHal to + // improve performance. However, even if unsubscribed property events are delivered, they + // will be filtered out by DefaultVehicleHal. + // + // A subscription from VHAL client might not necessarily trigger this function. + // DefaultVehicleHal will aggregate all the subscriptions from all the clients and notify + // IVehicleHardware if new subscriptions are required or subscribe options are updated. + // + // For example: + // 1. VHAL initially have no subscriber for speed. + // 2. A new subscriber is subscribing speed for 10 times/s, 'subscribe' is called + // with sampleRate as 10. The impl is now polling vehicle speed from bus 10 times/s. + // 3. A new subscriber is subscribing speed for 5 times/s, because it is less than 10 + // times/sec, 'subscribe' is not called. + // 4. The initial subscriber is removed, 'subscribe' is called with sampleRate as + // 5, because now it only needs to report event 5times/sec. The impl can now poll vehicle + // speed 5 times/s. If the impl is still polling at 10 times/s, that is okay as long as + // the polling rate is larger than 5times/s. DefaultVehicleHal would ignore the additional + // events. + // 5. The second subscriber is removed, 'unsubscribe' is called. + // The impl can optionally disable the polling for vehicle speed. + // + virtual aidlvhal::StatusCode subscribe([[maybe_unused]] aidlvhal::SubscribeOptions options) { + return aidlvhal::StatusCode::OK; + } + + // A [propId, areaId] is unsubscribed. This applies for both continuous or on-change property. + virtual aidlvhal::StatusCode unsubscribe([[maybe_unused]] int32_t propId, + [[maybe_unused]] int32_t areaId) { + return aidlvhal::StatusCode::OK; + } + + // This function is deprecated, subscribe/unsubscribe should be used instead. + // + // Update the sampling rate for the specified property and the specified areaId (0 for global + // property) if server supports it. The property must be a continuous property. + // {@code sampleRate} means that for this specific property, the server must generate at least + // this many OnPropertyChange events per seconds. + // A sampleRate of 0 means the property is no longer subscribed and server does not need to + // generate any onPropertyEvent for this property. + // This would be called if sample rate is updated for a subscriber, a new subscriber is added + // or an existing subscriber is removed. For example: + // 1. We have no subscriber for speed. + // 2. A new subscriber is subscribing speed for 10 times/s, updateSampleRate would be called + // with sampleRate as 10. The impl is now polling vehicle speed from bus 10 times/s. + // 3. A new subscriber is subscribing speed for 5 times/s, because it is less than 10 + // times/sec, updateSampleRate would not be called. + // 4. The initial subscriber is removed, updateSampleRate would be called with sampleRate as + // 5, because now it only needs to report event 5times/sec. The impl can now poll vehicle + // speed 5 times/s. If the impl is still polling at 10 times/s, that is okay as long as + // the polling rate is larger than 5times/s. DefaultVehicleHal would ignore the additional + // events. + // 5. The second subscriber is removed, updateSampleRate would be called with sampleRate as 0. + // The impl can optionally disable the polling for vehicle speed. + // + // If the impl is always polling at {@code maxSampleRate} as specified in config, then this + // function can be a no-op. + virtual aidlvhal::StatusCode updateSampleRate([[maybe_unused]] int32_t propId, + [[maybe_unused]] int32_t areaId, + [[maybe_unused]] float sampleRate) { + return aidlvhal::StatusCode::OK; + } +}; + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_aidl_impl_hardware_include_IVehicleHardware_H_ diff --git a/automotive/vehicle/aidl/impl/proto/Android.bp b/automotive/vehicle/aidl/impl/current/proto/Android.bp similarity index 92% rename from automotive/vehicle/aidl/impl/proto/Android.bp rename to automotive/vehicle/aidl/impl/current/proto/Android.bp index 0d3df49d46ca002dde57dcc0192cc9e66ec4fa31..2b5cdf40ce7d2d5b9ff2faac5183ede7a4269a42 100644 --- a/automotive/vehicle/aidl/impl/proto/Android.bp +++ b/automotive/vehicle/aidl/impl/current/proto/Android.bp @@ -35,7 +35,7 @@ genrule { "aprotoc", "protoc-gen-grpc-cpp-plugin", ], - cmd: "$(location aprotoc) -Ihardware/interfaces/automotive/vehicle/aidl/impl/proto -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(in) --grpc_out=$(genDir) --cpp_out=$(genDir)", + cmd: "$(location aprotoc) -Ihardware/interfaces/automotive/vehicle/aidl/impl/current/proto -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(in) --grpc_out=$(genDir) --cpp_out=$(genDir)", srcs: [ ":VehicleHalProtoFiles", ], @@ -62,7 +62,7 @@ genrule { "aprotoc", "protoc-gen-grpc-cpp-plugin", ], - cmd: "$(location aprotoc) -Ihardware/interfaces/automotive/vehicle/aidl/impl/proto -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(in) --grpc_out=$(genDir) --cpp_out=$(genDir)", + cmd: "$(location aprotoc) -Ihardware/interfaces/automotive/vehicle/aidl/impl/current/proto -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(in) --grpc_out=$(genDir) --cpp_out=$(genDir)", srcs: [ ":VehicleHalProtoFiles", ], @@ -123,4 +123,5 @@ rust_protobuf { proto_flags: [ "-I external/protobuf/src", ], + min_sdk_version: "35", } diff --git a/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/DumpOptions.proto b/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/DumpOptions.proto new file mode 100644 index 0000000000000000000000000000000000000000..4bed927288eb2f49c3bca30befc54cc8bb2a82a5 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/DumpOptions.proto @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2023 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. + */ + +syntax = "proto3"; + +package android.hardware.automotive.vehicle.proto; + +message DumpOptions { + repeated string options = 1; +} diff --git a/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/DumpResult.proto b/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/DumpResult.proto new file mode 100644 index 0000000000000000000000000000000000000000..fbfb505f5188315b12e23a49082a16e64ca6a325 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/DumpResult.proto @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2021 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. + */ + +syntax = "proto3"; + +package android.hardware.automotive.vehicle.proto; + +message DumpResult { + /* If callerShouldDumpState is true, caller would print the information in buffer and + * continue to dump its state, otherwise would just dump the buffer and skip its own + * dumping logic. */ + bool caller_should_dump_state = 1; + /* The dumped information for the caller to print. */ + string buffer = 2; + /* To pass if DefaultVehicleHal should refresh the property configs. */ + bool refresh_property_configs = 3; +} diff --git a/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/StatusCode.proto b/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/StatusCode.proto new file mode 100644 index 0000000000000000000000000000000000000000..95e766a2ea03ed4d08aebc159a01a395c13657f0 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/StatusCode.proto @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2021 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. + */ + +syntax = "proto3"; + +package android.hardware.automotive.vehicle.proto; + +/* Must be in sync with StatusCode.aidl. */ +enum StatusCode { + OK = 0; + + /* Try again. */ + TRY_AGAIN = 1; + + /* Invalid argument provided. */ + INVALID_ARG = 2; + + /* This code must be returned when device that associated with the vehicle + * property is not available. For example, when client tries to set HVAC + * temperature when the whole HVAC unit is turned OFF. */ + NOT_AVAILABLE = 3; + + /* Access denied */ + ACCESS_DENIED = 4; + + /* Something unexpected has happened in Vehicle HAL */ + INTERNAL_ERROR = 5; + + /** + * For features that are not available because the underlying feature is + * disabled. + */ + NOT_AVAILABLE_DISABLED = 6; + + /** + * For features that are not available because the vehicle speed is too low. + */ + NOT_AVAILABLE_SPEED_LOW = 7; + + /** + * For features that are not available because the vehicle speed is too + * high. + */ + NOT_AVAILABLE_SPEED_HIGH = 8; + + /** + * For features that are not available because of bad camera or sensor + * visibility. Examples might be bird poop blocking the camera or a bumper + * cover blocking an ultrasonic sensor. + */ + NOT_AVAILABLE_POOR_VISIBILITY = 9; + + /** + * The feature cannot be accessed due to safety reasons. Eg. System could be + * in a faulty state, an object or person could be blocking the requested + * operation such as closing a trunk door, etc. + */ + NOT_AVAILABLE_SAFETY = 10; +}; + +message VehicleHalCallStatus { + StatusCode status_code = 1; +} diff --git a/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/SubscribeOptions.proto b/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/SubscribeOptions.proto new file mode 100644 index 0000000000000000000000000000000000000000..3fc6581fcb674d78e19caf60aa08935b4890ecbf --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/SubscribeOptions.proto @@ -0,0 +1,27 @@ +/* + * 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. + */ + +syntax = "proto3"; + +package android.hardware.automotive.vehicle.proto; + +message SubscribeOptions { + int32 prop_id = 1; + repeated int32 area_ids = 2; + float sample_rate = 3; + float resolution = 4; + bool enable_variable_update_rate = 5; +} \ No newline at end of file diff --git a/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/SubscribeRequest.proto b/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/SubscribeRequest.proto new file mode 100644 index 0000000000000000000000000000000000000000..4ce63359e754e9b599fa333c7e317431bf6b2d17 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/SubscribeRequest.proto @@ -0,0 +1,25 @@ +/* + * 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. + */ + +syntax = "proto3"; + +package android.hardware.automotive.vehicle.proto; + +import "android/hardware/automotive/vehicle/SubscribeOptions.proto"; + +message SubscribeRequest { + SubscribeOptions options = 1; +} \ No newline at end of file diff --git a/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/UnsubscribeRequest.proto b/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/UnsubscribeRequest.proto new file mode 100644 index 0000000000000000000000000000000000000000..314fbf0f65deff728cde3e04abc50a1d34b71a5d --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/UnsubscribeRequest.proto @@ -0,0 +1,24 @@ +/* + * 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. + */ + +syntax = "proto3"; + +package android.hardware.automotive.vehicle.proto; + +message UnsubscribeRequest { + int32 prop_id = 1; + int32 area_id = 2; +} \ No newline at end of file diff --git a/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/VehicleAreaConfig.proto b/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/VehicleAreaConfig.proto new file mode 100644 index 0000000000000000000000000000000000000000..7ea8540cc3a71c10ca8be87b05feaba6b328ccb5 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/VehicleAreaConfig.proto @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2021 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. + */ + +syntax = "proto3"; + +package android.hardware.automotive.vehicle.proto; + +import "android/hardware/automotive/vehicle/VehiclePropertyAccess.proto"; + +/* Must be in sync with VehicleAreaConfig.aidl. */ +message VehicleAreaConfig { + /* Area id is ignored for VehiclePropertyGroup:GLOBAL properties. */ + int32 area_id = 1; + + /* If the property has @data_enum, leave the range to zero. + * + * Range will be ignored in the following cases: + * - The VehiclePropertyType is not INT32, INT64 or FLOAT. + * - Both of min value and max value are zero. */ + int32 min_int32_value = 2; + int32 max_int32_value = 3; + + int64 min_int64_value = 4; + int64 max_int64_value = 5; + + float min_float_value = 6; + float max_float_value = 7; + + /** + * If the property has a @data_enum, then it is possible to specify a supported subset of the + * @data_enum. If the property has a @data_enum and supported_enum_values is null, then it is + * assumed all @data_enum values are supported unless specified through another mechanism. + */ + repeated int64 supported_enum_values = 8; + VehiclePropertyAccess access = 9; + bool support_variable_update_rate = 10; +}; diff --git a/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/VehiclePropConfig.proto b/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/VehiclePropConfig.proto new file mode 100644 index 0000000000000000000000000000000000000000..e230d15d064136229b19edc22376e609706c02c7 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/VehiclePropConfig.proto @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2021 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. + */ + +syntax = "proto3"; + +package android.hardware.automotive.vehicle.proto; + +import "android/hardware/automotive/vehicle/VehicleAreaConfig.proto"; +import "android/hardware/automotive/vehicle/VehiclePropertyAccess.proto"; +import "android/hardware/automotive/vehicle/VehiclePropertyChangeMode.proto"; + +/* Must be in sync with VehiclePropConfig.aidl. */ +message VehiclePropConfig { + /* Property identifier */ + int32 prop = 1; + + /* Defines if the property is read or write or both. */ + VehiclePropertyAccess access = 2; + + /* Defines the change mode of the property. */ + VehiclePropertyChangeMode change_mode = 3; + + /* Contains per-area configuration. */ + repeated VehicleAreaConfig area_configs = 4; + + /* Contains additional configuration parameters */ + repeated int32 config_array = 5; + + /* Some properties may require additional information passed over this + * string. Most properties do not need to set this. */ + bytes config_string = 6; + + /* Min sample rate in Hz. + * Must be defined for VehiclePropertyChangeMode::CONTINUOUS */ + float min_sample_rate = 7; + + /* Must be defined for VehiclePropertyChangeMode::CONTINUOUS + * Max sample rate in Hz. */ + float max_sample_rate = 8; +}; diff --git a/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/VehiclePropValue.proto b/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/VehiclePropValue.proto new file mode 100644 index 0000000000000000000000000000000000000000..dda9ff51195f56fa34aeaa69eaf00c36f2b71993 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/VehiclePropValue.proto @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2021 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. + */ + +syntax = "proto3"; + +package android.hardware.automotive.vehicle.proto; + +import "android/hardware/automotive/vehicle/VehiclePropertyStatus.proto"; + +/* Must be in sync with VehiclePropValue.aidl. */ +message VehiclePropValue { + /* Time is elapsed nanoseconds since boot */ + int64 timestamp = 1; + + /* Area type(s) for non-global property it must be one of the value from + * VehicleArea* enums or 0 for global properties. */ + int32 area_id = 2; + + /* Property identifier */ + int32 prop = 3; + + /* Status of the property */ + VehiclePropertyStatus status = 4; + + /* This is used for properties of types VehiclePropertyType#INT + * and VehiclePropertyType#INT_VEC */ + repeated int32 int32_values = 5; + + /* This is used for properties of types VehiclePropertyType#FLOAT + * and VehiclePropertyType#FLOAT_VEC */ + repeated float float_values = 6; + + /* This is used for properties of type VehiclePropertyType#INT64 */ + repeated int64 int64_values = 7; + + /* This is used for properties of type VehiclePropertyType#BYTES */ + bytes byte_values = 8; + + /* This is used for properties of type VehiclePropertyType#STRING */ + string string_value = 9; +}; + +message VehiclePropValues { + repeated VehiclePropValue values = 1; +} diff --git a/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/VehiclePropValueRequest.proto b/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/VehiclePropValueRequest.proto new file mode 100644 index 0000000000000000000000000000000000000000..c347a800c30293163a2c9f3576727169e246b15d --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/VehiclePropValueRequest.proto @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2021 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. + */ + +syntax = "proto3"; + +package android.hardware.automotive.vehicle.proto; + +import "android/hardware/automotive/vehicle/StatusCode.proto"; +import "android/hardware/automotive/vehicle/VehiclePropValue.proto"; + +message VehiclePropValueRequest { + int64 request_id = 1; + VehiclePropValue value = 2; +}; + +message UpdateSampleRateRequest { + /* Property identifier */ + int32 prop = 1; + + /* Area type(s) for non-global property it must be one of the value from + * VehicleArea* enums or 0 for global properties. */ + int32 area_id = 2; + + float sample_rate = 3; +}; + +message SetValueResult { + int64 request_id = 1; + StatusCode status = 2; +}; + +message GetValueResult { + int64 request_id = 1; + StatusCode status = 2; + VehiclePropValue value = 3; +}; + +message VehiclePropValueRequests { + repeated VehiclePropValueRequest requests = 1; +}; + +message SetValueResults { + repeated SetValueResult results = 1; +}; + +message GetValueResults { + repeated GetValueResult results = 1; +}; diff --git a/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/VehiclePropertyAccess.proto b/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/VehiclePropertyAccess.proto new file mode 100644 index 0000000000000000000000000000000000000000..55840f07d4ae47043b371df26c97280c063f0791 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/VehiclePropertyAccess.proto @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2021 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. + */ + +syntax = "proto3"; + +package android.hardware.automotive.vehicle.proto; + +/* Must be in sync with VehiclePropertyAccess.aidl. */ +enum VehiclePropertyAccess { + NONE = 0; + READ = 1; + WRITE = 2; + READ_WRITE = 3; +}; diff --git a/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/VehiclePropertyChangeMode.proto b/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/VehiclePropertyChangeMode.proto new file mode 100644 index 0000000000000000000000000000000000000000..c681e3b4c3cc07c94676f9e36f40e3eae4be9139 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/VehiclePropertyChangeMode.proto @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2021 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. + */ + +syntax = "proto3"; + +package android.hardware.automotive.vehicle.proto; + +/* Must be in sync with VehiclePropertyChangeMode.aidl. */ +enum VehiclePropertyChangeMode { + /* Property of this type must never be changed. Subscription is not supported + * for these properties. */ + STATIC = 0; + + /* Properties of this type must report when there is a change. + * IVehicle#get call must return the current value. + * Set operation for this property is assumed to be asynchronous. When the + * property is read (using IVehicle#get) after IVehicle#set, it may still + * return old value until underlying H/W backing this property has actually + * changed the state. Once state is changed, the property must dispatch + * changed value as event. */ + ON_CHANGE = 1; + + /* Properties of this type change continuously and require a fixed rate of + * sampling to retrieve the data. Implementers may choose to send extra + * notifications on significant value changes. */ + CONTINUOUS = 2; +}; diff --git a/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/VehiclePropertyStatus.proto b/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/VehiclePropertyStatus.proto new file mode 100644 index 0000000000000000000000000000000000000000..a44c8f03e685d11bf63080b40f4cff5741e845c9 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/VehiclePropertyStatus.proto @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2021 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. + */ + +syntax = "proto3"; + +package android.hardware.automotive.vehicle.proto; + +/* Must be in sync with VehiclePropertyStatus.aidl. */ +enum VehiclePropertyStatus { + /* Property is available and behaving normally */ + AVAILABLE = 0; + /* A property in this state is not available for reading and writing. This + * is a transient state that depends on the availability of the underlying + * implementation (e.g. hardware or driver). It MUST NOT be used to + * represent features that this vehicle is always incapable of. A get() of + * a property in this state MAY return an undefined value, but MUST + * correctly describe its status as UNAVAILABLE A set() of a property in + * this state MAY return NOT_AVAILABLE. The HAL implementation MUST ignore + * the value of the status field when writing a property value coming from + * Android. */ + UNAVAILABLE = 1; + /* There is an error with this property. */ + ERROR = 2; +}; diff --git a/automotive/vehicle/aidl/impl/current/utils/README.md b/automotive/vehicle/aidl/impl/current/utils/README.md new file mode 100644 index 0000000000000000000000000000000000000000..255131ddc16e3888506f5d2e8058aae6f14fabcb --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/utils/README.md @@ -0,0 +1,62 @@ +# Utility classes for VHAL implementation +--- + +This directory stores utility classes for VHAL implementation. Vendor +implementation could use utility classes from `common` folder in their +VHAL implementation. + +## common + +Defines common utility libraries. + +### ConcurrentQueue + +Provides a thread-safe concurrent queue object. Useful for adding object to +a queue in one thread (usually binder thread) and handle the objects in a +separate handler thread. + +### ParcelableUtils + +Provides functions to convert between a regular parcelable and a +`LargeParcelabe`. + +A `LargeParcelable` is a parcelable that marshals the payload +into a shared memory file if the payload is too large to pass across binder. +It is used to pass large data across binder. Before sending the data, VHAL +impl should convert a regular parcelabe to a `LargeParcelable`. After receving +data, VHAL impl should convert a `LargeParcelable` back to regular parcelabe. + +### PendingRequestPool + +Defines A class for managing pending requests and automatically call timeout +callback if the request timed-out. + +### PropertyUtils + +Defines some useful constants. + +### RecurrentTimer + +Defines a thread-safe recurrent timer that can call a function periodically. + +### VehicleHalTypes + +Provides a header file that includes many commonly used header files. Useful +when you are using multiple types defined in VHAL interface. + +### VehicleObjectPool + +Defines a reusable in-memory pool for `VehiclePropValue`. + +### VehiclePropertyStore + +Defines an in-memory map for storing vehicle properties. Allows easier insert, +delete and lookup. + +### VehicleUtils + +Defines many useful utility functions. + +## test_vendor_properties + +Contains vendor properties used for testing purpose in reference VHAL. diff --git a/automotive/vehicle/aidl/impl/utils/common/Android.bp b/automotive/vehicle/aidl/impl/current/utils/common/Android.bp similarity index 100% rename from automotive/vehicle/aidl/impl/utils/common/Android.bp rename to automotive/vehicle/aidl/impl/current/utils/common/Android.bp diff --git a/automotive/vehicle/aidl/impl/current/utils/common/include/ConcurrentQueue.h b/automotive/vehicle/aidl/impl/current/utils/common/include/ConcurrentQueue.h new file mode 100644 index 0000000000000000000000000000000000000000..b636aa344c3048e0db81a550973de8a531dd8d95 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/utils/common/include/ConcurrentQueue.h @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_aidl_impl_utils_common_include_ConcurrentQueue_H_ +#define android_hardware_automotive_vehicle_aidl_impl_utils_common_include_ConcurrentQueue_H_ + +#include + +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +template +class ConcurrentQueue { + public: + bool waitForItems() { + std::unique_lock lockGuard(mLock); + android::base::ScopedLockAssertion lockAssertion(mLock); + while (mQueue.empty() && mIsActive) { + mCond.wait(lockGuard); + } + return mIsActive; + } + + std::vector flush() { + std::vector items; + + std::scoped_lock lockGuard(mLock); + if (mQueue.empty()) { + return items; + } + while (!mQueue.empty()) { + // Even if the queue is deactivated, we should still flush all the remaining values + // in the queue. + items.push_back(std::move(mQueue.front())); + mQueue.pop(); + } + return items; + } + + void push(T&& item) { + { + std::scoped_lock lockGuard(mLock); + if (!mIsActive) { + return; + } + mQueue.push(std::move(item)); + } + mCond.notify_one(); + } + + void push(std::vector&& items) { + { + std::scoped_lock lockGuard(mLock); + if (!mIsActive) { + return; + } + for (T& item : items) { + mQueue.push(std::move(item)); + } + } + mCond.notify_one(); + } + + // Deactivates the queue, thus no one can push items to it, also notifies all waiting thread. + // The items already in the queue could still be flushed even after the queue is deactivated. + void deactivate() { + { + std::scoped_lock lockGuard(mLock); + mIsActive = false; + } + // To unblock all waiting consumers. + mCond.notify_all(); + } + + ConcurrentQueue() = default; + + ConcurrentQueue(const ConcurrentQueue&) = delete; + ConcurrentQueue& operator=(const ConcurrentQueue&) = delete; + + private: + mutable std::mutex mLock; + bool mIsActive GUARDED_BY(mLock) = true; + std::condition_variable mCond; + std::queue mQueue GUARDED_BY(mLock); +}; + +template +class BatchingConsumer { + private: + enum class State { + INIT = 0, + RUNNING = 1, + STOP_REQUESTED = 2, + STOPPED = 3, + }; + + public: + BatchingConsumer() : mState(State::INIT) {} + + BatchingConsumer(const BatchingConsumer&) = delete; + BatchingConsumer& operator=(const BatchingConsumer&) = delete; + + using OnBatchReceivedFunc = std::function vec)>; + + void run(ConcurrentQueue* queue, std::chrono::nanoseconds batchInterval, + const OnBatchReceivedFunc& func) { + mQueue = queue; + mBatchInterval = batchInterval; + + mWorkerThread = std::thread(&BatchingConsumer::runInternal, this, func); + } + + void requestStop() { mState = State::STOP_REQUESTED; } + + void waitStopped() { + if (mWorkerThread.joinable()) { + mWorkerThread.join(); + } + } + + private: + void runInternal(const OnBatchReceivedFunc& onBatchReceived) { + if (mState.exchange(State::RUNNING) == State::INIT) { + while (State::RUNNING == mState) { + mQueue->waitForItems(); + if (State::STOP_REQUESTED == mState) break; + + std::this_thread::sleep_for(mBatchInterval); + if (State::STOP_REQUESTED == mState) break; + + std::vector items = mQueue->flush(); + + if (items.size() > 0) { + onBatchReceived(std::move(items)); + } + } + } + + mState = State::STOPPED; + } + + private: + std::thread mWorkerThread; + + std::atomic mState; + std::chrono::nanoseconds mBatchInterval; + ConcurrentQueue* mQueue; +}; + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_aidl_impl_utils_common_include_ConcurrentQueue_H_ diff --git a/automotive/vehicle/aidl/impl/current/utils/common/include/ParcelableUtils.h b/automotive/vehicle/aidl/impl/current/utils/common/include/ParcelableUtils.h new file mode 100644 index 0000000000000000000000000000000000000000..ab7b895f2078497e08ecefeac5a43086a564f9ee --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/utils/common/include/ParcelableUtils.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_aidl_impl_vhal_include_ParcelableUtils_H_ +#define android_hardware_automotive_vehicle_aidl_impl_vhal_include_ParcelableUtils_H_ + +#include +#include +#include + +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +// Turns the values into a stable large parcelable that could be sent via binder. +// If values is small enough, it would be put into output.payloads, otherwise a shared memory file +// would be created and output.sharedMemoryFd would be filled in. +template +ndk::ScopedAStatus vectorToStableLargeParcelable(std::vector&& values, T2* output) { + output->payloads = std::move(values); + auto result = android::automotive::car_binder_lib::LargeParcelableBase:: + parcelableToStableLargeParcelable(*output); + if (!result.ok()) { + return toScopedAStatus( + result, aidl::android::hardware::automotive::vehicle::StatusCode::INTERNAL_ERROR); + } + auto& fd = result.value(); + if (fd != nullptr) { + // Move the returned ScopedFileDescriptor pointer to ScopedFileDescriptor value in + // 'sharedMemoryFd' field. + output->payloads.clear(); + output->sharedMemoryFd = std::move(*fd); + } else { + output->sharedMemoryFd = ndk::ScopedFileDescriptor(); + // Do not modify payloads. + } + return ndk::ScopedAStatus::ok(); +} + +template +ndk::ScopedAStatus vectorToStableLargeParcelable(const std::vector& values, T2* output) { + // Because 'values' is passed in as const reference, we have to do a copy here. + std::vector valuesCopy = values; + + return vectorToStableLargeParcelable(std::move(valuesCopy), output); +} + +template +android::base::expected< + android::automotive::car_binder_lib::LargeParcelableBase::BorrowedOwnedObject, + ndk::ScopedAStatus> +fromStableLargeParcelable(const T& largeParcelable) { + auto result = android::automotive::car_binder_lib::LargeParcelableBase:: + stableLargeParcelableToParcelable(largeParcelable); + + if (!result.ok()) { + return android::base::unexpected(toScopedAStatus( + result, aidl::android::hardware::automotive::vehicle::StatusCode::INVALID_ARG, + "failed to parse large parcelable")); + } + + return std::move(result.value()); +} + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_aidl_impl_vhal_include_ParcelableUtils_H_ diff --git a/automotive/vehicle/aidl/impl/current/utils/common/include/PendingRequestPool.h b/automotive/vehicle/aidl/impl/current/utils/common/include/PendingRequestPool.h new file mode 100644 index 0000000000000000000000000000000000000000..28cf08e93b617f761ad4176fe08aef158f8f45ed --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/utils/common/include/PendingRequestPool.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_aidl_impl_vhal_include_PendingRequestPool_H_ +#define android_hardware_automotive_vehicle_aidl_impl_vhal_include_PendingRequestPool_H_ + +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +// A thread-safe pending request pool that tracks whether each request has timed-out. +class PendingRequestPool final { + public: + using TimeoutCallbackFunc = std::function&)>; + + explicit PendingRequestPool(int64_t timeoutInNano); + + ~PendingRequestPool(); + + // Adds a list of requests to the request pool. + // The clientId is the key for all the requests. It could be a number or an address to a data + // structure that represents a client. The caller must maintain this data structure. + // All the request IDs must be unique for one client, if any of the requestIds is duplicate with + // any pending request IDs for the client, this function returns error and no requests would be + // added. Otherwise, they would be added to the request pool. + // The callback would be called if requests are not finished within {@code mTimeoutInNano} + // seconds. + VhalResult addRequests(const void* clientId, + const std::unordered_set& requestIds, + std::shared_ptr callback); + + // Checks whether the request is currently pending. + bool isRequestPending(const void* clientId, int64_t requestId) const; + + // Tries to mark the requests as finished and remove them from the pool if the request is + // currently pending. Returns the list of request that is pending and has been finished + // successfully. This function would try to finish any valid requestIds even though some of the + // requestIds are not valid. + std::unordered_set tryFinishRequests(const void* clientId, + const std::unordered_set& requestIds); + + // Returns how many pending requests in the pool, for testing purpose. + size_t countPendingRequests(const void* clientId) const; + + size_t countPendingRequests() const; + + private: + // The maximum number of pending requests allowed per client. If exceeds this number, adding + // more requests would fail. This is to prevent spamming from client. + static constexpr size_t MAX_PENDING_REQUEST_PER_CLIENT = 10000; + + struct PendingRequest { + std::unordered_set requestIds; + int64_t timeoutTimestamp; + std::shared_ptr callback; + }; + + int64_t mTimeoutInNano; + mutable std::mutex mLock; + std::unordered_map> mPendingRequestsByClient + GUARDED_BY(mLock); + std::thread mThread; + bool mThreadStop = false; + std::condition_variable mCv; + std::mutex mCvLock; + + bool isRequestPendingLocked(const void* clientId, int64_t requestId) const REQUIRES(mLock); + + // Checks whether the requests in the pool has timed-out, run periodically in a separate thread. + void checkTimeout(); +}; + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_aidl_impl_vhal_include_PendingRequestPool_H_ diff --git a/automotive/vehicle/aidl/impl/current/utils/common/include/PropertyUtils.h b/automotive/vehicle/aidl/impl/current/utils/common/include/PropertyUtils.h new file mode 100644 index 0000000000000000000000000000000000000000..f2327e194261efc9de4a7b2a68c37e999223079c --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/utils/common/include/PropertyUtils.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_aidl_impl_utils_common_include_PropertyUtils_H_ +#define android_hardware_automotive_vehicle_aidl_impl_utils_common_include_PropertyUtils_H_ + +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +namespace propertyutils_impl { + +// These names are not part of the API since we only expose ints. +using ::aidl::android::hardware::automotive::vehicle::EvStoppingMode; +using ::aidl::android::hardware::automotive::vehicle::PortLocationType; +using ::aidl::android::hardware::automotive::vehicle::VehicleArea; +using ::aidl::android::hardware::automotive::vehicle::VehicleAreaDoor; +using ::aidl::android::hardware::automotive::vehicle::VehicleAreaSeat; +using ::aidl::android::hardware::automotive::vehicle::VehicleAreaWheel; +using ::aidl::android::hardware::automotive::vehicle::VehicleAreaWindow; +using ::aidl::android::hardware::automotive::vehicle::VehicleHvacFanDirection; +using ::aidl::android::hardware::automotive::vehicle::VehicleLightState; +using ::aidl::android::hardware::automotive::vehicle::VehicleLightSwitch; +using ::aidl::android::hardware::automotive::vehicle::VehicleProperty; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType; + +} // namespace propertyutils_impl + +// Some handy constants to avoid conversions from enum to int. +constexpr int ABS_ACTIVE = toInt(propertyutils_impl::VehicleProperty::ABS_ACTIVE); +constexpr int AP_POWER_STATE_REQ = toInt(propertyutils_impl::VehicleProperty::AP_POWER_STATE_REQ); +constexpr int AP_POWER_STATE_REPORT = + toInt(propertyutils_impl::VehicleProperty::AP_POWER_STATE_REPORT); +constexpr int DOOR_1_LEFT = toInt(propertyutils_impl::VehicleAreaDoor::ROW_1_LEFT); +constexpr int DOOR_1_RIGHT = toInt(propertyutils_impl::VehicleAreaDoor::ROW_1_RIGHT); +constexpr int DOOR_2_LEFT = toInt(propertyutils_impl::VehicleAreaDoor::ROW_2_LEFT); +constexpr int DOOR_2_RIGHT = toInt(propertyutils_impl::VehicleAreaDoor::ROW_2_RIGHT); +constexpr int DOOR_REAR = toInt(propertyutils_impl::VehicleAreaDoor::REAR); +constexpr int WINDOW_1_LEFT = toInt(propertyutils_impl::VehicleAreaWindow::ROW_1_LEFT); +constexpr int WINDOW_1_RIGHT = toInt(propertyutils_impl::VehicleAreaWindow::ROW_1_RIGHT); +constexpr int WINDOW_2_LEFT = toInt(propertyutils_impl::VehicleAreaWindow::ROW_2_LEFT); +constexpr int WINDOW_2_RIGHT = toInt(propertyutils_impl::VehicleAreaWindow::ROW_2_RIGHT); +constexpr int WINDOW_ROOF_TOP_1 = toInt(propertyutils_impl::VehicleAreaWindow::ROOF_TOP_1); +constexpr int FAN_DIRECTION_FACE = toInt(propertyutils_impl::VehicleHvacFanDirection::FACE); +constexpr int FAN_DIRECTION_FLOOR = toInt(propertyutils_impl::VehicleHvacFanDirection::FLOOR); +constexpr int FAN_DIRECTION_DEFROST = toInt(propertyutils_impl::VehicleHvacFanDirection::DEFROST); +constexpr int OBD2_LIVE_FRAME = toInt(propertyutils_impl::VehicleProperty::OBD2_LIVE_FRAME); +constexpr int OBD2_FREEZE_FRAME = toInt(propertyutils_impl::VehicleProperty::OBD2_FREEZE_FRAME); +constexpr int OBD2_FREEZE_FRAME_INFO = + toInt(propertyutils_impl::VehicleProperty::OBD2_FREEZE_FRAME_INFO); +constexpr int OBD2_FREEZE_FRAME_CLEAR = + toInt(propertyutils_impl::VehicleProperty::OBD2_FREEZE_FRAME_CLEAR); +constexpr int TRACTION_CONTROL_ACTIVE = + toInt(propertyutils_impl::VehicleProperty::TRACTION_CONTROL_ACTIVE); +constexpr int VEHICLE_MAP_SERVICE = toInt(propertyutils_impl::VehicleProperty::VEHICLE_MAP_SERVICE); +constexpr int WHEEL_TICK = toInt(propertyutils_impl::VehicleProperty::WHEEL_TICK); +constexpr int SEAT_1_LEFT = toInt(propertyutils_impl::VehicleAreaSeat::ROW_1_LEFT); +constexpr int SEAT_1_RIGHT = toInt(propertyutils_impl::VehicleAreaSeat::ROW_1_RIGHT); +constexpr int SEAT_2_LEFT = toInt(propertyutils_impl::VehicleAreaSeat::ROW_2_LEFT); +constexpr int SEAT_2_RIGHT = toInt(propertyutils_impl::VehicleAreaSeat::ROW_2_RIGHT); +constexpr int SEAT_2_CENTER = toInt(propertyutils_impl::VehicleAreaSeat::ROW_2_CENTER); +constexpr int FUEL_DOOR_REAR_LEFT = toInt(propertyutils_impl::PortLocationType::REAR_LEFT); +constexpr int CHARGE_PORT_FRONT_LEFT = toInt(propertyutils_impl::PortLocationType::FRONT_LEFT); +constexpr int CHARGE_PORT_REAR_LEFT = toInt(propertyutils_impl::PortLocationType::REAR_LEFT); +constexpr int LIGHT_STATE_ON = toInt(propertyutils_impl::VehicleLightState::ON); +constexpr int LIGHT_STATE_OFF = toInt(propertyutils_impl::VehicleLightState::OFF); +constexpr int LIGHT_SWITCH_OFF = toInt(propertyutils_impl::VehicleLightSwitch::OFF); +constexpr int LIGHT_SWITCH_ON = toInt(propertyutils_impl::VehicleLightSwitch::ON); +constexpr int LIGHT_SWITCH_AUTO = toInt(propertyutils_impl::VehicleLightSwitch::AUTOMATIC); +constexpr int EV_STOPPING_MODE_CREEP = toInt(propertyutils_impl::EvStoppingMode::CREEP); +constexpr int EV_STOPPING_MODE_ROLL = toInt(propertyutils_impl::EvStoppingMode::ROLL); +constexpr int EV_STOPPING_MODE_HOLD = toInt(propertyutils_impl::EvStoppingMode::HOLD); +constexpr int WHEEL_FRONT_LEFT = toInt(propertyutils_impl::VehicleAreaWheel::LEFT_FRONT); +constexpr int WHEEL_FRONT_RIGHT = toInt(propertyutils_impl::VehicleAreaWheel::RIGHT_FRONT); +constexpr int WHEEL_REAR_LEFT = toInt(propertyutils_impl::VehicleAreaWheel::LEFT_REAR); +constexpr int WHEEL_REAR_RIGHT = toInt(propertyutils_impl::VehicleAreaWheel::RIGHT_REAR); +constexpr int ALL_WHEELS = + WHEEL_FRONT_LEFT | WHEEL_FRONT_RIGHT | WHEEL_REAR_LEFT | WHEEL_REAR_RIGHT; +constexpr int HVAC_LEFT = SEAT_1_LEFT | SEAT_2_LEFT | SEAT_2_CENTER; +constexpr int HVAC_RIGHT = SEAT_1_RIGHT | SEAT_2_RIGHT; +constexpr int HVAC_ALL = HVAC_LEFT | HVAC_RIGHT; +constexpr int HVAC_FRONT_ROW = SEAT_1_LEFT | SEAT_1_RIGHT; +constexpr int HVAC_REAR_ROW = SEAT_2_LEFT | SEAT_2_CENTER | SEAT_2_RIGHT; + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_aidl_impl_utils_common_include_PropertyUtils_H_ diff --git a/automotive/vehicle/aidl/impl/current/utils/common/include/RecurrentTimer.h b/automotive/vehicle/aidl/impl/current/utils/common/include/RecurrentTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..712359a885b42501ddf6ded01e882e281c3499d2 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/utils/common/include/RecurrentTimer.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_aidl_impl_vhal_include_RecurrentTimer_H_ +#define android_hardware_automotive_vehicle_aidl_impl_vhal_include_RecurrentTimer_H_ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +// Forward declaration +class RecurrentMessageHandler; + +// A thread-safe recurrent timer. +class RecurrentTimer final { + public: + // The class for the function that would be called recurrently. + using Callback = std::function; + + RecurrentTimer(); + + ~RecurrentTimer(); + + // Registers a recurrent callback for a given interval. + // Registering the same callback twice will override the interval provided before. + void registerTimerCallback(int64_t intervalInNanos, std::shared_ptr callback); + + // Unregisters a previously registered recurrent callback. + void unregisterTimerCallback(std::shared_ptr callback); + + private: + friend class RecurrentMessageHandler; + + // For unit test + friend class RecurrentTimerTest; + + struct CallbackInfo { + std::shared_ptr callback; + int64_t intervalInNanos; + int64_t nextTimeInNanos; + }; + + android::sp mLooper; + android::sp mHandler; + + std::atomic mStopRequested = false; + std::atomic mCallbackId = 0; + std::mutex mLock; + std::thread mThread; + std::unordered_map, int> mIdByCallback GUARDED_BY(mLock); + std::unordered_map> mCallbackInfoById GUARDED_BY(mLock); + + void handleMessage(const android::Message& message) EXCLUDES(mLock); + int getCallbackIdLocked(std::shared_ptr callback) REQUIRES(mLock); +}; + +class RecurrentMessageHandler final : public android::MessageHandler { + public: + RecurrentMessageHandler(RecurrentTimer* timer) { mTimer = timer; } + void handleMessage(const android::Message& message) override; + + private: + RecurrentTimer* mTimer; +}; + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_aidl_impl_vhal_include_RecurrentTimer_H_ diff --git a/automotive/vehicle/aidl/impl/current/utils/common/include/VehicleHalTypes.h b/automotive/vehicle/aidl/impl/current/utils/common/include/VehicleHalTypes.h new file mode 100644 index 0000000000000000000000000000000000000000..4fa0a06dd2cce931d49ec8c639de57db3fda1fef --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/utils/common/include/VehicleHalTypes.h @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehicleHalTypes_H_ +#define android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehicleHalTypes_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehicleHalTypes_H_ diff --git a/automotive/vehicle/aidl/impl/current/utils/common/include/VehicleObjectPool.h b/automotive/vehicle/aidl/impl/current/utils/common/include/VehicleObjectPool.h new file mode 100644 index 0000000000000000000000000000000000000000..e18413bcd59fd0460319e27d7b6f6c4a78c99906 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/utils/common/include/VehicleObjectPool.h @@ -0,0 +1,293 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_utils_include_VehicleObjectPool_H_ +#define android_hardware_automotive_vehicle_utils_include_VehicleObjectPool_H_ + +#include +#include +#include +#include + +#include + +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +// Handy metric mostly for unit tests and debug. +#define INC_METRIC_IF_DEBUG(val) PoolStats::instance()->val++; + +struct PoolStats { + std::atomic Obtained{0}; + std::atomic Created{0}; + std::atomic Recycled{0}; + std::atomic Deleted{0}; + + static PoolStats* instance() { + static PoolStats inst; + return &inst; + } +}; + +template +struct Deleter { + using OnDeleteFunc = std::function; + + explicit Deleter(const OnDeleteFunc& f) : mOnDelete(f) {}; + + Deleter() = default; + Deleter(const Deleter&) = default; + + void operator()(T* o) { mOnDelete(o); } + + private: + OnDeleteFunc mOnDelete; +}; + +// This is std::unique_ptr<> with custom delete operation that typically moves the pointer it holds +// back to ObjectPool. +template +using recyclable_ptr = typename std::unique_ptr>; + +// Generic abstract object pool class. Users of this class must implement {@Code createObject}. +// +// This class is thread-safe. Concurrent calls to {@Code obtain} from multiple threads is OK, also +// client can obtain an object in one thread and then move ownership to another thread. +template +class ObjectPool { + public: + using GetSizeFunc = std::function; + + ObjectPool(size_t maxPoolObjectsSize, GetSizeFunc getSizeFunc) + : mMaxPoolObjectsSize(maxPoolObjectsSize), mGetSizeFunc(getSizeFunc) {}; + virtual ~ObjectPool() = default; + + virtual recyclable_ptr obtain() { + std::scoped_lock lock(mLock); + INC_METRIC_IF_DEBUG(Obtained) + if (mObjects.empty()) { + INC_METRIC_IF_DEBUG(Created) + return wrap(createObject()); + } + + auto o = wrap(mObjects.front().release()); + mObjects.pop_front(); + mPoolObjectsSize -= mGetSizeFunc(*o); + return o; + } + + ObjectPool& operator=(const ObjectPool&) = delete; + ObjectPool(const ObjectPool&) = delete; + + protected: + virtual T* createObject() = 0; + + virtual void recycle(T* o) { + std::scoped_lock lock(mLock); + size_t objectSize = mGetSizeFunc(*o); + + if (objectSize > mMaxPoolObjectsSize || + mPoolObjectsSize > mMaxPoolObjectsSize - objectSize) { + INC_METRIC_IF_DEBUG(Deleted) + + // We have no space left in the pool. + delete o; + return; + } + + INC_METRIC_IF_DEBUG(Recycled) + + mObjects.push_back(std::unique_ptr{o}); + mPoolObjectsSize += objectSize; + } + + const size_t mMaxPoolObjectsSize; + + private: + const Deleter& getDeleter() { + if (!mDeleter.get()) { + Deleter* d = + new Deleter(std::bind(&ObjectPool::recycle, this, std::placeholders::_1)); + mDeleter.reset(d); + } + return *mDeleter.get(); + } + + recyclable_ptr wrap(T* raw) { return recyclable_ptr{raw, getDeleter()}; } + + mutable std::mutex mLock; + std::deque> mObjects GUARDED_BY(mLock); + std::unique_ptr> mDeleter; + size_t mPoolObjectsSize GUARDED_BY(mLock); + GetSizeFunc mGetSizeFunc; +}; + +#undef INC_METRIC_IF_DEBUG + +// This class provides a pool of recyclable VehiclePropertyValue objects. +// +// It has only one overloaded public method - obtain(...), users must call this method when new +// object is needed with given VehiclePropertyType and vector size (for vector properties). This +// method returns a recyclable smart pointer to VehiclePropertyValue, essentially this is a +// std::unique_ptr with custom delete function, so recyclable object has only one owner and +// developers can safely pass it around. Once this object goes out of scope, it will be returned to +// the object pool. +// +// Some objects are not recyclable: strings and vector data types with vector +// length > maxRecyclableVectorSize (provided in the constructor). These objects will be deleted +// immediately once the go out of scope. There's no synchronization penalty for these objects since +// we do not store them in the pool. +// +// This class is thread-safe. Users can obtain an object in one thread and pass it to another. +// +// Sample usage: +// +// VehiclePropValuePool pool; +// auto v = pool.obtain(VehiclePropertyType::INT32); +// v->propId = VehicleProperty::HVAC_FAN_SPEED; +// v->areaId = VehicleAreaSeat::ROW_1_LEFT; +// v->timestamp = elapsedRealtimeNano(); +// v->value->int32Values[0] = 42; +class VehiclePropValuePool { + public: + using RecyclableType = + recyclable_ptr; + + // Creates VehiclePropValuePool + // + // @param maxRecyclableVectorSize - vector value types (e.g. VehiclePropertyType::INT32_VEC) + // with size equal or less to this value will be stored in the pool. If users tries to obtain + // value with vector size greater than maxRecyclableVectorSize, user will receive a regular + // unique pointer instead of a recyclable pointer. The object would not be recycled once it + // goes out of scope, but would be deleted. + // @param maxPoolObjectsSize - The approximate upper bound of memory each internal recycling + // pool could take. We have 4 different type pools, each with 4 different vector size, so + // approximately this pool would at-most take 4 * 4 * 10240 = 160k memory. + VehiclePropValuePool(size_t maxRecyclableVectorSize = 4, size_t maxPoolObjectsSize = 10240) + : mMaxRecyclableVectorSize(maxRecyclableVectorSize), + mMaxPoolObjectsSize(maxPoolObjectsSize) {}; + + // Obtain a recyclable VehiclePropertyValue object from the pool for the given type. If the + // given type is not MIXED or STRING, the internal value vector size would be set to 1. + // If the given type is MIXED or STRING, all the internal vector sizes would be initialized to + // 0. + RecyclableType obtain(aidl::android::hardware::automotive::vehicle::VehiclePropertyType type); + + // Obtain a recyclable VehiclePropertyValue object from the pool for the given type. If the + // given type is *_VEC or BYTES, the internal value vector size would be set to vectorSize. If + // the given type is BOOLEAN, INT32, FLOAT, or INT64, the internal value vector size would be + // set to 1. If the given type is MIXED or STRING, all the internal value vector sizes would be + // set to 0. vectorSize must be larger than 0. + RecyclableType obtain(aidl::android::hardware::automotive::vehicle::VehiclePropertyType type, + size_t vectorSize); + // Obtain a recyclable VehicePropertyValue object that is a copy of src. If src does not contain + // any value or the src property type is not valid, this function would return an empty + // VehiclePropValue. + RecyclableType obtain( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& src); + // Obtain a recyclable boolean object. + RecyclableType obtainBoolean(bool value); + // Obtain a recyclable int32 object. + RecyclableType obtainInt32(int32_t value); + // Obtain a recyclable int64 object. + RecyclableType obtainInt64(int64_t value); + // Obtain a recyclable float object. + RecyclableType obtainFloat(float value); + // Obtain a recyclable float object. + RecyclableType obtainString(const char* cstr); + // Obtain a recyclable mixed object. + RecyclableType obtainComplex(); + + VehiclePropValuePool(VehiclePropValuePool&) = delete; + VehiclePropValuePool& operator=(VehiclePropValuePool&) = delete; + + private: + static inline bool isSingleValueType( + aidl::android::hardware::automotive::vehicle::VehiclePropertyType type) { + return type == aidl::android::hardware::automotive::vehicle::VehiclePropertyType::BOOLEAN || + type == aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT32 || + type == aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT64 || + type == aidl::android::hardware::automotive::vehicle::VehiclePropertyType::FLOAT; + } + + static inline bool isComplexType( + aidl::android::hardware::automotive::vehicle::VehiclePropertyType type) { + return type == aidl::android::hardware::automotive::vehicle::VehiclePropertyType::MIXED || + type == aidl::android::hardware::automotive::vehicle::VehiclePropertyType::STRING; + } + + bool isDisposable(aidl::android::hardware::automotive::vehicle::VehiclePropertyType type, + size_t vectorSize) const { + return vectorSize == 0 || vectorSize > mMaxRecyclableVectorSize || isComplexType(type); + } + + RecyclableType obtainDisposable( + aidl::android::hardware::automotive::vehicle::VehiclePropertyType valueType, + size_t vectorSize) const; + RecyclableType obtainRecyclable( + aidl::android::hardware::automotive::vehicle::VehiclePropertyType type, + size_t vectorSize); + + class InternalPool + : public ObjectPool { + public: + InternalPool(aidl::android::hardware::automotive::vehicle::VehiclePropertyType type, + size_t vectorSize, size_t maxPoolObjectsSize, + ObjectPool::GetSizeFunc getSizeFunc) + : ObjectPool(maxPoolObjectsSize, getSizeFunc), + mPropType(type), + mVectorSize(vectorSize) {} + + protected: + aidl::android::hardware::automotive::vehicle::VehiclePropValue* createObject() override; + void recycle(aidl::android::hardware::automotive::vehicle::VehiclePropValue* o) override; + + private: + bool check(aidl::android::hardware::automotive::vehicle::RawPropValues* v); + + template + bool check(std::vector* vec, bool isVectorType) { + return vec->size() == (isVectorType ? mVectorSize : 0); + } + + private: + aidl::android::hardware::automotive::vehicle::VehiclePropertyType mPropType; + size_t mVectorSize; + }; + const Deleter + mDisposableDeleter{ + [](aidl::android::hardware::automotive::vehicle::VehiclePropValue* v) { + delete v; + }}; + + mutable std::mutex mLock; + const size_t mMaxRecyclableVectorSize; + const size_t mMaxPoolObjectsSize; + // A map with 'property_type' | 'value_vector_size' as key and a recyclable object pool as + // value. We would create a recyclable pool for each property type and vector size combination. + std::map> mValueTypePools GUARDED_BY(mLock); +}; + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_utils_include_VehicleObjectPool_H_ diff --git a/automotive/vehicle/aidl/impl/current/utils/common/include/VehiclePropertyStore.h b/automotive/vehicle/aidl/impl/current/utils/common/include/VehiclePropertyStore.h new file mode 100644 index 0000000000000000000000000000000000000000..d9599ed72c76c05bd014637840c42e748ca6df04 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/utils/common/include/VehiclePropertyStore.h @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehiclePropertyStore_H_ +#define android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehiclePropertyStore_H_ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +// Encapsulates work related to storing and accessing configuration, storing and modifying +// vehicle property values. +// +// VehiclePropertyValues stored in a sorted map thus it makes easier to get range of values, e.g. +// to get value for all areas for particular property. +// +// This class is thread-safe, however it uses blocking synchronization across all methods. +class VehiclePropertyStore final { + public: + using ValueResultType = VhalResult; + using ValuesResultType = VhalResult>; + + enum class EventMode : uint8_t { + /** + * Only invoke OnValueChangeCallback or OnValuesChangeCallback if the new property value + * (ignoring timestamp) is different than the existing value. + * + * This should be used for regular cases. + */ + ON_VALUE_CHANGE, + /** + * Always invoke OnValueChangeCallback or OnValuesChangeCallback. + * + * This should be used for the special properties that are used for delivering event, e.g. + * HW_KEY_INPUT. + */ + ALWAYS, + /** + * Never invoke OnValueChangeCallback or OnValuesChangeCalblack. + * + * This should be used for continuous property subscription when the sample rate for the + * subscription is smaller than the refresh rate for the property. E.g., the vehicle speed + * is refreshed at 20hz, but we are only subscribing at 10hz. In this case, we want to + * generate the property change event at 10hz, not 20hz, but we still want to refresh the + * timestamp (via writeValue) at 20hz. + */ + NEVER, + }; + + explicit VehiclePropertyStore(std::shared_ptr valuePool) + : mValuePool(valuePool) {} + + ~VehiclePropertyStore(); + + // Callback when a property value has been updated or a new value added. + using OnValueChangeCallback = std::function; + + // Callback when one or more property values have been updated or new values added. + using OnValuesChangeCallback = std::function)>; + + // Function that used to calculate unique token for given VehiclePropValue. + using TokenFunction = std::function; + + // Register the given property according to the config. A property has to be registered first + // before write/read. If tokenFunc is not nullptr, it would be used to generate a unique + // property token to act as the key the property store. Otherwise, {propertyID, areaID} would be + // used as the key. + void registerProperty( + const aidl::android::hardware::automotive::vehicle::VehiclePropConfig& config, + TokenFunction tokenFunc = nullptr) EXCLUDES(mLock); + + // Stores provided value. Returns error if config wasn't registered. If 'updateStatus' is + // true, the 'status' in 'propValue' would be stored. Otherwise, if this is a new value, + // 'status' would be initialized to {@code VehiclePropertyStatus::AVAILABLE}, if this is to + // override an existing value, the status for the existing value would be used for the + // overridden value. + // 'EventMode' controls whether the 'OnValueChangeCallback' or 'OnValuesChangeCallback' will be + // called for this operation. + // If 'useCurrentTimestamp' is true, the property value will be set to the current timestamp. + VhalResult writeValue(VehiclePropValuePool::RecyclableType propValue, + bool updateStatus = false, + EventMode mode = EventMode::ON_VALUE_CHANGE, + bool useCurrentTimestamp = false) EXCLUDES(mLock); + + // Refresh the timestamp for the stored property value for [propId, areaId]. If eventMode is + // always, generates the property update event, otherwise, only update the stored timestamp + // without generating event. This operation is atomic with other writeValue operations. + void refreshTimestamp(int32_t propId, int32_t areaId, EventMode eventMode) EXCLUDES(mLock); + + // Refresh the timestamp for multiple [propId, areaId]s. + void refreshTimestamps( + std::unordered_map eventModeByPropIdAreaId) + EXCLUDES(mLock); + + // Remove a given property value from the property store. The 'propValue' would be used to + // generate the key for the value to remove. + void removeValue( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue) + EXCLUDES(mLock); + + // Remove all the values for the property. + void removeValuesForProperty(int32_t propId) EXCLUDES(mLock); + + // Read all the stored values. + std::vector readAllValues() const EXCLUDES(mLock); + + // Read all the values for the property. + ValuesResultType readValuesForProperty(int32_t propId) const EXCLUDES(mLock); + + // Read the value for the requested property. Returns {@code StatusCode::NOT_AVAILABLE} if the + // value has not been set yet. Returns {@code StatusCode::INVALID_ARG} if the property is + // not configured. + ValueResultType readValue( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& request) const + EXCLUDES(mLock); + + // Read the value for the requested property. Returns {@code StatusCode::NOT_AVAILABLE} if the + // value has not been set yet. Returns {@code StatusCode::INVALID_ARG} if the property is + // not configured. + ValueResultType readValue(int32_t prop, int32_t area = 0, int64_t token = 0) const + EXCLUDES(mLock); + + // Get all property configs. + std::vector getAllConfigs() + const EXCLUDES(mLock); + + // Deprecated, use getPropConfig instead. This is unsafe to use if registerProperty overwrites + // an existing config. + android::base::Result + getConfig(int32_t propId) const EXCLUDES(mLock); + + // Get the property config for the requested property. + android::base::Result + getPropConfig(int32_t propId) const EXCLUDES(mLock); + + // Set a callback that would be called when a property value has been updated. + void setOnValueChangeCallback(const OnValueChangeCallback& callback) EXCLUDES(mLock); + + // Set a callback that would be called when one or more property values have been updated. + // For backward compatibility, this is optional. If this is not set, then multiple property + // updates will be delivered through multiple OnValueChangeCallback instead. + // It is recommended to set this and batch the property update events for better performance. + // If this is set, then OnValueChangeCallback will not be used. + void setOnValuesChangeCallback(const OnValuesChangeCallback& callback) EXCLUDES(mLock); + + inline std::shared_ptr getValuePool() { return mValuePool; } + + private: + struct RecordId { + int32_t area; + int64_t token; + + std::string toString() const; + + bool operator==(const RecordId& other) const; + }; + + struct RecordIdHash { + size_t operator()(RecordId const& recordId) const; + }; + + struct Record { + aidl::android::hardware::automotive::vehicle::VehiclePropConfig propConfig; + TokenFunction tokenFunction; + std::unordered_map values; + }; + + // {@code VehiclePropValuePool} is thread-safe. + std::shared_ptr mValuePool; + mutable std::mutex mLock; + std::unordered_map mRecordsByPropId GUARDED_BY(mLock); + OnValueChangeCallback mOnValueChangeCallback GUARDED_BY(mLock); + OnValuesChangeCallback mOnValuesChangeCallback GUARDED_BY(mLock); + + const Record* getRecordLocked(int32_t propId) const; + + Record* getRecordLocked(int32_t propId); + + RecordId getRecordIdLocked( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue, + const Record& record) const; + + ValueResultType readValueLocked(const RecordId& recId, const Record& record) const; +}; + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehiclePropertyStore_H_ diff --git a/automotive/vehicle/aidl/impl/current/utils/common/include/VehicleUtils.h b/automotive/vehicle/aidl/impl/current/utils/common/include/VehicleUtils.h new file mode 100644 index 0000000000000000000000000000000000000000..90a7c46f3fae1be5050b037102aaa8ca12636b87 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/utils/common/include/VehicleUtils.h @@ -0,0 +1,365 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehicleUtils_H_ +#define android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehicleUtils_H_ + +#include + +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +// Represents all supported areas for a property. +constexpr int32_t kAllSupportedAreas = 0; + +// Returns underlying (integer) value for given enum. +template ::type> +inline constexpr U toInt(ENUM const value) { + return static_cast(value); +} + +inline constexpr aidl::android::hardware::automotive::vehicle::VehiclePropertyType getPropType( + int32_t prop) { + return static_cast( + prop & toInt(aidl::android::hardware::automotive::vehicle::VehiclePropertyType::MASK)); +} + +inline constexpr aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup getPropGroup( + int32_t prop) { + return static_cast( + prop & toInt(aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup::MASK)); +} + +inline constexpr aidl::android::hardware::automotive::vehicle::VehicleArea getPropArea( + int32_t prop) { + return static_cast( + prop & toInt(aidl::android::hardware::automotive::vehicle::VehicleArea::MASK)); +} + +inline constexpr bool isGlobalProp(int32_t prop) { + return getPropArea(prop) == aidl::android::hardware::automotive::vehicle::VehicleArea::GLOBAL; +} + +inline constexpr bool isSystemProp(int32_t prop) { + return aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup::SYSTEM == + getPropGroup(prop); +} + +inline const aidl::android::hardware::automotive::vehicle::VehicleAreaConfig* getAreaConfig( + int32_t propId, int32_t areaId, + const aidl::android::hardware::automotive::vehicle::VehiclePropConfig& config) { + if (config.areaConfigs.size() == 0) { + return nullptr; + } + + if (isGlobalProp(propId)) { + return &(config.areaConfigs[0]); + } + + for (const auto& c : config.areaConfigs) { + if (c.areaId == areaId) { + return &c; + } + } + return nullptr; +} + +inline const aidl::android::hardware::automotive::vehicle::VehicleAreaConfig* getAreaConfig( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue, + const aidl::android::hardware::automotive::vehicle::VehiclePropConfig& config) { + return getAreaConfig(propValue.prop, propValue.areaId, config); +} + +inline std::unique_ptr +createVehiclePropValueVec(aidl::android::hardware::automotive::vehicle::VehiclePropertyType type, + size_t vecSize) { + auto val = std::unique_ptr( + new aidl::android::hardware::automotive::vehicle::VehiclePropValue); + switch (type) { + case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT32: + [[fallthrough]]; + case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::BOOLEAN: + vecSize = 1; + [[fallthrough]]; + case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT32_VEC: + val->value.int32Values.resize(vecSize); + break; + case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::FLOAT: + vecSize = 1; + [[fallthrough]]; + case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::FLOAT_VEC: + val->value.floatValues.resize(vecSize); + break; + case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT64: + vecSize = 1; + [[fallthrough]]; + case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT64_VEC: + val->value.int64Values.resize(vecSize); + break; + case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::BYTES: + val->value.byteValues.resize(vecSize); + break; + case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::STRING: + case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::MIXED: + break; // Valid, but nothing to do. + default: + ALOGE("createVehiclePropValue: unknown type: %d", toInt(type)); + } + return val; +} + +inline std::unique_ptr +createVehiclePropValue(aidl::android::hardware::automotive::vehicle::VehiclePropertyType type) { + return createVehiclePropValueVec(type, 1); +} + +inline size_t getVehicleRawValueVectorSize( + const aidl::android::hardware::automotive::vehicle::RawPropValues& value, + aidl::android::hardware::automotive::vehicle::VehiclePropertyType type) { + switch (type) { + case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT32: + [[fallthrough]]; + case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::BOOLEAN: + return std::min(value.int32Values.size(), static_cast(1)); + case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::FLOAT: + return std::min(value.floatValues.size(), static_cast(1)); + case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT64: + return std::min(value.int64Values.size(), static_cast(1)); + case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT32_VEC: + return value.int32Values.size(); + case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::FLOAT_VEC: + return value.floatValues.size(); + case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT64_VEC: + return value.int64Values.size(); + case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::BYTES: + return value.byteValues.size(); + case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::STRING: + [[fallthrough]]; + case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::MIXED: + return 0; + default: + ALOGE("getVehicleRawValueVectorSize: unknown type: %d", toInt(type)); + return 0; + } +} + +inline void copyVehicleRawValue( + aidl::android::hardware::automotive::vehicle::RawPropValues* dest, + const aidl::android::hardware::automotive::vehicle::RawPropValues& src) { + dest->int32Values = src.int32Values; + dest->floatValues = src.floatValues; + dest->int64Values = src.int64Values; + dest->byteValues = src.byteValues; + dest->stringValue = src.stringValue; +} + +// getVehiclePropValueSize returns approximately how much memory 'value' would take. This should +// only be used in a limited-size memory pool to set an upper bound for memory consumption. +inline size_t getVehiclePropValueSize( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& prop) { + size_t size = 0; + size += sizeof(prop.timestamp); + size += sizeof(prop.areaId); + size += sizeof(prop.prop); + size += sizeof(prop.status); + size += prop.value.int32Values.size() * sizeof(int32_t); + size += prop.value.int64Values.size() * sizeof(int64_t); + size += prop.value.floatValues.size() * sizeof(float); + size += prop.value.byteValues.size() * sizeof(uint8_t); + size += prop.value.stringValue.size(); + return size; +} + +// Check whether the value is valid according to config. +// We check for the following: +// * If the type is INT32, {@code value.int32Values} must contain one element. +// * If the type is INT32_VEC, {@code value.int32Values} must contain at least one element. +// * If the type is INT64, {@code value.int64Values} must contain one element. +// * If the type is INT64_VEC, {@code value.int64Values} must contain at least one element. +// * If the type is FLOAT, {@code value.floatValues} must contain one element. +// * If the type is FLOAT_VEC, {@code value.floatValues} must contain at least one element. +// * If the type is MIXED, see checkVendorMixedPropValue. +android::base::Result checkPropValue( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value, + const aidl::android::hardware::automotive::vehicle::VehiclePropConfig* config); + +// Check whether the Mixed type value is valid according to config. +// We check for the following: +// * configArray[1] + configArray[2] + configArray[3] must be equal to the number of +// {@code value.int32Values} elements. +// * configArray[4] + configArray[5] must be equal to the number of {@code value.int64Values} +// elements. +// * configArray[6] + configArray[7] must be equal to the number of {@code value.floatValues} +// elements. +// * configArray[8] must be equal to the number of {@code value.byteValues} elements. +android::base::Result checkVendorMixedPropValue( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value, + const aidl::android::hardware::automotive::vehicle::VehiclePropConfig* config); + +// Check whether the value is within the configured range. +// We check for the following types: +// * If type is INT32 or INT32_VEC, all {@code value.int32Values} elements must be within +// {@code minInt32Value} and {@code maxInt32Value} if either of them is not 0. +// * If type is INT64 or INT64_VEC, all {@code value.int64Values} elements must be within +// {@code minInt64Value} and {@code maxInt64Value} if either of them is not 0. +// * If type is FLOAT or FLOAT_VEC, all {@code value.floatValues} elements must be within +// {@code minFloatValues} and {@code maxFloatValues} if either of them is not 0. +// We don't check other types. If more checks are required, they should be added in VehicleHardware +// implementation. +android::base::Result checkValueRange( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value, + const aidl::android::hardware::automotive::vehicle::VehicleAreaConfig* config); + +// VhalError is a wrapper class for {@code StatusCode} that could act as E in {@code Result}. +class VhalError final { + public: + VhalError() : mCode(aidl::android::hardware::automotive::vehicle::StatusCode::OK) {} + + VhalError(aidl::android::hardware::automotive::vehicle::StatusCode&& code) : mCode(code) {} + + VhalError(const aidl::android::hardware::automotive::vehicle::StatusCode& code) : mCode(code) {} + + aidl::android::hardware::automotive::vehicle::StatusCode value() const; + + inline operator aidl::android::hardware::automotive::vehicle::StatusCode() const { + return value(); + } + + std::string print() const; + + private: + aidl::android::hardware::automotive::vehicle::StatusCode mCode; +}; + +// VhalResult is a {@code Result} that contains {@code StatusCode} as error type. +template +using VhalResult = android::base::Result; + +// StatusError could be cast to {@code ResultError} with a {@code StatusCode} and should be used +// as error type for {@VhalResult}. +using StatusError = android::base::Error; + +template +aidl::android::hardware::automotive::vehicle::StatusCode getErrorCode(const VhalResult& result) { + if (result.ok()) { + return aidl::android::hardware::automotive::vehicle::StatusCode::OK; + } + return result.error().code(); +} + +template +int getIntErrorCode(const VhalResult& result) { + return toInt(getErrorCode(result)); +} + +template +std::string getErrorMsg(const android::base::Result& result) { + if (result.ok()) { + return ""; + } + return result.error().message(); +} + +template +ndk::ScopedAStatus toScopedAStatus(const android::base::Result& result, + aidl::android::hardware::automotive::vehicle::StatusCode status, + const std::string& additionalErrorMsg) { + if (result.ok()) { + return ndk::ScopedAStatus::ok(); + } + return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage( + toInt(status), + fmt::format("{}, error: {}", additionalErrorMsg, getErrorMsg(result)).c_str()); +} + +template +ndk::ScopedAStatus toScopedAStatus( + const android::base::Result& result, + aidl::android::hardware::automotive::vehicle::StatusCode status) { + return toScopedAStatus(result, status, ""); +} + +template +ndk::ScopedAStatus toScopedAStatus(const VhalResult& result) { + return toScopedAStatus(result, getErrorCode(result)); +} + +template +ndk::ScopedAStatus toScopedAStatus(const VhalResult& result, + const std::string& additionalErrorMsg) { + return toScopedAStatus(result, getErrorCode(result), additionalErrorMsg); +} + +struct PropIdAreaId { + int32_t propId; + int32_t areaId; + + inline bool operator==(const PropIdAreaId& other) const { + return areaId == other.areaId && propId == other.propId; + } +}; + +struct PropIdAreaIdHash { + inline size_t operator()(const PropIdAreaId& propIdAreaId) const { + size_t res = 0; + hashCombine(res, propIdAreaId.propId); + hashCombine(res, propIdAreaId.areaId); + return res; + } +}; + +// This is for debug purpose only. +inline std::string propIdToString(int32_t propId) { + return toString( + static_cast(propId)); +} + +// This is for debug purpose only. +android::base::Result stringToPropId(const std::string& propName); + +// This is for debug purpose only. Converts an area's name to its enum definition. +android::base::Result stringToArea(const std::string& areaName, int32_t propId); + +template +void roundToNearestResolution(std::vector& arrayToSanitize, float resolution) { + if (resolution == 0) { + return; + } + for (size_t i = 0; i < arrayToSanitize.size(); i++) { + arrayToSanitize[i] = (T)((std::round(arrayToSanitize[i] / resolution)) * resolution); + } +} + +inline void sanitizeByResolution(aidl::android::hardware::automotive::vehicle::RawPropValues* value, + float resolution) { + roundToNearestResolution(value->int32Values, resolution); + roundToNearestResolution(value->floatValues, resolution); + roundToNearestResolution(value->int64Values, resolution); +} + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehicleUtils_H_ diff --git a/automotive/vehicle/aidl/impl/current/utils/common/src/PendingRequestPool.cpp b/automotive/vehicle/aidl/impl/current/utils/common/src/PendingRequestPool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ab504992e46e279bb938712b2256ccb45c96e2d7 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/utils/common/src/PendingRequestPool.cpp @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2021 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 "PendingRequestPool.h" + +#include +#include + +#include +#include + +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +namespace { + +using ::aidl::android::hardware::automotive::vehicle::StatusCode; +using ::android::base::Result; + +// At least check every 1s. +constexpr int64_t CHECK_TIME_IN_NANO = 1'000'000'000; + +} // namespace + +PendingRequestPool::PendingRequestPool(int64_t timeoutInNano) : mTimeoutInNano(timeoutInNano) { + mThread = std::thread([this] { + // [this] must be alive within this thread because destructor would wait for this thread + // to exit. + int64_t sleepTime = std::min(mTimeoutInNano, static_cast(CHECK_TIME_IN_NANO)); + std::unique_lock lk(mCvLock); + while (!mCv.wait_for(lk, std::chrono::nanoseconds(sleepTime), + [this] { return mThreadStop; })) { + checkTimeout(); + } + }); +} + +PendingRequestPool::~PendingRequestPool() { + { + // Even if the shared variable is atomic, it must be modified under the + // mutex in order to correctly publish the modification to the waiting + // thread. + std::unique_lock lk(mCvLock); + mThreadStop = true; + } + mCv.notify_all(); + if (mThread.joinable()) { + mThread.join(); + } + + // If this pool is being destructed, send out all pending requests as timeout. + { + std::scoped_lock lockGuard(mLock); + + for (auto& [_, pendingRequests] : mPendingRequestsByClient) { + for (const auto& request : pendingRequests) { + (*request.callback)(request.requestIds); + } + } + mPendingRequestsByClient.clear(); + } +} + +VhalResult PendingRequestPool::addRequests( + const void* clientId, const std::unordered_set& requestIds, + std::shared_ptr callback) { + std::scoped_lock lockGuard(mLock); + std::list* pendingRequests; + size_t pendingRequestCount = 0; + if (mPendingRequestsByClient.find(clientId) != mPendingRequestsByClient.end()) { + pendingRequests = &mPendingRequestsByClient[clientId]; + for (const auto& pendingRequest : *pendingRequests) { + const auto& pendingRequestIds = pendingRequest.requestIds; + for (int64_t requestId : requestIds) { + if (pendingRequestIds.find(requestId) != pendingRequestIds.end()) { + return StatusError(StatusCode::INVALID_ARG) + << "duplicate request ID: " << requestId; + } + } + pendingRequestCount += pendingRequestIds.size(); + } + } else { + // Create a new empty list for this client. + pendingRequests = &mPendingRequestsByClient[clientId]; + } + + if (requestIds.size() > MAX_PENDING_REQUEST_PER_CLIENT - pendingRequestCount) { + return StatusError(StatusCode::TRY_AGAIN) << "too many pending requests"; + } + + int64_t currentTime = elapsedRealtimeNano(); + int64_t timeoutTimestamp = currentTime + mTimeoutInNano; + + pendingRequests->push_back({ + .requestIds = std::unordered_set(requestIds.begin(), requestIds.end()), + .timeoutTimestamp = timeoutTimestamp, + .callback = callback, + }); + + return {}; +} + +bool PendingRequestPool::isRequestPending(const void* clientId, int64_t requestId) const { + std::scoped_lock lockGuard(mLock); + + return isRequestPendingLocked(clientId, requestId); +} + +size_t PendingRequestPool::countPendingRequests() const { + std::scoped_lock lockGuard(mLock); + + size_t count = 0; + for (const auto& [clientId, requests] : mPendingRequestsByClient) { + for (const auto& request : requests) { + count += request.requestIds.size(); + } + } + return count; +} + +size_t PendingRequestPool::countPendingRequests(const void* clientId) const { + std::scoped_lock lockGuard(mLock); + + auto it = mPendingRequestsByClient.find(clientId); + if (it == mPendingRequestsByClient.end()) { + return 0; + } + + size_t count = 0; + for (const auto& pendingRequest : it->second) { + count += pendingRequest.requestIds.size(); + } + + return count; +} + +bool PendingRequestPool::isRequestPendingLocked(const void* clientId, int64_t requestId) const { + auto it = mPendingRequestsByClient.find(clientId); + if (it == mPendingRequestsByClient.end()) { + return false; + } + for (const auto& pendingRequest : it->second) { + const auto& requestIds = pendingRequest.requestIds; + if (requestIds.find(requestId) != requestIds.end()) { + return true; + } + } + return false; +} + +void PendingRequestPool::checkTimeout() { + std::vector timeoutRequests; + { + std::scoped_lock lockGuard(mLock); + + int64_t currentTime = elapsedRealtimeNano(); + + std::vector clientsWithEmptyRequests; + + for (auto& [clientId, pendingRequests] : mPendingRequestsByClient) { + auto it = pendingRequests.begin(); + while (it != pendingRequests.end()) { + if (it->timeoutTimestamp >= currentTime) { + break; + } + timeoutRequests.push_back(std::move(*it)); + it = pendingRequests.erase(it); + } + + if (pendingRequests.empty()) { + clientsWithEmptyRequests.push_back(clientId); + } + } + + for (const void* clientId : clientsWithEmptyRequests) { + mPendingRequestsByClient.erase(clientId); + } + } + + // Call the callback outside the lock. + for (const auto& request : timeoutRequests) { + (*request.callback)(request.requestIds); + } +} + +std::unordered_set PendingRequestPool::tryFinishRequests( + const void* clientId, const std::unordered_set& requestIds) { + std::scoped_lock lockGuard(mLock); + + std::unordered_set foundIds; + + if (mPendingRequestsByClient.find(clientId) == mPendingRequestsByClient.end()) { + return foundIds; + } + + auto& pendingRequests = mPendingRequestsByClient[clientId]; + auto it = pendingRequests.begin(); + while (it != pendingRequests.end()) { + auto& pendingRequestIds = it->requestIds; + for (int64_t requestId : requestIds) { + auto idIt = pendingRequestIds.find(requestId); + if (idIt == pendingRequestIds.end()) { + continue; + } + pendingRequestIds.erase(idIt); + foundIds.insert(requestId); + } + if (pendingRequestIds.empty()) { + it = pendingRequests.erase(it); + continue; + } + it++; + } + + return foundIds; +} + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/current/utils/common/src/RecurrentTimer.cpp b/automotive/vehicle/aidl/impl/current/utils/common/src/RecurrentTimer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8dec695df149957c517d8a09e096842721149780 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/utils/common/src/RecurrentTimer.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2021 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 "RecurrentTimer.h" + +#include +#include +#include + +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +namespace { + +using ::android::base::ScopedLockAssertion; + +constexpr int INVALID_ID = -1; + +} // namespace + +RecurrentTimer::RecurrentTimer() { + mHandler = sp::make(this); + mLooper = sp::make(/*allowNonCallbacks=*/false); + mThread = std::thread([this] { + Looper::setForThread(mLooper); + + while (!mStopRequested) { + mLooper->pollOnce(/*timeoutMillis=*/-1); + } + }); +} + +RecurrentTimer::~RecurrentTimer() { + mStopRequested = true; + mLooper->removeMessages(mHandler); + mLooper->wake(); + if (mThread.joinable()) { + mThread.join(); + } +} + +int RecurrentTimer::getCallbackIdLocked(std::shared_ptr callback) { + const auto& it = mIdByCallback.find(callback); + if (it != mIdByCallback.end()) { + return it->second; + } + return INVALID_ID; +} + +void RecurrentTimer::registerTimerCallback(int64_t intervalInNanos, + std::shared_ptr callback) { + { + std::scoped_lock lockGuard(mLock); + + int callbackId = getCallbackIdLocked(callback); + + if (callbackId == INVALID_ID) { + callbackId = mCallbackId++; + mIdByCallback.insert({callback, callbackId}); + } else { + ALOGI("Replacing an existing timer callback with a new interval, current: %" PRId64 + " ns, new: %" PRId64 " ns", + mCallbackInfoById[callbackId]->intervalInNanos, intervalInNanos); + mLooper->removeMessages(mHandler, callbackId); + } + + // Aligns the nextTime to multiply of interval. + int64_t nextTimeInNanos = ceil(uptimeNanos() / intervalInNanos) * intervalInNanos; + + std::unique_ptr info = std::make_unique(); + info->callback = callback; + info->intervalInNanos = intervalInNanos; + info->nextTimeInNanos = nextTimeInNanos; + mCallbackInfoById.insert({callbackId, std::move(info)}); + + mLooper->sendMessageAtTime(nextTimeInNanos, mHandler, Message(callbackId)); + } +} + +void RecurrentTimer::unregisterTimerCallback(std::shared_ptr callback) { + { + std::scoped_lock lockGuard(mLock); + + int callbackId = getCallbackIdLocked(callback); + + if (callbackId == INVALID_ID) { + ALOGE("No event found to unregister"); + return; + } + + mLooper->removeMessages(mHandler, callbackId); + mCallbackInfoById.erase(callbackId); + mIdByCallback.erase(callback); + } +} + +void RecurrentTimer::handleMessage(const Message& message) { + std::shared_ptr callback; + { + std::scoped_lock lockGuard(mLock); + + int callbackId = message.what; + + auto it = mCallbackInfoById.find(callbackId); + if (it == mCallbackInfoById.end()) { + ALOGW("The event for callback ID: %d is outdated, ignore", callbackId); + return; + } + + CallbackInfo* callbackInfo = it->second.get(); + callback = callbackInfo->callback; + int64_t nowNanos = uptimeNanos(); + // intervalCount is the number of interval we have to advance until we pass now. + size_t intervalCount = + (nowNanos - callbackInfo->nextTimeInNanos) / callbackInfo->intervalInNanos + 1; + callbackInfo->nextTimeInNanos += intervalCount * callbackInfo->intervalInNanos; + + mLooper->sendMessageAtTime(callbackInfo->nextTimeInNanos, mHandler, Message(callbackId)); + } + + (*callback)(); +} + +void RecurrentMessageHandler::handleMessage(const Message& message) { + mTimer->handleMessage(message); +} + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/current/utils/common/src/VehicleObjectPool.cpp b/automotive/vehicle/aidl/impl/current/utils/common/src/VehicleObjectPool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7e0276739eeb2d6915347b29f98022558d30fe14 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/utils/common/src/VehicleObjectPool.cpp @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "VehicleObjectPool" + +#include + +#include + +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +using ::aidl::android::hardware::automotive::vehicle::RawPropValues; +using ::aidl::android::hardware::automotive::vehicle::VehicleProperty; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; + +VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtain(VehiclePropertyType type) { + if (isComplexType(type)) { + return obtain(type, 0); + } + return obtain(type, 1); +} + +VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtain(VehiclePropertyType type, + size_t vectorSize) { + if (isSingleValueType(type)) { + vectorSize = 1; + } else if (isComplexType(type)) { + vectorSize = 0; + } + return isDisposable(type, vectorSize) ? obtainDisposable(type, vectorSize) + : obtainRecyclable(type, vectorSize); +} + +VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtain(const VehiclePropValue& src) { + int propId = src.prop; + VehiclePropertyType type = getPropType(propId); + size_t vectorSize = getVehicleRawValueVectorSize(src.value, type); + auto dest = obtain(type, vectorSize); + + dest->prop = propId; + dest->areaId = src.areaId; + dest->status = src.status; + dest->timestamp = src.timestamp; + copyVehicleRawValue(&dest->value, src.value); + + return dest; +} + +VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainInt32(int32_t value) { + auto val = obtain(VehiclePropertyType::INT32); + val->value.int32Values[0] = value; + return val; +} + +VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainInt64(int64_t value) { + auto val = obtain(VehiclePropertyType::INT64); + val->value.int64Values[0] = value; + return val; +} + +VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainFloat(float value) { + auto val = obtain(VehiclePropertyType::FLOAT); + val->value.floatValues[0] = value; + return val; +} + +VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainString(const char* cstr) { + auto val = obtain(VehiclePropertyType::STRING); + val->value.stringValue = cstr; + return val; +} + +VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainComplex() { + return obtain(VehiclePropertyType::MIXED); +} + +VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainRecyclable( + VehiclePropertyType type, size_t vectorSize) { + std::scoped_lock lock(mLock); + assert(vectorSize > 0); + + // VehiclePropertyType is not overlapping with vectorSize. + int32_t key = static_cast(type) | static_cast(vectorSize); + auto it = mValueTypePools.find(key); + + if (it == mValueTypePools.end()) { + auto newPool(std::make_unique(type, vectorSize, mMaxPoolObjectsSize, + getVehiclePropValueSize)); + it = mValueTypePools.emplace(key, std::move(newPool)).first; + } + return it->second->obtain(); +} + +VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainBoolean(bool value) { + return obtainInt32(value); +} + +VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainDisposable( + VehiclePropertyType valueType, size_t vectorSize) const { + return RecyclableType{createVehiclePropValueVec(valueType, vectorSize).release(), + mDisposableDeleter}; +} + +void VehiclePropValuePool::InternalPool::recycle(VehiclePropValue* o) { + if (o == nullptr) { + ALOGE("Attempt to recycle nullptr"); + return; + } + + if (!check(&o->value)) { + ALOGE("Discarding value for prop 0x%x because it contains " + "data that is not consistent with this pool. " + "Expected type: %d, vector size: %zu", + o->prop, toInt(mPropType), mVectorSize); + delete o; + } else { + ObjectPool::recycle(o); + } +} + +bool VehiclePropValuePool::InternalPool::check(RawPropValues* v) { + return check(&v->int32Values, (VehiclePropertyType::INT32 == mPropType || + VehiclePropertyType::INT32_VEC == mPropType || + VehiclePropertyType::BOOLEAN == mPropType)) && + check(&v->floatValues, (VehiclePropertyType::FLOAT == mPropType || + VehiclePropertyType::FLOAT_VEC == mPropType)) && + check(&v->int64Values, (VehiclePropertyType::INT64 == mPropType || + VehiclePropertyType::INT64_VEC == mPropType)) && + check(&v->byteValues, VehiclePropertyType::BYTES == mPropType) && + v->stringValue.size() == 0; +} + +VehiclePropValue* VehiclePropValuePool::InternalPool::createObject() { + return createVehiclePropValueVec(mPropType, mVectorSize).release(); +} + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/current/utils/common/src/VehiclePropertyStore.cpp b/automotive/vehicle/aidl/impl/current/utils/common/src/VehiclePropertyStore.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c3a46c6dc8cbc4a79602a83bdbac2aa845797c9c --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/utils/common/src/VehiclePropertyStore.cpp @@ -0,0 +1,394 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "VehiclePropertyStore" +#include +#include + +#include "VehiclePropertyStore.h" + +#include +#include +#include +#include + +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +using ::aidl::android::hardware::automotive::vehicle::StatusCode; +using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; +using ::android::base::Result; +using ::android::base::StringPrintf; + +bool VehiclePropertyStore::RecordId::operator==(const VehiclePropertyStore::RecordId& other) const { + return area == other.area && token == other.token; +} + +std::string VehiclePropertyStore::RecordId::toString() const { + return StringPrintf("RecordID{{.areaId=% " PRId32 ", .token=%" PRId64 "}", area, token); +} + +size_t VehiclePropertyStore::RecordIdHash::operator()(RecordId const& recordId) const { + size_t res = 0; + hashCombine(res, recordId.area); + hashCombine(res, recordId.token); + return res; +} + +VehiclePropertyStore::~VehiclePropertyStore() { + std::scoped_lock lockGuard(mLock); + + // Recycling record requires mValuePool, so need to recycle them before destroying mValuePool. + mRecordsByPropId.clear(); + mValuePool.reset(); +} + +const VehiclePropertyStore::Record* VehiclePropertyStore::getRecordLocked(int32_t propId) const + REQUIRES(mLock) { + auto RecordIt = mRecordsByPropId.find(propId); + return RecordIt == mRecordsByPropId.end() ? nullptr : &RecordIt->second; +} + +VehiclePropertyStore::Record* VehiclePropertyStore::getRecordLocked(int32_t propId) + REQUIRES(mLock) { + auto RecordIt = mRecordsByPropId.find(propId); + return RecordIt == mRecordsByPropId.end() ? nullptr : &RecordIt->second; +} + +VehiclePropertyStore::RecordId VehiclePropertyStore::getRecordIdLocked( + const VehiclePropValue& propValue, const VehiclePropertyStore::Record& record) const + REQUIRES(mLock) { + VehiclePropertyStore::RecordId recId{ + .area = isGlobalProp(propValue.prop) ? 0 : propValue.areaId, .token = 0}; + + if (record.tokenFunction != nullptr) { + recId.token = record.tokenFunction(propValue); + } + return recId; +} + +VhalResult VehiclePropertyStore::readValueLocked( + const RecordId& recId, const Record& record) const REQUIRES(mLock) { + if (auto it = record.values.find(recId); it != record.values.end()) { + return mValuePool->obtain(*(it->second)); + } + return StatusError(StatusCode::NOT_AVAILABLE) + << "Record ID: " << recId.toString() << " is not found"; +} + +void VehiclePropertyStore::registerProperty(const VehiclePropConfig& config, + VehiclePropertyStore::TokenFunction tokenFunc) { + std::scoped_lock g(mLock); + + mRecordsByPropId[config.prop] = Record{ + .propConfig = config, + .tokenFunction = tokenFunc, + }; +} + +VhalResult VehiclePropertyStore::writeValue(VehiclePropValuePool::RecyclableType propValue, + bool updateStatus, + VehiclePropertyStore::EventMode eventMode, + bool useCurrentTimestamp) { + bool valueUpdated = true; + VehiclePropValue updatedValue; + OnValueChangeCallback onValueChangeCallback = nullptr; + OnValuesChangeCallback onValuesChangeCallback = nullptr; + int32_t propId; + int32_t areaId; + { + std::scoped_lock g(mLock); + + // Must set timestamp inside the lock to make sure no other writeValue will update the + // the timestamp to a newer one while we are writing this value. + if (useCurrentTimestamp) { + propValue->timestamp = elapsedRealtimeNano(); + } + + propId = propValue->prop; + areaId = propValue->areaId; + + VehiclePropertyStore::Record* record = getRecordLocked(propId); + if (record == nullptr) { + return StatusError(StatusCode::INVALID_ARG) + << "property: " << propId << " not registered"; + } + + if (!isGlobalProp(propId) && getAreaConfig(*propValue, record->propConfig) == nullptr) { + return StatusError(StatusCode::INVALID_ARG) + << "no config for property: " << propId << " area ID: " << propValue->areaId; + } + + VehiclePropertyStore::RecordId recId = getRecordIdLocked(*propValue, *record); + if (auto it = record->values.find(recId); it != record->values.end()) { + const VehiclePropValue* valueToUpdate = it->second.get(); + int64_t oldTimestampNanos = valueToUpdate->timestamp; + VehiclePropertyStatus oldStatus = valueToUpdate->status; + // propValue is outdated and drops it. + if (oldTimestampNanos > propValue->timestamp) { + return StatusError(StatusCode::INVALID_ARG) + << "outdated timestampNanos: " << propValue->timestamp; + } + if (!updateStatus) { + propValue->status = oldStatus; + } + + // areaId and propId must be the same between valueToUpdate and propValue. + valueUpdated = (valueToUpdate->value != propValue->value || + valueToUpdate->status != propValue->status); + } else if (!updateStatus) { + propValue->status = VehiclePropertyStatus::AVAILABLE; + } + + record->values[recId] = std::move(propValue); + + if (eventMode == EventMode::NEVER) { + return {}; + } + updatedValue = *(record->values[recId]); + + onValuesChangeCallback = mOnValuesChangeCallback; + onValueChangeCallback = mOnValueChangeCallback; + } + + if (onValuesChangeCallback == nullptr && onValueChangeCallback == nullptr) { + // No callback registered. + return {}; + } + + // Invoke the callback outside the lock to prevent dead-lock. + if (eventMode == EventMode::ALWAYS || valueUpdated) { + if (onValuesChangeCallback != nullptr) { + onValuesChangeCallback({updatedValue}); + } else { + onValueChangeCallback(updatedValue); + } + } + return {}; +} + +void VehiclePropertyStore::refreshTimestamp(int32_t propId, int32_t areaId, EventMode eventMode) { + std::unordered_map eventModeByPropIdAreaId; + PropIdAreaId propIdAreaId = { + .propId = propId, + .areaId = areaId, + }; + eventModeByPropIdAreaId[propIdAreaId] = eventMode; + refreshTimestamps(eventModeByPropIdAreaId); +} + +void VehiclePropertyStore::refreshTimestamps( + std::unordered_map eventModeByPropIdAreaId) { + std::vector updatedValues; + OnValuesChangeCallback onValuesChangeCallback = nullptr; + OnValueChangeCallback onValueChangeCallback = nullptr; + { + std::scoped_lock g(mLock); + + onValuesChangeCallback = mOnValuesChangeCallback; + onValueChangeCallback = mOnValueChangeCallback; + + for (const auto& [propIdAreaId, eventMode] : eventModeByPropIdAreaId) { + int32_t propId = propIdAreaId.propId; + int32_t areaId = propIdAreaId.areaId; + VehiclePropertyStore::Record* record = getRecordLocked(propId); + if (record == nullptr) { + continue; + } + + VehiclePropValue propValue = { + .areaId = areaId, + .prop = propId, + .value = {}, + }; + + VehiclePropertyStore::RecordId recId = getRecordIdLocked(propValue, *record); + if (auto it = record->values.find(recId); it != record->values.end()) { + it->second->timestamp = elapsedRealtimeNano(); + if (eventMode == EventMode::ALWAYS) { + updatedValues.push_back(*(it->second)); + } + } else { + continue; + } + } + } + + // Invoke the callback outside the lock to prevent dead-lock. + if (updatedValues.empty()) { + return; + } + if (!onValuesChangeCallback && !onValueChangeCallback) { + // If no callback is set, then we don't have to do anything. + for (const auto& updateValue : updatedValues) { + ALOGW("No callback registered, ignoring property update for propId: %" PRId32 + ", area ID: %" PRId32, + updateValue.prop, updateValue.areaId); + } + return; + } + if (onValuesChangeCallback != nullptr) { + onValuesChangeCallback(updatedValues); + } else { + // Fallback to use multiple onValueChangeCallback + for (const auto& updateValue : updatedValues) { + onValueChangeCallback(updateValue); + } + } +} + +void VehiclePropertyStore::removeValue(const VehiclePropValue& propValue) { + std::scoped_lock g(mLock); + + VehiclePropertyStore::Record* record = getRecordLocked(propValue.prop); + if (record == nullptr) { + return; + } + + VehiclePropertyStore::RecordId recId = getRecordIdLocked(propValue, *record); + if (auto it = record->values.find(recId); it != record->values.end()) { + record->values.erase(it); + } +} + +void VehiclePropertyStore::removeValuesForProperty(int32_t propId) { + std::scoped_lock g(mLock); + + VehiclePropertyStore::Record* record = getRecordLocked(propId); + if (record == nullptr) { + return; + } + + record->values.clear(); +} + +std::vector VehiclePropertyStore::readAllValues() const { + std::scoped_lock g(mLock); + + std::vector allValues; + + for (auto const& [_, record] : mRecordsByPropId) { + for (auto const& [_, value] : record.values) { + allValues.push_back(mValuePool->obtain(*value)); + } + } + + return allValues; +} + +VehiclePropertyStore::ValuesResultType VehiclePropertyStore::readValuesForProperty( + int32_t propId) const { + std::scoped_lock g(mLock); + + std::vector values; + + const VehiclePropertyStore::Record* record = getRecordLocked(propId); + if (record == nullptr) { + return StatusError(StatusCode::INVALID_ARG) << "property: " << propId << " not registered"; + } + + for (auto const& [_, value] : record->values) { + values.push_back(mValuePool->obtain(*value)); + } + return values; +} + +VehiclePropertyStore::ValueResultType VehiclePropertyStore::readValue( + const VehiclePropValue& propValue) const { + std::scoped_lock g(mLock); + + int32_t propId = propValue.prop; + const VehiclePropertyStore::Record* record = getRecordLocked(propId); + if (record == nullptr) { + return StatusError(StatusCode::INVALID_ARG) << "property: " << propId << " not registered"; + } + + VehiclePropertyStore::RecordId recId = getRecordIdLocked(propValue, *record); + return readValueLocked(recId, *record); +} + +VehiclePropertyStore::ValueResultType VehiclePropertyStore::readValue(int32_t propId, + int32_t areaId, + int64_t token) const { + std::scoped_lock g(mLock); + + const VehiclePropertyStore::Record* record = getRecordLocked(propId); + if (record == nullptr) { + return StatusError(StatusCode::INVALID_ARG) << "property: " << propId << " not registered"; + } + + VehiclePropertyStore::RecordId recId{.area = isGlobalProp(propId) ? 0 : areaId, .token = token}; + return readValueLocked(recId, *record); +} + +std::vector VehiclePropertyStore::getAllConfigs() const { + std::scoped_lock g(mLock); + + std::vector configs; + configs.reserve(mRecordsByPropId.size()); + for (auto& [_, config] : mRecordsByPropId) { + configs.push_back(config.propConfig); + } + return configs; +} + +VhalResult VehiclePropertyStore::getConfig(int32_t propId) const { + std::scoped_lock g(mLock); + + const VehiclePropertyStore::Record* record = getRecordLocked(propId); + if (record == nullptr) { + return StatusError(StatusCode::INVALID_ARG) << "property: " << propId << " not registered"; + } + + return &record->propConfig; +} + +VhalResult VehiclePropertyStore::getPropConfig(int32_t propId) const { + std::scoped_lock g(mLock); + + const VehiclePropertyStore::Record* record = getRecordLocked(propId); + if (record == nullptr) { + return StatusError(StatusCode::INVALID_ARG) << "property: " << propId << " not registered"; + } + + return record->propConfig; +} + +void VehiclePropertyStore::setOnValueChangeCallback( + const VehiclePropertyStore::OnValueChangeCallback& callback) { + std::scoped_lock g(mLock); + + mOnValueChangeCallback = callback; +} + +void VehiclePropertyStore::setOnValuesChangeCallback( + const VehiclePropertyStore::OnValuesChangeCallback& callback) { + std::scoped_lock g(mLock); + + mOnValuesChangeCallback = callback; +} + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/current/utils/common/src/VehicleUtils.cpp b/automotive/vehicle/aidl/impl/current/utils/common/src/VehicleUtils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7814c9993e145a52e14d8fa82aaf5be9116451c5 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/utils/common/src/VehicleUtils.cpp @@ -0,0 +1,316 @@ +/* + * Copyright (C) 2021 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 "VehicleUtils.h" + +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +using ::aidl::android::hardware::automotive::vehicle::StatusCode; +using ::aidl::android::hardware::automotive::vehicle::toString; +using ::aidl::android::hardware::automotive::vehicle::VehicleArea; +using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig; +using ::aidl::android::hardware::automotive::vehicle::VehicleAreaDoor; +using ::aidl::android::hardware::automotive::vehicle::VehicleAreaMirror; +using ::aidl::android::hardware::automotive::vehicle::VehicleAreaSeat; +using ::aidl::android::hardware::automotive::vehicle::VehicleAreaWheel; +using ::aidl::android::hardware::automotive::vehicle::VehicleAreaWindow; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig; +using ::aidl::android::hardware::automotive::vehicle::VehicleProperty; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; +using ::android::base::Error; +using ::android::base::Result; +using ::ndk::ScopedAStatus; + +namespace { + +class PropertyIdByNameSingleton { + public: + static PropertyIdByNameSingleton& getInstance() { + static PropertyIdByNameSingleton instance; + return instance; + } + + Result getPropertyId(const std::string& name) const { + auto it = mPropertyIdByName.find(name); + if (it == mPropertyIdByName.end()) { + return Error(); + } + return it->second; + } + + PropertyIdByNameSingleton(PropertyIdByNameSingleton const&) = delete; + void operator=(PropertyIdByNameSingleton const&) = delete; + + private: + std::unordered_map mPropertyIdByName; + + PropertyIdByNameSingleton() { + constexpr auto values = ndk::internal::enum_values; + for (unsigned int i = 0; i < values.size(); i++) { + mPropertyIdByName.emplace(toString(values[i]), toInt(values[i])); + } + } +}; + +class AreaByNameSingleton { + public: + static AreaByNameSingleton& getInstance() { + static AreaByNameSingleton instance; + return instance; + } + + Result getArea(const std::string& name, int32_t propId) const { + VehicleArea areaType = getPropArea(propId); + + auto mapIt = mAreaByNameByAreaType.find(areaType); + if (mapIt == mAreaByNameByAreaType.end()) { + return Error() << "Invalid area type for property ID: " << propIdToString(propId); + } + + const auto& areaByName = mapIt->second; + auto it = areaByName.find(name); + if (it == areaByName.end()) { + return Error() << "Invalid area name for property " << propIdToString(propId) << ": " + << name; + } + return it->second; + } + + AreaByNameSingleton(AreaByNameSingleton const&) = delete; + void operator=(AreaByNameSingleton const&) = delete; + + private: + std::unordered_map> mAreaByNameByAreaType; + + AreaByNameSingleton() { + populateMap(VehicleArea::WINDOW, ndk::internal::enum_values); + populateMap(VehicleArea::MIRROR, ndk::internal::enum_values); + populateMap(VehicleArea::SEAT, ndk::internal::enum_values); + populateMap(VehicleArea::DOOR, ndk::internal::enum_values); + populateMap(VehicleArea::WHEEL, ndk::internal::enum_values); + } + + template + void populateMap(VehicleArea areaType, std::array values) { + for (unsigned int i = 0; i < values.size(); i++) { + mAreaByNameByAreaType[areaType].emplace(toString(values[i]), toInt(values[i])); + } + } +}; + +} // namespace + +Result checkPropValue(const VehiclePropValue& value, const VehiclePropConfig* config) { + int32_t property = value.prop; + VehiclePropertyType type = getPropType(property); + switch (type) { + case VehiclePropertyType::BOOLEAN: + [[fallthrough]]; + case VehiclePropertyType::INT32: + if (value.value.int32Values.size() != 1) { + return Error() << "expect 1 int32Values for INT32 type"; + } + break; + case VehiclePropertyType::INT32_VEC: + if (value.value.int32Values.size() < 1) { + return Error() << "expect >=1 int32Values for INT32_VEC type"; + } + break; + case VehiclePropertyType::INT64: + if (value.value.int64Values.size() != 1) { + return Error() << "expect 1 int64Values for INT64 type"; + } + break; + case VehiclePropertyType::INT64_VEC: + if (value.value.int64Values.size() < 1) { + return Error() << "expect >=1 int64Values for INT64_VEC type"; + } + break; + case VehiclePropertyType::FLOAT: + if (value.value.floatValues.size() != 1) { + return Error() << "expect 1 floatValues for FLOAT type"; + } + break; + case VehiclePropertyType::FLOAT_VEC: + if (value.value.floatValues.size() < 1) { + return Error() << "expect >=1 floatValues for FLOAT_VEC type"; + } + break; + case VehiclePropertyType::BYTES: + // We allow setting an empty bytes array. + break; + case VehiclePropertyType::STRING: + // We allow setting an empty string. + break; + case VehiclePropertyType::MIXED: + if (getPropGroup(property) == VehiclePropertyGroup::VENDOR) { + // We only checks vendor mixed properties. + return checkVendorMixedPropValue(value, config); + } + break; + default: + return Error() << "unknown property type: " << toInt(type); + } + return {}; +} + +Result checkVendorMixedPropValue(const VehiclePropValue& value, + const VehiclePropConfig* config) { + auto configArray = config->configArray; + // configArray[0], 1 indicates the property has a String value, we allow the string value to + // be empty. + + size_t int32Count = 0; + // configArray[1], 1 indicates the property has a Boolean value. + if (configArray[1] == 1) { + int32Count++; + } + // configArray[2], 1 indicates the property has an Integer value. + if (configArray[2] == 1) { + int32Count++; + } + // configArray[3], the number indicates the size of Integer[] in the property. + int32Count += static_cast(configArray[3]); + size_t int32Size = value.value.int32Values.size(); + if (int32Size != int32Count) { + return Error() << "invalid mixed property, got " << int32Size << " int32Values, expect " + << int32Count; + } + + size_t int64Count = 0; + // configArray[4], 1 indicates the property has a Long value. + if (configArray[4] == 1) { + int64Count++; + } + // configArray[5], the number indicates the size of Long[] in the property. + int64Count += static_cast(configArray[5]); + size_t int64Size = value.value.int64Values.size(); + if (int64Size != int64Count) { + return Error() << "invalid mixed property, got " << int64Size << " int64Values, expect " + << int64Count; + } + + size_t floatCount = 0; + // configArray[6], 1 indicates the property has a Float value. + if (configArray[6] == 1) { + floatCount++; + } + // configArray[7], the number indicates the size of Float[] in the property. + floatCount += static_cast(configArray[7]); + size_t floatSize = value.value.floatValues.size(); + if (floatSize != floatCount) { + return Error() << "invalid mixed property, got " << floatSize << " floatValues, expect " + << floatCount; + } + + // configArray[8], the number indicates the size of byte[] in the property. + size_t byteSize = value.value.byteValues.size(); + size_t byteCount = static_cast(configArray[8]); + if (byteCount != 0 && byteSize != byteCount) { + return Error() << "invalid mixed property, got " << byteSize << " byteValues, expect " + << byteCount; + } + return {}; +} + +Result checkValueRange(const VehiclePropValue& value, const VehicleAreaConfig* areaConfig) { + if (areaConfig == nullptr) { + return {}; + } + int32_t property = value.prop; + VehiclePropertyType type = getPropType(property); + switch (type) { + case VehiclePropertyType::INT32: + [[fallthrough]]; + case VehiclePropertyType::INT32_VEC: + if (areaConfig->minInt32Value == 0 && areaConfig->maxInt32Value == 0) { + break; + } + for (int32_t int32Value : value.value.int32Values) { + if (int32Value < areaConfig->minInt32Value || + int32Value > areaConfig->maxInt32Value) { + return Error() << "int32Value: " << int32Value + << " out of range, min: " << areaConfig->minInt32Value + << " max: " << areaConfig->maxInt32Value; + } + } + break; + case VehiclePropertyType::INT64: + [[fallthrough]]; + case VehiclePropertyType::INT64_VEC: + if (areaConfig->minInt64Value == 0 && areaConfig->maxInt64Value == 0) { + break; + } + for (int64_t int64Value : value.value.int64Values) { + if (int64Value < areaConfig->minInt64Value || + int64Value > areaConfig->maxInt64Value) { + return Error() << "int64Value: " << int64Value + << " out of range, min: " << areaConfig->minInt64Value + << " max: " << areaConfig->maxInt64Value; + } + } + break; + case VehiclePropertyType::FLOAT: + [[fallthrough]]; + case VehiclePropertyType::FLOAT_VEC: + if (areaConfig->minFloatValue == 0.f && areaConfig->maxFloatValue == 0.f) { + break; + } + for (float floatValue : value.value.floatValues) { + if (floatValue < areaConfig->minFloatValue || + floatValue > areaConfig->maxFloatValue) { + return Error() << "floatValue: " << floatValue + << " out of range, min: " << areaConfig->minFloatValue + << " max: " << areaConfig->maxFloatValue; + } + } + break; + default: + // We don't check the rest of property types. Additional logic needs to be added if + // required in VehicleHardware, e.g. you might want to check the range for mixed + // property. + break; + } + return {}; +} + +StatusCode VhalError::value() const { + return mCode; +} + +std::string VhalError::print() const { + return aidl::android::hardware::automotive::vehicle::toString(mCode); +} + +Result stringToPropId(const std::string& propName) { + return PropertyIdByNameSingleton::getInstance().getPropertyId(propName); +} + +Result stringToArea(const std::string& areaName, int32_t propId) { + return AreaByNameSingleton::getInstance().getArea(areaName, propId); +} + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/utils/common/test/Android.bp b/automotive/vehicle/aidl/impl/current/utils/common/test/Android.bp similarity index 100% rename from automotive/vehicle/aidl/impl/utils/common/test/Android.bp rename to automotive/vehicle/aidl/impl/current/utils/common/test/Android.bp diff --git a/automotive/vehicle/aidl/impl/current/utils/common/test/PendingRequestPoolTest.cpp b/automotive/vehicle/aidl/impl/current/utils/common/test/PendingRequestPoolTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..734c7392a9a62ce98bf7f23f9b12e9e60550341c --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/utils/common/test/PendingRequestPoolTest.cpp @@ -0,0 +1,274 @@ +/* + * Copyright (C) 2021 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 "PendingRequestPool.h" + +#include +#include + +#include +#include + +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +using ::aidl::android::hardware::automotive::vehicle::StatusCode; + +using ::testing::ElementsAre; +using ::testing::UnorderedElementsAre; +using ::testing::WhenSorted; + +class PendingRequestPoolTest : public ::testing::Test { + public: + void SetUp() override { mPool = std::make_unique(TEST_TIMEOUT); } + + void TearDown() override { + if (mPool != nullptr) { + ASSERT_EQ(mPool->countPendingRequests(getTestClientId()), static_cast(0)) + << "at least one pending request still exists in the pool when finish"; + } + } + + PendingRequestPool* getPool() { return mPool.get(); } + + void destroyPool() { mPool.reset(); } + + int64_t getTimeout() { return TEST_TIMEOUT; } + + const void* getTestClientId() { return reinterpret_cast(0); } + + private: + // Test timeout is 0.1s. + static const int64_t TEST_TIMEOUT = 100000000; + + std::unique_ptr mPool; +}; + +TEST_F(PendingRequestPoolTest, testFinishAllRequests) { + std::mutex lock; + std::vector timeoutRequestIds; + + std::unordered_set requestIds; + for (int64_t i = 0; i < 10; i++) { + requestIds.insert(i); + } + + auto callback = std::make_shared( + [&lock, &timeoutRequestIds](const std::unordered_set& requests) { + std::scoped_lock lockGuard(lock); + for (int64_t request : requests) { + timeoutRequestIds.push_back(request); + } + }); + + ASSERT_RESULT_OK(getPool()->addRequests(getTestClientId(), requestIds, callback)); + + for (int64_t i = 0; i < 10; i++) { + ASSERT_TRUE(getPool()->isRequestPending(getTestClientId(), i)); + } + + for (int64_t i = 0; i < 10; i++) { + ASSERT_THAT(getPool()->tryFinishRequests(getTestClientId(), {i}), UnorderedElementsAre(i)); + } + + for (int64_t i = 0; i < 10; i++) { + ASSERT_FALSE(getPool()->isRequestPending(getTestClientId(), i)); + } +} + +TEST_F(PendingRequestPoolTest, testFinishHalfOfRequest) { + int64_t timeout = getTimeout(); + std::mutex lock; + std::vector timeoutRequestIds; + + std::unordered_set requestIds; + for (int64_t i = 0; i < 10; i++) { + requestIds.insert(i); + } + + auto callback = std::make_shared( + [&lock, &timeoutRequestIds](const std::unordered_set& requests) { + std::scoped_lock lockGuard(lock); + for (int64_t request : requests) { + timeoutRequestIds.push_back(request); + } + }); + + ASSERT_RESULT_OK(getPool()->addRequests(getTestClientId(), requestIds, callback)); + + for (int64_t i = 0; i < 10; i++) { + ASSERT_TRUE(getPool()->isRequestPending(getTestClientId(), i)); + } + + // Finish half of the requests. + requestIds.clear(); + for (int64_t i = 0; i < 5; i++) { + requestIds.insert(i); + } + + ASSERT_EQ(getPool()->tryFinishRequests(getTestClientId(), requestIds), requestIds); + + for (int64_t i = 0; i < 5; i++) { + ASSERT_FALSE(getPool()->isRequestPending(getTestClientId(), i)); + } + for (int64_t i = 5; i < 10; i++) { + ASSERT_TRUE(getPool()->isRequestPending(getTestClientId(), i)); + } + + // Wait until the unfinished requests timeout. The check interval is timeout, so at max we + // would wait an additional interval, which is 2 * timeout until the callback is called. + std::this_thread::sleep_for(2 * std::chrono::nanoseconds(timeout)); + + ASSERT_THAT(timeoutRequestIds, WhenSorted(ElementsAre(5, 6, 7, 8, 9))); +} + +TEST_F(PendingRequestPoolTest, testFinishRequestTwice) { + std::mutex lock; + std::vector timeoutRequestIds; + + auto callback = std::make_shared( + [&lock, &timeoutRequestIds](const std::unordered_set& requests) { + std::scoped_lock lockGuard(lock); + for (int64_t request : requests) { + timeoutRequestIds.push_back(request); + } + }); + + ASSERT_RESULT_OK(getPool()->addRequests(getTestClientId(), {0}, callback)); + + ASSERT_THAT(getPool()->tryFinishRequests(getTestClientId(), {0}), UnorderedElementsAre(0)) + << "failed to finish an added request"; + ASSERT_TRUE(getPool()->tryFinishRequests(getTestClientId(), {0}).empty()) + << "finish a request second time must return empty result"; +} + +TEST_F(PendingRequestPoolTest, testFinishRequestNonExistingId) { + std::mutex lock; + std::vector timeoutRequestIds; + + auto callback = std::make_shared( + [&lock, &timeoutRequestIds](const std::unordered_set& requests) { + std::scoped_lock lockGuard(lock); + for (int64_t request : requests) { + timeoutRequestIds.push_back(request); + } + }); + + ASSERT_RESULT_OK(getPool()->addRequests(getTestClientId(), {0, 1, 2}, callback)); + + ASSERT_THAT(getPool()->tryFinishRequests(getTestClientId(), {0, 1, 2, 3}), + UnorderedElementsAre(0, 1, 2)) + << "finished request IDs must not contain non-existing request ID"; + // Even though one of the request to finish does not exist, the rest of the requests should be + // finished. + ASSERT_EQ(getPool()->countPendingRequests(getTestClientId()), static_cast(0)) + << "requests not being finished correctly"; +} + +TEST_F(PendingRequestPoolTest, testFinishAfterTimeout) { + std::mutex lock; + std::vector timeoutRequestIds; + + auto callback = std::make_shared( + [&lock, &timeoutRequestIds](const std::unordered_set& requests) { + std::scoped_lock lockGuard(lock); + for (int64_t request : requests) { + timeoutRequestIds.push_back(request); + } + }); + + ASSERT_RESULT_OK(getPool()->addRequests(getTestClientId(), {0}, callback)); + + std::this_thread::sleep_for(2 * std::chrono::nanoseconds(getTimeout())); + + ASSERT_TRUE(getPool()->tryFinishRequests(getTestClientId(), {0}).empty()) + << "finish a request after timeout must do nothing"; +} + +TEST_F(PendingRequestPoolTest, testDestroyWithPendingRequests) { + std::mutex lock; + std::vector timeoutRequestIds; + + auto callback = std::make_shared( + [&lock, &timeoutRequestIds](const std::unordered_set& requests) { + std::scoped_lock lockGuard(lock); + for (int64_t request : requests) { + timeoutRequestIds.push_back(request); + } + }); + + ASSERT_RESULT_OK(getPool()->addRequests(getTestClientId(), {0}, callback)); + + destroyPool(); + + // Before the pool is destroyed, the pending requests should be notified as timeout. + ASSERT_THAT(timeoutRequestIds, UnorderedElementsAre(0)) + << "timeout not triggered when the pool is destroyed"; +} + +TEST_F(PendingRequestPoolTest, testDuplicateRequestId) { + auto callback = std::make_shared( + [](std::unordered_set) {}); + + ASSERT_RESULT_OK(getPool()->addRequests(getTestClientId(), {0}, callback)); + ASSERT_FALSE(getPool()->addRequests(getTestClientId(), {1, 2, 0}, callback).ok()) + << "adding duplicate request IDs must fail"; + + ASSERT_THAT(getPool()->tryFinishRequests(getTestClientId(), {0}), UnorderedElementsAre(0)); +} + +TEST_F(PendingRequestPoolTest, testSameRequestIdForDifferentClient) { + auto callback = std::make_shared( + [](std::unordered_set) {}); + + ASSERT_RESULT_OK(getPool()->addRequests(reinterpret_cast(0), {0}, callback)); + ASSERT_RESULT_OK(getPool()->addRequests(reinterpret_cast(1), {1, 2, 0}, callback)); + + ASSERT_THAT(getPool()->tryFinishRequests(reinterpret_cast(0), {0}), + UnorderedElementsAre(0)); + ASSERT_THAT(getPool()->tryFinishRequests(reinterpret_cast(1), {1, 2, 0}), + UnorderedElementsAre(0, 1, 2)); +} + +TEST_F(PendingRequestPoolTest, testPendingRequestCountLimit) { + auto callback = std::make_shared( + [](std::unordered_set) {}); + + std::unordered_set requests; + + // MAX_PENDING_REQUEST_PER_CLIENT = 10000 + for (size_t i = 0; i < 10000; i++) { + requests.insert(static_cast(i)); + } + ASSERT_RESULT_OK(getPool()->addRequests(reinterpret_cast(0), requests, callback)); + + auto result = getPool()->addRequests(reinterpret_cast(0), + {static_cast(10000)}, callback); + ASSERT_FALSE(result.ok()) << "adding more pending requests than limit must fail"; + ASSERT_EQ(result.error().code(), StatusCode::TRY_AGAIN); + + getPool()->tryFinishRequests(reinterpret_cast(0), requests); +} + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/current/utils/common/test/RecurrentTimerTest.cpp b/automotive/vehicle/aidl/impl/current/utils/common/test/RecurrentTimerTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e8ac2a5b3800747346be9c37f2b021299d6cb99a --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/utils/common/test/RecurrentTimerTest.cpp @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2021 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 "RecurrentTimer.h" + +#include +#include +#include + +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +using ::android::base::ScopedLockAssertion; + +class RecurrentTimerTest : public testing::Test { + public: + std::shared_ptr getCallback(size_t token) { + return std::make_shared([this, token] { + std::scoped_lock lockGuard(mLock); + + mCallbacks.push_back(token); + mCond.notify_all(); + }); + } + + bool waitForCalledCallbacks(size_t count, size_t timeoutInMs) { + std::unique_lock uniqueLock(mLock); + return mCond.wait_for(uniqueLock, std::chrono::milliseconds(timeoutInMs), [this, count] { + ScopedLockAssertion lockAssertion(mLock); + return mCallbacks.size() >= count; + }); + } + + std::vector getCalledCallbacks() { + std::scoped_lock lockGuard(mLock); + return mCallbacks; + } + + void clearCalledCallbacks() { + std::scoped_lock lockGuard(mLock); + mCallbacks.clear(); + } + + size_t countCallbackInfoById(RecurrentTimer* timer) { + std::scoped_lock lockGuard(timer->mLock); + return timer->mCallbackInfoById.size(); + } + + size_t countIdByCallback(RecurrentTimer* timer) { + std::scoped_lock lockGuard(timer->mLock); + return timer->mIdByCallback.size(); + } + + private: + std::condition_variable mCond; + std::mutex mLock; + std::vector mCallbacks GUARDED_BY(mLock); +}; + +TEST_F(RecurrentTimerTest, testRegisterCallback) { + RecurrentTimer timer; + // 0.1s + int64_t interval = 100000000; + + auto action = getCallback(0); + timer.registerTimerCallback(interval, action); + + // Should only takes 1s, use 5s as timeout to be safe. + ASSERT_TRUE(waitForCalledCallbacks(/* count= */ 10u, /* timeoutInMs= */ 5000)) + << "Not enough callbacks called before timeout"; + + timer.unregisterTimerCallback(action); +} + +TEST_F(RecurrentTimerTest, testRegisterUnregisterRegister) { + RecurrentTimer timer; + // 0.1s + int64_t interval = 100000000; + + auto action = getCallback(0); + timer.registerTimerCallback(interval, action); + + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + + timer.unregisterTimerCallback(action); + + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + + clearCalledCallbacks(); + + timer.registerTimerCallback(interval, action); + + // Should only takes 1s, use 5s as timeout to be safe. + ASSERT_TRUE(waitForCalledCallbacks(/* count= */ 10u, /* timeoutInMs= */ 5000)) + << "Not enough callbacks called before timeout"; + + timer.unregisterTimerCallback(action); + + ASSERT_EQ(countCallbackInfoById(&timer), 0u); + ASSERT_EQ(countIdByCallback(&timer), 0u); +} + +TEST_F(RecurrentTimerTest, testDestroyTimerWithCallback) { + std::unique_ptr timer = std::make_unique(); + // 0.1s + int64_t interval = 100000000; + + auto action = getCallback(0); + timer->registerTimerCallback(interval, action); + + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + + timer.reset(); + + clearCalledCallbacks(); + + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + + // Should be 0, but in rare cases there might be 1 events in the queue while the timer is + // being destroyed. + ASSERT_LE(getCalledCallbacks().size(), 1u); +} + +TEST_F(RecurrentTimerTest, testRegisterMultipleCallbacks) { + RecurrentTimer timer; + // 0.1s + int64_t interval1 = 100000000; + auto action1 = getCallback(1); + timer.registerTimerCallback(interval1, action1); + // 0.05s + int64_t interval2 = 50000000; + auto action2 = getCallback(2); + timer.registerTimerCallback(interval2, action2); + // 0.03s + int64_t interval3 = 30000000; + auto action3 = getCallback(3); + timer.registerTimerCallback(interval3, action3); + + // In 1s, we should generate 10 + 20 + 33 = 63 events. + // Here we are waiting for more events to make sure we receive enough events for each actions. + // Use 5s as timeout to be safe. + ASSERT_TRUE(waitForCalledCallbacks(/* count= */ 70u, /* timeoutInMs= */ 5000)) + << "Not enough callbacks called before timeout"; + + timer.unregisterTimerCallback(action1); + timer.unregisterTimerCallback(action2); + timer.unregisterTimerCallback(action3); + + size_t action1Count = 0; + size_t action2Count = 0; + size_t action3Count = 0; + for (size_t token : getCalledCallbacks()) { + if (token == 1) { + action1Count++; + } + if (token == 2) { + action2Count++; + } + if (token == 3) { + action3Count++; + } + } + + ASSERT_GE(action1Count, static_cast(10)); + ASSERT_GE(action2Count, static_cast(20)); + ASSERT_GE(action3Count, static_cast(33)); +} + +TEST_F(RecurrentTimerTest, testRegisterSameCallbackMultipleTimes) { + RecurrentTimer timer; + // 0.2s + int64_t interval1 = 200'000'000; + // 0.1s + int64_t interval2 = 100'000'000; + + auto action = getCallback(0); + for (int i = 0; i < 10; i++) { + timer.registerTimerCallback(interval1, action); + timer.registerTimerCallback(interval2, action); + } + + clearCalledCallbacks(); + + // Should only takes 1s, use 5s as timeout to be safe. + ASSERT_TRUE(waitForCalledCallbacks(/* count= */ 10u, /* timeoutInMs= */ 5000)) + << "Not enough callbacks called before timeout"; + + timer.unregisterTimerCallback(action); + + ASSERT_EQ(countCallbackInfoById(&timer), 0u); + ASSERT_EQ(countIdByCallback(&timer), 0u); +} + +TEST_F(RecurrentTimerTest, testRegisterCallbackMultipleTimesNoDeadLock) { + // We want to avoid the following situation: + // Caller holds a lock while calling registerTimerCallback, registerTimerCallback will try + // to obtain an internal lock inside timer. + // Meanwhile an recurrent action happens with timer holding an internal lock. The action + // tries to obtain the lock currently hold by the caller. + // The solution is that while calling recurrent actions, timer must not hold the internal lock. + + std::unique_ptr timer = std::make_unique(); + std::mutex lock; + for (size_t i = 0; i < 1000; i++) { + std::scoped_lock lockGuard(lock); + auto action = std::make_shared([&lock] { + // While calling this function, the timer must not hold lock in order not to dead + // lock. + std::scoped_lock lockGuard(lock); + }); + // 10ms + int64_t interval = 10'000'000; + timer->registerTimerCallback(interval, action); + // Sleep for a little while to let the recurrent actions begin. + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + // Make sure we stop the timer before we destroy lock. + timer.reset(); +} + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/current/utils/common/test/VehicleObjectPoolTest.cpp b/automotive/vehicle/aidl/impl/current/utils/common/test/VehicleObjectPoolTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6226e8943c008a8d336abf0862cce5efd3943b62 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/utils/common/test/VehicleObjectPoolTest.cpp @@ -0,0 +1,395 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +#include + +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +namespace { + +using ::aidl::android::hardware::automotive::vehicle::VehicleProperty; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; + +struct TestPropertyTypeInfo { + VehiclePropertyType type; + bool recyclable; + size_t vecSize; +}; + +std::vector getAllPropertyTypes() { + return { + { + .type = VehiclePropertyType::INT32, + .recyclable = true, + .vecSize = 1, + }, + { + .type = VehiclePropertyType::INT64, + .recyclable = true, + .vecSize = 1, + }, + { + .type = VehiclePropertyType::FLOAT, + .recyclable = true, + .vecSize = 1, + }, + { + .type = VehiclePropertyType::INT32_VEC, + .recyclable = true, + .vecSize = 4, + }, + { + .type = VehiclePropertyType::INT64_VEC, + .recyclable = true, + .vecSize = 4, + }, + { + .type = VehiclePropertyType::FLOAT_VEC, + .recyclable = true, + .vecSize = 4, + }, + { + .type = VehiclePropertyType::BYTES, + .recyclable = true, + .vecSize = 4, + }, + { + .type = VehiclePropertyType::INT32_VEC, + .recyclable = false, + .vecSize = 5, + }, + { + .type = VehiclePropertyType::INT64_VEC, + .recyclable = false, + .vecSize = 5, + }, + { + .type = VehiclePropertyType::FLOAT_VEC, + .recyclable = false, + .vecSize = 5, + }, + { + .type = VehiclePropertyType::BYTES, + .recyclable = false, + .vecSize = 5, + }, + { + .type = VehiclePropertyType::STRING, + .recyclable = false, + .vecSize = 0, + }, + { + .type = VehiclePropertyType::MIXED, + .recyclable = false, + .vecSize = 0, + }, + }; +} + +} // namespace + +class VehicleObjectPoolTest : public ::testing::Test { + protected: + void SetUp() override { + mStats = PoolStats::instance(); + resetStats(); + mValuePool.reset(new VehiclePropValuePool); + } + + void TearDown() override { + // At the end, all created objects should be either recycled or deleted. + ASSERT_EQ(mStats->Obtained, mStats->Recycled + mStats->Deleted); + // Some objects could be recycled multiple times. + ASSERT_LE(mStats->Created, mStats->Recycled + mStats->Deleted); + } + + PoolStats* mStats; + std::unique_ptr mValuePool; + + private: + void resetStats() { + mStats->Obtained = 0; + mStats->Created = 0; + mStats->Recycled = 0; + mStats->Deleted = 0; + } +}; + +class VehiclePropertyTypesTest : public VehicleObjectPoolTest, + public testing::WithParamInterface {}; + +TEST_P(VehiclePropertyTypesTest, testRecycle) { + auto info = GetParam(); + if (!info.recyclable) { + GTEST_SKIP(); + } + + auto value = mValuePool->obtain(info.type, info.vecSize); + void* raw = value.get(); + value.reset(); + // At this point, value should be recycled and the only object in the pool. + ASSERT_EQ(mValuePool->obtain(info.type, info.vecSize).get(), raw); + + ASSERT_EQ(mStats->Obtained, 2u); + ASSERT_EQ(mStats->Created, 1u); +} + +TEST_P(VehiclePropertyTypesTest, testNotRecyclable) { + auto info = GetParam(); + if (info.recyclable) { + GTEST_SKIP(); + } + + auto value = mValuePool->obtain(info.type, info.vecSize); + + ASSERT_EQ(mStats->Obtained, 0u) << "Non recyclable object should not be obtained from the pool"; + ASSERT_EQ(mStats->Created, 0u) << "Non recyclable object should not be created from the pool"; +} + +INSTANTIATE_TEST_SUITE_P(AllPropertyTypes, VehiclePropertyTypesTest, + ::testing::ValuesIn(getAllPropertyTypes())); + +TEST_F(VehicleObjectPoolTest, testObtainNewObject) { + auto value = mValuePool->obtain(VehiclePropertyType::INT32); + void* raw = value.get(); + value.reset(); + // At this point, value should be recycled and the only object in the pool. + ASSERT_EQ(mValuePool->obtain(VehiclePropertyType::INT32).get(), raw); + // Obtaining value of another type - should return a new object + ASSERT_NE(mValuePool->obtain(VehiclePropertyType::FLOAT).get(), raw); + + ASSERT_EQ(mStats->Obtained, 3u); + ASSERT_EQ(mStats->Created, 2u); +} + +TEST_F(VehicleObjectPoolTest, testObtainStrings) { + mValuePool->obtain(VehiclePropertyType::STRING); + auto stringProp = mValuePool->obtain(VehiclePropertyType::STRING); + stringProp->value.stringValue = "Hello"; + void* raw = stringProp.get(); + stringProp.reset(); // delete the pointer + + auto newStringProp = mValuePool->obtain(VehiclePropertyType::STRING); + + ASSERT_EQ(newStringProp->value.stringValue.size(), 0u); + ASSERT_NE(mValuePool->obtain(VehiclePropertyType::STRING).get(), raw); + ASSERT_EQ(mStats->Obtained, 0u); +} + +TEST_F(VehicleObjectPoolTest, testObtainBoolean) { + auto prop = mValuePool->obtainBoolean(true); + + ASSERT_NE(prop, nullptr); + ASSERT_EQ(*prop, (VehiclePropValue{ + .value = {.int32Values = {1}}, + })); +} + +TEST_F(VehicleObjectPoolTest, testObtainInt32) { + auto prop = mValuePool->obtainInt32(1234); + + ASSERT_NE(prop, nullptr); + ASSERT_EQ(*prop, (VehiclePropValue{ + .value = {.int32Values = {1234}}, + })); +} + +TEST_F(VehicleObjectPoolTest, testObtainInt64) { + auto prop = mValuePool->obtainInt64(1234); + + ASSERT_NE(prop, nullptr); + ASSERT_EQ(*prop, (VehiclePropValue{ + .value = {.int64Values = {1234}}, + })); +} + +TEST_F(VehicleObjectPoolTest, testObtainFloat) { + auto prop = mValuePool->obtainFloat(1.234); + + ASSERT_NE(prop, nullptr); + ASSERT_EQ(*prop, (VehiclePropValue{ + .value = {.floatValues = {1.234}}, + })); +} + +TEST_F(VehicleObjectPoolTest, testObtainString) { + auto prop = mValuePool->obtainString("test"); + + ASSERT_NE(prop, nullptr); + ASSERT_EQ(*prop, (VehiclePropValue{ + .value = {.stringValue = "test"}, + })); +} + +TEST_F(VehicleObjectPoolTest, testObtainComplex) { + auto prop = mValuePool->obtainComplex(); + + ASSERT_NE(prop, nullptr); + ASSERT_EQ(*prop, VehiclePropValue{}); +} + +TEST_F(VehicleObjectPoolTest, testObtainCopyInt32Values) { + VehiclePropValue prop{ + // INT32_VEC property. + .prop = toInt(VehicleProperty::INFO_FUEL_TYPE), + .areaId = 2, + .timestamp = 3, + .value = {.int32Values = {1, 2, 3, 4}}, + }; + auto gotValue = mValuePool->obtain(prop); + + ASSERT_NE(gotValue, nullptr); + ASSERT_EQ(*gotValue, prop); +} + +TEST_F(VehicleObjectPoolTest, testObtainCopyInt32ValuesEmptyArray) { + VehiclePropValue prop{ + // INT32_VEC property. + .prop = toInt(VehicleProperty::INFO_FUEL_TYPE), + .areaId = 2, + .timestamp = 3, + .value = {.int32Values = {}}, + }; + auto gotValue = mValuePool->obtain(prop); + + ASSERT_NE(gotValue, nullptr); + ASSERT_EQ(*gotValue, prop); +} + +TEST_F(VehicleObjectPoolTest, testObtainCopyInt64Values) { + VehiclePropValue prop{ + // INT64_VEC property. + .prop = toInt(VehicleProperty::WHEEL_TICK), + .areaId = 2, + .timestamp = 3, + .value = {.int64Values = {1, 2, 3, 4}}, + }; + auto gotValue = mValuePool->obtain(prop); + + ASSERT_NE(gotValue, nullptr); + ASSERT_EQ(*gotValue, prop); +} + +TEST_F(VehicleObjectPoolTest, testObtainCopyFloatValues) { + VehiclePropValue prop{ + // FLOAT_VEC property. + .prop = toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION), + .areaId = 2, + .timestamp = 3, + .value = {.floatValues = {1, 2, 3, 4}}, + }; + auto gotValue = mValuePool->obtain(prop); + + ASSERT_NE(gotValue, nullptr); + ASSERT_EQ(*gotValue, prop); +} + +TEST_F(VehicleObjectPoolTest, testObtainCopyString) { + VehiclePropValue prop{ + // STRING property. + .prop = toInt(VehicleProperty::INFO_VIN), + .areaId = 2, + .timestamp = 3, + .value = {.stringValue = "test"}, + }; + auto gotValue = mValuePool->obtain(prop); + + ASSERT_NE(gotValue, nullptr); + ASSERT_EQ(*gotValue, prop); +} + +TEST_F(VehicleObjectPoolTest, testObtainCopyMixed) { + VehiclePropValue prop{ + // MIxed property. + .prop = toInt(VehicleProperty::VEHICLE_MAP_SERVICE), + .areaId = 2, + .timestamp = 3, + .value = + { + .int32Values = {1, 2, 3}, + .floatValues = {4.0, 5.0}, + .stringValue = "test", + }, + }; + auto gotValue = mValuePool->obtain(prop); + + ASSERT_NE(gotValue, nullptr); + ASSERT_EQ(*gotValue, prop); +} + +TEST_F(VehicleObjectPoolTest, testMultithreaded) { + // In this test we have T threads that concurrently in C cycles + // obtain and release O VehiclePropValue objects of FLOAT / INT32 types. + + const int T = 2; + const int C = 500; + const int O = 100; + + auto poolPtr = mValuePool.get(); + + std::vector threads; + for (int i = 0; i < T; i++) { + threads.push_back(std::thread([&poolPtr]() { + for (int j = 0; j < C; j++) { + std::vector> vec; + for (int k = 0; k < O; k++) { + vec.push_back(poolPtr->obtain(k % 2 == 0 ? VehiclePropertyType::FLOAT + : VehiclePropertyType::INT32)); + } + } + })); + } + + for (auto& t : threads) { + t.join(); + } + + ASSERT_EQ(mStats->Obtained, static_cast(T * C * O)); + ASSERT_EQ(mStats->Recycled + mStats->Deleted, static_cast(T * C * O)); + // Created less than obtained in one cycle. + ASSERT_LE(mStats->Created, static_cast(T * O)); +} + +TEST_F(VehicleObjectPoolTest, testMemoryLimitation) { + std::vector> vec; + for (size_t i = 0; i < 10000; i++) { + vec.push_back(mValuePool->obtain(VehiclePropertyType::INT32)); + } + // We have too many values, not all of them would be recycled, some of them will be deleted. + vec.clear(); + + ASSERT_EQ(mStats->Obtained, 10000u); + ASSERT_EQ(mStats->Created, 10000u); + ASSERT_GT(mStats->Deleted, 0u) << "expect some values to be deleted, not recycled if too many " + "values are in the pool"; +} + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/current/utils/common/test/VehiclePropertyStoreTest.cpp b/automotive/vehicle/aidl/impl/current/utils/common/test/VehiclePropertyStoreTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..22f5c7391ff03e8021038a8342230426d0b8c61e --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/utils/common/test/VehiclePropertyStoreTest.cpp @@ -0,0 +1,661 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +namespace { + +using ::aidl::android::hardware::automotive::vehicle::StatusCode; +using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig; +using ::aidl::android::hardware::automotive::vehicle::VehicleProperty; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyChangeMode; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; +using ::testing::ElementsAre; +using ::testing::Eq; +using ::testing::WhenSortedBy; + +constexpr int INVALID_PROP_ID = 0; + +struct PropValueCmp { + bool operator()(const VehiclePropValue& a, const VehiclePropValue& b) const { + return (a.prop < b.prop) || ((a.prop == b.prop) && (a.value < b.value)) || + ((a.prop == b.prop) && (a.value == b.value) && (a.areaId < b.areaId)); + } +} propValueCmp; + +int64_t timestampToken(const VehiclePropValue& value) { + return value.timestamp; +} + +// A helper function to turn value pointer to value structure for easier comparison. +std::vector convertValuePtrsToValues( + const std::vector& values) { + std::vector returnValues; + returnValues.reserve(values.size()); + for (auto& value : values) { + returnValues.push_back(*value); + } + return returnValues; +} + +} // namespace + +class VehiclePropertyStoreTest : public ::testing::Test { + protected: + void SetUp() override { + mConfigFuelCapacity = { + .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY), + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::STATIC, + }; + VehiclePropConfig configTirePressure = { + .prop = toInt(VehicleProperty::TIRE_PRESSURE), + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::CONTINUOUS, + .areaConfigs = {VehicleAreaConfig{.areaId = WHEEL_FRONT_LEFT}, + VehicleAreaConfig{.areaId = WHEEL_FRONT_RIGHT}, + VehicleAreaConfig{.areaId = WHEEL_REAR_LEFT}, + VehicleAreaConfig{.areaId = WHEEL_REAR_RIGHT}}, + }; + mValuePool = std::make_shared(); + mStore.reset(new VehiclePropertyStore(mValuePool)); + mStore->registerProperty(mConfigFuelCapacity); + mStore->registerProperty(configTirePressure); + } + + VehiclePropConfig mConfigFuelCapacity; + std::shared_ptr mValuePool; + std::unique_ptr mStore; +}; + +TEST_F(VehiclePropertyStoreTest, testGetAllConfigs) { + std::vector configs = mStore->getAllConfigs(); + + ASSERT_EQ(configs.size(), static_cast(2)); +} + +TEST_F(VehiclePropertyStoreTest, testGetPropConfig) { + VhalResult result = + mStore->getPropConfig(toInt(VehicleProperty::INFO_FUEL_CAPACITY)); + + ASSERT_RESULT_OK(result); + ASSERT_EQ(result.value(), mConfigFuelCapacity); +} + +TEST_F(VehiclePropertyStoreTest, testGetPropConfigWithInvalidPropId) { + VhalResult result = mStore->getPropConfig(INVALID_PROP_ID); + + EXPECT_FALSE(result.ok()) << "expect error when getting a config for an invalid property ID"; + EXPECT_EQ(result.error().code(), StatusCode::INVALID_ARG); +} + +std::vector getTestPropValues() { + VehiclePropValue fuelCapacity = { + .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY), + .value = {.floatValues = {1.0}}, + }; + + VehiclePropValue leftTirePressure = { + .prop = toInt(VehicleProperty::TIRE_PRESSURE), + .value = {.floatValues = {170.0}}, + .areaId = WHEEL_FRONT_LEFT, + }; + + VehiclePropValue rightTirePressure = { + .prop = toInt(VehicleProperty::TIRE_PRESSURE), + .value = {.floatValues = {180.0}}, + .areaId = WHEEL_FRONT_RIGHT, + }; + + return {fuelCapacity, leftTirePressure, rightTirePressure}; +} + +TEST_F(VehiclePropertyStoreTest, testWriteValueOk) { + auto values = getTestPropValues(); + + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(values[0]))); +} + +TEST_F(VehiclePropertyStoreTest, testReadAllValues) { + auto values = getTestPropValues(); + for (const auto& value : values) { + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(value))); + } + + auto gotValues = mStore->readAllValues(); + + ASSERT_THAT(convertValuePtrsToValues(gotValues), WhenSortedBy(propValueCmp, Eq(values))); +} + +TEST_F(VehiclePropertyStoreTest, testReadValuesForPropertyOneValue) { + auto values = getTestPropValues(); + for (const auto& value : values) { + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(value))); + } + + auto result = mStore->readValuesForProperty(toInt(VehicleProperty::INFO_FUEL_CAPACITY)); + + ASSERT_RESULT_OK(result); + ASSERT_THAT(convertValuePtrsToValues(result.value()), ElementsAre(values[0])); +} + +TEST_F(VehiclePropertyStoreTest, testReadValuesForPropertyMultipleValues) { + auto values = getTestPropValues(); + for (const auto& value : values) { + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(value))); + } + + auto result = mStore->readValuesForProperty(toInt(VehicleProperty::TIRE_PRESSURE)); + + ASSERT_RESULT_OK(result); + ASSERT_THAT(convertValuePtrsToValues(result.value()), + WhenSortedBy(propValueCmp, ElementsAre(values[1], values[2]))); +} + +TEST_F(VehiclePropertyStoreTest, testReadValuesForPropertyError) { + auto result = mStore->readValuesForProperty(INVALID_PROP_ID); + + EXPECT_FALSE(result.ok()) << "expect error when reading values for an invalid property"; + EXPECT_EQ(result.error().code(), StatusCode::INVALID_ARG); +} + +TEST_F(VehiclePropertyStoreTest, testReadValueOk) { + auto values = getTestPropValues(); + for (const auto& value : values) { + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(value))); + } + + VehiclePropValue requestValue = { + .prop = toInt(VehicleProperty::TIRE_PRESSURE), + .areaId = WHEEL_FRONT_LEFT, + }; + + auto result = mStore->readValue(requestValue); + + ASSERT_RESULT_OK(result); + ASSERT_EQ(*(result.value()), values[1]); +} + +TEST_F(VehiclePropertyStoreTest, testReadValueByPropIdOk) { + auto values = getTestPropValues(); + for (const auto& value : values) { + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(value))); + } + + auto result = mStore->readValue(toInt(VehicleProperty::TIRE_PRESSURE), WHEEL_FRONT_RIGHT); + + ASSERT_EQ(*(result.value()), values[2]); +} + +TEST_F(VehiclePropertyStoreTest, testReadValueError) { + auto values = getTestPropValues(); + for (const auto& value : values) { + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(value))); + } + + auto result = mStore->readValue(toInt(VehicleProperty::TIRE_PRESSURE), WHEEL_REAR_LEFT); + + EXPECT_FALSE(result.ok()) << "expect error when reading a value that has not been written"; + EXPECT_EQ(result.error().code(), StatusCode::NOT_AVAILABLE); +} + +TEST_F(VehiclePropertyStoreTest, testWriteValueError) { + auto v = mValuePool->obtain(VehiclePropertyType::FLOAT); + v->prop = INVALID_PROP_ID; + v->value.floatValues = {1.0}; + + auto result = mStore->writeValue(std::move(v)); + + EXPECT_FALSE(result.ok()) << "expect error when writing value for an invalid property ID"; + EXPECT_EQ(result.error().code(), StatusCode::INVALID_ARG); +} + +TEST_F(VehiclePropertyStoreTest, testWriteValueNoAreaConfig) { + auto v = mValuePool->obtain(VehiclePropertyType::FLOAT); + v->prop = toInt(VehicleProperty::TIRE_PRESSURE); + v->value.floatValues = {1.0}; + // There is no config for ALL_WHEELS. + v->areaId = ALL_WHEELS; + + auto result = mStore->writeValue(std::move(v)); + + EXPECT_FALSE(result.ok()) << "expect error when writing value for an area without config"; + EXPECT_EQ(result.error().code(), StatusCode::INVALID_ARG); +} + +TEST_F(VehiclePropertyStoreTest, testWriteOutdatedValue) { + auto v = mValuePool->obtain(VehiclePropertyType::FLOAT); + v->timestamp = 1; + v->prop = toInt(VehicleProperty::TIRE_PRESSURE); + v->value.floatValues = {180.0}; + v->areaId = WHEEL_FRONT_LEFT; + ASSERT_RESULT_OK(mStore->writeValue(std::move(v))); + + // Write an older value. + auto v2 = mValuePool->obtain(VehiclePropertyType::FLOAT); + v2->timestamp = 0; + v2->prop = toInt(VehicleProperty::TIRE_PRESSURE); + v2->value.floatValues = {180.0}; + v2->areaId = WHEEL_FRONT_LEFT; + + auto result = mStore->writeValue(std::move(v2)); + + EXPECT_FALSE(result.ok()) << "expect error when writing an outdated value"; + EXPECT_EQ(result.error().code(), StatusCode::INVALID_ARG); +} + +TEST_F(VehiclePropertyStoreTest, testToken) { + int propId = toInt(VehicleProperty::INFO_FUEL_CAPACITY); + VehiclePropConfig config = { + .prop = propId, + }; + + // Replace existing config. + mStore->registerProperty(config, timestampToken); + + VehiclePropValue fuelCapacityValueToken1 = { + .timestamp = 1, + .prop = propId, + .value = {.floatValues = {1.0}}, + }; + + VehiclePropValue fuelCapacityValueToken2 = { + .timestamp = 2, + .prop = propId, + .value = {.floatValues = {2.0}}, + }; + + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacityValueToken1))); + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacityValueToken2))); + + auto result = mStore->readValuesForProperty(propId); + + ASSERT_RESULT_OK(result); + ASSERT_EQ(result.value().size(), static_cast(2)); + + auto tokenResult = mStore->readValue(propId, /*areaId=*/0, /*token=*/2); + + ASSERT_RESULT_OK(tokenResult); + ASSERT_EQ(*(tokenResult.value()), fuelCapacityValueToken2); +} + +TEST_F(VehiclePropertyStoreTest, testRemoveValue) { + auto values = getTestPropValues(); + for (const auto& value : values) { + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(value))); + } + + mStore->removeValue(values[0]); + auto result = mStore->readValue(values[0]); + + EXPECT_FALSE(result.ok()) << "expect error when reading a removed value"; + EXPECT_EQ(result.error().code(), StatusCode::NOT_AVAILABLE); + + auto leftTirePressureResult = mStore->readValue(values[1]); + + ASSERT_RESULT_OK(leftTirePressureResult); + ASSERT_EQ(*(leftTirePressureResult.value()), values[1]); +} + +TEST_F(VehiclePropertyStoreTest, testRemoveValuesForProperty) { + auto values = getTestPropValues(); + for (const auto& value : values) { + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(value))); + } + + mStore->removeValuesForProperty(toInt(VehicleProperty::INFO_FUEL_CAPACITY)); + mStore->removeValuesForProperty(toInt(VehicleProperty::TIRE_PRESSURE)); + + auto gotValues = mStore->readAllValues(); + ASSERT_TRUE(gotValues.empty()); +} + +TEST_F(VehiclePropertyStoreTest, testWriteValueUpdateStatus) { + VehiclePropValue fuelCapacity = { + .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY), + .value = {.floatValues = {1.0}}, + }; + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity), true)); + + fuelCapacity.status = VehiclePropertyStatus::UNAVAILABLE; + + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity), true)); + + VehiclePropValue requestValue = { + .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY), + }; + + auto result = mStore->readValue(requestValue); + + ASSERT_RESULT_OK(result); + ASSERT_EQ(result.value()->status, VehiclePropertyStatus::UNAVAILABLE); +} + +TEST_F(VehiclePropertyStoreTest, testWriteValueNoUpdateStatus) { + VehiclePropValue fuelCapacity = { + .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY), + .value = {.floatValues = {1.0}}, + }; + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity), true)); + + fuelCapacity.status = VehiclePropertyStatus::UNAVAILABLE; + + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity), false)); + + VehiclePropValue requestValue = { + .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY), + }; + + auto result = mStore->readValue(requestValue); + + ASSERT_RESULT_OK(result); + ASSERT_EQ(result.value()->status, VehiclePropertyStatus::AVAILABLE); +} + +TEST_F(VehiclePropertyStoreTest, testWriteValueNoUpdateStatusForNewValue) { + VehiclePropValue fuelCapacity = { + .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY), + .value = {.floatValues = {1.0}}, + .status = VehiclePropertyStatus::UNAVAILABLE, + }; + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity), false)); + + VehiclePropValue requestValue = { + .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY), + }; + + auto result = mStore->readValue(requestValue); + + ASSERT_RESULT_OK(result); + ASSERT_EQ(result.value()->status, VehiclePropertyStatus::AVAILABLE); +} + +TEST_F(VehiclePropertyStoreTest, testPropertyChangeCallbackNewValue) { + VehiclePropValue updatedValue; + mStore->setOnValueChangeCallback( + [&updatedValue](const VehiclePropValue& value) { updatedValue = value; }); + VehiclePropValue fuelCapacity = { + .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY), + .value = {.floatValues = {1.0}}, + }; + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity))); + + ASSERT_EQ(updatedValue, fuelCapacity); +} + +TEST_F(VehiclePropertyStoreTest, testPropertyChangeCallbackUpdateValue) { + VehiclePropValue updatedValue; + VehiclePropValue fuelCapacity = { + .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY), + .value = {.floatValues = {1.0}}, + }; + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity))); + + mStore->setOnValueChangeCallback( + [&updatedValue](const VehiclePropValue& value) { updatedValue = value; }); + + fuelCapacity.value.floatValues[0] = 2.0; + fuelCapacity.timestamp = 1; + + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity))); + + ASSERT_EQ(updatedValue, fuelCapacity); +} + +TEST_F(VehiclePropertyStoreTest, testPropertyChangeCallbackNoUpdate) { + VehiclePropValue updatedValue{ + .prop = INVALID_PROP_ID, + }; + VehiclePropValue fuelCapacity = { + .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY), + .value = {.floatValues = {1.0}}, + }; + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity))); + + mStore->setOnValueChangeCallback( + [&updatedValue](const VehiclePropValue& value) { updatedValue = value; }); + + // Write the same value again should succeed but should not trigger callback. + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity))); + + ASSERT_EQ(updatedValue.prop, INVALID_PROP_ID); +} + +TEST_F(VehiclePropertyStoreTest, testPropertyChangeCallbackNoUpdateForTimestampChange) { + VehiclePropValue updatedValue{ + .prop = INVALID_PROP_ID, + }; + VehiclePropValue fuelCapacity = { + .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY), + .value = {.floatValues = {1.0}}, + }; + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity))); + + mStore->setOnValueChangeCallback( + [&updatedValue](const VehiclePropValue& value) { updatedValue = value; }); + + // Write the same value with different timestamp should succeed but should not trigger callback. + fuelCapacity.timestamp = 1; + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity))); + + ASSERT_EQ(updatedValue.prop, INVALID_PROP_ID); +} + +TEST_F(VehiclePropertyStoreTest, testPropertyChangeCallbackForceUpdate) { + VehiclePropValue updatedValue{ + .prop = INVALID_PROP_ID, + }; + VehiclePropValue fuelCapacity = { + .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY), + .value = {.floatValues = {1.0}}, + }; + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity))); + + mStore->setOnValueChangeCallback( + [&updatedValue](const VehiclePropValue& value) { updatedValue = value; }); + + fuelCapacity.timestamp = 1; + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity), /*updateStatus=*/false, + VehiclePropertyStore::EventMode::ALWAYS)); + + ASSERT_EQ(updatedValue, fuelCapacity); +} + +TEST_F(VehiclePropertyStoreTest, testPropertyChangeCallbackForceNoUpdate) { + VehiclePropValue updatedValue{ + .prop = INVALID_PROP_ID, + }; + VehiclePropValue fuelCapacity = { + .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY), + .value = {.floatValues = {1.0}}, + }; + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity))); + + mStore->setOnValueChangeCallback( + [&updatedValue](const VehiclePropValue& value) { updatedValue = value; }); + fuelCapacity.value.floatValues[0] = 2.0; + fuelCapacity.timestamp = 1; + + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity), /*updateStatus=*/false, + VehiclePropertyStore::EventMode::NEVER)); + + ASSERT_EQ(updatedValue.prop, INVALID_PROP_ID); +} + +TEST_F(VehiclePropertyStoreTest, testPropertyChangeCallbackUseVehiclePropertyStore_noDeadLock) { + VehiclePropValue fuelCapacity = { + .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY), + .value = {.floatValues = {1.0}}, + }; + + std::vector configs; + + mStore->setOnValueChangeCallback( + [this, &configs]([[maybe_unused]] const VehiclePropValue& value) { + configs = mStore->getAllConfigs(); + }); + + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity), /*updateStatus=*/true, + VehiclePropertyStore::EventMode::ALWAYS)); + ASSERT_EQ(configs.size(), static_cast(2)); +} + +TEST_F(VehiclePropertyStoreTest, testOnValuesChangeCallback) { + std::vector updatedValues; + VehiclePropValue fuelCapacity = { + .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY), + .value = {.floatValues = {1.0}}, + }; + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity))); + + mStore->setOnValuesChangeCallback( + [&updatedValues](std::vector values) { updatedValues = values; }); + + fuelCapacity.value.floatValues[0] = 2.0; + fuelCapacity.timestamp = 1; + + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity))); + + ASSERT_THAT(updatedValues, ElementsAre(fuelCapacity)); +} + +TEST_F(VehiclePropertyStoreTest, testRefreshTimestamp) { + std::vector updatedValues; + mStore->setOnValuesChangeCallback( + [&updatedValues](std::vector values) { updatedValues = values; }); + + int64_t now = elapsedRealtimeNano(); + int propId = toInt(VehicleProperty::TIRE_PRESSURE); + int areaId = WHEEL_FRONT_LEFT; + VehiclePropValue tirePressure = { + .prop = propId, + .areaId = areaId, + .value = {.floatValues = {1.0}}, + }; + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(tirePressure))); + updatedValues.clear(); + + mStore->refreshTimestamp(propId, areaId, VehiclePropertyStore::EventMode::ALWAYS); + + ASSERT_EQ(updatedValues.size(), 1u); + ASSERT_EQ(updatedValues[0].prop, propId); + ASSERT_EQ(updatedValues[0].areaId, areaId); + ASSERT_EQ(updatedValues[0].value.floatValues[0], 1.0); + int64_t timestamp = updatedValues[0].timestamp; + ASSERT_GE(timestamp, now); + + auto result = mStore->readValue(tirePressure); + + ASSERT_RESULT_OK(result); + ASSERT_EQ((result.value())->timestamp, timestamp); +} + +TEST_F(VehiclePropertyStoreTest, testRefreshTimestamp_eventModeOnValueChange) { + std::vector updatedValues; + mStore->setOnValuesChangeCallback( + [&updatedValues](std::vector values) { updatedValues = values; }); + + int64_t now = elapsedRealtimeNano(); + int propId = toInt(VehicleProperty::TIRE_PRESSURE); + int areaId = WHEEL_FRONT_LEFT; + VehiclePropValue tirePressure = { + .prop = propId, + .areaId = areaId, + .value = {.floatValues = {1.0}}, + }; + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(tirePressure))); + updatedValues.clear(); + + mStore->refreshTimestamp(propId, areaId, VehiclePropertyStore::EventMode::ON_VALUE_CHANGE); + + ASSERT_EQ(updatedValues.size(), 0u) + << "Must generate no property update events if only the timestamp is refreshed"; + + auto result = mStore->readValue(tirePressure); + + ASSERT_RESULT_OK(result); + ASSERT_GE((result.value())->timestamp, now) + << "Even though event mode is on value change, the store timestamp must be updated"; +} + +TEST_F(VehiclePropertyStoreTest, testRefreshTimestamps) { + std::vector updatedValues; + mStore->setOnValuesChangeCallback( + [&updatedValues](std::vector values) { updatedValues = values; }); + + int64_t now = elapsedRealtimeNano(); + int propId1 = toInt(VehicleProperty::INFO_FUEL_CAPACITY); + int areaId1 = 0; + VehiclePropValue fuelCapacity = { + .prop = propId1, + .areaId = areaId1, + .value = {.floatValues = {1.0}}, + }; + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity))); + + int propId2 = toInt(VehicleProperty::TIRE_PRESSURE); + int areaId2 = WHEEL_FRONT_LEFT; + VehiclePropValue tirePressure = { + .prop = propId2, + .areaId = areaId2, + .value = {.floatValues = {2.0}}, + }; + ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(tirePressure))); + updatedValues.clear(); + + std::unordered_map + eventModeByPropIdAreaId; + eventModeByPropIdAreaId[PropIdAreaId{ + .propId = propId1, + .areaId = areaId1, + }] = VehiclePropertyStore::EventMode::ALWAYS; + eventModeByPropIdAreaId[PropIdAreaId{ + .propId = propId2, + .areaId = areaId2, + }] = VehiclePropertyStore::EventMode::ALWAYS; + + mStore->refreshTimestamps(eventModeByPropIdAreaId); + + ASSERT_EQ(updatedValues.size(), 2u); + ASSERT_EQ(updatedValues[0].prop, propId1); + ASSERT_EQ(updatedValues[0].areaId, areaId1); + ASSERT_EQ(updatedValues[0].value.floatValues[0], 1.0); + ASSERT_GE(updatedValues[0].timestamp, now); + ASSERT_EQ(updatedValues[1].prop, propId2); + ASSERT_EQ(updatedValues[1].areaId, areaId2); + ASSERT_EQ(updatedValues[1].value.floatValues[0], 2.0); + ASSERT_GE(updatedValues[1].timestamp, now); +} + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/current/utils/common/test/VehicleUtilsTest.cpp b/automotive/vehicle/aidl/impl/current/utils/common/test/VehicleUtilsTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..104887720116567351b72d8ca7ef9da1743cfb1b --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/utils/common/test/VehicleUtilsTest.cpp @@ -0,0 +1,827 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include + +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +namespace { + +using ::aidl::android::hardware::automotive::vehicle::StatusCode; +using ::aidl::android::hardware::automotive::vehicle::VehicleArea; +using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig; +using ::aidl::android::hardware::automotive::vehicle::VehicleProperty; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; +using ::android::base::Error; +using ::android::base::Result; + +struct InvalidPropValueTestCase { + std::string name; + VehiclePropValue value; + bool valid = false; + VehiclePropConfig config; +}; + +constexpr int32_t int32Prop = toInt(VehicleProperty::INFO_MODEL_YEAR); +constexpr int32_t int32VecProp = toInt(VehicleProperty::INFO_FUEL_TYPE); +constexpr int32_t int64Prop = toInt(VehicleProperty::ANDROID_EPOCH_TIME); +constexpr int32_t int64VecProp = toInt(VehicleProperty::WHEEL_TICK); +constexpr int32_t floatProp = toInt(VehicleProperty::ENV_OUTSIDE_TEMPERATURE); +constexpr int32_t floatVecProp = toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION); +constexpr int32_t kMixedTypePropertyForTest = 0x1111 | toInt(VehiclePropertyGroup::VENDOR) | + toInt(VehicleArea::GLOBAL) | + toInt(VehiclePropertyType::MIXED); + +std::vector getInvalidPropValuesTestCases() { + return std::vector( + { + InvalidPropValueTestCase{ + .name = "int32_normal", + .value = + { + .prop = int32Prop, + .value.int32Values = {0}, + }, + .valid = true, + }, + InvalidPropValueTestCase{ + .name = "int32_no_value", + .value = + { + .prop = int32Prop, + }, + }, + InvalidPropValueTestCase{ + .name = "int32_more_than_one_value", + .value = + { + .prop = int32Prop, + .value.int32Values = {0, 1}, + }, + }, + InvalidPropValueTestCase{ + .name = "int32_vec_normal", + .value = + { + .prop = int32VecProp, + .value.int32Values = {0, 1}, + }, + .valid = true, + }, + InvalidPropValueTestCase{ + .name = "int32_vec_no_value", + .value = + { + .prop = int32VecProp, + }, + }, + InvalidPropValueTestCase{ + .name = "int64_normal", + .value = + { + .prop = int64Prop, + .value.int64Values = {0}, + }, + .valid = true, + }, + InvalidPropValueTestCase{ + .name = "int64_no_value", + .value = + { + .prop = int64Prop, + }, + }, + InvalidPropValueTestCase{ + .name = "int64_more_than_one_value", + .value = + { + .prop = int64Prop, + .value.int64Values = {0, 1}, + }, + }, + InvalidPropValueTestCase{ + .name = "int64_vec_normal", + .value = + { + .prop = int64VecProp, + .value.int64Values = {0, 1}, + }, + .valid = true, + }, + InvalidPropValueTestCase{ + .name = "int64_vec_no_value", + .value = + { + .prop = int64VecProp, + }, + }, + InvalidPropValueTestCase{ + .name = "float_normal", + .value = + { + .prop = floatProp, + .value.floatValues = {0.0}, + }, + .valid = true, + }, + InvalidPropValueTestCase{ + .name = "float_no_value", + .value = + { + .prop = floatProp, + }, + }, + InvalidPropValueTestCase{ + .name = "float_more_than_one_value", + .value = + { + .prop = floatProp, + .value.floatValues = {0.0, 1.0}, + }, + }, + InvalidPropValueTestCase{ + .name = "float_vec_normal", + .value = + { + .prop = floatVecProp, + .value.floatValues = {0.0, 1.0}, + }, + .valid = true, + }, + InvalidPropValueTestCase{ + .name = "float_vec_no_value", + .value = + { + .prop = floatVecProp, + }, + }, + InvalidPropValueTestCase{ + .name = "mixed_normal", + .value = + { + .prop = kMixedTypePropertyForTest, + // Expect 3 values. + .value.int32Values = {0, 1, 2}, + // Expect 2 values. + .value.int64Values = {0, 1}, + // Expect 2 values. + .value.floatValues = {0.0, 1.0}, + // Expect 1 value. + .value.byteValues = {static_cast(0)}, + }, + .config = + { + .prop = kMixedTypePropertyForTest, + .configArray = {0, 1, 1, 1, 1, 1, 1, 1, 1}, + }, + .valid = true, + }, + InvalidPropValueTestCase{ + .name = "mixed_mismatch_int32_values_count", + .value = + { + .prop = kMixedTypePropertyForTest, + // Expect 3 values. + .value.int32Values = {0, 1}, + // Expect 2 values. + .value.int64Values = {0, 1}, + // Expect 2 values. + .value.floatValues = {0.0, 1.0}, + // Expect 1 value. + .value.byteValues = {static_cast(0)}, + }, + .config = + { + .prop = kMixedTypePropertyForTest, + .configArray = {0, 1, 1, 1, 1, 1, 1, 1, 1}, + }, + }, + InvalidPropValueTestCase{ + .name = "mixed_mismatch_int64_values_count", + .value = + { + .prop = kMixedTypePropertyForTest, + // Expect 3 values. + .value.int32Values = {0, 1, 2}, + // Expect 2 values. + .value.int64Values = {0}, + // Expect 2 values. + .value.floatValues = {0.0, 1.0}, + // Expect 1 value. + .value.byteValues = {static_cast(0)}, + }, + .config = + { + .prop = kMixedTypePropertyForTest, + .configArray = {0, 1, 1, 1, 1, 1, 1, 1, 1}, + }, + }, + InvalidPropValueTestCase{ + .name = "mixed_mismatch_float_values_count", + .value = + { + .prop = kMixedTypePropertyForTest, + // Expect 3 values. + .value.int32Values = {0, 1, 2}, + // Expect 2 values. + .value.int64Values = {0, 1}, + // Expect 2 values. + .value.floatValues = {0.0}, + // Expect 1 value. + .value.byteValues = {static_cast(0)}, + }, + .config = + { + .prop = kMixedTypePropertyForTest, + .configArray = {0, 1, 1, 1, 1, 1, 1, 1, 1}, + }, + }, + InvalidPropValueTestCase{ + .name = "mixed_mismatch_byte_values_count", + .value = + { + .prop = kMixedTypePropertyForTest, + // Expect 3 values. + .value.int32Values = {0, 1, 2}, + // Expect 2 values. + .value.int64Values = {0, 1}, + // Expect 2 values. + .value.floatValues = {0.0, 1.0}, + // Expect 1 value. + .value.byteValues = {static_cast(0), + static_cast(1)}, + }, + .config = + { + .prop = kMixedTypePropertyForTest, + .configArray = {0, 1, 1, 1, 1, 1, 1, 1, 1}, + }, + }, + }); +} + +struct InvalidValueRangeTestCase { + std::string name; + VehiclePropValue value; + bool valid = false; + VehicleAreaConfig config; +}; + +std::vector getInvalidValueRangeTestCases() { + return std::vector({{ + InvalidValueRangeTestCase{ + .name = "int32_normal", + .value = + { + .prop = int32Prop, + .value.int32Values = {0}, + }, + .valid = true, + .config = + { + .minInt32Value = 0, + .maxInt32Value = 10, + }, + }, + InvalidValueRangeTestCase{ + .name = "int32_vec_normal", + .value = + { + .prop = int32VecProp, + .value.int32Values = {0, 1}, + }, + .valid = true, + .config = + { + .minInt32Value = 0, + .maxInt32Value = 10, + }, + }, + InvalidValueRangeTestCase{ + .name = "int32_vec_underflow", + .value = + { + .prop = int32VecProp, + .value.int32Values = {-1, 1}, + }, + + .config = + { + .minInt32Value = 0, + .maxInt32Value = 10, + }, + }, + InvalidValueRangeTestCase{ + .name = "int32_vec_overflow", + .value = + { + .prop = int32VecProp, + .value.int32Values = {0, 100}, + }, + .config = + { + .minInt32Value = 0, + .maxInt32Value = 10, + }, + }, + InvalidValueRangeTestCase{ + .name = "int64_normal", + .value = + { + .prop = int64Prop, + .value.int64Values = {0}, + }, + .valid = true, + .config = + { + .minInt64Value = 0, + .maxInt64Value = 10, + }, + }, + InvalidValueRangeTestCase{ + .name = "int64_vec_normal", + .value = + { + .prop = int64VecProp, + .value.int64Values = {0, 1}, + }, + .valid = true, + .config = + { + .minInt64Value = 0, + .maxInt64Value = 10, + }, + }, + InvalidValueRangeTestCase{ + .name = "int64_vec_underflow", + .value = + { + .prop = int64VecProp, + .value.int64Values = {-1, 1}, + }, + + .config = + { + .minInt64Value = 0, + .maxInt64Value = 10, + }, + }, + InvalidValueRangeTestCase{ + .name = "int64_vec_overflow", + .value = + { + .prop = int64VecProp, + .value.int64Values = {0, 100}, + }, + .config = + { + .minInt64Value = 0, + .maxInt64Value = 10, + }, + }, + InvalidValueRangeTestCase{ + .name = "float_normal", + .value = + { + .prop = floatProp, + .value.floatValues = {0.0}, + }, + .valid = true, + .config = + { + .minFloatValue = 0.0, + .maxFloatValue = 10.0, + }, + }, + InvalidValueRangeTestCase{ + .name = "float_vec_normal", + .value = + { + .prop = floatVecProp, + .value.floatValues = {0.0, 10.0}, + }, + .valid = true, + .config = + { + .minFloatValue = 0.0, + .maxFloatValue = 10.0, + }, + }, + InvalidValueRangeTestCase{ + .name = "float_vec_underflow", + .value = + { + .prop = floatVecProp, + .value.floatValues = {-0.1, 1.1}, + }, + + .config = + { + .minFloatValue = 0.0, + .maxFloatValue = 10.0, + }, + }, + InvalidValueRangeTestCase{ + .name = "float_vec_overflow", + .value = + { + .prop = floatVecProp, + .value.floatValues = {0.0, 10.1}, + }, + .config = + { + .minFloatValue = 0.0, + .maxFloatValue = 10.0, + }, + }, + }}); +} + +} // namespace + +TEST(VehicleUtilsTest, testToInt) { + int areaGlobal = toInt(VehicleArea::GLOBAL); + + ASSERT_EQ(areaGlobal, 0x01000000); +} + +TEST(VehicleUtilsTest, testGetPropType) { + VehiclePropertyType type = getPropType(toInt(VehicleProperty::INFO_VIN)); + + ASSERT_EQ(type, VehiclePropertyType::STRING); +} + +TEST(VehicleUtilsTest, testGetPropGroup) { + VehiclePropertyGroup group = getPropGroup(toInt(VehicleProperty::INFO_VIN)); + + ASSERT_EQ(group, VehiclePropertyGroup::SYSTEM); +} + +TEST(VehicleUtilsTest, testGetPropArea) { + VehicleArea area = getPropArea(toInt(VehicleProperty::INFO_VIN)); + + ASSERT_EQ(area, VehicleArea::GLOBAL); +} + +TEST(VehicleUtilsTest, testIsGlobalPropTrue) { + ASSERT_TRUE(isGlobalProp(toInt(VehicleProperty::INFO_VIN))); +} + +TEST(VehicleUtilsTest, testIsGlobalPropFalse) { + ASSERT_FALSE(isGlobalProp(toInt(VehicleProperty::TIRE_PRESSURE))); +} + +TEST(VehicleUtilsTest, testIsSystemPropTrue) { + ASSERT_TRUE(isSystemProp(toInt(VehicleProperty::INFO_VIN))); +} + +TEST(VehicleUtilsTest, testIsSystemPropFalse) { + // VehiclePropertyGroup:VENDOR,VehicleArea:GLOBAL,VehiclePropertyType:STRING + int vendorProp = 0x0100 + 0x20000000 + 0x01000000 + 0x00100000; + + ASSERT_FALSE(isSystemProp(vendorProp)); +} + +TEST(VehicleUtilsTest, testGetAreaConfigGlobal) { + VehiclePropValue testPropValue{.prop = toInt(VehicleProperty::INFO_VIN)}; + VehicleAreaConfig testAreaConfig{.areaId = 0, .minInt32Value = 1}; + VehiclePropConfig testConfig{.areaConfigs = {testAreaConfig}}; + + const VehicleAreaConfig* gotConfig = getAreaConfig(testPropValue, testConfig); + + ASSERT_EQ(*gotConfig, testAreaConfig); +} + +TEST(VehicleUtilsTest, testGetAreaConfigGlobalNoAreaConfig) { + VehiclePropValue testPropValue{.prop = toInt(VehicleProperty::INFO_VIN)}; + VehiclePropConfig testConfig{}; + + const VehicleAreaConfig* gotConfig = getAreaConfig(testPropValue, testConfig); + + ASSERT_EQ(gotConfig, nullptr); +} + +TEST(VehicleUtilsTest, testGetAreaConfigNonGlobal) { + VehiclePropValue testPropValue = { + .prop = toInt(VehicleProperty::TIRE_PRESSURE), + }; + VehicleAreaConfig leftConfig{.areaId = WHEEL_FRONT_LEFT, .minInt32Value = 1}; + VehicleAreaConfig rightConfig{.areaId = WHEEL_FRONT_RIGHT, .minInt32Value = 2}; + VehiclePropConfig testConfig{.areaConfigs = {leftConfig, rightConfig}}; + + testPropValue.areaId = WHEEL_FRONT_LEFT; + const VehicleAreaConfig* gotConfig = getAreaConfig(testPropValue, testConfig); + + ASSERT_EQ(*gotConfig, leftConfig); +} + +TEST(VehicleUtilsTest, testGetAreaConfigNonGlobalNull) { + VehiclePropValue testPropValue = { + .prop = toInt(VehicleProperty::TIRE_PRESSURE), + }; + VehicleAreaConfig leftConfig{.areaId = WHEEL_FRONT_LEFT, .minInt32Value = 1}; + VehicleAreaConfig rightConfig{.areaId = WHEEL_FRONT_RIGHT, .minInt32Value = 2}; + VehiclePropConfig testConfig{.areaConfigs = {leftConfig, rightConfig}}; + + // No config for this area. + testPropValue.areaId = 0; + const VehicleAreaConfig* gotConfig = getAreaConfig(testPropValue, testConfig); + + ASSERT_EQ(gotConfig, nullptr); +} + +TEST(VehicleUtilsTest, testCreateVehiclePropValueInt32) { + std::unique_ptr value = createVehiclePropValue(VehiclePropertyType::INT32); + + ASSERT_NE(value, nullptr); + ASSERT_EQ(1u, value->value.int32Values.size()); +} + +TEST(VehicleUtilsTest, testCreateVehiclePropValueInt32Vec) { + std::unique_ptr value = + createVehiclePropValue(VehiclePropertyType::INT32_VEC); + + ASSERT_NE(value, nullptr); + ASSERT_EQ(1u, value->value.int32Values.size()); +} + +TEST(VehicleUtilsTest, testCreateVehiclePropValueInt64) { + std::unique_ptr value = createVehiclePropValue(VehiclePropertyType::INT64); + + ASSERT_NE(value, nullptr); + ASSERT_EQ(1u, value->value.int64Values.size()); +} + +TEST(VehicleUtilsTest, testCreateVehiclePropValueInt64Vec) { + std::unique_ptr value = + createVehiclePropValue(VehiclePropertyType::INT64_VEC); + + ASSERT_NE(value, nullptr); + ASSERT_EQ(1u, value->value.int64Values.size()); +} + +TEST(VehicleUtilsTest, testCreateVehiclePropValueFloat) { + std::unique_ptr value = createVehiclePropValue(VehiclePropertyType::FLOAT); + + ASSERT_NE(value, nullptr); + ASSERT_EQ(1u, value->value.floatValues.size()); +} + +TEST(VehicleUtilsTest, testCreateVehiclePropValueFloatVec) { + std::unique_ptr value = + createVehiclePropValue(VehiclePropertyType::FLOAT_VEC); + + ASSERT_NE(value, nullptr); + ASSERT_EQ(1u, value->value.floatValues.size()); +} + +TEST(VehicleUtilsTest, testCreateVehiclePropValueBytes) { + std::unique_ptr value = createVehiclePropValue(VehiclePropertyType::BYTES); + + ASSERT_NE(value, nullptr); + ASSERT_EQ(1u, value->value.byteValues.size()); +} + +TEST(VehicleUtilsTest, testCreateVehiclePropValueString) { + std::unique_ptr value = createVehiclePropValue(VehiclePropertyType::STRING); + + ASSERT_NE(value, nullptr); +} + +TEST(VehicleUtilsTest, testCreateVehiclePropValueMixed) { + std::unique_ptr value = createVehiclePropValue(VehiclePropertyType::MIXED); + + ASSERT_NE(value, nullptr); +} + +TEST(VehicleUtilsTest, testCreateVehiclePropValueVecInt32) { + std::unique_ptr value = + createVehiclePropValueVec(VehiclePropertyType::INT32, /*vecSize=*/2); + + ASSERT_NE(value, nullptr); + ASSERT_EQ(1u, value->value.int32Values.size()) + << "vector size should always be 1 for single value type"; +} + +TEST(VehicleUtilsTest, testCreateVehiclePropValueIntVec32Vec) { + std::unique_ptr value = + createVehiclePropValueVec(VehiclePropertyType::INT32_VEC, /*vecSize=*/2); + + ASSERT_NE(value, nullptr); + ASSERT_EQ(2u, value->value.int32Values.size()); +} + +TEST(VehicleUtilsTest, testCreateVehiclePropValueVecInt64) { + std::unique_ptr value = + createVehiclePropValueVec(VehiclePropertyType::INT64, /*vecSize=*/2); + + ASSERT_NE(value, nullptr); + ASSERT_EQ(1u, value->value.int64Values.size()) + << "vector size should always be 1 for single value type"; +} + +TEST(VehicleUtilsTest, testCreateVehiclePropValueIntVec64Vec) { + std::unique_ptr value = + createVehiclePropValueVec(VehiclePropertyType::INT64_VEC, /*vecSize=*/2); + + ASSERT_NE(value, nullptr); + ASSERT_EQ(2u, value->value.int64Values.size()); +} + +TEST(VehicleUtilsTest, testCreateVehiclePropValueVecFloat) { + std::unique_ptr value = + createVehiclePropValueVec(VehiclePropertyType::FLOAT, /*vecSize=*/2); + + ASSERT_NE(value, nullptr); + ASSERT_EQ(1u, value->value.floatValues.size()) + << "vector size should always be 1 for single value type"; +} + +TEST(VehicleUtilsTest, testCreateVehiclePropValueFloatVecMultiValues) { + std::unique_ptr value = + createVehiclePropValueVec(VehiclePropertyType::FLOAT_VEC, /*vecSize=*/2); + + ASSERT_NE(value, nullptr); + ASSERT_EQ(2u, value->value.floatValues.size()); +} + +TEST(VehicleUtilsTest, testCreateVehiclePropValueVecBytes) { + std::unique_ptr value = + createVehiclePropValueVec(VehiclePropertyType::BYTES, /*vecSize=*/2); + + ASSERT_NE(value, nullptr); + ASSERT_EQ(2u, value->value.byteValues.size()); +} + +TEST(VehicleUtilsTest, testConcurrentQueueOneThread) { + ConcurrentQueue queue; + + queue.push(1); + queue.push(2); + auto result = queue.flush(); + + ASSERT_EQ(result, std::vector({1, 2})); +} + +TEST(VehicleUtilsTest, testConcurrentQueueMultipleThreads) { + ConcurrentQueue queue; + std::vector results; + std::atomic stop = false; + + std::thread t1([&queue]() { + for (int i = 0; i < 100; i++) { + queue.push(0); + } + }); + std::thread t2([&queue]() { + for (int i = 0; i < 100; i++) { + queue.push(1); + } + }); + std::thread t3([&queue, &results, &stop]() { + while (!stop) { + queue.waitForItems(); + for (int i : queue.flush()) { + results.push_back(i); + } + } + + // After we stop, get all the remaining values in the queue. + for (int i : queue.flush()) { + results.push_back(i); + } + }); + + t1.join(); + t2.join(); + + stop = true; + queue.deactivate(); + t3.join(); + + size_t zeroCount = 0; + size_t oneCount = 0; + for (int i : results) { + if (i == 0) { + zeroCount++; + } + if (i == 1) { + oneCount++; + } + } + + EXPECT_EQ(results.size(), static_cast(200)); + EXPECT_EQ(zeroCount, static_cast(100)); + EXPECT_EQ(oneCount, static_cast(100)); +} + +TEST(VehicleUtilsTest, testConcurrentQueuePushAfterDeactivate) { + ConcurrentQueue queue; + + queue.deactivate(); + queue.push(1); + + ASSERT_TRUE(queue.flush().empty()); +} + +TEST(VehicleUtilsTest, testConcurrentQueueDeactivateNotifyWaitingThread) { + ConcurrentQueue queue; + + std::thread t([&queue]() { + // This would block until queue is deactivated. + queue.waitForItems(); + }); + + queue.deactivate(); + + t.join(); +} + +TEST(VehicleUtilsTest, testVhalError) { + VhalResult result = Error(StatusCode::INVALID_ARG) << "error message"; + + ASSERT_EQ(result.error().message(), "error message: INVALID_ARG"); +} + +TEST(VehicleUtilsTest, testPropIdToString) { + ASSERT_EQ(propIdToString(toInt(VehicleProperty::PERF_VEHICLE_SPEED)), "PERF_VEHICLE_SPEED"); +} + +TEST(VehicleUtilsTest, testStringToPropId) { + auto result = stringToPropId("PERF_VEHICLE_SPEED"); + + ASSERT_TRUE(result.ok()); + ASSERT_EQ(result.value(), toInt(VehicleProperty::PERF_VEHICLE_SPEED)); +} + +TEST(VehicleUtilsTest, testStringToPropId_InvalidName) { + auto result = stringToPropId("PERF_VEHICLE_SPEED12345"); + + ASSERT_FALSE(result.ok()); +} + +class InvalidPropValueTest : public testing::TestWithParam {}; + +INSTANTIATE_TEST_SUITE_P(InvalidPropValueTests, InvalidPropValueTest, + testing::ValuesIn(getInvalidPropValuesTestCases()), + [](const testing::TestParamInfo& info) { + return info.param.name; + }); + +TEST_P(InvalidPropValueTest, testCheckPropValue) { + InvalidPropValueTestCase tc = GetParam(); + + // Config is not used for non-mixed types. + auto result = checkPropValue(tc.value, &tc.config); + + ASSERT_EQ(tc.valid, result.ok()); +} + +class InvalidValueRangeTest : public testing::TestWithParam {}; + +INSTANTIATE_TEST_SUITE_P(InvalidValueRangeTests, InvalidValueRangeTest, + testing::ValuesIn(getInvalidValueRangeTestCases()), + [](const testing::TestParamInfo& info) { + return info.param.name; + }); + +TEST_P(InvalidValueRangeTest, testCheckValueRange) { + InvalidValueRangeTestCase tc = GetParam(); + + // Config is not used for non-mixed types. + auto result = checkValueRange(tc.value, &tc.config); + + ASSERT_EQ(tc.valid, result.ok()); +} + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/utils/test_vendor_properties/Android.bp b/automotive/vehicle/aidl/impl/current/utils/test_vendor_properties/Android.bp similarity index 100% rename from automotive/vehicle/aidl/impl/utils/test_vendor_properties/Android.bp rename to automotive/vehicle/aidl/impl/current/utils/test_vendor_properties/Android.bp diff --git a/automotive/vehicle/aidl/impl/current/utils/test_vendor_properties/android/hardware/automotive/vehicle/TestVendorProperty.aidl b/automotive/vehicle/aidl/impl/current/utils/test_vendor_properties/android/hardware/automotive/vehicle/TestVendorProperty.aidl new file mode 100644 index 0000000000000000000000000000000000000000..3c877fa1ce30380448f49c62f1b00f41b388c419 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/utils/test_vendor_properties/android/hardware/automotive/vehicle/TestVendorProperty.aidl @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.automotive.vehicle; + +/** + * Test vendor properties used in reference VHAL implementation. + */ +@Backing(type="int") +enum TestVendorProperty { + + /** + * Vendor version of CLUSTER_SWITCH_UI, used for the end-to-end testing of ClusterHomeService. + * + * VehiclePropertyGroup.VENDOR | VehicleArea.GLOBAL | VehiclePropertyType.INT32, + */ + VENDOR_CLUSTER_SWITCH_UI = 0x0F34 + 0x20000000 + 0x01000000 + 0x00400000, + + /** + * Vendor version of CLUSTER_DISPLAY_STATE, used for the end-to-end testing of + * ClusterHomeService. + * + * VehiclePropertyGroup.VENDOR | VehicleArea.GLOBAL | VehiclePropertyType.INT32_VEC + */ + VENDOR_CLUSTER_DISPLAY_STATE = 0x0F35 + 0x20000000 + 0x01000000 + 0x00410000, + + /** + * Vendor version of CLUSTER_REPORT_STATE, used for the end-to-end testing of + * ClusterHomeService. + * + * VehiclePropertyGroup.VENDOR | VehicleArea.GLOBAL | VehiclePropertyGroup.MIXED + */ + VENDOR_CLUSTER_REPORT_STATE = 0x0F36 + 0x20000000 + 0x01000000 + 0x00E00000, + + /** + * Vendor version of CLUSTER_REQUEST_DISPLAY, used for the end-to-end testing of + * ClusterHomeService. + * + * VehiclePropertyGroup.VENDOR | VehicleArea.GLOBAL | VehiclePropertyType.INT32 + */ + VENDOR_CLUSTER_REQUEST_DISPLAY = 0x0F37 + 0x20000000 + 0x01000000 + 0x00400000, + + /** + * Vendor version of CLUSTER_NAVIGATION_STATE, used for the end-to-end testing of + * ClusterHomeService. + * + * VehiclePropertyGroup.VENDOR | VehicleArea.GLOBAL | VehiclePropertyType.BYTES + */ + VENDOR_CLUSTER_NAVIGATION_STATE = 0x0F38 + 0x20000000 + 0x01000000 + 0x00700000, + + // These properties are placeholder properties for developers to test new features without + // implementing a real property. + + /** + * VehiclePropertyGroup.VENDOR | VehicleArea.GLOBAL | VehiclePropertyType.INT32 + */ + PLACEHOLDER_PROPERTY_INT = 0x2A11 + 0x20000000 + 0x01000000 + 0x00400000, + + /** + * VehiclePropertyGroup.VENDOR | VehicleArea.GLOBAL | VehiclePropertyType.FLOAT + */ + PLACEHOLDER_PROPERTY_FLOAT = 0x2A11 + 0x20000000 + 0x01000000 + 0x00600000, + + /** + * VehiclePropertyGroup.VENDOR | VehicleArea.GLOBAL | VehiclePropertyType.BOOLEAN + */ + PLACEHOLDER_PROPERTY_BOOLEAN = 0x2A11 + 0x20000000 + 0x01000000 + 0x00200000, + + /** + * VehiclePropertyGroup.VENDOR | VehicleArea.GLOBAL | VehiclePropertyType.STRING + */ + PLACEHOLDER_PROPERTY_STRING = 0x2A11 + 0x20000000 + 0x01000000 + 0x00100000, + + /** + * This property is used for testing LargeParcelable marshalling/unmarhsalling end to end. + * It acts as an regular property that stores the property value when setting and return the + * value when getting, except that all the byteValues used in the setValue response would be + * filled in the reverse order. + * + * This is used in {@code VehicleHalLargeParcelableTest}. + * + * VehiclePropertyGroup.VENDOR | VehicleArea.GLOBAL | VehiclePropertyType.BYTES + * + * 0x21702a12 + */ + ECHO_REVERSE_BYTES = 0x2A12 + 0x20000000 + 0x01000000 + 0x00700000, + + /** + * This property is used for testing vendor error codes end to end. + * + * VehiclePropertyGroup.VENDOR | VehicleArea.GLOBAL | VehiclePropertyType.INT32 + * + * 0x21402a13 + */ + VENDOR_PROPERTY_FOR_ERROR_CODE_TESTING = 0x2A13 + 0x20000000 + 0x01000000 + 0x00400000, + + /** + * This property is used for test purpose. End to end tests use this property to test set and + * get method for MIXED type properties. + * + * VehiclePropertyGroup.VENDOR | VehicleArea.GLOBAL | VehiclePropertyGroup.MIXED + */ + MIXED_TYPE_PROPERTY_FOR_TEST = 0x1111 + 0x20000000 + 0x01000000 + 0x00E00000, + + /** + * Property used for {@code CarVendorPropertyCustomPermissionTest}. + * + * VehiclePropertyGroup.VENDOR | VehicleArea.DOOR | VehiclePropertyGroup.BOOLEAN + */ + VENDOR_EXTENSION_BOOLEAN_PROPERTY = 0x0101 + 0x20000000 + 0x06000000 + 0x00200000, + + /** + * Property used for {@code CarVendorPropertyCustomPermissionTest}. + * + * VehiclePropertyGroup.VENDOR | VehicleArea.SEAT | VehiclePropertyGroup.FLOAT + */ + VENDOR_EXTENSION_FLOAT_PROPERTY = 0x102 + 0x20000000 + 0x05000000 + 0x00600000, + + /** + * Property used for {@code CarVendorPropertyCustomPermissionTest}. + * + * VehiclePropertyGroup.VENDOR | VehicleArea.WINDOW | VehiclePropertyGroup.INT32 + */ + VENDOR_EXTENSION_INT_PROPERTY = 0x103 + 0x20000000 + 0x03000000 + 0x00400000, + + /** + * Property used for {@code CarVendorPropertyCustomPermissionTest}. + * + * VehiclePropertyGroup.VENDOR | VehicleArea.GLOBAL | VehiclePropertyGroup.STRING + */ + VENDOR_EXTENSION_STRING_PROPERTY = 0x103 + 0x20000000 + 0x01000000 + 0x00100000, +} diff --git a/automotive/vehicle/aidl/impl/vhal/Android.bp b/automotive/vehicle/aidl/impl/current/vhal/Android.bp similarity index 96% rename from automotive/vehicle/aidl/impl/vhal/Android.bp rename to automotive/vehicle/aidl/impl/current/vhal/Android.bp index 6eda1afe12843c26c79f03dd0f599b18624da65c..8764eff7f6cee978399638ca9e86181519faa7f4 100644 --- a/automotive/vehicle/aidl/impl/vhal/Android.bp +++ b/automotive/vehicle/aidl/impl/current/vhal/Android.bp @@ -20,7 +20,7 @@ package { } cc_binary { - name: "android.hardware.automotive.vehicle@V3-default-service", + name: "android.hardware.automotive.vehicle@V4-default-service", vendor: true, defaults: [ "FakeVehicleHardwareDefaults", @@ -47,7 +47,6 @@ cc_binary { cc_library { name: "DefaultVehicleHal", vendor: true, - host_supported: true, defaults: [ "VehicleHalDefaults", ], diff --git a/automotive/vehicle/aidl/impl/current/vhal/include/ConnectedClient.h b/automotive/vehicle/aidl/impl/current/vhal/include/ConnectedClient.h new file mode 100644 index 0000000000000000000000000000000000000000..addc9014fce3026ae9615c3cba9a75b8c0c57b3b --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/vhal/include/ConnectedClient.h @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_aidl_impl_vhal_include_ConnectedClient_H_ +#define android_hardware_automotive_vehicle_aidl_impl_vhal_include_ConnectedClient_H_ + +#include "PendingRequestPool.h" + +#include +#include +#include + +#include +#include + +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +// A class to represent a binder client with a callback interface. Each callback function, e.g. +// GetValues or SetValues for a specific binder client is a separate {@code ConnectedClient}. +// For one {@code ConnectedClient}, we use one pending request pool to manage all pending requests, +// so the request IDs must be unique for one client. We also manage a set of callback functions +// for one client, e.g. timeoutCallback which could be passed to hardware. +// This class is thread-safe. +class ConnectedClient { + public: + using CallbackType = + std::shared_ptr; + + ConnectedClient(std::shared_ptr requestPool, CallbackType callback); + + virtual ~ConnectedClient() = default; + + // Gets the unique ID for this client. + const void* id(); + + // Adds client requests. The requests would be registered as pending requests until + // {@code tryFinishRequests} is called for them. + // Returns {@code INVALID_ARG} error if any of the requestIds are duplicate with one of the + // pending request IDs or {@code TRY_AGAIN} error if the pending request pool is full and could + // no longer add requests. + VhalResult addRequests(const std::unordered_set& requestIds); + + // Marks the requests as finished. Returns a list of request IDs that was pending and has been + // finished. It must be a set of the requested request IDs. + std::unordered_set tryFinishRequests(const std::unordered_set& requestIds); + + protected: + // Gets the callback to be called when the request for this client has timeout. + virtual std::shared_ptr getTimeoutCallback() = 0; + + const std::shared_ptr mRequestPool; + const CallbackType mCallback; +}; + +// A class to represent a client that calls {@code IVehicle.setValues} or {@code +// IVehicle.getValues}. +template +class GetSetValuesClient final : public ConnectedClient { + public: + GetSetValuesClient(std::shared_ptr requestPool, CallbackType callback); + + // Sends the results to this client. + void sendResults(std::vector&& results); + + // Sends each result separately to this client. Each result would be sent through one callback + // invocation. + void sendResultsSeparately(const std::vector& results); + + // Gets the callback to be called when the request for this client has finished. + std::shared_ptr)>> getResultCallback(); + + protected: + // Gets the callback to be called when the request for this client has timeout. + std::shared_ptr getTimeoutCallback() override; + + private: + // The following members are only initialized during construction. + std::shared_ptr mTimeoutCallback; + std::shared_ptr)>> mResultCallback; +}; + +class SubscriptionClient { + public: + using CallbackType = + std::shared_ptr; + + // Marshals the updated values into largeParcelable and sends it through {@code onPropertyEvent} + // callback. + static void sendUpdatedValues( + CallbackType callback, + std::vector&& + updatedValues); + // Marshals the set property error events into largeParcelable and sends it through + // {@code onPropertySetError} callback. + static void sendPropertySetErrors( + CallbackType callback, + std::vector&& + vehiclePropErrors); +}; + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_aidl_impl_vhal_include_ConnectedClient_H_ diff --git a/automotive/vehicle/aidl/impl/current/vhal/include/DefaultVehicleHal.h b/automotive/vehicle/aidl/impl/current/vhal/include/DefaultVehicleHal.h new file mode 100644 index 0000000000000000000000000000000000000000..5d64e6fdf57c3bf8d2c5247fa747cc973f8c52f2 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/vhal/include/DefaultVehicleHal.h @@ -0,0 +1,280 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_aidl_impl_vhal_include_DefaultVehicleHal_H_ +#define android_hardware_automotive_vehicle_aidl_impl_vhal_include_DefaultVehicleHal_H_ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +namespace aidlvhal = ::aidl::android::hardware::automotive::vehicle; + +class DefaultVehicleHal final : public aidlvhal::BnVehicle { + public: + using CallbackType = std::shared_ptr; + + explicit DefaultVehicleHal(std::unique_ptr hardware); + + // Test-only + DefaultVehicleHal(std::unique_ptr hardware, int32_t testInterfaceVersion); + + ~DefaultVehicleHal(); + + ndk::ScopedAStatus getAllPropConfigs(aidlvhal::VehiclePropConfigs* returnConfigs) override; + ndk::ScopedAStatus getValues(const CallbackType& callback, + const aidlvhal::GetValueRequests& requests) override; + ndk::ScopedAStatus setValues(const CallbackType& callback, + const aidlvhal::SetValueRequests& requests) override; + ndk::ScopedAStatus getPropConfigs(const std::vector& props, + aidlvhal::VehiclePropConfigs* returnConfigs) override; + ndk::ScopedAStatus subscribe(const CallbackType& callback, + const std::vector& options, + int32_t maxSharedMemoryFileCount) override; + ndk::ScopedAStatus unsubscribe(const CallbackType& callback, + const std::vector& propIds) override; + ndk::ScopedAStatus returnSharedMemory(const CallbackType& callback, + int64_t sharedMemoryId) override; + ndk::ScopedAStatus getSupportedValuesLists( + const std::vector& propIdAreaIds, + aidlvhal::SupportedValuesListResults* supportedValuesListResults) override; + ndk::ScopedAStatus getMinMaxSupportedValue( + const std::vector& propIdAreaIds, + aidlvhal::MinMaxSupportedValueResults* minMaxSupportedValueResults) override; + ndk::ScopedAStatus registerSupportedValueChangeCallback( + const std::shared_ptr& callback, + const std::vector& propIdAreaIds) override; + ndk::ScopedAStatus unregisterSupportedValueChangeCallback( + const std::shared_ptr& callback, + const std::vector& propIdAreaIds) override; + binder_status_t dump(int fd, const char** args, uint32_t numArgs) override; + + IVehicleHardware* getHardware(); + + private: + // friend class for unit testing. + friend class DefaultVehicleHalTest; + + using GetValuesClient = GetSetValuesClient; + using SetValuesClient = GetSetValuesClient; + + // A wrapper for binder lifecycle operations to enable stubbing for test. + class BinderLifecycleInterface { + public: + virtual ~BinderLifecycleInterface() = default; + + virtual binder_status_t linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient, + void* cookie) = 0; + + virtual bool isAlive(const AIBinder* binder) = 0; + }; + + // A real implementation for BinderLifecycleInterface. + class BinderLifecycleHandler final : public BinderLifecycleInterface { + public: + binder_status_t linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient, + void* cookie) override; + + bool isAlive(const AIBinder* binder) override; + }; + + // OnBinderDiedContext is a type used as a cookie passed deathRecipient. The deathRecipient's + // onBinderDied function takes only a cookie as input and we have to store all the contexts + // as the cookie. + struct OnBinderDiedContext { + DefaultVehicleHal* vhal; + const AIBinder* clientId; + }; + + // BinderDiedUnlinkedEvent represents either an onBinderDied or an onBinderUnlinked event. + struct BinderDiedUnlinkedEvent { + // true for onBinderDied, false for onBinderUnlinked. + bool forOnBinderDied; + const AIBinder* clientId; + }; + + // The default timeout of get or set value requests is 30s. + // TODO(b/214605968): define TIMEOUT_IN_NANO in IVehicle and allow getValues/setValues/subscribe + // to specify custom timeouts. + static constexpr int64_t TIMEOUT_IN_NANO = 30'000'000'000; + // heart beat event interval: 3s + static constexpr int64_t HEART_BEAT_INTERVAL_IN_NANO = 3'000'000'000; + bool mShouldRefreshPropertyConfigs; + std::unique_ptr mVehicleHardware; + + // PendingRequestPool is thread-safe. + std::shared_ptr mPendingRequestPool; + // SubscriptionManager is thread-safe. + std::shared_ptr mSubscriptionManager; + // ConcurrentQueue is thread-safe. + std::shared_ptr> mBatchedEventQueue; + // BatchingConsumer is thread-safe. + std::shared_ptr> + mPropertyChangeEventsBatchingConsumer; + // Only set once during initialization. + std::chrono::nanoseconds mEventBatchingWindow; + // Only used for testing. + int32_t mTestInterfaceVersion = 0; + + mutable std::atomic mConfigInit = false; + mutable std::shared_timed_mutex mConfigLock; + mutable std::unordered_map mConfigsByPropId + GUARDED_BY(mConfigLock); + mutable std::unique_ptr mConfigFile GUARDED_BY(mConfigLock); + + std::mutex mLock; + std::unordered_map> mOnBinderDiedContexts + GUARDED_BY(mLock); + std::unordered_map> mGetValuesClients + GUARDED_BY(mLock); + std::unordered_map> mSetValuesClients + GUARDED_BY(mLock); + // mBinderLifecycleHandler is only going to be changed in test. + std::unique_ptr mBinderLifecycleHandler; + + // Only initialized once. + std::shared_ptr> mRecurrentAction; + // RecurrentTimer is thread-safe. + RecurrentTimer mRecurrentTimer; + + ndk::ScopedAIBinder_DeathRecipient mDeathRecipient; + + // ConcurrentQueue is thread-safe. + ConcurrentQueue mBinderEvents; + + // A thread to handle onBinderDied or onBinderUnlinked event. + std::thread mOnBinderDiedUnlinkedHandlerThread; + + android::base::Result checkProperty(const aidlvhal::VehiclePropValue& propValue); + + android::base::Result> checkDuplicateRequests( + const std::vector& requests); + + android::base::Result> checkDuplicateRequests( + const std::vector& requests); + VhalResult checkSubscribeOptions( + const std::vector& options, + const std::unordered_map& configsByPropId) + REQUIRES_SHARED(mConfigLock); + + VhalResult checkPermissionHelper(const aidlvhal::VehiclePropValue& value, + aidlvhal::VehiclePropertyAccess accessToTest) const; + + VhalResult checkReadPermission(const aidlvhal::VehiclePropValue& value) const; + + VhalResult checkWritePermission(const aidlvhal::VehiclePropValue& value) const; + + android::base::Result getConfig(int32_t propId) const; + + void onBinderDiedWithContext(const AIBinder* clientId); + + void onBinderUnlinkedWithContext(const AIBinder* clientId); + + // Registers a onBinderDied callback for the client if not already registered. + // Returns true if the client Binder is alive, false otherwise. + bool monitorBinderLifeCycleLocked(const AIBinder* clientId) REQUIRES(mLock); + + bool checkDumpPermission(); + + bool isConfigSupportedForCurrentVhalVersion(const aidlvhal::VehiclePropConfig& config) const; + + bool getAllPropConfigsFromHardwareLocked() const EXCLUDES(mConfigLock); + + // The looping handler function to process all onBinderDied or onBinderUnlinked events in + // mBinderEvents. + void onBinderDiedUnlinkedHandler(); + + size_t countSubscribeClients(); + + // Handles the property change events in batch. + void handleBatchedPropertyEvents(std::vector&& batchedEvents); + + int32_t getVhalInterfaceVersion() const; + + // Gets mConfigsByPropId, lazy init it if necessary. Note that the reference is only valid in + // the scope of the callback and it is guaranteed that read lock is obtained during the + // callback. + void getConfigsByPropId( + std::function&)> + callback) const EXCLUDES(mConfigLock); + + // Puts the property change events into a queue so that they can handled in batch. + static void batchPropertyChangeEvent( + const std::weak_ptr>& batchedEventQueue, + std::vector&& updatedValues); + + // Gets or creates a {@code T} object for the client to or from {@code clients}. + template + static std::shared_ptr getOrCreateClient( + std::unordered_map>* clients, + const CallbackType& callback, std::shared_ptr pendingRequestPool); + + static void onPropertyChangeEvent(const std::weak_ptr& subscriptionManager, + std::vector&& updatedValues); + + static void onPropertySetErrorEvent( + const std::weak_ptr& subscriptionManager, + const std::vector& errorEvents); + + static void checkHealth(IVehicleHardware* hardware, + std::weak_ptr subscriptionManager); + + static void onBinderDied(void* cookie); + + static void onBinderUnlinked(void* cookie); + + static void parseSubscribeOptions( + const std::vector& options, + const std::unordered_map& configsByPropId, + std::vector& onChangeSubscriptions, + std::vector& continuousSubscriptions); + + // Test-only + // Set the default timeout for pending requests. + void setTimeout(int64_t timeoutInNano); + + // Test-only + void setBinderLifecycleHandler(std::unique_ptr impl); +}; + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_aidl_impl_vhal_include_DefaultVehicleHal_H_ diff --git a/automotive/vehicle/aidl/impl/current/vhal/include/SubscriptionManager.h b/automotive/vehicle/aidl/impl/current/vhal/include/SubscriptionManager.h new file mode 100644 index 0000000000000000000000000000000000000000..2f16fca93c79f548242b1a19c06aa377a5855eac --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/vhal/include/SubscriptionManager.h @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_aidl_impl_vhal_include_SubscriptionManager_H_ +#define android_hardware_automotive_vehicle_aidl_impl_vhal_include_SubscriptionManager_H_ + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +// A structure to represent subscription config for one subscription client. +struct SubConfig { + float sampleRateHz; + float resolution; + bool enableVur; +}; + +// A class to represent all the subscription configs for a continuous [propId, areaId]. +class ContSubConfigs final { + public: + using ClientIdType = const AIBinder*; + + void addClient(const ClientIdType& clientId, const SubConfig& subConfig); + void removeClient(const ClientIdType& clientId); + float getMaxSampleRateHz() const; + float getMinRequiredResolution() const; + bool isVurEnabled() const; + bool isVurEnabledForClient(const ClientIdType& clientId) const; + float getResolutionForClient(const ClientIdType& clientId) const; + + private: + float mMaxSampleRateHz = 0.; + // Baseline for resolution is maximum possible float. We want to sanitize to the highest + // requested resolution, which is the smallest float value for resolution. + float mMinRequiredResolution = std::numeric_limits::max(); + bool mEnableVur; + std::unordered_map mConfigByClient; + + void refreshCombinedConfig(); +}; + +// A thread-safe subscription manager that manages all VHAL subscriptions. +class SubscriptionManager final { + public: + using ClientIdType = const AIBinder*; + using CallbackType = + std::shared_ptr; + using VehiclePropValue = aidl::android::hardware::automotive::vehicle::VehiclePropValue; + + explicit SubscriptionManager(IVehicleHardware* vehicleHardware); + ~SubscriptionManager(); + + // Subscribes to properties according to {@code SubscribeOptions}. Note that all option must + // contain non-empty areaIds field, which contains all area IDs to subscribe. As a result, + // the options here is different from the options passed from VHAL client. + // Returns error if any of the subscribe options is not valid or one of the properties failed + // to subscribe. Part of the properties maybe be subscribed successfully if this function + // returns error. Caller is safe to retry since subscribing to an already subscribed property + // is okay. + // Returns ok if all the options are parsed correctly and all the properties are subscribed. + VhalResult subscribe( + const CallbackType& callback, + const std::vector& + options, + bool isContinuousProperty); + + // Unsubscribes from the properties for the client. + // Returns error if the client was not subscribed before, or one of the given property was not + // subscribed, or one of the property failed to unsubscribe. Caller is safe to retry since + // unsubscribing to an already unsubscribed property is okay (it would be ignored). + // Returns ok if all the requested properties for the client are unsubscribed. + VhalResult unsubscribe(ClientIdType client, const std::vector& propIds); + + // Unsubscribes from all the properties for the client. + // Returns error if the client was not subscribed before or one of the subscribed properties + // for the client failed to unsubscribe. Caller is safe to retry. + // Returns ok if all the properties for the client are unsubscribed. + VhalResult unsubscribe(ClientIdType client); + + // For a list of updated properties, returns a map that maps clients subscribing to + // the updated properties to a list of updated values. This would only return on-change property + // clients that should be informed for the given updated values. + std::unordered_map> getSubscribedClients( + std::vector&& updatedValues); + + // For a list of set property error events, returns a map that maps clients subscribing to the + // properties to a list of errors for each client. + std::unordered_map> + getSubscribedClientsForErrorEvents(const std::vector& errorEvents); + + // Returns the number of subscribed clients. + size_t countClients(); + + // Checks whether the sample rate is valid. + static bool checkSampleRateHz(float sampleRateHz); + + // Checks whether the resolution is valid. + static bool checkResolution(float resolution); + + private: + // Friend class for testing. + friend class DefaultVehicleHalTest; + + IVehicleHardware* mVehicleHardware; + + struct VehiclePropValueHashPropIdAreaId { + inline size_t operator()(const VehiclePropValue& vehiclePropValue) const { + size_t res = 0; + hashCombine(res, vehiclePropValue.prop); + hashCombine(res, vehiclePropValue.areaId); + return res; + } + }; + + struct VehiclePropValueEqualPropIdAreaId { + inline bool operator()(const VehiclePropValue& left, const VehiclePropValue& right) const { + return left.prop == right.prop && left.areaId == right.areaId; + } + }; + + mutable std::mutex mLock; + std::unordered_map, + PropIdAreaIdHash> + mClientsByPropIdAreaId GUARDED_BY(mLock); + std::unordered_map> + mSubscribedPropsByClient GUARDED_BY(mLock); + std::unordered_map mContSubConfigsByPropIdArea + GUARDED_BY(mLock); + std::unordered_map> + mContSubValuesByCallback GUARDED_BY(mLock); + + VhalResult addContinuousSubscriberLocked(const ClientIdType& clientId, + const PropIdAreaId& propIdAreaId, + float sampleRateHz, float resolution, + bool enableVur) REQUIRES(mLock); + VhalResult addOnChangeSubscriberLocked(const PropIdAreaId& propIdAreaId) REQUIRES(mLock); + // Removes the subscription client for the continuous [propId, areaId]. + VhalResult removeContinuousSubscriberLocked(const ClientIdType& clientId, + const PropIdAreaId& propIdAreaId) + REQUIRES(mLock); + // Removes one subscription client for the on-change [propId, areaId]. + VhalResult removeOnChangeSubscriberLocked(const PropIdAreaId& propIdAreaId) + REQUIRES(mLock); + + VhalResult updateContSubConfigsLocked(const PropIdAreaId& PropIdAreaId, + const ContSubConfigs& newConfig) REQUIRES(mLock); + + VhalResult unsubscribePropIdAreaIdLocked(SubscriptionManager::ClientIdType clientId, + const PropIdAreaId& propIdAreaId) + REQUIRES(mLock); + + // Checks whether the manager is empty. For testing purpose. + bool isEmpty(); + + bool isValueUpdatedLocked(const CallbackType& callback, const VehiclePropValue& value) + REQUIRES(mLock); + + // Get the interval in nanoseconds accroding to sample rate. + static android::base::Result getIntervalNanos(float sampleRateHz); +}; + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_aidl_impl_vhal_include_SubscriptionManager_H_ diff --git a/automotive/vehicle/aidl/impl/current/vhal/src/ConnectedClient.cpp b/automotive/vehicle/aidl/impl/current/vhal/src/ConnectedClient.cpp new file mode 100644 index 0000000000000000000000000000000000000000..35b93d2128b3c9a649db60b8acc42dc5d0c5663e --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/vhal/src/ConnectedClient.cpp @@ -0,0 +1,312 @@ +/* + * Copyright (C) 2021 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 "ConnectedClient.h" +#include "ParcelableUtils.h" + +#include + +#include + +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +namespace { + +using ::aidl::android::hardware::automotive::vehicle::GetValueResult; +using ::aidl::android::hardware::automotive::vehicle::GetValueResults; +using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback; +using ::aidl::android::hardware::automotive::vehicle::SetValueResult; +using ::aidl::android::hardware::automotive::vehicle::SetValueResults; +using ::aidl::android::hardware::automotive::vehicle::StatusCode; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropError; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropErrors; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValues; +using ::android::base::Result; +using ::ndk::ScopedAStatus; + +// A function to call the specific callback based on results type. +template +ScopedAStatus callCallback(std::shared_ptr callback, const T& results); + +template <> +ScopedAStatus callCallback(std::shared_ptr callback, + const GetValueResults& results) { + return callback->onGetValues(results); +} + +template <> +ScopedAStatus callCallback(std::shared_ptr callback, + const SetValueResults& results) { + return callback->onSetValues(results); +} + +// Send a single GetValue/SetValue result through the callback. +template +void sendGetOrSetValueResult(std::shared_ptr callback, const ResultType& result) { + ResultsType parcelableResults; + parcelableResults.payloads.resize(1); + parcelableResults.payloads[0] = result; + if (ScopedAStatus callbackStatus = callCallback(callback, parcelableResults); + !callbackStatus.isOk()) { + ALOGE("failed to call GetOrSetValueResult callback, client ID: %p, error: %s, " + "exception: %d, service specific error: %d", + callback->asBinder().get(), callbackStatus.getMessage(), + callbackStatus.getExceptionCode(), callbackStatus.getServiceSpecificError()); + } +} + +// Send all the GetValue/SetValue results through callback, one result in each callback invocation. +template +void sendGetOrSetValueResultsSeparately(std::shared_ptr callback, + const std::vector& results) { + for (const auto& result : results) { + sendGetOrSetValueResult(callback, result); + } +} + +// Send all the GetValue/SetValue results through callback in a single callback invocation. +template +void sendGetOrSetValueResults(std::shared_ptr callback, + std::vector&& results) { + ResultsType parcelableResults; + ScopedAStatus status = vectorToStableLargeParcelable(std::move(results), &parcelableResults); + if (status.isOk()) { + if (ScopedAStatus callbackStatus = callCallback(callback, parcelableResults); + !callbackStatus.isOk()) { + ALOGE("failed to call GetOrSetValueResults callback, client ID: %p, error: %s, " + "exception: %d, service specific error: %d", + callback->asBinder().get(), callbackStatus.getMessage(), + callbackStatus.getExceptionCode(), callbackStatus.getServiceSpecificError()); + } + return; + } + int statusCode = status.getServiceSpecificError(); + ALOGE("failed to marshal result into large parcelable, error: " + "%s, code: %d", + status.getMessage(), statusCode); + sendGetOrSetValueResultsSeparately(callback, + parcelableResults.payloads); +} + +// The timeout callback for GetValues/SetValues. +template +void onTimeout( + std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback> callback, + const std::unordered_set& timeoutIds) { + std::vector timeoutResults; + for (int64_t requestId : timeoutIds) { + ALOGD("hardware request timeout, request ID: %" PRId64, requestId); + timeoutResults.push_back({ + .requestId = requestId, + .status = StatusCode::TRY_AGAIN, + }); + } + sendGetOrSetValueResults(callback, std::move(timeoutResults)); +} + +// The on-results callback for GetValues/SetValues. +template +void getOrSetValuesCallback( + const void* clientId, + std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback> callback, + std::vector&& results, std::shared_ptr requestPool) { + std::unordered_set requestIds; + for (const auto& result : results) { + requestIds.insert(result.requestId); + } + + auto finishedRequests = requestPool->tryFinishRequests(clientId, requestIds); + + auto it = results.begin(); + while (it != results.end()) { + int64_t requestId = it->requestId; + if (finishedRequests.find(requestId) == finishedRequests.end()) { + ALOGD("no pending request for the result from hardware, " + "possibly already time-out, ID: %" PRId64, + requestId); + it = results.erase(it); + } else { + it++; + } + } + + if (!results.empty()) { + sendGetOrSetValueResults(callback, std::move(results)); + } +} + +// Specify the functions for GetValues and SetValues types. +template void sendGetOrSetValueResult( + std::shared_ptr callback, const GetValueResult& result); +template void sendGetOrSetValueResult( + std::shared_ptr callback, const SetValueResult& result); + +template void sendGetOrSetValueResults( + std::shared_ptr callback, std::vector&& results); +template void sendGetOrSetValueResults( + std::shared_ptr callback, std::vector&& results); + +template void sendGetOrSetValueResultsSeparately( + std::shared_ptr callback, const std::vector& results); +template void sendGetOrSetValueResultsSeparately( + std::shared_ptr callback, const std::vector& results); + +template void onTimeout( + std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback> callback, + const std::unordered_set& timeoutIds); +template void onTimeout( + std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback> callback, + const std::unordered_set& timeoutIds); + +template void getOrSetValuesCallback( + const void* clientId, + std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback> callback, + std::vector&& results, std::shared_ptr requestPool); +template void getOrSetValuesCallback( + const void* clientId, + std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback> callback, + std::vector&& results, std::shared_ptr requestPool); + +} // namespace + +ConnectedClient::ConnectedClient(std::shared_ptr requestPool, + std::shared_ptr callback) + : mRequestPool(requestPool), mCallback(callback) {} + +const void* ConnectedClient::id() { + return reinterpret_cast(this); +} + +VhalResult ConnectedClient::addRequests(const std::unordered_set& requestIds) { + return mRequestPool->addRequests(id(), requestIds, getTimeoutCallback()); +} + +std::unordered_set ConnectedClient::tryFinishRequests( + const std::unordered_set& requestIds) { + return mRequestPool->tryFinishRequests(id(), requestIds); +} + +template +GetSetValuesClient::GetSetValuesClient( + std::shared_ptr requestPool, std::shared_ptr callback) + : ConnectedClient(requestPool, callback) { + mTimeoutCallback = std::make_shared( + [callback](const std::unordered_set& timeoutIds) { + return onTimeout(callback, timeoutIds); + }); + auto requestPoolCopy = mRequestPool; + const void* clientId = id(); + mResultCallback = std::make_shared)>>( + [clientId, callback, requestPoolCopy](std::vector results) { + return getOrSetValuesCallback( + clientId, callback, std::move(results), requestPoolCopy); + }); +} + +template +std::shared_ptr)>> +GetSetValuesClient::getResultCallback() { + return mResultCallback; +} + +template +std::shared_ptr +GetSetValuesClient::getTimeoutCallback() { + return mTimeoutCallback; +} + +template +void GetSetValuesClient::sendResults(std::vector&& results) { + return sendGetOrSetValueResults(mCallback, std::move(results)); +} + +template +void GetSetValuesClient::sendResultsSeparately( + const std::vector& results) { + return sendGetOrSetValueResultsSeparately(mCallback, results); +} + +template class GetSetValuesClient; +template class GetSetValuesClient; + +void SubscriptionClient::sendUpdatedValues(std::shared_ptr callback, + std::vector&& updatedValues) { + if (updatedValues.empty()) { + return; + } + + // TODO(b/205189110): Use memory pool here and fill in sharedMemoryId. + VehiclePropValues vehiclePropValues; + int32_t sharedMemoryFileCount = 0; + ScopedAStatus status = + vectorToStableLargeParcelable(std::move(updatedValues), &vehiclePropValues); + if (!status.isOk()) { + int statusCode = status.getServiceSpecificError(); + ALOGE("subscribe: failed to marshal result into large parcelable, error: " + "%s, code: %d", + status.getMessage(), statusCode); + return; + } + + if (ScopedAStatus callbackStatus = + callback->onPropertyEvent(vehiclePropValues, sharedMemoryFileCount); + !callbackStatus.isOk()) { + ALOGE("subscribe: failed to call onPropertyEvent callback, client ID: %p, error: %s, " + "exception: %d, service specific error: %d", + callback->asBinder().get(), callbackStatus.getMessage(), + callbackStatus.getExceptionCode(), callbackStatus.getServiceSpecificError()); + } +} + +void SubscriptionClient::sendPropertySetErrors(std::shared_ptr callback, + std::vector&& vehiclePropErrors) { + if (vehiclePropErrors.empty()) { + return; + } + + VehiclePropErrors vehiclePropErrorsLargeParcelable; + ScopedAStatus status = vectorToStableLargeParcelable(std::move(vehiclePropErrors), + &vehiclePropErrorsLargeParcelable); + if (!status.isOk()) { + int statusCode = status.getServiceSpecificError(); + ALOGE("subscribe: failed to marshal result into large parcelable, error: " + "%s, code: %d", + status.getMessage(), statusCode); + return; + } + + if (ScopedAStatus callbackStatus = + callback->onPropertySetError(vehiclePropErrorsLargeParcelable); + !callbackStatus.isOk()) { + ALOGE("subscribe: failed to call onPropertySetError callback, client ID: %p, error: %s, " + "exception: %d, service specific error: %d", + callback->asBinder().get(), callbackStatus.getMessage(), + callbackStatus.getExceptionCode(), callbackStatus.getServiceSpecificError()); + } +} + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/current/vhal/src/DefaultVehicleHal.cpp b/automotive/vehicle/aidl/impl/current/vhal/src/DefaultVehicleHal.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1e55a1acce1f87ec1aa67d261fb9cf642e3497d5 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/vhal/src/DefaultVehicleHal.cpp @@ -0,0 +1,1121 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "DefaultVehicleHal" +#define ATRACE_TAG ATRACE_TAG_HAL + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +namespace { + +using ::aidl::android::hardware::automotive::vehicle::GetValueRequest; +using ::aidl::android::hardware::automotive::vehicle::GetValueRequests; +using ::aidl::android::hardware::automotive::vehicle::GetValueResult; +using ::aidl::android::hardware::automotive::vehicle::GetValueResults; +using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback; +using ::aidl::android::hardware::automotive::vehicle::MinMaxSupportedValueResults; +using ::aidl::android::hardware::automotive::vehicle::SetValueRequest; +using ::aidl::android::hardware::automotive::vehicle::SetValueRequests; +using ::aidl::android::hardware::automotive::vehicle::SetValueResult; +using ::aidl::android::hardware::automotive::vehicle::SetValueResults; +using ::aidl::android::hardware::automotive::vehicle::StatusCode; +using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions; +using ::aidl::android::hardware::automotive::vehicle::SupportedValuesListResults; +using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfigs; +using ::aidl::android::hardware::automotive::vehicle::VehicleProperty; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyChangeMode; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; +using ::aidl::android::hardware::automotive::vehicle::VersionForVehicleProperty; +using ::android::automotive::car_binder_lib::LargeParcelableBase; +using ::android::base::Error; +using ::android::base::expected; +using ::android::base::Result; +using ::android::base::StringPrintf; + +using ::ndk::ScopedAIBinder_DeathRecipient; +using ::ndk::ScopedAStatus; +using ::ndk::ScopedFileDescriptor; + +std::string toString(const std::unordered_set& values) { + std::string str = ""; + for (auto it = values.begin(); it != values.end(); it++) { + str += std::to_string(*it); + if (std::next(it, 1) != values.end()) { + str += ", "; + } + } + return str; +} + +float getDefaultSampleRateHz(float sampleRateHz, float minSampleRateHz, float maxSampleRateHz) { + if (sampleRateHz < minSampleRateHz) { + return minSampleRateHz; + } + if (sampleRateHz > maxSampleRateHz) { + return maxSampleRateHz; + } + return sampleRateHz; +} + +class SCOPED_CAPABILITY SharedScopedLockAssertion { + public: + SharedScopedLockAssertion(std::shared_timed_mutex& mutex) ACQUIRE_SHARED(mutex) {} + ~SharedScopedLockAssertion() RELEASE() {} +}; + +class SCOPED_CAPABILITY UniqueScopedLockAssertion { + public: + UniqueScopedLockAssertion(std::shared_timed_mutex& mutex) ACQUIRE(mutex) {} + ~UniqueScopedLockAssertion() RELEASE() {} +}; + +} // namespace + +DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr vehicleHardware) + : DefaultVehicleHal(std::move(vehicleHardware), /* testInterfaceVersion= */ 0) {}; + +DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr vehicleHardware, + int32_t testInterfaceVersion) + : mVehicleHardware(std::move(vehicleHardware)), + mPendingRequestPool(std::make_shared(TIMEOUT_IN_NANO)), + mTestInterfaceVersion(testInterfaceVersion) { + ALOGD("DefaultVehicleHal init"); + IVehicleHardware* vehicleHardwarePtr = mVehicleHardware.get(); + mSubscriptionManager = std::make_shared(vehicleHardwarePtr); + mEventBatchingWindow = mVehicleHardware->getPropertyOnChangeEventBatchingWindow(); + if (mEventBatchingWindow != std::chrono::nanoseconds(0)) { + mBatchedEventQueue = std::make_shared>(); + mPropertyChangeEventsBatchingConsumer = + std::make_shared>(); + mPropertyChangeEventsBatchingConsumer->run( + mBatchedEventQueue.get(), mEventBatchingWindow, + [this](std::vector batchedEvents) { + handleBatchedPropertyEvents(std::move(batchedEvents)); + }); + } + + std::weak_ptr> batchedEventQueueCopy = mBatchedEventQueue; + std::chrono::nanoseconds eventBatchingWindow = mEventBatchingWindow; + std::weak_ptr subscriptionManagerCopy = mSubscriptionManager; + mVehicleHardware->registerOnPropertyChangeEvent( + std::make_unique( + [subscriptionManagerCopy, batchedEventQueueCopy, + eventBatchingWindow](std::vector updatedValues) { + if (eventBatchingWindow != std::chrono::nanoseconds(0)) { + batchPropertyChangeEvent(batchedEventQueueCopy, + std::move(updatedValues)); + } else { + onPropertyChangeEvent(subscriptionManagerCopy, + std::move(updatedValues)); + } + })); + mVehicleHardware->registerOnPropertySetErrorEvent( + std::make_unique( + [subscriptionManagerCopy](std::vector errorEvents) { + onPropertySetErrorEvent(subscriptionManagerCopy, errorEvents); + })); + + // Register heartbeat event. + mRecurrentAction = std::make_shared>( + [vehicleHardwarePtr, subscriptionManagerCopy]() { + checkHealth(vehicleHardwarePtr, subscriptionManagerCopy); + }); + mRecurrentTimer.registerTimerCallback(HEART_BEAT_INTERVAL_IN_NANO, mRecurrentAction); + + mBinderLifecycleHandler = std::make_unique(); + mOnBinderDiedUnlinkedHandlerThread = std::thread([this] { onBinderDiedUnlinkedHandler(); }); + mDeathRecipient = ScopedAIBinder_DeathRecipient( + AIBinder_DeathRecipient_new(&DefaultVehicleHal::onBinderDied)); + AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(), + &DefaultVehicleHal::onBinderUnlinked); +} + +DefaultVehicleHal::~DefaultVehicleHal() { + // Delete the deathRecipient so that onBinderDied would not be called to reference 'this'. + mDeathRecipient = ScopedAIBinder_DeathRecipient(); + mBinderEvents.deactivate(); + if (mOnBinderDiedUnlinkedHandlerThread.joinable()) { + mOnBinderDiedUnlinkedHandlerThread.join(); + } + // mRecurrentAction uses pointer to mVehicleHardware, so it has to be unregistered before + // mVehicleHardware. + mRecurrentTimer.unregisterTimerCallback(mRecurrentAction); + + if (mBatchedEventQueue) { + // mPropertyChangeEventsBatchingConsumer uses mSubscriptionManager and mBatchedEventQueue. + mBatchedEventQueue->deactivate(); + mPropertyChangeEventsBatchingConsumer->requestStop(); + mPropertyChangeEventsBatchingConsumer->waitStopped(); + mPropertyChangeEventsBatchingConsumer.reset(); + mBatchedEventQueue.reset(); + } + + // mSubscriptionManager uses pointer to mVehicleHardware, so it has to be destroyed before + // mVehicleHardware. + mSubscriptionManager.reset(); + mVehicleHardware.reset(); +} + +void DefaultVehicleHal::batchPropertyChangeEvent( + const std::weak_ptr>& batchedEventQueue, + std::vector&& updatedValues) { + auto batchedEventQueueStrong = batchedEventQueue.lock(); + if (batchedEventQueueStrong == nullptr) { + ALOGW("the batched property events queue is destroyed, DefaultVehicleHal is ending"); + return; + } + batchedEventQueueStrong->push(std::move(updatedValues)); +} + +void DefaultVehicleHal::handleBatchedPropertyEvents(std::vector&& batchedEvents) { + onPropertyChangeEvent(mSubscriptionManager, std::move(batchedEvents)); +} + +void DefaultVehicleHal::onPropertyChangeEvent( + const std::weak_ptr& subscriptionManager, + std::vector&& updatedValues) { + ATRACE_CALL(); + auto manager = subscriptionManager.lock(); + if (manager == nullptr) { + ALOGW("the SubscriptionManager is destroyed, DefaultVehicleHal is ending"); + return; + } + auto updatedValuesByClients = manager->getSubscribedClients(std::move(updatedValues)); + for (auto& [callback, values] : updatedValuesByClients) { + SubscriptionClient::sendUpdatedValues(callback, std::move(values)); + } +} + +void DefaultVehicleHal::onPropertySetErrorEvent( + const std::weak_ptr& subscriptionManager, + const std::vector& errorEvents) { + auto manager = subscriptionManager.lock(); + if (manager == nullptr) { + ALOGW("the SubscriptionManager is destroyed, DefaultVehicleHal is ending"); + return; + } + auto vehiclePropErrorsByClient = manager->getSubscribedClientsForErrorEvents(errorEvents); + for (auto& [callback, vehiclePropErrors] : vehiclePropErrorsByClient) { + SubscriptionClient::sendPropertySetErrors(callback, std::move(vehiclePropErrors)); + } +} + +template +std::shared_ptr DefaultVehicleHal::getOrCreateClient( + std::unordered_map>* clients, + const CallbackType& callback, std::shared_ptr pendingRequestPool) { + const AIBinder* clientId = callback->asBinder().get(); + if (clients->find(clientId) == clients->end()) { + (*clients)[clientId] = std::make_shared(pendingRequestPool, callback); + } + return (*clients)[clientId]; +} + +bool DefaultVehicleHal::monitorBinderLifeCycleLocked(const AIBinder* clientId) { + OnBinderDiedContext* contextPtr = nullptr; + if (mOnBinderDiedContexts.find(clientId) != mOnBinderDiedContexts.end()) { + return mBinderLifecycleHandler->isAlive(clientId); + } else { + std::unique_ptr context = std::make_unique( + OnBinderDiedContext{.vhal = this, .clientId = clientId}); + // We know context must be alive when we use contextPtr because context would only + // be removed in OnBinderUnlinked, which must be called after OnBinderDied. + contextPtr = context.get(); + // Insert into a map to keep the context object alive. + mOnBinderDiedContexts[clientId] = std::move(context); + } + + // If this function fails, onBinderUnlinked would be called to remove the added context. + binder_status_t status = mBinderLifecycleHandler->linkToDeath( + const_cast(clientId), mDeathRecipient.get(), static_cast(contextPtr)); + if (status == STATUS_OK) { + return true; + } + ALOGE("failed to call linkToDeath on client binder, client may already died, status: %d", + static_cast(status)); + return false; +} + +void DefaultVehicleHal::onBinderDied(void* cookie) { + OnBinderDiedContext* context = reinterpret_cast(cookie); + // To be handled in mOnBinderDiedUnlinkedHandlerThread. We cannot handle the event in the same + // thread because we might be holding the mLock the handler requires. + context->vhal->mBinderEvents.push( + BinderDiedUnlinkedEvent{/*forOnBinderDied=*/true, context->clientId}); +} + +void DefaultVehicleHal::onBinderDiedWithContext(const AIBinder* clientId) { + std::scoped_lock lockGuard(mLock); + ALOGD("binder died, client ID: %p", clientId); + mSetValuesClients.erase(clientId); + mGetValuesClients.erase(clientId); + mSubscriptionManager->unsubscribe(clientId); +} + +void DefaultVehicleHal::onBinderUnlinked(void* cookie) { + OnBinderDiedContext* context = reinterpret_cast(cookie); + // To be handled in mOnBinderDiedUnlinkedHandlerThread. We cannot handle the event in the same + // thread because we might be holding the mLock the handler requires. + context->vhal->mBinderEvents.push( + BinderDiedUnlinkedEvent{/*forOnBinderDied=*/false, context->clientId}); +} + +void DefaultVehicleHal::onBinderUnlinkedWithContext(const AIBinder* clientId) { + ALOGD("binder unlinked"); + std::scoped_lock lockGuard(mLock); + // Delete the context associated with this cookie. + mOnBinderDiedContexts.erase(clientId); +} + +void DefaultVehicleHal::onBinderDiedUnlinkedHandler() { + while (mBinderEvents.waitForItems()) { + for (BinderDiedUnlinkedEvent& event : mBinderEvents.flush()) { + if (event.forOnBinderDied) { + onBinderDiedWithContext(event.clientId); + } else { + onBinderUnlinkedWithContext(event.clientId); + } + } + } +} + +template std::shared_ptr +DefaultVehicleHal::getOrCreateClient( + std::unordered_map>* clients, + const CallbackType& callback, std::shared_ptr pendingRequestPool); +template std::shared_ptr +DefaultVehicleHal::getOrCreateClient( + std::unordered_map>* clients, + const CallbackType& callback, std::shared_ptr pendingRequestPool); + +void DefaultVehicleHal::setTimeout(int64_t timeoutInNano) { + mPendingRequestPool = std::make_unique(timeoutInNano); +} + +int32_t DefaultVehicleHal::getVhalInterfaceVersion() const { + if (mTestInterfaceVersion != 0) { + return mTestInterfaceVersion; + } + int32_t myVersion = 0; + // getInterfaceVersion is in-reality a const method. + const_cast(this)->getInterfaceVersion(&myVersion); + return myVersion; +} + +bool DefaultVehicleHal::isConfigSupportedForCurrentVhalVersion( + const VehiclePropConfig& config) const { + int32_t myVersion = getVhalInterfaceVersion(); + if (!isSystemProp(config.prop)) { + return true; + } + VehicleProperty property = static_cast(config.prop); + std::string propertyName = aidl::android::hardware::automotive::vehicle::toString(property); + auto it = VersionForVehicleProperty.find(property); + if (it == VersionForVehicleProperty.end()) { + ALOGE("The property: %s is not a supported system property, ignore", propertyName.c_str()); + return false; + } + int requiredVersion = it->second; + if (myVersion < requiredVersion) { + ALOGE("The property: %s is not supported for current client VHAL version, " + "require %d, current version: %d, ignore", + propertyName.c_str(), requiredVersion, myVersion); + return false; + } + return true; +} + +bool DefaultVehicleHal::getAllPropConfigsFromHardwareLocked() const { + ALOGD("Get all property configs from hardware"); + auto configs = mVehicleHardware->getAllPropertyConfigs(); + std::vector filteredConfigs; + for (const auto& config : configs) { + if (isConfigSupportedForCurrentVhalVersion(config)) { + filteredConfigs.push_back(std::move(config)); + } + } + + { + std::unique_lock configWriteLock(mConfigLock); + UniqueScopedLockAssertion lockAssertion(mConfigLock); + + for (auto& config : filteredConfigs) { + mConfigsByPropId[config.prop] = config; + } + VehiclePropConfigs vehiclePropConfigs; + vehiclePropConfigs.payloads = std::move(filteredConfigs); + auto result = LargeParcelableBase::parcelableToStableLargeParcelable(vehiclePropConfigs); + if (!result.ok()) { + ALOGE("failed to convert configs to shared memory file, error: %s, code: %d", + result.error().message().c_str(), static_cast(result.error().code())); + mConfigFile = nullptr; + return false; + } + + if (result.value() != nullptr) { + mConfigFile = std::move(result.value()); + } + } + + mConfigInit = true; + return true; +} + +void DefaultVehicleHal::getConfigsByPropId( + std::function&)> callback) const { + if (!mConfigInit) { + CHECK(getAllPropConfigsFromHardwareLocked()) + << "Failed to get property configs from hardware"; + } + + std::shared_lock configReadLock(mConfigLock); + SharedScopedLockAssertion lockAssertion(mConfigLock); + + callback(mConfigsByPropId); +} + +ScopedAStatus DefaultVehicleHal::getAllPropConfigs(VehiclePropConfigs* output) { + if (!mConfigInit) { + CHECK(getAllPropConfigsFromHardwareLocked()) + << "Failed to get property configs from hardware"; + } + + std::shared_lock configReadLock(mConfigLock); + SharedScopedLockAssertion lockAssertion(mConfigLock); + + if (mConfigFile != nullptr) { + output->payloads.clear(); + output->sharedMemoryFd.set(dup(mConfigFile->get())); + return ScopedAStatus::ok(); + } + + output->payloads.reserve(mConfigsByPropId.size()); + for (const auto& [_, config] : mConfigsByPropId) { + output->payloads.push_back(config); + } + return ScopedAStatus::ok(); +} + +Result DefaultVehicleHal::getConfig(int32_t propId) const { + Result result; + + if (!mConfigInit) { + std::optional config = mVehicleHardware->getPropertyConfig(propId); + if (!config.has_value()) { + return Error() << "no config for property, ID: " << propId; + } + if (!isConfigSupportedForCurrentVhalVersion(config.value())) { + return Error() << "property not supported for current VHAL interface, ID: " << propId; + } + + return config.value(); + } + + getConfigsByPropId([this, &result, propId](const auto& configsByPropId) { + SharedScopedLockAssertion lockAssertion(mConfigLock); + + auto it = configsByPropId.find(propId); + if (it == configsByPropId.end()) { + result = Error() << "no config for property, ID: " << propId; + return; + } + // Copy the VehiclePropConfig + result = it->second; + }); + return result; +} + +Result DefaultVehicleHal::checkProperty(const VehiclePropValue& propValue) { + int32_t propId = propValue.prop; + auto result = getConfig(propId); + if (!result.ok()) { + return result.error(); + } + const VehiclePropConfig& config = result.value(); + const VehicleAreaConfig* areaConfig = getAreaConfig(propValue, config); + if (!isGlobalProp(propId) && areaConfig == nullptr) { + // Ignore areaId for global property. For non global property, check whether areaId is + // allowed. areaId must appear in areaConfig. + return Error() << "invalid area ID: " << propValue.areaId << " for prop ID: " << propId + << ", not listed in config"; + } + if (auto result = checkPropValue(propValue, &config); !result.ok()) { + return Error() << "invalid property value: " << propValue.toString() + << ", error: " << getErrorMsg(result); + } + if (auto result = checkValueRange(propValue, areaConfig); !result.ok()) { + return Error() << "property value out of range: " << propValue.toString() + << ", error: " << getErrorMsg(result); + } + return {}; +} + +ScopedAStatus DefaultVehicleHal::getValues(const CallbackType& callback, + const GetValueRequests& requests) { + ATRACE_CALL(); + if (callback == nullptr) { + return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER); + } + expected, ScopedAStatus> + deserializedResults = fromStableLargeParcelable(requests); + if (!deserializedResults.ok()) { + ALOGE("getValues: failed to parse getValues requests"); + return std::move(deserializedResults.error()); + } + const std::vector& getValueRequests = + deserializedResults.value().getObject()->payloads; + + auto maybeRequestIds = checkDuplicateRequests(getValueRequests); + if (!maybeRequestIds.ok()) { + ALOGE("getValues: duplicate request ID"); + return toScopedAStatus(maybeRequestIds, StatusCode::INVALID_ARG); + } + + // A list of failed result we already know before sending to hardware. + std::vector failedResults; + // The list of requests that we would send to hardware. + std::vector hardwareRequests; + + for (const auto& request : getValueRequests) { + if (auto result = checkReadPermission(request.prop); !result.ok()) { + ALOGW("property does not support reading: %s", getErrorMsg(result).c_str()); + failedResults.push_back(GetValueResult{ + .requestId = request.requestId, + .status = getErrorCode(result), + .prop = {}, + }); + continue; + } + hardwareRequests.push_back(request); + } + + // The set of request Ids that we would send to hardware. + std::unordered_set hardwareRequestIds; + for (const auto& request : hardwareRequests) { + hardwareRequestIds.insert(request.requestId); + } + + std::shared_ptr client; + { + // Lock to make sure onBinderDied would not be called concurrently. + std::scoped_lock lockGuard(mLock); + if (!monitorBinderLifeCycleLocked(callback->asBinder().get())) { + return ScopedAStatus::fromExceptionCodeWithMessage(EX_TRANSACTION_FAILED, + "client died"); + } + + client = getOrCreateClient(&mGetValuesClients, callback, mPendingRequestPool); + } + + // Register the pending hardware requests and also check for duplicate request Ids. + if (auto addRequestResult = client->addRequests(hardwareRequestIds); !addRequestResult.ok()) { + ALOGE("getValues[%s]: failed to add pending requests, error: %s", + toString(hardwareRequestIds).c_str(), getErrorMsg(addRequestResult).c_str()); + return toScopedAStatus(addRequestResult); + } + + if (!failedResults.empty()) { + // First send the failed results we already know back to the client. + client->sendResults(std::move(failedResults)); + } + + if (hardwareRequests.empty()) { + return ScopedAStatus::ok(); + } + + if (StatusCode status = + mVehicleHardware->getValues(client->getResultCallback(), hardwareRequests); + status != StatusCode::OK) { + // If the hardware returns error, finish all the pending requests for this request because + // we never expect hardware to call callback for these requests. + client->tryFinishRequests(hardwareRequestIds); + ALOGE("getValues[%s]: failed to get value from VehicleHardware, status: %d", + toString(hardwareRequestIds).c_str(), toInt(status)); + return ScopedAStatus::fromServiceSpecificErrorWithMessage( + toInt(status), "failed to get value from VehicleHardware"); + } + return ScopedAStatus::ok(); +} + +ScopedAStatus DefaultVehicleHal::setValues(const CallbackType& callback, + const SetValueRequests& requests) { + ATRACE_CALL(); + if (callback == nullptr) { + return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER); + } + expected, ScopedAStatus> + deserializedResults = fromStableLargeParcelable(requests); + if (!deserializedResults.ok()) { + ALOGE("setValues: failed to parse setValues requests"); + return std::move(deserializedResults.error()); + } + const std::vector& setValueRequests = + deserializedResults.value().getObject()->payloads; + + // A list of failed result we already know before sending to hardware. + std::vector failedResults; + // The list of requests that we would send to hardware. + std::vector hardwareRequests; + + auto maybeRequestIds = checkDuplicateRequests(setValueRequests); + if (!maybeRequestIds.ok()) { + ALOGE("setValues: duplicate request ID"); + return toScopedAStatus(maybeRequestIds, StatusCode::INVALID_ARG); + } + + for (auto& request : setValueRequests) { + int64_t requestId = request.requestId; + if (auto result = checkWritePermission(request.value); !result.ok()) { + ALOGW("property does not support writing: %s", getErrorMsg(result).c_str()); + failedResults.push_back(SetValueResult{ + .requestId = requestId, + .status = getErrorCode(result), + }); + continue; + } + if (auto result = checkProperty(request.value); !result.ok()) { + ALOGW("setValues[%" PRId64 "]: property is not valid: %s", requestId, + getErrorMsg(result).c_str()); + failedResults.push_back(SetValueResult{ + .requestId = requestId, + .status = StatusCode::INVALID_ARG, + }); + continue; + } + + hardwareRequests.push_back(request); + } + + // The set of request Ids that we would send to hardware. + std::unordered_set hardwareRequestIds; + for (const auto& request : hardwareRequests) { + hardwareRequestIds.insert(request.requestId); + } + + std::shared_ptr client; + { + // Lock to make sure onBinderDied would not be called concurrently. + std::scoped_lock lockGuard(mLock); + if (!monitorBinderLifeCycleLocked(callback->asBinder().get())) { + return ScopedAStatus::fromExceptionCodeWithMessage(EX_TRANSACTION_FAILED, + "client died"); + } + client = getOrCreateClient(&mSetValuesClients, callback, mPendingRequestPool); + } + + // Register the pending hardware requests and also check for duplicate request Ids. + if (auto addRequestResult = client->addRequests(hardwareRequestIds); !addRequestResult.ok()) { + ALOGE("setValues[%s], failed to add pending requests, error: %s", + toString(hardwareRequestIds).c_str(), getErrorMsg(addRequestResult).c_str()); + return toScopedAStatus(addRequestResult); + } + + if (!failedResults.empty()) { + // First send the failed results we already know back to the client. + client->sendResults(std::move(failedResults)); + } + + if (hardwareRequests.empty()) { + return ScopedAStatus::ok(); + } + + if (StatusCode status = + mVehicleHardware->setValues(client->getResultCallback(), hardwareRequests); + status != StatusCode::OK) { + // If the hardware returns error, finish all the pending requests for this request because + // we never expect hardware to call callback for these requests. + client->tryFinishRequests(hardwareRequestIds); + ALOGE("setValues[%s], failed to set value to VehicleHardware, status: %d", + toString(hardwareRequestIds).c_str(), toInt(status)); + return ScopedAStatus::fromServiceSpecificErrorWithMessage( + toInt(status), "failed to set value to VehicleHardware"); + } + + return ScopedAStatus::ok(); +} + +#define CHECK_DUPLICATE_REQUESTS(PROP_NAME) \ + do { \ + std::vector requestIds; \ + std::set<::aidl::android::hardware::automotive::vehicle::VehiclePropValue> requestProps; \ + for (const auto& request : requests) { \ + const auto& prop = request.PROP_NAME; \ + if (requestProps.count(prop) != 0) { \ + return ::android::base::Error() \ + << "duplicate request for property: " << prop.toString(); \ + } \ + requestProps.insert(prop); \ + requestIds.push_back(request.requestId); \ + } \ + return requestIds; \ + } while (0); + +::android::base::Result> DefaultVehicleHal::checkDuplicateRequests( + const std::vector& requests) { + CHECK_DUPLICATE_REQUESTS(prop); +} + +::android::base::Result> DefaultVehicleHal::checkDuplicateRequests( + const std::vector& requests) { + CHECK_DUPLICATE_REQUESTS(value); +} + +#undef CHECK_DUPLICATE_REQUESTS + +ScopedAStatus DefaultVehicleHal::getPropConfigs(const std::vector& props, + VehiclePropConfigs* output) { + std::vector configs; + + if (!mConfigInit) { + for (int32_t prop : props) { + auto maybeConfig = mVehicleHardware->getPropertyConfig(prop); + if (!maybeConfig.has_value() || + !isConfigSupportedForCurrentVhalVersion(maybeConfig.value())) { + return ScopedAStatus::fromServiceSpecificErrorWithMessage( + toInt(StatusCode::INVALID_ARG), + StringPrintf("no config for property, ID: %" PRId32, prop).c_str()); + } + configs.push_back(maybeConfig.value()); + } + + return vectorToStableLargeParcelable(std::move(configs), output); + } + + ScopedAStatus status = ScopedAStatus::ok(); + getConfigsByPropId([this, &configs, &status, &props](const auto& configsByPropId) { + SharedScopedLockAssertion lockAssertion(mConfigLock); + + for (int32_t prop : props) { + auto it = configsByPropId.find(prop); + if (it != configsByPropId.end()) { + configs.push_back(it->second); + } else { + status = ScopedAStatus::fromServiceSpecificErrorWithMessage( + toInt(StatusCode::INVALID_ARG), + StringPrintf("no config for property, ID: %" PRId32, prop).c_str()); + return; + } + } + }); + + if (!status.isOk()) { + return status; + } + + return vectorToStableLargeParcelable(std::move(configs), output); +} + +bool hasRequiredAccess(VehiclePropertyAccess access, VehiclePropertyAccess requiredAccess) { + return access == requiredAccess || access == VehiclePropertyAccess::READ_WRITE; +} + +bool areaConfigsHaveRequiredAccess(const std::vector& areaConfigs, + VehiclePropertyAccess requiredAccess) { + if (areaConfigs.empty()) { + return false; + } + for (VehicleAreaConfig areaConfig : areaConfigs) { + if (!hasRequiredAccess(areaConfig.access, requiredAccess)) { + return false; + } + } + return true; +} + +VhalResult DefaultVehicleHal::checkSubscribeOptions( + const std::vector& options, + const std::unordered_map& configsByPropId) { + for (const auto& option : options) { + int32_t propId = option.propId; + auto it = configsByPropId.find(propId); + if (it == configsByPropId.end()) { + return StatusError(StatusCode::INVALID_ARG) + << StringPrintf("no config for property, ID: %" PRId32, propId); + } + const VehiclePropConfig& config = it->second; + std::vector areaConfigs; + if (option.areaIds.empty()) { + areaConfigs = config.areaConfigs; + } else { + std::unordered_map areaConfigByAreaId; + for (const VehicleAreaConfig& areaConfig : config.areaConfigs) { + areaConfigByAreaId.emplace(areaConfig.areaId, areaConfig); + } + for (int areaId : option.areaIds) { + auto it = areaConfigByAreaId.find(areaId); + if (it != areaConfigByAreaId.end()) { + areaConfigs.push_back(it->second); + } else if (areaId != 0 || !areaConfigByAreaId.empty()) { + return StatusError(StatusCode::INVALID_ARG) + << StringPrintf("invalid area ID: %" PRId32 " for prop ID: %" PRId32 + ", not listed in config", + areaId, propId); + } + } + } + + if (config.changeMode != VehiclePropertyChangeMode::ON_CHANGE && + config.changeMode != VehiclePropertyChangeMode::CONTINUOUS) { + return StatusError(StatusCode::INVALID_ARG) + << "only support subscribing to ON_CHANGE or CONTINUOUS property"; + } + + // Either VehiclePropConfig.access or VehicleAreaConfig.access will be specified + if (!hasRequiredAccess(config.access, VehiclePropertyAccess::READ) && + !areaConfigsHaveRequiredAccess(areaConfigs, VehiclePropertyAccess::READ)) { + return StatusError(StatusCode::ACCESS_DENIED) + << StringPrintf("Property %" PRId32 " has no read access", propId); + } + + if (config.changeMode == VehiclePropertyChangeMode::CONTINUOUS) { + float sampleRateHz = option.sampleRate; + float minSampleRateHz = config.minSampleRate; + float maxSampleRateHz = config.maxSampleRate; + float defaultRateHz = + getDefaultSampleRateHz(sampleRateHz, minSampleRateHz, maxSampleRateHz); + if (sampleRateHz != defaultRateHz) { + ALOGW("sample rate: %f HZ out of range, must be within %f HZ and %f HZ , set to %f " + "HZ", + sampleRateHz, minSampleRateHz, maxSampleRateHz, defaultRateHz); + sampleRateHz = defaultRateHz; + } + if (!SubscriptionManager::checkSampleRateHz(sampleRateHz)) { + return StatusError(StatusCode::INVALID_ARG) + << "invalid sample rate: " << sampleRateHz << " HZ"; + } + if (!SubscriptionManager::checkResolution(option.resolution)) { + return StatusError(StatusCode::INVALID_ARG) + << "invalid resolution: " << option.resolution; + } + } + } + + return {}; +} + +void DefaultVehicleHal::parseSubscribeOptions( + const std::vector& options, + const std::unordered_map& configsByPropId, + std::vector& onChangeSubscriptions, + std::vector& continuousSubscriptions) { + for (const auto& option : options) { + int32_t propId = option.propId; + // We have already validate config exists. + const VehiclePropConfig& config = configsByPropId.at(propId); + + SubscribeOptions optionCopy = option; + // If areaIds is empty, subscribe to all areas. + if (optionCopy.areaIds.empty() && !isGlobalProp(propId)) { + for (const auto& areaConfig : config.areaConfigs) { + optionCopy.areaIds.push_back(areaConfig.areaId); + } + } + + if (isGlobalProp(propId)) { + optionCopy.areaIds = {0}; + } + + if (config.changeMode == VehiclePropertyChangeMode::CONTINUOUS) { + optionCopy.sampleRate = getDefaultSampleRateHz( + optionCopy.sampleRate, config.minSampleRate, config.maxSampleRate); + if (!optionCopy.enableVariableUpdateRate) { + continuousSubscriptions.push_back(std::move(optionCopy)); + } else { + // If clients enables to VUR, we need to check whether VUR is supported for the + // specific [propId, areaId] and overwrite the option to disable if not supported. + std::vector areasVurEnabled; + std::vector areasVurDisabled; + for (int32_t areaId : optionCopy.areaIds) { + const VehicleAreaConfig* areaConfig = getAreaConfig(propId, areaId, config); + if (areaConfig == nullptr) { + areasVurDisabled.push_back(areaId); + continue; + } + if (!areaConfig->supportVariableUpdateRate) { + areasVurDisabled.push_back(areaId); + continue; + } + areasVurEnabled.push_back(areaId); + } + if (!areasVurEnabled.empty()) { + SubscribeOptions optionVurEnabled = optionCopy; + optionVurEnabled.areaIds = areasVurEnabled; + optionVurEnabled.enableVariableUpdateRate = true; + continuousSubscriptions.push_back(std::move(optionVurEnabled)); + } + + if (!areasVurDisabled.empty()) { + // We use optionCopy for areas with VUR disabled. + optionCopy.areaIds = areasVurDisabled; + optionCopy.enableVariableUpdateRate = false; + continuousSubscriptions.push_back(std::move(optionCopy)); + } + } + } else { + onChangeSubscriptions.push_back(std::move(optionCopy)); + } + } +} + +ScopedAStatus DefaultVehicleHal::subscribe(const CallbackType& callback, + const std::vector& options, + [[maybe_unused]] int32_t maxSharedMemoryFileCount) { + // TODO(b/205189110): Use shared memory file count. + if (callback == nullptr) { + return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER); + } + std::vector onChangeSubscriptions; + std::vector continuousSubscriptions; + ScopedAStatus returnStatus = ScopedAStatus::ok(); + getConfigsByPropId([this, &returnStatus, &options, &onChangeSubscriptions, + &continuousSubscriptions](const auto& configsByPropId) { + SharedScopedLockAssertion lockAssertion(mConfigLock); + + if (auto result = checkSubscribeOptions(options, configsByPropId); !result.ok()) { + ALOGE("subscribe: invalid subscribe options: %s", getErrorMsg(result).c_str()); + returnStatus = toScopedAStatus(result); + return; + } + parseSubscribeOptions(options, configsByPropId, onChangeSubscriptions, + continuousSubscriptions); + }); + + if (!returnStatus.isOk()) { + return returnStatus; + } + + { + // Lock to make sure onBinderDied would not be called concurrently. + std::scoped_lock lockGuard(mLock); + if (!monitorBinderLifeCycleLocked(callback->asBinder().get())) { + return ScopedAStatus::fromExceptionCodeWithMessage(EX_TRANSACTION_FAILED, + "client died"); + } + + if (!onChangeSubscriptions.empty()) { + auto result = mSubscriptionManager->subscribe(callback, onChangeSubscriptions, + /*isContinuousProperty=*/false); + if (!result.ok()) { + return toScopedAStatus(result); + } + } + if (!continuousSubscriptions.empty()) { + auto result = mSubscriptionManager->subscribe(callback, continuousSubscriptions, + /*isContinuousProperty=*/true); + if (!result.ok()) { + return toScopedAStatus(result); + } + } + } + return ScopedAStatus::ok(); +} + +ScopedAStatus DefaultVehicleHal::unsubscribe(const CallbackType& callback, + const std::vector& propIds) { + if (callback == nullptr) { + return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER); + } + return toScopedAStatus(mSubscriptionManager->unsubscribe(callback->asBinder().get(), propIds)); +} + +ScopedAStatus DefaultVehicleHal::returnSharedMemory(const CallbackType&, int64_t) { + // TODO(b/200737967): implement this. + return ScopedAStatus::ok(); +} + +ScopedAStatus DefaultVehicleHal::getSupportedValuesLists( + const std::vector<::aidl::android::hardware::automotive::vehicle::PropIdAreaId>&, + SupportedValuesListResults*) { + // TODO(b/381020465): Add relevant implementation. + return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +} + +ScopedAStatus DefaultVehicleHal::getMinMaxSupportedValue( + const std::vector<::aidl::android::hardware::automotive::vehicle::PropIdAreaId>&, + MinMaxSupportedValueResults*) { + // TODO(b/381020465): Add relevant implementation. + return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +} + +ScopedAStatus DefaultVehicleHal::registerSupportedValueChangeCallback( + const std::shared_ptr&, + const std::vector<::aidl::android::hardware::automotive::vehicle::PropIdAreaId>&) { + // TODO(b/381020465): Add relevant implementation. + return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +} + +ScopedAStatus DefaultVehicleHal::unregisterSupportedValueChangeCallback( + const std::shared_ptr&, + const std::vector<::aidl::android::hardware::automotive::vehicle::PropIdAreaId>&) { + // TODO(b/381020465): Add relevant implementation. + return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +} + +IVehicleHardware* DefaultVehicleHal::getHardware() { + return mVehicleHardware.get(); +} + +VhalResult DefaultVehicleHal::checkPermissionHelper( + const VehiclePropValue& value, VehiclePropertyAccess accessToTest) const { + static const std::unordered_set validAccesses = { + VehiclePropertyAccess::WRITE, VehiclePropertyAccess::READ, + VehiclePropertyAccess::READ_WRITE}; + if (validAccesses.find(accessToTest) == validAccesses.end()) { + return StatusError(StatusCode::INVALID_ARG) + << "checkPermissionHelper parameter is an invalid access type"; + } + + int32_t propId = value.prop; + auto result = getConfig(propId); + if (!result.ok()) { + return StatusError(StatusCode::INVALID_ARG) << getErrorMsg(result); + } + + const VehiclePropConfig& config = result.value(); + const VehicleAreaConfig* areaConfig = getAreaConfig(value, config); + + if (areaConfig == nullptr && !isGlobalProp(propId)) { + return StatusError(StatusCode::INVALID_ARG) << "no config for area ID: " << value.areaId; + } + if (!hasRequiredAccess(config.access, accessToTest) && + (areaConfig == nullptr || !hasRequiredAccess(areaConfig->access, accessToTest))) { + return StatusError(StatusCode::ACCESS_DENIED) + << StringPrintf("Property %" PRId32 " does not have the following access: %" PRId32, + propId, static_cast(accessToTest)); + } + return {}; +} + +VhalResult DefaultVehicleHal::checkWritePermission(const VehiclePropValue& value) const { + return checkPermissionHelper(value, VehiclePropertyAccess::WRITE); +} + +VhalResult DefaultVehicleHal::checkReadPermission(const VehiclePropValue& value) const { + return checkPermissionHelper(value, VehiclePropertyAccess::READ); +} + +void DefaultVehicleHal::checkHealth(IVehicleHardware* vehicleHardware, + std::weak_ptr subscriptionManager) { + StatusCode status = vehicleHardware->checkHealth(); + if (status != StatusCode::OK) { + ALOGE("VHAL check health returns non-okay status"); + return; + } + std::vector values = {{ + .areaId = 0, + .prop = toInt(VehicleProperty::VHAL_HEARTBEAT), + .status = VehiclePropertyStatus::AVAILABLE, + .value.int64Values = {uptimeMillis()}, + }}; + onPropertyChangeEvent(subscriptionManager, std::move(values)); + return; +} + +binder_status_t DefaultVehicleHal::BinderLifecycleHandler::linkToDeath( + AIBinder* binder, AIBinder_DeathRecipient* recipient, void* cookie) { + return AIBinder_linkToDeath(binder, recipient, cookie); +} + +bool DefaultVehicleHal::BinderLifecycleHandler::isAlive(const AIBinder* binder) { + return AIBinder_isAlive(binder); +} + +void DefaultVehicleHal::setBinderLifecycleHandler( + std::unique_ptr handler) { + mBinderLifecycleHandler = std::move(handler); +} + +bool DefaultVehicleHal::checkDumpPermission() { + uid_t uid = AIBinder_getCallingUid(); + return uid == AID_ROOT || uid == AID_SHELL || uid == AID_SYSTEM; +} + +binder_status_t DefaultVehicleHal::dump(int fd, const char** args, uint32_t numArgs) { + if (!checkDumpPermission()) { + dprintf(fd, "Caller must be root, system or shell"); + return STATUS_PERMISSION_DENIED; + } + + std::vector options; + for (uint32_t i = 0; i < numArgs; i++) { + options.push_back(args[i]); + } + if (options.size() == 1 && options[0] == "-a") { + // Ignore "-a" option. Bugreport will call with this option. + options.clear(); + } + DumpResult result = mVehicleHardware->dump(options); + if (result.refreshPropertyConfigs) { + getAllPropConfigsFromHardwareLocked(); + } + dprintf(fd, "%s", (result.buffer + "\n").c_str()); + if (!result.callerShouldDumpState) { + return STATUS_OK; + } + dprintf(fd, "Vehicle HAL State: \n"); + std::unordered_map configsByPropIdCopy; + getConfigsByPropId([this, &configsByPropIdCopy](const auto& configsByPropId) { + SharedScopedLockAssertion lockAssertion(mConfigLock); + + configsByPropIdCopy = configsByPropId; + }); + { + std::scoped_lock lockGuard(mLock); + dprintf(fd, "Interface version: %" PRId32 "\n", getVhalInterfaceVersion()); + dprintf(fd, "Containing %zu property configs\n", configsByPropIdCopy.size()); + dprintf(fd, "Currently have %zu getValues clients\n", mGetValuesClients.size()); + dprintf(fd, "Currently have %zu setValues clients\n", mSetValuesClients.size()); + dprintf(fd, "Currently have %zu subscribe clients\n", countSubscribeClients()); + } + return STATUS_OK; +} + +size_t DefaultVehicleHal::countSubscribeClients() { + return mSubscriptionManager->countClients(); +} + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/current/vhal/src/SubscriptionManager.cpp b/automotive/vehicle/aidl/impl/current/vhal/src/SubscriptionManager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..14ee7070c41b5ad2db554d528954c666f86195b7 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/vhal/src/SubscriptionManager.cpp @@ -0,0 +1,499 @@ +/* + * Copyright (C) 2021 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 "SubscriptionManager.h" + +#include +#include +#include +#include + +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +namespace { + +using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback; +using ::aidl::android::hardware::automotive::vehicle::StatusCode; +using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropError; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; +using ::android::base::Error; +using ::android::base::Result; +using ::android::base::StringPrintf; +using ::ndk::ScopedAStatus; + +constexpr float EPSILON = 0.0000001; +constexpr float ONE_SECOND_IN_NANOS = 1'000'000'000.; + +SubscribeOptions newSubscribeOptions(int32_t propId, int32_t areaId, float sampleRateHz, + float resolution, bool enableVur) { + SubscribeOptions subscribedOptions; + subscribedOptions.propId = propId; + subscribedOptions.areaIds = {areaId}; + subscribedOptions.sampleRate = sampleRateHz; + subscribedOptions.resolution = resolution; + subscribedOptions.enableVariableUpdateRate = enableVur; + + return subscribedOptions; +} + +} // namespace + +SubscriptionManager::SubscriptionManager(IVehicleHardware* vehicleHardware) + : mVehicleHardware(vehicleHardware) {} + +SubscriptionManager::~SubscriptionManager() { + std::scoped_lock lockGuard(mLock); + + mClientsByPropIdAreaId.clear(); + mSubscribedPropsByClient.clear(); +} + +bool SubscriptionManager::checkSampleRateHz(float sampleRateHz) { + return getIntervalNanos(sampleRateHz).ok(); +} + +Result SubscriptionManager::getIntervalNanos(float sampleRateHz) { + int64_t intervalNanos = 0; + if (sampleRateHz <= 0) { + return Error() << "invalid sample rate, must be a positive number"; + } + if (sampleRateHz <= (ONE_SECOND_IN_NANOS / static_cast(INT64_MAX))) { + return Error() << "invalid sample rate: " << sampleRateHz << ", too small"; + } + intervalNanos = static_cast(ONE_SECOND_IN_NANOS / sampleRateHz); + return intervalNanos; +} + +bool SubscriptionManager::checkResolution(float resolution) { + if (resolution == 0) { + return true; + } + + float log = std::log10(resolution); + return std::abs(log - std::round(log)) < EPSILON; +} + +void ContSubConfigs::refreshCombinedConfig() { + float maxSampleRateHz = 0.; + float minRequiredResolution = std::numeric_limits::max(); + bool enableVur = true; + // This is not called frequently so a brute-focre is okay. More efficient way exists but this + // is simpler. + for (const auto& [_, subConfig] : mConfigByClient) { + if (subConfig.sampleRateHz > maxSampleRateHz) { + maxSampleRateHz = subConfig.sampleRateHz; + } + if (subConfig.resolution < minRequiredResolution) { + minRequiredResolution = subConfig.resolution; + } + if (!subConfig.enableVur) { + // If one client does not enable variable update rate, we cannot enable variable update + // rate in IVehicleHardware. + enableVur = false; + } + } + mMaxSampleRateHz = maxSampleRateHz; + mMinRequiredResolution = minRequiredResolution; + mEnableVur = enableVur; +} + +void ContSubConfigs::addClient(const ClientIdType& clientId, const SubConfig& subConfig) { + mConfigByClient[clientId] = subConfig; + refreshCombinedConfig(); +} + +void ContSubConfigs::removeClient(const ClientIdType& clientId) { + mConfigByClient.erase(clientId); + refreshCombinedConfig(); +} + +float ContSubConfigs::getMaxSampleRateHz() const { + return mMaxSampleRateHz; +} + +float ContSubConfigs::getMinRequiredResolution() const { + return mMinRequiredResolution; +} + +bool ContSubConfigs::isVurEnabled() const { + return mEnableVur; +} + +bool ContSubConfigs::isVurEnabledForClient(const ClientIdType& clientId) const { + if (mConfigByClient.find(clientId) == mConfigByClient.end()) { + return false; + } + return mConfigByClient.at(clientId).enableVur; +} + +float ContSubConfigs::getResolutionForClient(const ClientIdType& clientId) const { + if (mConfigByClient.find(clientId) == mConfigByClient.end()) { + return 0.0f; + } + return mConfigByClient.at(clientId).resolution; +} + +VhalResult SubscriptionManager::addOnChangeSubscriberLocked( + const PropIdAreaId& propIdAreaId) { + if (mClientsByPropIdAreaId.find(propIdAreaId) != mClientsByPropIdAreaId.end()) { + // This propId, areaId is already subscribed, ignore the request. + return {}; + } + + int32_t propId = propIdAreaId.propId; + int32_t areaId = propIdAreaId.areaId; + if (auto status = mVehicleHardware->subscribe( + newSubscribeOptions(propId, areaId, /*updateRateHz=*/0, /*resolution*/ 0.0f, + /*enableVur*/ false)); + status != StatusCode::OK) { + return StatusError(status) + << StringPrintf("failed subscribe for prop: %s, areaId: %" PRId32, + propIdToString(propId).c_str(), areaId); + } + return {}; +} + +VhalResult SubscriptionManager::addContinuousSubscriberLocked( + const ClientIdType& clientId, const PropIdAreaId& propIdAreaId, float sampleRateHz, + float resolution, bool enableVur) { + // Make a copy so that we don't modify 'mContSubConfigsByPropIdArea' on failure cases. + ContSubConfigs newConfig = mContSubConfigsByPropIdArea[propIdAreaId]; + SubConfig subConfig = { + .sampleRateHz = sampleRateHz, + .resolution = resolution, + .enableVur = enableVur, + }; + newConfig.addClient(clientId, subConfig); + return updateContSubConfigsLocked(propIdAreaId, newConfig); +} + +VhalResult SubscriptionManager::removeContinuousSubscriberLocked( + const ClientIdType& clientId, const PropIdAreaId& propIdAreaId) { + // Make a copy so that we don't modify 'mContSubConfigsByPropIdArea' on failure cases. + ContSubConfigs newConfig = mContSubConfigsByPropIdArea[propIdAreaId]; + newConfig.removeClient(clientId); + return updateContSubConfigsLocked(propIdAreaId, newConfig); +} + +VhalResult SubscriptionManager::removeOnChangeSubscriberLocked( + const PropIdAreaId& propIdAreaId) { + if (mClientsByPropIdAreaId[propIdAreaId].size() > 1) { + // After unsubscribing this client, there is still client subscribed, so do nothing. + return {}; + } + + int32_t propId = propIdAreaId.propId; + int32_t areaId = propIdAreaId.areaId; + if (auto status = mVehicleHardware->unsubscribe(propId, areaId); status != StatusCode::OK) { + return StatusError(status) + << StringPrintf("failed unsubscribe for prop: %s, areaId: %" PRId32, + propIdToString(propId).c_str(), areaId); + } + return {}; +} + +VhalResult SubscriptionManager::updateContSubConfigsLocked(const PropIdAreaId& propIdAreaId, + const ContSubConfigs& newConfig) { + const auto& oldConfig = mContSubConfigsByPropIdArea[propIdAreaId]; + float newRateHz = newConfig.getMaxSampleRateHz(); + float oldRateHz = oldConfig.getMaxSampleRateHz(); + float newResolution = newConfig.getMinRequiredResolution(); + float oldResolution = oldConfig.getMinRequiredResolution(); + if (newRateHz == oldRateHz && newResolution == oldResolution && + newConfig.isVurEnabled() == oldConfig.isVurEnabled()) { + mContSubConfigsByPropIdArea[propIdAreaId] = newConfig; + return {}; + } + int32_t propId = propIdAreaId.propId; + int32_t areaId = propIdAreaId.areaId; + if (newRateHz != oldRateHz) { + if (auto status = mVehicleHardware->updateSampleRate(propId, areaId, newRateHz); + status != StatusCode::OK) { + return StatusError(status) + << StringPrintf("failed to update sample rate for prop: %s, areaId: %" PRId32 + ", sample rate: %f HZ", + propIdToString(propId).c_str(), areaId, newRateHz); + } + } + if (newRateHz != 0) { + if (auto status = mVehicleHardware->subscribe(newSubscribeOptions( + propId, areaId, newRateHz, newResolution, newConfig.isVurEnabled())); + status != StatusCode::OK) { + return StatusError(status) << StringPrintf( + "failed subscribe for prop: %s, areaId" + ": %" PRId32 ", sample rate: %f HZ", + propIdToString(propId).c_str(), areaId, newRateHz); + } + } else { + if (auto status = mVehicleHardware->unsubscribe(propId, areaId); status != StatusCode::OK) { + return StatusError(status) << StringPrintf( + "failed unsubscribe for prop: %s, areaId" + ": %" PRId32, + propIdToString(propId).c_str(), areaId); + } + } + mContSubConfigsByPropIdArea[propIdAreaId] = newConfig; + return {}; +} + +VhalResult SubscriptionManager::subscribe(const std::shared_ptr& callback, + const std::vector& options, + bool isContinuousProperty) { + std::scoped_lock lockGuard(mLock); + + for (const auto& option : options) { + float sampleRateHz = option.sampleRate; + + if (isContinuousProperty) { + if (auto result = getIntervalNanos(sampleRateHz); !result.ok()) { + return StatusError(StatusCode::INVALID_ARG) << result.error().message(); + } + if (!checkResolution(option.resolution)) { + return StatusError(StatusCode::INVALID_ARG) << StringPrintf( + "SubscribeOptions.resolution %f is not an integer power of 10", + option.resolution); + } + } + + if (option.areaIds.empty()) { + ALOGE("area IDs to subscribe must not be empty"); + return StatusError(StatusCode::INVALID_ARG) + << "area IDs to subscribe must not be empty"; + } + } + + ClientIdType clientId = callback->asBinder().get(); + + for (const auto& option : options) { + int32_t propId = option.propId; + const std::vector& areaIds = option.areaIds; + for (int32_t areaId : areaIds) { + PropIdAreaId propIdAreaId = { + .propId = propId, + .areaId = areaId, + }; + VhalResult result; + if (isContinuousProperty) { + result = addContinuousSubscriberLocked(clientId, propIdAreaId, option.sampleRate, + option.resolution, + option.enableVariableUpdateRate); + } else { + result = addOnChangeSubscriberLocked(propIdAreaId); + } + + if (!result.ok()) { + return result; + } + + mSubscribedPropsByClient[clientId].insert(propIdAreaId); + mClientsByPropIdAreaId[propIdAreaId][clientId] = callback; + } + } + return {}; +} + +VhalResult SubscriptionManager::unsubscribePropIdAreaIdLocked( + SubscriptionManager::ClientIdType clientId, const PropIdAreaId& propIdAreaId) { + if (mContSubConfigsByPropIdArea.find(propIdAreaId) != mContSubConfigsByPropIdArea.end()) { + // This is a subscribed continuous property. + if (auto result = removeContinuousSubscriberLocked(clientId, propIdAreaId); !result.ok()) { + return result; + } + } else { + if (mClientsByPropIdAreaId.find(propIdAreaId) == mClientsByPropIdAreaId.end()) { + ALOGW("Unsubscribe: The property: %s, areaId: %" PRId32 + " was not previously subscribed, do nothing", + propIdToString(propIdAreaId.propId).c_str(), propIdAreaId.areaId); + return {}; + } + // This is an on-change property. + if (auto result = removeOnChangeSubscriberLocked(propIdAreaId); !result.ok()) { + return result; + } + } + + auto& clients = mClientsByPropIdAreaId[propIdAreaId]; + clients.erase(clientId); + if (clients.empty()) { + mClientsByPropIdAreaId.erase(propIdAreaId); + mContSubConfigsByPropIdArea.erase(propIdAreaId); + } + return {}; +} + +VhalResult SubscriptionManager::unsubscribe(SubscriptionManager::ClientIdType clientId, + const std::vector& propIds) { + std::scoped_lock lockGuard(mLock); + + if (mSubscribedPropsByClient.find(clientId) == mSubscribedPropsByClient.end()) { + return StatusError(StatusCode::INVALID_ARG) + << "No property was subscribed for the callback"; + } + + std::vector propIdAreaIdsToUnsubscribe; + std::unordered_set propIdSet; + for (int32_t propId : propIds) { + propIdSet.insert(propId); + } + auto& subscribedPropIdsAreaIds = mSubscribedPropsByClient[clientId]; + for (const auto& propIdAreaId : subscribedPropIdsAreaIds) { + if (propIdSet.find(propIdAreaId.propId) != propIdSet.end()) { + propIdAreaIdsToUnsubscribe.push_back(propIdAreaId); + } + } + + for (const auto& propIdAreaId : propIdAreaIdsToUnsubscribe) { + if (auto result = unsubscribePropIdAreaIdLocked(clientId, propIdAreaId); !result.ok()) { + return result; + } + subscribedPropIdsAreaIds.erase(propIdAreaId); + } + + if (subscribedPropIdsAreaIds.empty()) { + mSubscribedPropsByClient.erase(clientId); + } + return {}; +} + +VhalResult SubscriptionManager::unsubscribe(SubscriptionManager::ClientIdType clientId) { + std::scoped_lock lockGuard(mLock); + + if (mSubscribedPropsByClient.find(clientId) == mSubscribedPropsByClient.end()) { + return StatusError(StatusCode::INVALID_ARG) << "No property was subscribed for this client"; + } + + auto& subscriptions = mSubscribedPropsByClient[clientId]; + for (auto const& propIdAreaId : subscriptions) { + if (auto result = unsubscribePropIdAreaIdLocked(clientId, propIdAreaId); !result.ok()) { + return result; + } + } + mSubscribedPropsByClient.erase(clientId); + return {}; +} + +bool SubscriptionManager::isValueUpdatedLocked(const std::shared_ptr& callback, + const VehiclePropValue& value) { + const auto& it = mContSubValuesByCallback[callback].find(value); + if (it == mContSubValuesByCallback[callback].end()) { + mContSubValuesByCallback[callback].insert(value); + return true; + } + + if (it->timestamp > value.timestamp) { + ALOGE("The updated property value: %s is outdated, ignored", value.toString().c_str()); + return false; + } + + if (it->value == value.value && it->status == value.status) { + // Even though the property value is the same, we need to store the new property event to + // update the timestamp. + mContSubValuesByCallback[callback].insert(value); + ALOGD("The updated property value for propId: %" PRId32 ", areaId: %" PRId32 + " has the " + "same value and status, ignored if VUR is enabled", + it->prop, it->areaId); + return false; + } + + mContSubValuesByCallback[callback].insert(value); + return true; +} + +std::unordered_map, std::vector> +SubscriptionManager::getSubscribedClients(std::vector&& updatedValues) { + std::scoped_lock lockGuard(mLock); + std::unordered_map, std::vector> clients; + + for (auto& value : updatedValues) { + PropIdAreaId propIdAreaId{ + .propId = value.prop, + .areaId = value.areaId, + }; + if (mClientsByPropIdAreaId.find(propIdAreaId) == mClientsByPropIdAreaId.end()) { + continue; + } + + for (const auto& [client, callback] : mClientsByPropIdAreaId[propIdAreaId]) { + // if propId is on-change, propIdAreaId will not exist in mContSubConfigsByPropIdArea, + // returning an empty ContSubConfigs value for subConfigs i.e. with resolution = 0 and + // enableVur = false. + auto& subConfigs = mContSubConfigsByPropIdArea[propIdAreaId]; + // Clients must be sent different VehiclePropValues with different levels of granularity + // as requested by the client using resolution. + VehiclePropValue newValue = value; + sanitizeByResolution(&(newValue.value), subConfigs.getResolutionForClient(client)); + // If client wants VUR (and VUR is supported as checked in DefaultVehicleHal), it is + // possible that VUR is not enabled in IVehicleHardware because another client does not + // enable VUR. We will implement VUR filtering here for the client that enables it. + if (subConfigs.isVurEnabledForClient(client) && !subConfigs.isVurEnabled()) { + if (isValueUpdatedLocked(callback, newValue)) { + clients[callback].push_back(newValue); + } + } else { + clients[callback].push_back(newValue); + } + } + } + return clients; +} + +std::unordered_map, std::vector> +SubscriptionManager::getSubscribedClientsForErrorEvents( + const std::vector& errorEvents) { + std::scoped_lock lockGuard(mLock); + std::unordered_map, std::vector> clients; + + for (const auto& errorEvent : errorEvents) { + PropIdAreaId propIdAreaId{ + .propId = errorEvent.propId, + .areaId = errorEvent.areaId, + }; + if (mClientsByPropIdAreaId.find(propIdAreaId) == mClientsByPropIdAreaId.end()) { + continue; + } + + for (const auto& [_, client] : mClientsByPropIdAreaId[propIdAreaId]) { + clients[client].push_back({ + .propId = errorEvent.propId, + .areaId = errorEvent.areaId, + .errorCode = errorEvent.errorCode, + }); + } + } + return clients; +} + +bool SubscriptionManager::isEmpty() { + std::scoped_lock lockGuard(mLock); + return mSubscribedPropsByClient.empty() && mClientsByPropIdAreaId.empty(); +} + +size_t SubscriptionManager::countClients() { + std::scoped_lock lockGuard(mLock); + return mSubscribedPropsByClient.size(); +} + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/current/vhal/src/VehicleService.cpp b/automotive/vehicle/aidl/impl/current/vhal/src/VehicleService.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f8a4e7d14dc4db690fd9ddd48a8b93ca30dcbc49 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/vhal/src/VehicleService.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "VehicleService" + +#include +#include + +#include +#include +#include + +using ::android::hardware::automotive::vehicle::DefaultVehicleHal; +using ::android::hardware::automotive::vehicle::fake::FakeVehicleHardware; + +int main(int /* argc */, char* /* argv */[]) { + ALOGI("Starting thread pool..."); + if (!ABinderProcess_setThreadPoolMaxThreadCount(4)) { + ALOGE("%s", "failed to set thread pool max thread count"); + return 1; + } + ABinderProcess_startThreadPool(); + + std::unique_ptr hardware = std::make_unique(); + std::shared_ptr vhal = + ::ndk::SharedRefBase::make(std::move(hardware)); + + ALOGI("Registering as service..."); + binder_exception_t err = AServiceManager_addService( + vhal->asBinder().get(), "android.hardware.automotive.vehicle.IVehicle/default"); + if (err != EX_NONE) { + ALOGE("failed to register android.hardware.automotive.vehicle service, exception: %d", err); + return 1; + } + + ALOGI("Vehicle Service Ready"); + + ABinderProcess_joinThreadPool(); + + ALOGI("Vehicle Service Exiting"); + + return 0; +} diff --git a/automotive/vehicle/aidl/impl/current/vhal/src/fuzzer.cpp b/automotive/vehicle/aidl/impl/current/vhal/src/fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ac1e3b1a56ab17a187adeeb838d7afc9f2b28cad --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/vhal/src/fuzzer.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +using ::android::fuzzService; +using ::android::hardware::automotive::vehicle::DefaultVehicleHal; +using ::android::hardware::automotive::vehicle::fake::FakeVehicleHardware; +using ::ndk::SharedRefBase; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + std::unique_ptr hardware = std::make_unique(); + std::shared_ptr vhal = + ::ndk::SharedRefBase::make(std::move(hardware)); + + fuzzService(vhal->asBinder().get(), FuzzedDataProvider(data, size)); + + return 0; +} diff --git a/automotive/vehicle/aidl/impl/vhal/test/Android.bp b/automotive/vehicle/aidl/impl/current/vhal/test/Android.bp similarity index 100% rename from automotive/vehicle/aidl/impl/vhal/test/Android.bp rename to automotive/vehicle/aidl/impl/current/vhal/test/Android.bp diff --git a/automotive/vehicle/aidl/impl/current/vhal/test/ConnectedClientTest.cpp b/automotive/vehicle/aidl/impl/current/vhal/test/ConnectedClientTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..682e9e6a0658a3b33aaf12d71772a65a01b53239 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/vhal/test/ConnectedClientTest.cpp @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2021 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 "ConnectedClient.h" +#include "MockVehicleCallback.h" + +#include + +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +using ::aidl::android::hardware::automotive::vehicle::GetValueResult; +using ::aidl::android::hardware::automotive::vehicle::GetValueResults; +using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback; +using ::aidl::android::hardware::automotive::vehicle::SetValueResult; +using ::aidl::android::hardware::automotive::vehicle::SetValueResults; +using ::aidl::android::hardware::automotive::vehicle::StatusCode; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; + +class ConnectedClientTest : public testing::Test { + public: + void SetUp() override { + mCallback = ndk::SharedRefBase::make(); + mCallbackClient = IVehicleCallback::fromBinder(mCallback->asBinder()); + // timeout: 1s. + int64_t timeout = 1000000000; + mPool = std::make_shared(timeout); + } + + std::shared_ptr getCallbackClient() { return mCallbackClient; } + + MockVehicleCallback* getCallback() { return mCallback.get(); } + + std::shared_ptr getPool() { return mPool; } + + protected: + using GetValuesClient = GetSetValuesClient; + using SetValuesClient = GetSetValuesClient; + + private: + std::shared_ptr mCallback; + std::shared_ptr mCallbackClient; + std::shared_ptr mPool; +}; + +TEST_F(ConnectedClientTest, testSendGetValueResults) { + std::vector results = {{ + .requestId = 0, + .status = StatusCode::OK, + .prop = + VehiclePropValue{ + .prop = 0, + }, + }, + { + .requestId = 1, + .status = StatusCode::OK, + .prop = + VehiclePropValue{ + .prop = 1, + }, + }}; + + GetValuesClient client(getPool(), getCallbackClient()); + + auto resultsCopy = results; + client.sendResults(std::move(resultsCopy)); + + auto maybeGetValueResults = getCallback()->nextGetValueResults(); + ASSERT_TRUE(maybeGetValueResults.has_value()); + ASSERT_EQ(maybeGetValueResults.value().payloads, results); +} + +TEST_F(ConnectedClientTest, testSendGetValueResultsSeparately) { + std::vector results = {{ + .requestId = 0, + .status = StatusCode::OK, + .prop = + VehiclePropValue{ + .prop = 0, + }, + }, + { + .requestId = 1, + .status = StatusCode::OK, + .prop = + VehiclePropValue{ + .prop = 1, + }, + }}; + + GetValuesClient client(getPool(), getCallbackClient()); + + client.sendResultsSeparately(results); + + for (auto& result : results) { + auto maybeGetValueResults = getCallback()->nextGetValueResults(); + EXPECT_TRUE(maybeGetValueResults.has_value()); + if (!maybeGetValueResults.has_value()) { + continue; + } + EXPECT_EQ(maybeGetValueResults.value().payloads, std::vector({result})); + } +} + +TEST_F(ConnectedClientTest, testGetValuesGnResultCallback) { + std::vector results = {{ + .requestId = 0, + .status = StatusCode::OK, + .prop = + VehiclePropValue{ + .prop = 0, + }, + }, + { + .requestId = 1, + .status = StatusCode::OK, + .prop = + VehiclePropValue{ + .prop = 1, + }, + }}; + + GetValuesClient client(getPool(), getCallbackClient()); + + client.addRequests({0, 1}); + + (*(client.getResultCallback()))(results); + + auto maybeGetValueResults = getCallback()->nextGetValueResults(); + ASSERT_TRUE(maybeGetValueResults.has_value()); + ASSERT_EQ(maybeGetValueResults.value().payloads, results); +} + +TEST_F(ConnectedClientTest, testSendSetValueResults) { + std::vector results = {{ + .requestId = 0, + .status = StatusCode::OK, + }, + { + .requestId = 1, + .status = StatusCode::OK, + }}; + + SetValuesClient client(getPool(), getCallbackClient()); + + auto resultsCopy = results; + client.sendResults(std::move(resultsCopy)); + + auto maybeSetValueResults = getCallback()->nextSetValueResults(); + ASSERT_TRUE(maybeSetValueResults.has_value()); + ASSERT_EQ(maybeSetValueResults.value().payloads, results); +} + +TEST_F(ConnectedClientTest, testSendSetValueResultsSeparately) { + std::vector results = {{ + .requestId = 0, + .status = StatusCode::OK, + }, + { + .requestId = 1, + .status = StatusCode::OK, + }}; + + SetValuesClient client(getPool(), getCallbackClient()); + + client.sendResultsSeparately(results); + + for (auto& result : results) { + auto maybeSetValueResults = getCallback()->nextSetValueResults(); + EXPECT_TRUE(maybeSetValueResults.has_value()); + if (!maybeSetValueResults.has_value()) { + continue; + } + EXPECT_EQ(maybeSetValueResults.value().payloads, std::vector({result})); + } +} + +TEST_F(ConnectedClientTest, testSetValuesGetResultCallback) { + std::vector results = {{ + .requestId = 0, + .status = StatusCode::OK, + }, + { + .requestId = 1, + .status = StatusCode::OK, + }}; + + SetValuesClient client(getPool(), getCallbackClient()); + + client.addRequests({0, 1}); + + (*(client.getResultCallback()))(results); + + auto maybeSetValueResults = getCallback()->nextSetValueResults(); + ASSERT_TRUE(maybeSetValueResults.has_value()); + ASSERT_EQ(maybeSetValueResults.value().payloads, results); +} + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/current/vhal/test/DefaultVehicleHalTest.cpp b/automotive/vehicle/aidl/impl/current/vhal/test/DefaultVehicleHalTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ad34a4caca5b5f2868818a291ad39ea7eda0f305 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/vhal/test/DefaultVehicleHalTest.cpp @@ -0,0 +1,2127 @@ +/* + * Copyright (C) 2021 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 "ConnectedClient.h" +#include "DefaultVehicleHal.h" +#include "MockVehicleCallback.h" +#include "MockVehicleHardware.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +namespace { + +using ::aidl::android::hardware::automotive::vehicle::GetValueRequest; +using ::aidl::android::hardware::automotive::vehicle::GetValueRequests; +using ::aidl::android::hardware::automotive::vehicle::GetValueResult; +using ::aidl::android::hardware::automotive::vehicle::GetValueResults; +using ::aidl::android::hardware::automotive::vehicle::IVehicle; +using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback; +using ::aidl::android::hardware::automotive::vehicle::SetValueRequest; +using ::aidl::android::hardware::automotive::vehicle::SetValueRequests; +using ::aidl::android::hardware::automotive::vehicle::SetValueResult; +using ::aidl::android::hardware::automotive::vehicle::SetValueResults; +using ::aidl::android::hardware::automotive::vehicle::StatusCode; +using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions; +using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig; +using ::aidl::android::hardware::automotive::vehicle::VehicleAreaWindow; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfigs; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropError; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropErrors; +using ::aidl::android::hardware::automotive::vehicle::VehicleProperty; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyChangeMode; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValues; + +using ::android::automotive::car_binder_lib::LargeParcelableBase; +using ::android::base::Result; + +using ::ndk::ScopedAStatus; +using ::ndk::ScopedFileDescriptor; +using ::ndk::SpAIBinder; + +using ::testing::ContainsRegex; +using ::testing::ElementsAre; +using ::testing::Eq; +using ::testing::UnorderedElementsAre; +using ::testing::UnorderedElementsAreArray; +using ::testing::WhenSortedBy; + +constexpr int32_t INVALID_PROP_ID = 0; +// VehiclePropertyGroup:VENDOR,VehicleArea:WINDOW,VehiclePropertyType:INT32 +constexpr int32_t INT32_WINDOW_PROP = 10001 + 0x20000000 + 0x03000000 + 0x00400000; +// VehiclePropertyGroup:VENDOR,VehicleArea:GLOBAL,VehiclePropertyType:INT32 +constexpr int32_t GLOBAL_ON_CHANGE_PROP = 10002 + 0x20000000 + 0x01000000 + 0x00400000; +// VehiclePropertyGroup:VENDOR,VehicleArea:GLOBAL,VehiclePropertyType:INT32 +constexpr int32_t GLOBAL_CONTINUOUS_PROP = 10003 + 0x20000000 + 0x01000000 + 0x00400000; +// VehiclePropertyGroup:VENDOR,VehicleArea:WINDOW,VehiclePropertyType:INT32 +constexpr int32_t AREA_ON_CHANGE_PROP = 10004 + 0x20000000 + 0x03000000 + 0x00400000; +// VehiclePropertyGroup:VENDOR,VehicleArea:WINDOW,VehiclePropertyType:INT32 +constexpr int32_t AREA_CONTINUOUS_PROP = 10005 + 0x20000000 + 0x03000000 + 0x00400000; +// VehiclePropertyGroup:VENDOR,VehicleArea:GLOBAL,VehiclePropertyType:INT32 +constexpr int32_t READ_ONLY_PROP = 10006 + 0x20000000 + 0x01000000 + 0x00400000; +// VehiclePropertyGroup:VENDOR,VehicleArea:GLOBAL,VehiclePropertyType:INT32 +constexpr int32_t WRITE_ONLY_PROP = 10007 + 0x20000000 + 0x01000000 + 0x00400000; +// VehiclePropertyGroup:VENDOR,VehicleArea:GLOBAL,VehiclePropertyType:INT32 +constexpr int32_t GLOBAL_CONTINUOUS_PROP_NO_VUR = 10008 + 0x20000000 + 0x01000000 + 0x00400000; +// VehiclePropertyGroup:VENDOR,VehicleArea:GLOBAL,VehiclePropertyType:INT32 +constexpr int32_t GLOBAL_NONE_ACCESS_PROP = 10009 + 0x20000000 + 0x01000000 + 0x00400000; +// VehiclePropertyGroup:VENDOR,VehicleArea:WINDOW,VehiclePropertyType:INT32 +constexpr int32_t AREA_NONE_ACCESS_PROP = 10010 + 0x20000000 + 0x03000000 + 0x00400000; + +int32_t testInt32VecProp(size_t i) { + // VehiclePropertyGroup:VENDOR,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC + return static_cast(i) + 0x20000000 + 0x01000000 + 0x00410000; +} + +std::string toString(const std::vector& options) { + std::string optionsStr; + for (const auto& option : options) { + optionsStr += option.toString() + "\n"; + } + return optionsStr; +} + +struct PropConfigCmp { + bool operator()(const VehiclePropConfig& a, const VehiclePropConfig& b) const { + return (a.prop < b.prop); + } +} propConfigCmp; + +struct SetValuesInvalidRequestTestCase { + std::string name; + VehiclePropValue request; + StatusCode expectedStatus; +}; + +std::vector getSetValuesInvalidRequestTestCases() { + return {{ + .name = "config_not_found", + .request = + { + // No config for INVALID_PROP_ID. + .prop = INVALID_PROP_ID, + }, + .expectedStatus = StatusCode::INVALID_ARG, + }, + { + .name = "invalid_prop_value", + .request = + { + .prop = testInt32VecProp(0), + // No int32Values for INT32_VEC property. + .value.int32Values = {}, + }, + .expectedStatus = StatusCode::INVALID_ARG, + }, + { + .name = "value_out_of_range", + .request = + { + .prop = testInt32VecProp(0), + // We configured the range to be 0-100. + .value.int32Values = {0, -1}, + }, + .expectedStatus = StatusCode::INVALID_ARG, + }, + { + .name = "invalid_area", + .request = + { + .prop = INT32_WINDOW_PROP, + .value.int32Values = {0}, + // Only ROW_1_LEFT is allowed. + .areaId = toInt(VehicleAreaWindow::ROW_1_RIGHT), + }, + .expectedStatus = StatusCode::INVALID_ARG, + }, + { + .name = "no_write_permission", + .request = + { + .prop = READ_ONLY_PROP, + .value.int32Values = {0}, + }, + .expectedStatus = StatusCode::ACCESS_DENIED, + }, + { + .name = "none_access", + .request = + { + .prop = GLOBAL_NONE_ACCESS_PROP, + .value.int32Values = {0}, + }, + .expectedStatus = StatusCode::ACCESS_DENIED, + }, + { + .name = "none_area_access", + .request = + { + .prop = AREA_NONE_ACCESS_PROP, + .value.int32Values = {0}, + // Only ROW_1_LEFT is allowed. + .areaId = toInt(VehicleAreaWindow::ROW_1_RIGHT), + }, + .expectedStatus = StatusCode::ACCESS_DENIED, + }}; +} + +struct SubscribeInvalidOptionsTestCase { + std::string name; + SubscribeOptions option; +}; + +std::vector getSubscribeInvalidOptionsTestCases() { + return {{ + .name = "invalid_prop", + .option = + { + .propId = INVALID_PROP_ID, + }, + }, + { + .name = "invalid_area_ID", + .option = + { + .propId = AREA_ON_CHANGE_PROP, + .areaIds = {0}, + }, + }, + { + .name = "invalid_sample_rate", + .option = + { + .propId = GLOBAL_CONTINUOUS_PROP, + .sampleRate = 0.0, + }, + }, + { + .name = "invalid_resolution", + .option = + { + .propId = GLOBAL_CONTINUOUS_PROP, + .resolution = 2.0, + }, + }, + { + .name = "static_property", + .option = + { + // Default change mode is static. + .propId = testInt32VecProp(0), + }, + }}; +} + +} // namespace + +class DefaultVehicleHalTest : public testing::Test { + public: + void SetUp() override { init(std::make_unique()); } + + void init(std::unique_ptr hardware) { + std::vector testConfigs; + for (size_t i = 0; i < 10000; i++) { + testConfigs.push_back(VehiclePropConfig{ + .prop = testInt32VecProp(i), + .areaConfigs = + { + { + .areaId = 0, + .access = VehiclePropertyAccess::READ_WRITE, + .minInt32Value = 0, + .maxInt32Value = 100, + }, + }, + }); + } + // A property with area config. + testConfigs.push_back( + VehiclePropConfig{.prop = INT32_WINDOW_PROP, + .areaConfigs = {{ + .areaId = toInt(VehicleAreaWindow::ROW_1_LEFT), + .access = VehiclePropertyAccess::READ_WRITE, + .minInt32Value = 0, + .maxInt32Value = 100, + }}}); + // A global on-change property. + testConfigs.push_back(VehiclePropConfig{ + .prop = GLOBAL_ON_CHANGE_PROP, + .access = VehiclePropertyAccess::READ_WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + }); + // A global continuous property. + testConfigs.push_back(VehiclePropConfig{.prop = GLOBAL_CONTINUOUS_PROP, + .access = VehiclePropertyAccess::READ_WRITE, + .changeMode = VehiclePropertyChangeMode::CONTINUOUS, + .minSampleRate = 0.0, + .maxSampleRate = 100.0, + .areaConfigs = {{ + .areaId = 0, + .supportVariableUpdateRate = true, + }}}); + // A global continuous property that does not support VUR. + testConfigs.push_back(VehiclePropConfig{ + .prop = GLOBAL_CONTINUOUS_PROP_NO_VUR, + .access = VehiclePropertyAccess::READ_WRITE, + .changeMode = VehiclePropertyChangeMode::CONTINUOUS, + .minSampleRate = 0.0, + .maxSampleRate = 100.0, + }); + // A per-area on-change property. + testConfigs.push_back(VehiclePropConfig{ + .prop = AREA_ON_CHANGE_PROP, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .areaConfigs = + { + { + + .areaId = toInt(VehicleAreaWindow::ROW_1_LEFT), + .access = VehiclePropertyAccess::READ_WRITE, + .minInt32Value = 0, + .maxInt32Value = 100, + }, + { + .areaId = toInt(VehicleAreaWindow::ROW_1_RIGHT), + .access = VehiclePropertyAccess::READ, + .minInt32Value = 0, + .maxInt32Value = 100, + }, + }, + }); + // A per-area continuous property. + testConfigs.push_back(VehiclePropConfig{ + .prop = AREA_CONTINUOUS_PROP, + .changeMode = VehiclePropertyChangeMode::CONTINUOUS, + .minSampleRate = 0.0, + .maxSampleRate = 1000.0, + .areaConfigs = + { + { + + .areaId = toInt(VehicleAreaWindow::ROW_1_LEFT), + .access = VehiclePropertyAccess::READ_WRITE, + .minInt32Value = 0, + .maxInt32Value = 100, + .supportVariableUpdateRate = true, + }, + { + .areaId = toInt(VehicleAreaWindow::ROW_1_RIGHT), + .access = VehiclePropertyAccess::READ_WRITE, + .minInt32Value = 0, + .maxInt32Value = 100, + .supportVariableUpdateRate = false, + }, + }, + }); + // A read-only property. + testConfigs.push_back(VehiclePropConfig{ + .prop = READ_ONLY_PROP, + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::CONTINUOUS, + .minSampleRate = 0.0, + .maxSampleRate = 1000.0, + }); + // A write-only property. + testConfigs.push_back(VehiclePropConfig{ + .prop = WRITE_ONLY_PROP, + .access = VehiclePropertyAccess::WRITE, + .changeMode = VehiclePropertyChangeMode::CONTINUOUS, + .minSampleRate = 0.0, + .maxSampleRate = 1000.0, + }); + // Global access set to NONE + testConfigs.push_back(VehiclePropConfig{ + .prop = GLOBAL_NONE_ACCESS_PROP, + .access = VehiclePropertyAccess::NONE, + .changeMode = VehiclePropertyChangeMode::CONTINUOUS, + .minSampleRate = 0.0, + .maxSampleRate = 100.0, + }); + // Area access set to NONE + testConfigs.push_back(VehiclePropConfig{ + .prop = AREA_NONE_ACCESS_PROP, + .changeMode = VehiclePropertyChangeMode::CONTINUOUS, + .minSampleRate = 0.0, + .maxSampleRate = 1000.0, + .areaConfigs = + { + { + + .areaId = toInt(VehicleAreaWindow::ROW_1_LEFT), + .access = VehiclePropertyAccess::NONE, + .minInt32Value = 0, + .maxInt32Value = 100, + }, + { + .areaId = toInt(VehicleAreaWindow::ROW_1_RIGHT), + .access = VehiclePropertyAccess::NONE, + .minInt32Value = 0, + .maxInt32Value = 100, + }, + }, + }); + // Register the heartbeat event property. + testConfigs.push_back(VehiclePropConfig{ + .prop = toInt(VehicleProperty::VHAL_HEARTBEAT), + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + }); + hardware->setPropertyConfigs(testConfigs); + mHardwarePtr = hardware.get(); + mVhal = ndk::SharedRefBase::make(std::move(hardware)); + mVhalClient = IVehicle::fromBinder(mVhal->asBinder()); + mCallback = ndk::SharedRefBase::make(); + // Keep the local binder alive. + mBinder = mCallback->asBinder(); + mCallbackClient = IVehicleCallback::fromBinder(mBinder); + + // Set the linkToDeath to a fake implementation that always returns OK. + auto handler = std::make_unique(); + mBinderLifecycleHandler = handler.get(); + mVhal->setBinderLifecycleHandler(std::move(handler)); + } + + void TearDown() override { + ASSERT_EQ(countPendingRequests(), static_cast(0)) + << "must have no pending requests when test finishes"; + } + + MockVehicleHardware* getHardware() { return mHardwarePtr; } + + std::shared_ptr getClient() { return mVhal; } + + std::shared_ptr getCallbackClient() { return mCallbackClient; } + + MockVehicleCallback* getCallback() { return mCallback.get(); } + + void setTimeout(int64_t timeoutInNano) { mVhal->setTimeout(timeoutInNano); } + + size_t countPendingRequests() { return mVhal->mPendingRequestPool->countPendingRequests(); } + + size_t countClients() { + std::scoped_lock lockGuard(mVhal->mLock); + return mVhal->mGetValuesClients.size() + mVhal->mSetValuesClients.size() + + mVhal->countSubscribeClients(); + } + + std::shared_ptr getPool() { return mVhal->mPendingRequestPool; } + + void onBinderDied(void* cookie) { return mVhal->onBinderDied(cookie); } + + void onBinderUnlinked(void* cookie) { return mVhal->onBinderUnlinked(cookie); } + + void* getOnBinderDiedContexts(AIBinder* clientId) { + std::scoped_lock lockGuard(mVhal->mLock); + return mVhal->mOnBinderDiedContexts[clientId].get(); + } + + size_t countOnBinderDiedContexts() { + std::scoped_lock lockGuard(mVhal->mLock); + return mVhal->mOnBinderDiedContexts.size(); + } + + bool hasNoSubscriptions() { return mVhal->mSubscriptionManager->isEmpty(); } + + void setBinderAlive(bool isAlive) { mBinderLifecycleHandler->setAlive(isAlive); }; + + static Result getValuesTestCases(size_t size, GetValueRequests& requests, + std::vector& expectedResults, + std::vector& expectedHardwareRequests) { + expectedHardwareRequests.clear(); + for (size_t i = 0; i < size; i++) { + int64_t requestId = static_cast(i); + int32_t propId = testInt32VecProp(i); + expectedHardwareRequests.push_back(GetValueRequest{ + .prop = + VehiclePropValue{ + .prop = propId, + }, + .requestId = requestId, + }); + expectedResults.push_back(GetValueResult{ + .requestId = requestId, + .status = StatusCode::OK, + .prop = + VehiclePropValue{ + .prop = propId, + .value.int32Values = {1, 2, 3, 4}, + }, + }); + } + + requests.payloads = expectedHardwareRequests; + auto result = LargeParcelableBase::parcelableToStableLargeParcelable(requests); + if (!result.ok()) { + return result.error(); + } + if (result.value() != nullptr) { + requests.sharedMemoryFd = std::move(*result.value()); + requests.payloads.clear(); + } + return {}; + } + + static Result setValuesTestCases(size_t size, SetValueRequests& requests, + std::vector& expectedResults, + std::vector& expectedHardwareRequests) { + expectedHardwareRequests.clear(); + for (size_t i = 0; i < size; i++) { + int64_t requestId = static_cast(i); + int32_t propId = testInt32VecProp(i); + expectedHardwareRequests.push_back(SetValueRequest{ + .value = + VehiclePropValue{ + .prop = propId, + .value.int32Values = {1, 2, 3, 4}, + }, + .requestId = requestId, + }); + expectedResults.push_back(SetValueResult{ + .requestId = requestId, + .status = StatusCode::OK, + }); + } + + requests.payloads = expectedHardwareRequests; + auto result = LargeParcelableBase::parcelableToStableLargeParcelable(requests); + if (!result.ok()) { + return result.error(); + } + if (result.value() != nullptr) { + requests.payloads.clear(); + requests.sharedMemoryFd = std::move(*result.value()); + requests.payloads.clear(); + } + return {}; + } + + private: + class TestBinderLifecycleHandler final : public DefaultVehicleHal::BinderLifecycleInterface { + public: + binder_status_t linkToDeath(AIBinder*, AIBinder_DeathRecipient*, void*) override { + if (mIsAlive) { + return STATUS_OK; + } else { + return STATUS_FAILED_TRANSACTION; + } + } + + bool isAlive(const AIBinder*) override { return mIsAlive; } + + void setAlive(bool isAlive) { mIsAlive = isAlive; } + + private: + bool mIsAlive = true; + }; + + std::shared_ptr mVhal; + std::shared_ptr mVhalClient; + MockVehicleHardware* mHardwarePtr; + std::shared_ptr mCallback; + std::shared_ptr mCallbackClient; + SpAIBinder mBinder; + TestBinderLifecycleHandler* mBinderLifecycleHandler; +}; + +TEST_F(DefaultVehicleHalTest, testGetAllPropConfigsSmall) { + auto testConfigs = std::vector({ + VehiclePropConfig{ + .prop = testInt32VecProp(1), + }, + VehiclePropConfig{ + .prop = testInt32VecProp(2), + }, + }); + + auto hardware = std::make_unique(); + hardware->setPropertyConfigs(testConfigs); + auto vhal = ndk::SharedRefBase::make(std::move(hardware)); + std::shared_ptr client = IVehicle::fromBinder(vhal->asBinder()); + + VehiclePropConfigs output; + auto status = client->getAllPropConfigs(&output); + + ASSERT_TRUE(status.isOk()) << "getAllPropConfigs failed: " << status.getMessage(); + ASSERT_THAT(output.payloads, WhenSortedBy(propConfigCmp, Eq(testConfigs))); +} + +TEST_F(DefaultVehicleHalTest, testGetAllPropConfigsLarge) { + std::vector testConfigs; + // 5000 VehiclePropConfig exceeds 4k memory limit, so it would be sent through shared memory. + for (size_t i = 0; i < 5000; i++) { + testConfigs.push_back(VehiclePropConfig{ + .prop = testInt32VecProp(i), + }); + } + + auto hardware = std::make_unique(); + hardware->setPropertyConfigs(testConfigs); + auto vhal = ndk::SharedRefBase::make(std::move(hardware)); + std::shared_ptr client = IVehicle::fromBinder(vhal->asBinder()); + + VehiclePropConfigs output; + auto status = client->getAllPropConfigs(&output); + + ASSERT_TRUE(status.isOk()) << "getAllPropConfigs failed: " << status.getMessage(); + ASSERT_TRUE(output.payloads.empty()); + auto result = LargeParcelableBase::stableLargeParcelableToParcelable(output); + ASSERT_TRUE(result.ok()) << "failed to parse result shared memory file: " + << result.error().message(); + ASSERT_EQ(result.value().getObject()->payloads, testConfigs); +} + +TEST_F(DefaultVehicleHalTest, testGetAllPropConfigsFilterOutUnsupportedPropIdsForThisVersion) { + auto testConfigs = std::vector({ + // This is supported from V2. + VehiclePropConfig{ + .prop = toInt(VehicleProperty::PERF_VEHICLE_SPEED), + }, + // This is supported from V3 + VehiclePropConfig{ + .prop = toInt(VehicleProperty::ULTRASONICS_SENSOR_POSITION), + }, + }); + + auto hardware = std::make_unique(); + hardware->setPropertyConfigs(testConfigs); + auto vhal = ndk::SharedRefBase::make(std::move(hardware), + /* testInterfaceVersion= */ 2); + std::shared_ptr client = IVehicle::fromBinder(vhal->asBinder()); + + VehiclePropConfigs output; + auto status = client->getAllPropConfigs(&output); + + ASSERT_TRUE(status.isOk()) << "getAllPropConfigs failed: " << status.getMessage(); + ASSERT_THAT(output.payloads, ElementsAre(VehiclePropConfig{ + .prop = toInt(VehicleProperty::PERF_VEHICLE_SPEED), + })); +} + +TEST_F(DefaultVehicleHalTest, testGetPropConfigs) { + int32_t propId1 = testInt32VecProp(1); + int32_t propId2 = testInt32VecProp(2); + auto testConfigs = std::vector({ + VehiclePropConfig{ + .prop = propId1, + }, + VehiclePropConfig{ + .prop = propId2, + }, + }); + + auto hardware = std::make_unique(); + hardware->setPropertyConfigs(testConfigs); + // Store the pointer for testing. We are sure it is valid. + MockVehicleHardware* hardwarePtr = hardware.get(); + auto vhal = ndk::SharedRefBase::make(std::move(hardware)); + std::shared_ptr client = IVehicle::fromBinder(vhal->asBinder()); + + VehiclePropConfigs output; + auto status = client->getPropConfigs(std::vector({propId1, propId2}), &output); + + ASSERT_TRUE(status.isOk()) << "getPropConfigs failed: " << status.getMessage(); + ASSERT_EQ(output.payloads, testConfigs); + ASSERT_FALSE(hardwarePtr->getAllPropertyConfigsCalled()); +} + +TEST_F(DefaultVehicleHalTest, testGetPropConfigsInvalidArg) { + auto testConfigs = std::vector({ + VehiclePropConfig{ + .prop = testInt32VecProp(1), + }, + VehiclePropConfig{ + .prop = testInt32VecProp(2), + }, + }); + + auto hardware = std::make_unique(); + hardware->setPropertyConfigs(testConfigs); + auto vhal = ndk::SharedRefBase::make(std::move(hardware)); + std::shared_ptr client = IVehicle::fromBinder(vhal->asBinder()); + + VehiclePropConfigs output; + auto status = client->getPropConfigs( + std::vector({testInt32VecProp(1), testInt32VecProp(2), testInt32VecProp(3)}), + &output); + + ASSERT_FALSE(status.isOk()) << "getPropConfigs must fail with invalid prop ID"; + ASSERT_EQ(status.getServiceSpecificError(), toInt(StatusCode::INVALID_ARG)); +} + +TEST_F(DefaultVehicleHalTest, testGetValuesSmall) { + GetValueRequests requests; + std::vector expectedResults; + std::vector expectedHardwareRequests; + + ASSERT_TRUE(getValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok()); + + getHardware()->addGetValueResponses(expectedResults); + + auto status = getClient()->getValues(getCallbackClient(), requests); + + ASSERT_TRUE(status.isOk()) << "getValues failed: " << status.getMessage(); + + EXPECT_EQ(getHardware()->nextGetValueRequests(), expectedHardwareRequests) + << "requests to hardware mismatch"; + + auto maybeGetValueResults = getCallback()->nextGetValueResults(); + ASSERT_TRUE(maybeGetValueResults.has_value()) << "no results in callback"; + EXPECT_EQ(maybeGetValueResults.value().payloads, expectedResults) << "results mismatch"; + EXPECT_EQ(countClients(), static_cast(1)); + ASSERT_FALSE(getHardware()->getAllPropertyConfigsCalled()); +} + +TEST_F(DefaultVehicleHalTest, testGetValuesSmall_AfterGetAllPropConfigs) { + GetValueRequests requests; + std::vector expectedResults; + std::vector expectedHardwareRequests; + + // If we already called getAllPropConfigs, the configs will be cached. + VehiclePropConfigs output; + getClient()->getAllPropConfigs(&output); + + ASSERT_TRUE(getValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok()); + + getHardware()->addGetValueResponses(expectedResults); + + auto status = getClient()->getValues(getCallbackClient(), requests); + + ASSERT_TRUE(status.isOk()) << "getValues failed: " << status.getMessage(); + + EXPECT_EQ(getHardware()->nextGetValueRequests(), expectedHardwareRequests) + << "requests to hardware mismatch"; + + auto maybeGetValueResults = getCallback()->nextGetValueResults(); + ASSERT_TRUE(maybeGetValueResults.has_value()) << "no results in callback"; + EXPECT_EQ(maybeGetValueResults.value().payloads, expectedResults) << "results mismatch"; + EXPECT_EQ(countClients(), static_cast(1)); + ASSERT_TRUE(getHardware()->getAllPropertyConfigsCalled()); +} + +TEST_F(DefaultVehicleHalTest, testGetValuesLarge) { + GetValueRequests requests; + std::vector expectedResults; + std::vector expectedHardwareRequests; + + ASSERT_TRUE(getValuesTestCases(5000, requests, expectedResults, expectedHardwareRequests).ok()) + << "requests to hardware mismatch"; + + getHardware()->addGetValueResponses(expectedResults); + + auto status = getClient()->getValues(getCallbackClient(), requests); + + ASSERT_TRUE(status.isOk()) << "getValues failed: " << status.getMessage(); + + EXPECT_EQ(getHardware()->nextGetValueRequests(), expectedHardwareRequests); + + auto maybeGetValueResults = getCallback()->nextGetValueResults(); + ASSERT_TRUE(maybeGetValueResults.has_value()) << "no results in callback"; + const GetValueResults& getValueResults = maybeGetValueResults.value(); + ASSERT_TRUE(getValueResults.payloads.empty()) + << "payload should be empty, shared memory file should be used"; + + auto result = LargeParcelableBase::stableLargeParcelableToParcelable(getValueResults); + ASSERT_TRUE(result.ok()) << "failed to parse shared memory file"; + ASSERT_EQ(result.value().getObject()->payloads, expectedResults) << "results mismatch"; + EXPECT_EQ(countClients(), static_cast(1)); +} + +TEST_F(DefaultVehicleHalTest, testGetValuesErrorFromHardware) { + GetValueRequests requests; + std::vector expectedResults; + std::vector expectedHardwareRequests; + + ASSERT_TRUE(getValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok()); + + getHardware()->setStatus("getValues", StatusCode::INTERNAL_ERROR); + + auto status = getClient()->getValues(getCallbackClient(), requests); + + ASSERT_FALSE(status.isOk()) << "expect getValues to fail when hardware returns error"; + ASSERT_EQ(status.getServiceSpecificError(), toInt(StatusCode::INTERNAL_ERROR)); +} + +TEST_F(DefaultVehicleHalTest, testGetValuesInvalidLargeParcelableInput) { + GetValueRequests requests; + requests.sharedMemoryFd = ScopedFileDescriptor(0); + + auto status = getClient()->getValues(getCallbackClient(), requests); + + ASSERT_FALSE(status.isOk()) << "expect getValues to fail when input parcelable is not valid"; + ASSERT_EQ(status.getServiceSpecificError(), toInt(StatusCode::INVALID_ARG)); +} + +TEST_F(DefaultVehicleHalTest, testGetValuesNoReadPermission) { + GetValueRequests requests = { + .sharedMemoryFd = {}, + .payloads = + { + { + .requestId = 0, + .prop = + { + .prop = WRITE_ONLY_PROP, + }, + }, + { + .requestId = 1, + .prop = + { + .prop = GLOBAL_NONE_ACCESS_PROP, + }, + }, + { + .requestId = 2, + .prop = + { + .prop = AREA_NONE_ACCESS_PROP, + .areaId = toInt(VehicleAreaWindow::ROW_1_LEFT), + }, + }, + }, + }; + + auto status = getClient()->getValues(getCallbackClient(), requests); + + ASSERT_TRUE(status.isOk()) << "getValue with no read permission should return okay with error " + "returned from callback" + << ", error: " << status.getMessage(); + EXPECT_TRUE(getHardware()->nextGetValueRequests().empty()) << "expect no request to hardware"; + + auto maybeResult = getCallback()->nextGetValueResults(); + ASSERT_TRUE(maybeResult.has_value()) << "no results in callback"; + EXPECT_EQ(maybeResult.value().payloads, std::vector({ + { + .requestId = 0, + .status = StatusCode::ACCESS_DENIED, + }, + { + .requestId = 1, + .status = StatusCode::ACCESS_DENIED, + }, + { + .requestId = 2, + .status = StatusCode::ACCESS_DENIED, + }, + })) + << "expect to get ACCESS_DENIED status if no read permission"; +} + +TEST_F(DefaultVehicleHalTest, testGetValuesFinishBeforeTimeout) { + // timeout: 1s + int64_t timeout = 1000000000; + setTimeout(timeout); + + GetValueRequests requests; + std::vector expectedResults; + std::vector expectedHardwareRequests; + + ASSERT_TRUE(getValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok()); + + // The response would be returned after 0.01s. + getHardware()->setSleepTime(timeout / 100); + getHardware()->addGetValueResponses(expectedResults); + + auto status = getClient()->getValues(getCallbackClient(), requests); + + ASSERT_TRUE(status.isOk()) << "getValues failed: " << status.getMessage(); + + ASSERT_TRUE(getCallback()->waitForGetValueResults(1, timeout)) << "no results in callback"; + auto maybeGetValueResults = getCallback()->nextGetValueResults(); + ASSERT_TRUE(maybeGetValueResults.has_value()) << "no results in callback"; + EXPECT_EQ(maybeGetValueResults.value().payloads, expectedResults) << "results mismatch"; + ASSERT_FALSE(getCallback()->nextGetValueResults().has_value()) << "more results than expected"; +} + +TEST_F(DefaultVehicleHalTest, testGetValuesFinishAfterTimeout) { + // timeout: 0.01s + int64_t timeout = 10000000; + setTimeout(timeout); + + GetValueRequests requests; + std::vector expectedResults; + std::vector expectedHardwareRequests; + + ASSERT_TRUE(getValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok()); + + // The response would be returned after 0.1s. + getHardware()->setSleepTime(timeout * 10); + getHardware()->addGetValueResponses(expectedResults); + + auto status = getClient()->getValues(getCallbackClient(), requests); + + ASSERT_TRUE(status.isOk()) << "getValues failed: " << status.getMessage(); + + for (size_t i = 0; i < expectedResults.size(); i++) { + expectedResults[i] = { + .requestId = expectedResults[i].requestId, + .status = StatusCode::TRY_AGAIN, + .prop = std::nullopt, + }; + } + + ASSERT_TRUE(getCallback()->waitForGetValueResults(1, timeout * 100)) + << "no results in callback"; + auto maybeGetValueResults = getCallback()->nextGetValueResults(); + ASSERT_TRUE(maybeGetValueResults.has_value()) << "no results in callback"; + ASSERT_THAT(maybeGetValueResults.value().payloads, UnorderedElementsAreArray(expectedResults)) + << "results mismatch, expect TRY_AGAIN error."; + ASSERT_FALSE(getCallback()->nextGetValueResults().has_value()) << "more results than expected"; +} + +TEST_F(DefaultVehicleHalTest, testGetValuesDuplicateRequestIdsInTwoRequests) { + // timeout: 0.1s + int64_t timeout = 100000000; + setTimeout(timeout); + + GetValueRequests requests; + std::vector expectedResults; + std::vector expectedHardwareRequests; + + ASSERT_TRUE(getValuesTestCases(1, requests, expectedResults, expectedHardwareRequests).ok()); + + getHardware()->setSleepTime(timeout * 2); + getHardware()->addGetValueResponses(expectedResults); + + auto status = getClient()->getValues(getCallbackClient(), requests); + + ASSERT_TRUE(status.isOk()) << "getValues failed: " << status.getMessage(); + + // Use the same request ID again. + status = getClient()->getValues(getCallbackClient(), requests); + + ASSERT_FALSE(status.isOk()) + << "Use the same request ID before the previous request finishes must fail"; + + // Wait for the request to finish. + std::this_thread::sleep_for(std::chrono::nanoseconds(timeout * 5)); +} + +TEST_F(DefaultVehicleHalTest, testGetValuesDuplicateRequestIdsInOneRequest) { + GetValueRequests requests = {.payloads = { + { + .requestId = 0, + .prop = + VehiclePropValue{ + .prop = testInt32VecProp(0), + }, + }, + { + .requestId = 0, + .prop = + VehiclePropValue{ + .prop = testInt32VecProp(1), + }, + }, + }}; + + auto status = getClient()->getValues(getCallbackClient(), requests); + + ASSERT_FALSE(status.isOk()) << "duplicate Ids in one request must fail"; +} + +TEST_F(DefaultVehicleHalTest, testGetValuesDuplicateRequestProps) { + GetValueRequests requests = {.payloads = { + { + .requestId = 0, + .prop = + VehiclePropValue{ + .prop = testInt32VecProp(0), + }, + }, + { + .requestId = 1, + .prop = + VehiclePropValue{ + .prop = testInt32VecProp(0), + }, + }, + }}; + + auto status = getClient()->getValues(getCallbackClient(), requests); + + ASSERT_FALSE(status.isOk()) << "duplicate request properties in one request must fail"; +} + +TEST_F(DefaultVehicleHalTest, testGetValuesNewClientDied) { + GetValueRequests requests; + std::vector expectedResults; + std::vector expectedHardwareRequests; + + ASSERT_TRUE(getValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok()); + + getHardware()->addGetValueResponses(expectedResults); + + setBinderAlive(false); + + auto status = getClient()->getValues(getCallbackClient(), requests); + + ASSERT_FALSE(status.isOk()) << "getValues must fail if client died"; + ASSERT_EQ(status.getExceptionCode(), EX_TRANSACTION_FAILED); + EXPECT_EQ(countClients(), static_cast(0)) + << "No client should be created if the client binder died"; +} + +TEST_F(DefaultVehicleHalTest, testGetValuesExistingClientDied) { + GetValueRequests requests; + std::vector expectedResults; + std::vector expectedHardwareRequests; + + ASSERT_TRUE(getValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok()); + + getHardware()->addGetValueResponses(expectedResults); + + // Try a normal getValue request to cache a GetValueClient first. + auto status = getClient()->getValues(getCallbackClient(), requests); + + ASSERT_TRUE(status.isOk()) << "getValues failed: " << status.getMessage(); + EXPECT_EQ(countClients(), static_cast(1)); + + // The client binder died before onBinderUnlinked clean up the GetValueClient. + setBinderAlive(false); + + status = getClient()->getValues(getCallbackClient(), requests); + + ASSERT_FALSE(status.isOk()) << "getValues must fail if client died"; + ASSERT_EQ(status.getExceptionCode(), EX_TRANSACTION_FAILED); + // The client count should still be 1 but onBinderUnlinked will remove this later. + EXPECT_EQ(countClients(), static_cast(1)); +} + +TEST_F(DefaultVehicleHalTest, testSetValuesSmall) { + SetValueRequests requests; + std::vector expectedResults; + std::vector expectedHardwareRequests; + + ASSERT_TRUE(setValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok()); + + getHardware()->addSetValueResponses(expectedResults); + + auto status = getClient()->setValues(getCallbackClient(), requests); + + ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage(); + + EXPECT_EQ(getHardware()->nextSetValueRequests(), expectedHardwareRequests) + << "requests to hardware mismatch"; + + auto maybeSetValueResults = getCallback()->nextSetValueResults(); + ASSERT_TRUE(maybeSetValueResults.has_value()) << "no results in callback"; + ASSERT_EQ(maybeSetValueResults.value().payloads, expectedResults) << "results mismatch"; + EXPECT_EQ(countClients(), static_cast(1)); + ASSERT_FALSE(getHardware()->getAllPropertyConfigsCalled()); +} + +TEST_F(DefaultVehicleHalTest, testSetValuesSmall_AfterGetAllPropConfigs) { + SetValueRequests requests; + std::vector expectedResults; + std::vector expectedHardwareRequests; + + // If we already called getAllPropConfigs, the configs will be cached. + VehiclePropConfigs output; + getClient()->getAllPropConfigs(&output); + + ASSERT_TRUE(setValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok()); + + getHardware()->addSetValueResponses(expectedResults); + + auto status = getClient()->setValues(getCallbackClient(), requests); + + ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage(); + + EXPECT_EQ(getHardware()->nextSetValueRequests(), expectedHardwareRequests) + << "requests to hardware mismatch"; + + auto maybeSetValueResults = getCallback()->nextSetValueResults(); + ASSERT_TRUE(maybeSetValueResults.has_value()) << "no results in callback"; + ASSERT_EQ(maybeSetValueResults.value().payloads, expectedResults) << "results mismatch"; + EXPECT_EQ(countClients(), static_cast(1)); + ASSERT_TRUE(getHardware()->getAllPropertyConfigsCalled()); +} + +TEST_F(DefaultVehicleHalTest, testSetValuesLarge) { + SetValueRequests requests; + std::vector expectedResults; + std::vector expectedHardwareRequests; + + ASSERT_TRUE(setValuesTestCases(5000, requests, expectedResults, expectedHardwareRequests).ok()); + + getHardware()->addSetValueResponses(expectedResults); + + auto status = getClient()->setValues(getCallbackClient(), requests); + + ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage(); + + EXPECT_EQ(getHardware()->nextSetValueRequests(), expectedHardwareRequests) + << "requests to hardware mismatch"; + + auto maybeSetValueResults = getCallback()->nextSetValueResults(); + ASSERT_TRUE(maybeSetValueResults.has_value()) << "no results in callback"; + const SetValueResults& setValueResults = maybeSetValueResults.value(); + ASSERT_TRUE(setValueResults.payloads.empty()) + << "payload should be empty, shared memory file should be used"; + + auto result = LargeParcelableBase::stableLargeParcelableToParcelable(setValueResults); + ASSERT_TRUE(result.ok()) << "failed to parse shared memory file"; + ASSERT_EQ(result.value().getObject()->payloads, expectedResults) << "results mismatch"; + EXPECT_EQ(countClients(), static_cast(1)); +} + +class SetValuesInvalidRequestTest + : public DefaultVehicleHalTest, + public testing::WithParamInterface {}; + +INSTANTIATE_TEST_SUITE_P( + SetValuesInvalidRequestTests, SetValuesInvalidRequestTest, + testing::ValuesIn(getSetValuesInvalidRequestTestCases()), + [](const testing::TestParamInfo& info) { + return info.param.name; + }); + +TEST_P(SetValuesInvalidRequestTest, testSetValuesInvalidRequest) { + SetValuesInvalidRequestTestCase tc = GetParam(); + std::vector expectedHardwareResults{ + SetValueResult{ + .requestId = 1, + .status = StatusCode::OK, + }, + }; + getHardware()->addSetValueResponses(expectedHardwareResults); + + SetValueRequests requests; + SetValueRequest invalidRequest{ + .requestId = 0, + .value = tc.request, + }; + SetValueRequest normalRequest{.requestId = 1, + .value = { + .prop = testInt32VecProp(0), + .value.int32Values = {0}, + }}; + requests.payloads = {invalidRequest, normalRequest}; + auto status = getClient()->setValues(getCallbackClient(), requests); + + ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage(); + + EXPECT_EQ(getHardware()->nextSetValueRequests(), std::vector({normalRequest})) + << "requests to hardware mismatch"; + + auto maybeSetValueResults = getCallback()->nextSetValueResults(); + ASSERT_TRUE(maybeSetValueResults.has_value()) << "no results in callback"; + EXPECT_EQ(maybeSetValueResults.value().payloads, std::vector({ + { + .requestId = 0, + .status = tc.expectedStatus, + }, + })) + << "invalid argument result mismatch"; + + maybeSetValueResults = getCallback()->nextSetValueResults(); + ASSERT_TRUE(maybeSetValueResults.has_value()) << "no results from hardware in callback"; + EXPECT_EQ(maybeSetValueResults.value().payloads, expectedHardwareResults) + << "results from hardware mismatch"; +} + +TEST_F(DefaultVehicleHalTest, testSetValuesFinishBeforeTimeout) { + // timeout: 1s + int64_t timeout = 1000000000; + setTimeout(timeout); + + SetValueRequests requests; + std::vector expectedResults; + std::vector expectedHardwareRequests; + + ASSERT_TRUE(setValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok()); + + // The response would be returned after 0.01s. + getHardware()->setSleepTime(timeout / 100); + getHardware()->addSetValueResponses(expectedResults); + + auto status = getClient()->setValues(getCallbackClient(), requests); + + ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage(); + + ASSERT_TRUE(getCallback()->waitForSetValueResults(1, timeout)) << "no set value results"; + auto maybeSetValueResults = getCallback()->nextSetValueResults(); + ASSERT_TRUE(maybeSetValueResults.has_value()) << "no results in callback"; + EXPECT_EQ(maybeSetValueResults.value().payloads, expectedResults) << "results mismatch"; + ASSERT_FALSE(getCallback()->nextSetValueResults().has_value()) << "more results than expected"; +} + +TEST_F(DefaultVehicleHalTest, testSetValuesFinishAfterTimeout) { + // timeout: 0.01s + int64_t timeout = 10000000; + setTimeout(timeout); + + SetValueRequests requests; + std::vector expectedResults; + std::vector expectedHardwareRequests; + + ASSERT_TRUE(setValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok()); + + // The response would be returned after 0.1s. + getHardware()->setSleepTime(timeout * 10); + getHardware()->addSetValueResponses(expectedResults); + + auto status = getClient()->setValues(getCallbackClient(), requests); + + ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage(); + + for (size_t i = 0; i < expectedResults.size(); i++) { + expectedResults[i] = { + .requestId = expectedResults[i].requestId, + .status = StatusCode::TRY_AGAIN, + }; + } + + ASSERT_TRUE(getCallback()->waitForSetValueResults(1, timeout * 100)) << "no set value results"; + auto maybeSetValueResults = getCallback()->nextSetValueResults(); + ASSERT_TRUE(maybeSetValueResults.has_value()) << "no results in callback"; + ASSERT_THAT(maybeSetValueResults.value().payloads, UnorderedElementsAreArray(expectedResults)) + << "results mismatch, expect TRY_AGAIN error."; + ASSERT_FALSE(getCallback()->nextSetValueResults().has_value()) << "more results than expected"; +} + +TEST_F(DefaultVehicleHalTest, testSetValuesDuplicateRequestIdsInTwoRequests) { + // timeout: 0.1s + int64_t timeout = 100000000; + setTimeout(timeout); + + SetValueRequests requests; + std::vector expectedResults; + std::vector expectedHardwareRequests; + + ASSERT_TRUE(setValuesTestCases(1, requests, expectedResults, expectedHardwareRequests).ok()); + + getHardware()->setSleepTime(timeout * 2); + getHardware()->addSetValueResponses(expectedResults); + + auto status = getClient()->setValues(getCallbackClient(), requests); + + ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage(); + + // Use the same request ID again. + status = getClient()->setValues(getCallbackClient(), requests); + + ASSERT_FALSE(status.isOk()) + << "Use the same request ID before the previous request finishes must fail"; + + // Wait for the request to finish. + std::this_thread::sleep_for(std::chrono::nanoseconds(timeout * 5)); +} + +TEST_F(DefaultVehicleHalTest, testSetValuesDuplicateRequestIdsInOneRequest) { + SetValueRequests requests = {.payloads = { + { + .requestId = 0, + .value = + VehiclePropValue{ + .prop = testInt32VecProp(0), + .value.int32Values = {0}, + }, + }, + { + .requestId = 0, + .value = + VehiclePropValue{ + .prop = testInt32VecProp(1), + .value.int32Values = {0}, + }, + }, + }}; + + auto status = getClient()->setValues(getCallbackClient(), requests); + + ASSERT_FALSE(status.isOk()) << "duplicate Ids in one request must fail"; +} + +TEST_F(DefaultVehicleHalTest, testSetValuesDuplicateRequestProps) { + SetValueRequests requests = {.payloads = { + { + .requestId = 0, + .value = + VehiclePropValue{ + .prop = testInt32VecProp(0), + .value.int32Values = {0}, + }, + }, + { + .requestId = 1, + .value = + VehiclePropValue{ + .prop = testInt32VecProp(0), + .value.int32Values = {0}, + }, + }, + }}; + + auto status = getClient()->setValues(getCallbackClient(), requests); + + ASSERT_FALSE(status.isOk()) << "duplicate request properties in one request must fail"; +} + +TEST_F(DefaultVehicleHalTest, testSubscribeUnsubscribe) { + std::vector options = { + { + .propId = GLOBAL_ON_CHANGE_PROP, + }, + }; + + auto status = getClient()->subscribe(getCallbackClient(), options, 0); + + ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage(); + + status = getClient()->unsubscribe(getCallbackClient(), + std::vector({GLOBAL_ON_CHANGE_PROP})); + + ASSERT_TRUE(status.isOk()) << "unsubscribe failed: " << status.getMessage(); +} + +TEST_F(DefaultVehicleHalTest, testSubscribeGlobalOnChangeNormal) { + std::vector options = { + { + .propId = GLOBAL_ON_CHANGE_PROP, + }, + }; + + auto status = getClient()->subscribe(getCallbackClient(), options, 0); + + ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage(); + + VehiclePropValue testValue{ + .prop = GLOBAL_ON_CHANGE_PROP, + .value.int32Values = {0}, + }; + SetValueRequests setValueRequests = { + .payloads = + { + SetValueRequest{ + .requestId = 0, + .value = testValue, + }, + }, + }; + std::vector setValueResults = {{ + .requestId = 0, + .status = StatusCode::OK, + }}; + + // Set the value to trigger a property change event. + getHardware()->addSetValueResponses(setValueResults); + status = getClient()->setValues(getCallbackClient(), setValueRequests); + + ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage(); + + auto maybeResults = getCallback()->nextOnPropertyEventResults(); + ASSERT_TRUE(maybeResults.has_value()) << "no results in callback"; + ASSERT_THAT(maybeResults.value().payloads, UnorderedElementsAre(testValue)) + << "results mismatch, expect on change event for the updated value"; + ASSERT_FALSE(getCallback()->nextOnPropertyEventResults().has_value()) + << "more results than expected"; + EXPECT_EQ(countClients(), static_cast(2)) + << "expect 2 clients, 1 subscribe client and 1 setvalue client"; +} + +TEST_F(DefaultVehicleHalTest, testSubscribeGlobalOnchangeUnrelatedEventIgnored) { + std::vector options = { + { + .propId = GLOBAL_ON_CHANGE_PROP, + }, + }; + + auto status = getClient()->subscribe(getCallbackClient(), options, 0); + + ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage(); + + VehiclePropValue testValue{ + .prop = GLOBAL_CONTINUOUS_PROP, + .value.int32Values = {0}, + }; + + // Set the value to trigger a property change event. This event should be ignored because we + // have not subscribed to it. + getHardware()->addSetValueResponses({{ + .requestId = 0, + .status = StatusCode::OK, + }}); + status = getClient()->setValues(getCallbackClient(), + { + .payloads = + { + SetValueRequest{ + .requestId = 0, + .value = testValue, + }, + }, + }); + + ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage(); + + ASSERT_FALSE(getCallback()->nextOnPropertyEventResults().has_value()) + << "must receive no property update event if the property is not subscribed"; +} + +TEST_F(DefaultVehicleHalTest, testSubscribeAreaOnChange) { + int testAreaId = toInt(VehicleAreaWindow::ROW_1_LEFT); + std::vector options = { + { + .propId = AREA_ON_CHANGE_PROP, + .areaIds = {testAreaId}, + }, + }; + + auto status = getClient()->subscribe(getCallbackClient(), options, 0); + + ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage(); + + VehiclePropValue testValue{ + .prop = AREA_ON_CHANGE_PROP, + .areaId = testAreaId, + .value.int32Values = {0}, + }; + + // Set the value to trigger a property change event. + getHardware()->addSetValueResponses({{ + .requestId = 0, + .status = StatusCode::OK, + }}); + status = getClient()->setValues(getCallbackClient(), + { + .payloads = + { + SetValueRequest{ + .requestId = 0, + .value = testValue, + }, + }, + }); + + ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage(); + + auto maybeResults = getCallback()->nextOnPropertyEventResults(); + ASSERT_TRUE(maybeResults.has_value()) << "no results in callback"; + ASSERT_THAT(maybeResults.value().payloads, UnorderedElementsAre(testValue)) + << "results mismatch, expect on change event for the updated value"; + ASSERT_FALSE(getCallback()->nextOnPropertyEventResults().has_value()) + << "more results than expected"; +} + +TEST_F(DefaultVehicleHalTest, testSubscribeAreaOnChangeAllAreas) { + std::vector options = { + { + .propId = AREA_ON_CHANGE_PROP, + // No areaIds means subscribing to all area IDs. + .areaIds = {}, + }, + }; + + auto status = getClient()->subscribe(getCallbackClient(), options, 0); + + ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage(); + + VehiclePropValue testValue1{ + .prop = AREA_ON_CHANGE_PROP, + .areaId = toInt(VehicleAreaWindow::ROW_1_LEFT), + .value.int32Values = {0}, + }; + VehiclePropValue testValue2{ + .prop = AREA_ON_CHANGE_PROP, + .areaId = toInt(VehicleAreaWindow::ROW_1_RIGHT), + .value.int32Values = {0}, + }; + + // Set the values to trigger property change events for two areas. + getHardware()->addSetValueResponses({{ + .requestId = 0, + .status = StatusCode::OK, + }, + { + .requestId = 1, + .status = StatusCode::OK, + }}); + status = getClient()->setValues(getCallbackClient(), + { + .payloads = + { + SetValueRequest{ + .requestId = 0, + .value = testValue1, + }, + SetValueRequest{ + .requestId = 1, + .value = testValue2, + }, + }, + }); + + ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage(); + + auto maybeResults = getCallback()->nextOnPropertyEventResults(); + ASSERT_TRUE(maybeResults.has_value()) << "no results in callback"; + ASSERT_THAT(maybeResults.value().payloads, UnorderedElementsAre(testValue1)) + << "results mismatch, expect one on-change events for all updated areas"; + ASSERT_FALSE(getCallback()->nextOnPropertyEventResults().has_value()) + << "more results than expected"; +} + +TEST_F(DefaultVehicleHalTest, testSubscribeGlobalContinuous) { + VehiclePropValue testValue{ + .prop = GLOBAL_CONTINUOUS_PROP, + }; + + std::vector options = { + { + .propId = GLOBAL_CONTINUOUS_PROP, + .sampleRate = 20.0, + }, + }; + + auto status = getClient()->subscribe(getCallbackClient(), options, 0); + + ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage(); + + // Sleep for 1s, which should generate ~20 events. + std::this_thread::sleep_for(std::chrono::seconds(1)); + + // Should trigger about 20 times, check for at least 15 events to be safe. + for (size_t i = 0; i < 15; i++) { + auto maybeResults = getCallback()->nextOnPropertyEventResults(); + ASSERT_TRUE(maybeResults.has_value()) << "no results in callback"; + ASSERT_THAT(maybeResults.value().payloads, UnorderedElementsAre(testValue)) + << "results mismatch, expect to get the updated value"; + } + EXPECT_EQ(countClients(), static_cast(1)); +} + +TEST_F(DefaultVehicleHalTest, testSubscribeGlobalContinuousRateOutOfRange) { + // The maxSampleRate is 100, so the sample rate should be the default max 100. + std::vector options = { + { + .propId = GLOBAL_CONTINUOUS_PROP, + .sampleRate = 1000.0, + }, + }; + + auto status = getClient()->subscribe(getCallbackClient(), options, 0); + + ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage(); + + // Sleep for 1s, which should generate ~100 events. + std::this_thread::sleep_for(std::chrono::seconds(1)); + + size_t eventCount = getCallback()->countOnPropertyEventResults(); + ASSERT_GE(eventCount, 50u) << "expect at least 50 events to be generated"; + ASSERT_LE(eventCount, 150u) << "expect no more than 150 events to be generated"; + + EXPECT_EQ(countClients(), static_cast(1)); +} + +TEST_F(DefaultVehicleHalTest, testSubscribeContinuous_propNotSupportVur) { + std::vector options = { + { + .propId = GLOBAL_CONTINUOUS_PROP, + .sampleRate = 20.0, + .enableVariableUpdateRate = true, + }, + { + .propId = GLOBAL_CONTINUOUS_PROP_NO_VUR, + .sampleRate = 30.0, + .enableVariableUpdateRate = true, + }, + }; + + auto status = getClient()->subscribe(getCallbackClient(), options, 0); + + ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage(); + auto receivedSubscribeOptions = getHardware()->getSubscribeOptions(); + ASSERT_THAT(receivedSubscribeOptions, UnorderedElementsAre( + SubscribeOptions{ + .propId = GLOBAL_CONTINUOUS_PROP, + .areaIds = {0}, + .enableVariableUpdateRate = true, + .sampleRate = 20.0, + }, + SubscribeOptions{ + .propId = GLOBAL_CONTINUOUS_PROP_NO_VUR, + .areaIds = {0}, + .enableVariableUpdateRate = false, + .sampleRate = 30.0, + })) + << "received unexpected subscribe options: " << toString(receivedSubscribeOptions); +} + +TEST_F(DefaultVehicleHalTest, testSubscribeContinuous_propSupportVurNotEnabled) { + std::vector options = { + { + .propId = GLOBAL_CONTINUOUS_PROP, + .sampleRate = 20.0, + .enableVariableUpdateRate = false, + }, + }; + + auto status = getClient()->subscribe(getCallbackClient(), options, 0); + + ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage(); + auto receivedSubscribeOptions = getHardware()->getSubscribeOptions(); + ASSERT_THAT(receivedSubscribeOptions, UnorderedElementsAre(SubscribeOptions{ + .propId = GLOBAL_CONTINUOUS_PROP, + .areaIds = {0}, + .enableVariableUpdateRate = false, + .sampleRate = 20.0, + })) + << "received unexpected subscribe options: " << toString(receivedSubscribeOptions); +} + +TEST_F(DefaultVehicleHalTest, testSubscribeAreaContinuous) { + std::vector options = { + { + .propId = AREA_CONTINUOUS_PROP, + .sampleRate = 20.0, + .areaIds = {toInt(VehicleAreaWindow::ROW_1_LEFT)}, + }, + { + .propId = AREA_CONTINUOUS_PROP, + .sampleRate = 10.0, + .areaIds = {toInt(VehicleAreaWindow::ROW_1_RIGHT)}, + }, + }; + + auto status = getClient()->subscribe(getCallbackClient(), options, 0); + + ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage(); + + // Sleep for 1s, which should generate ~20 events. + std::this_thread::sleep_for(std::chrono::seconds(1)); + + getClient()->unsubscribe(getCallbackClient(), std::vector({AREA_CONTINUOUS_PROP})); + + std::vector events; + while (true) { + auto maybeResults = getCallback()->nextOnPropertyEventResults(); + if (!maybeResults.has_value()) { + break; + } + for (const auto& value : maybeResults.value().payloads) { + events.push_back(value); + } + } + + size_t leftCount = 0; + size_t rightCount = 0; + + for (const auto& event : events) { + ASSERT_EQ(event.prop, AREA_CONTINUOUS_PROP); + if (event.areaId == toInt(VehicleAreaWindow::ROW_1_LEFT)) { + leftCount++; + continue; + } + rightCount++; + } + + // Should trigger about 20 times, check for at least 15 events to be safe. + ASSERT_GE(leftCount, static_cast(15)); + // Should trigger about 10 times, check for at least 5 events to be safe. + ASSERT_GE(rightCount, static_cast(5)); +} + +TEST_F(DefaultVehicleHalTest, testAreaContinuous_areaNotSupportVur) { + std::vector options = { + { + .propId = AREA_CONTINUOUS_PROP, + .sampleRate = 20.0, + .areaIds = {toInt(VehicleAreaWindow::ROW_1_LEFT)}, + .enableVariableUpdateRate = true, + }, + { + .propId = AREA_CONTINUOUS_PROP, + .sampleRate = 10.0, + .areaIds = {toInt(VehicleAreaWindow::ROW_1_RIGHT)}, + .enableVariableUpdateRate = true, + }, + }; + + auto status = getClient()->subscribe(getCallbackClient(), options, 0); + + ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage(); + auto receivedSubscribeOptions = getHardware()->getSubscribeOptions(); + ASSERT_THAT(receivedSubscribeOptions, + UnorderedElementsAre( + SubscribeOptions{ + .propId = AREA_CONTINUOUS_PROP, + .sampleRate = 20.0, + .areaIds = {toInt(VehicleAreaWindow::ROW_1_LEFT)}, + .enableVariableUpdateRate = true, + }, + SubscribeOptions{ + .propId = AREA_CONTINUOUS_PROP, + .sampleRate = 10.0, + .areaIds = {toInt(VehicleAreaWindow::ROW_1_RIGHT)}, + // Area2 actually does not support VUR. + .enableVariableUpdateRate = false, + })) + << "received unexpected subscribe options: " << toString(receivedSubscribeOptions); +} + +TEST_F(DefaultVehicleHalTest, testUnsubscribeOnChange) { + std::vector options = { + { + .propId = GLOBAL_ON_CHANGE_PROP, + }, + }; + + auto status = getClient()->subscribe(getCallbackClient(), options, 0); + + ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage(); + + status = getClient()->unsubscribe(getCallbackClient(), + std::vector({GLOBAL_ON_CHANGE_PROP})); + + ASSERT_TRUE(status.isOk()) << "unsubscribe failed: " << status.getMessage(); + + VehiclePropValue testValue{ + .prop = GLOBAL_ON_CHANGE_PROP, + .value.int32Values = {0}, + }; + + // Set the value to trigger a property change event. + getHardware()->addSetValueResponses({{ + .requestId = 0, + .status = StatusCode::OK, + }}); + status = getClient()->setValues(getCallbackClient(), + { + .payloads = + { + SetValueRequest{ + .requestId = 0, + .value = testValue, + }, + }, + }); + + ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage(); + + ASSERT_FALSE(getCallback()->nextOnPropertyEventResults().has_value()) + << "No property event should be generated after unsubscription"; +} + +TEST_F(DefaultVehicleHalTest, testUnsubscribeContinuous) { + std::vector options = { + { + .propId = GLOBAL_CONTINUOUS_PROP, + .sampleRate = 100.0, + }, + }; + + auto status = getClient()->subscribe(getCallbackClient(), options, 0); + + ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage(); + + status = getClient()->unsubscribe(getCallbackClient(), + std::vector({GLOBAL_CONTINUOUS_PROP})); + + ASSERT_TRUE(status.isOk()) << "unsubscribe failed: " << status.getMessage(); + + // Wait for the last events to come. + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + // Clear existing events. + while (getCallback()->nextOnPropertyEventResults().has_value()) { + // Do nothing. + } + + // Wait for a while, make sure no new events are generated. If still subscribed, this should + // generate around 10 events. + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + ASSERT_EQ(getCallback()->countOnPropertyEventResults(), 0u) + << "Property event generation must stop after unsubscription"; +} + +class SubscribeInvalidOptionsTest + : public DefaultVehicleHalTest, + public testing::WithParamInterface {}; + +INSTANTIATE_TEST_SUITE_P( + SubscribeInvalidOptionsTests, SubscribeInvalidOptionsTest, + testing::ValuesIn(getSubscribeInvalidOptionsTestCases()), + [](const testing::TestParamInfo& info) { + return info.param.name; + }); + +TEST_P(SubscribeInvalidOptionsTest, testSubscribeInvalidOptions) { + std::vector options = {GetParam().option}; + + auto status = getClient()->subscribe(getCallbackClient(), options, 0); + + ASSERT_FALSE(status.isOk()) << "invalid subscribe options must fail"; + ASSERT_EQ(status.getServiceSpecificError(), toInt(StatusCode::INVALID_ARG)); +} + +TEST_F(DefaultVehicleHalTest, testSubscribeNoReadPermission) { + std::vector options = {{ + .propId = WRITE_ONLY_PROP, + }}; + + auto status = getClient()->subscribe(getCallbackClient(), options, 0); + + ASSERT_FALSE(status.isOk()) << "subscribe to a write-only property must fail"; + ASSERT_EQ(status.getServiceSpecificError(), toInt(StatusCode::ACCESS_DENIED)); +} + +TEST_F(DefaultVehicleHalTest, testSubscribeGlobalNoneAccess) { + std::vector options = {{ + .propId = GLOBAL_NONE_ACCESS_PROP, + }}; + + auto status = getClient()->subscribe(getCallbackClient(), options, 0); + + ASSERT_FALSE(status.isOk()) << "subscribe to a property with NONE global access must fail"; + ASSERT_EQ(status.getServiceSpecificError(), toInt(StatusCode::ACCESS_DENIED)); +} + +TEST_F(DefaultVehicleHalTest, testSubscribeAreaNoneAccess) { + std::vector options = { + {.propId = AREA_NONE_ACCESS_PROP, .areaIds = {toInt(VehicleAreaWindow::ROW_1_LEFT)}}}; + + auto status = getClient()->subscribe(getCallbackClient(), options, 0); + + ASSERT_FALSE(status.isOk()) << "subscribe to a property with NONE area access must fail"; + ASSERT_EQ(status.getServiceSpecificError(), toInt(StatusCode::ACCESS_DENIED)); +} + +TEST_F(DefaultVehicleHalTest, testUnsubscribeFailure) { + auto status = getClient()->unsubscribe(getCallbackClient(), + std::vector({GLOBAL_ON_CHANGE_PROP})); + + ASSERT_FALSE(status.isOk()) << "unsubscribe to a not-subscribed property must fail"; + ASSERT_EQ(status.getServiceSpecificError(), toInt(StatusCode::INVALID_ARG)); +} + +TEST_F(DefaultVehicleHalTest, testHeartbeatEvent) { + std::vector options = {{ + .propId = toInt(VehicleProperty::VHAL_HEARTBEAT), + }}; + int64_t currentTime = uptimeMillis(); + auto status = getClient()->subscribe(getCallbackClient(), options, 0); + + ASSERT_TRUE(status.isOk()) << "unable to subscribe to heartbeat event: " << status.getMessage(); + + // We send out a heartbeat event every 3s, so sleep for 3s. + std::this_thread::sleep_for(std::chrono::seconds(3)); + + auto maybeResults = getCallback()->nextOnPropertyEventResults(); + size_t retryCount = 0; + // Add a 1s (100ms * 10) buffer time. + while (!maybeResults.has_value() && retryCount < 10) { + retryCount++; + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + ASSERT_TRUE(maybeResults.has_value()) << "no results in callback"; + ASSERT_EQ(maybeResults.value().payloads.size(), static_cast(1)); + VehiclePropValue gotValue = maybeResults.value().payloads[0]; + ASSERT_EQ(gotValue.prop, toInt(VehicleProperty::VHAL_HEARTBEAT)); + ASSERT_EQ(gotValue.value.int64Values.size(), static_cast(1)); + ASSERT_GE(gotValue.value.int64Values[0], currentTime) + << "expect to get the latest timestamp with the heartbeat event"; +} + +TEST_F(DefaultVehicleHalTest, testOnBinderDiedUnlinked) { + // Set responses for all the hardware getValues requests. + getHardware()->setGetValueResponder( + [](std::shared_ptr callback, + const std::vector& requests) { + std::vector results; + for (auto& request : requests) { + VehiclePropValue prop = request.prop; + prop.value.int32Values = {0}; + results.push_back({ + .requestId = request.requestId, + .status = StatusCode::OK, + .prop = prop, + }); + } + (*callback)(results); + return StatusCode::OK; + }); + std::vector options = { + { + .propId = GLOBAL_CONTINUOUS_PROP, + .sampleRate = 20.0, + }, + }; + auto status = getClient()->subscribe(getCallbackClient(), options, 0); + ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage(); + // Sleep for 100ms so that the subscriptionClient gets created because we would at least try to + // get value once. + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + // Issue another getValue request on the same client. + GetValueRequests requests; + std::vector expectedResults; + std::vector expectedHardwareRequests; + ASSERT_TRUE(getValuesTestCases(1, requests, expectedResults, expectedHardwareRequests).ok()); + getHardware()->addGetValueResponses(expectedResults); + status = getClient()->getValues(getCallbackClient(), requests); + ASSERT_TRUE(status.isOk()) << "getValues failed: " << status.getMessage(); + + ASSERT_EQ(countOnBinderDiedContexts(), static_cast(1)) + << "expect one OnBinderDied context when one client is registered"; + + // Get the death recipient cookie for our callback that would be used in onBinderDied and + // onBinderUnlinked. + AIBinder* clientId = getCallbackClient()->asBinder().get(); + void* context = getOnBinderDiedContexts(clientId); + + onBinderDied(context); + + // Sleep for 100ms between checks. + int64_t sleep = 100; + // Timeout: 10s. + int64_t timeout = 10'000'000'000; + int64_t stopTime = elapsedRealtimeNano() + timeout; + // Wait until the onBinderDied event is handled. + while (countClients() != 0u && elapsedRealtimeNano() <= stopTime) { + std::this_thread::sleep_for(std::chrono::milliseconds(sleep)); + } + + ASSERT_EQ(countClients(), static_cast(0)) + << "expect all clients to be removed when binder died"; + ASSERT_TRUE(hasNoSubscriptions()) << "expect no subscriptions when binder died"; + + onBinderUnlinked(context); + + stopTime = elapsedRealtimeNano() + timeout; + // Wait until the onBinderUnlinked event is handled. + while (countOnBinderDiedContexts() != 0u && elapsedRealtimeNano() <= stopTime) { + std::this_thread::sleep_for(std::chrono::milliseconds(sleep)); + } + + ASSERT_EQ(countOnBinderDiedContexts(), static_cast(0)) + << "expect OnBinderDied context to be deleted when binder is unlinked"; +} + +TEST_F(DefaultVehicleHalTest, testDumpCallerShouldDump) { + std::string buffer = "Dump from hardware"; + getHardware()->setDumpResult({ + .callerShouldDumpState = true, + .buffer = buffer, + }); + int fd = memfd_create("memfile", 0); + getClient()->dump(fd, nullptr, 0); + + lseek(fd, 0, SEEK_SET); + char buf[10240] = {}; + read(fd, buf, sizeof(buf)); + close(fd); + + std::string msg(buf); + + ASSERT_THAT(msg, ContainsRegex(buffer + "\nVehicle HAL State: \n")); +} + +TEST_F(DefaultVehicleHalTest, testDumpCallerShouldNotDump) { + std::string buffer = "Dump from hardware"; + getHardware()->setDumpResult({ + .callerShouldDumpState = false, + .buffer = buffer, + }); + int fd = memfd_create("memfile", 0); + getClient()->dump(fd, nullptr, 0); + + lseek(fd, 0, SEEK_SET); + char buf[10240] = {}; + read(fd, buf, sizeof(buf)); + close(fd); + + std::string msg(buf); + + ASSERT_THAT(msg, ContainsRegex(buffer)); + ASSERT_EQ(msg.find("Vehicle HAL State: "), std::string::npos); +} + +TEST_F(DefaultVehicleHalTest, testOnPropertySetErrorEvent) { + std::vector options = { + { + .propId = GLOBAL_ON_CHANGE_PROP, + .areaIds = {0}, + }, + { + .propId = GLOBAL_CONTINUOUS_PROP, + .areaIds = {0}, + .sampleRate = 1, + }, + }; + auto status = getClient()->subscribe(getCallbackClient(), options, 0); + ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage(); + std::vector errorEvents = { + { + .propId = GLOBAL_ON_CHANGE_PROP, + .areaId = 0, + .errorCode = StatusCode::INTERNAL_ERROR, + }, + { + .propId = GLOBAL_ON_CHANGE_PROP, + .areaId = 0, + .errorCode = StatusCode::ACCESS_DENIED, + }, + { + .propId = GLOBAL_CONTINUOUS_PROP, + .areaId = 0, + .errorCode = StatusCode::INVALID_ARG, + }, + }; + std::vector expectedResults = { + { + .propId = GLOBAL_ON_CHANGE_PROP, + .areaId = 0, + .errorCode = StatusCode::INTERNAL_ERROR, + }, + { + .propId = GLOBAL_ON_CHANGE_PROP, + .areaId = 0, + .errorCode = StatusCode::ACCESS_DENIED, + }, + { + .propId = GLOBAL_CONTINUOUS_PROP, + .areaId = 0, + .errorCode = StatusCode::INVALID_ARG, + }, + }; + getHardware()->sendOnPropertySetErrorEvent(errorEvents); + + ASSERT_EQ(getCallback()->countOnPropertySetErrorResults(), 1u); + auto maybeVehiclePropErrors = getCallback()->nextOnPropertySetErrorResults(); + ASSERT_TRUE(maybeVehiclePropErrors.has_value()); + const auto& vehiclePropErrors = maybeVehiclePropErrors.value(); + ASSERT_THAT(vehiclePropErrors.payloads, UnorderedElementsAreArray(expectedResults)); +} + +TEST_F(DefaultVehicleHalTest, testBatchOnPropertyChangeEvents) { + auto hardware = std::make_unique(); + hardware->setPropertyOnChangeEventBatchingWindow(std::chrono::milliseconds(10)); + init(std::move(hardware)); + + std::vector options = { + { + .propId = GLOBAL_ON_CHANGE_PROP, + }, + { + .propId = AREA_ON_CHANGE_PROP, + // No areaIds means subscribing to all area IDs. + .areaIds = {}, + }, + }; + + getClient()->subscribe(getCallbackClient(), options, 0); + VehiclePropValue testValue1 = { + .prop = GLOBAL_ON_CHANGE_PROP, + .value.int32Values = {0}, + }; + SetValueRequest request1 = { + .requestId = 1, + .value = testValue1, + }; + SetValueResult result1 = { + .requestId = 1, + .status = StatusCode::OK, + }; + VehiclePropValue testValue2 = { + .prop = AREA_ON_CHANGE_PROP, + .areaId = toInt(VehicleAreaWindow::ROW_1_LEFT), + .value.int32Values = {1}, + }; + SetValueRequest request2 = { + .requestId = 2, + .value = testValue2, + }; + SetValueResult result2 = { + .requestId = 2, + .status = StatusCode::OK, + }; + VehiclePropValue testValue3 = { + .prop = AREA_ON_CHANGE_PROP, + .areaId = toInt(VehicleAreaWindow::ROW_1_RIGHT), + .value.int32Values = {1}, + }; + SetValueRequest request3 = { + .requestId = 3, + .value = testValue3, + }; + SetValueResult result3 = { + .requestId = 3, + .status = StatusCode::ACCESS_DENIED, + }; + // Prepare the responses + for (int i = 0; i < 2; i++) { + getHardware()->addSetValueResponses({result1}); + getHardware()->addSetValueResponses({result2, result3}); + } + + // Try to cause two batches, each with three on property change events. + // Set GLOBAL_ON_CHANGE_PROP causing one event. + // Set AREA_ON_CHANGE_PROP with two areas causing two events. + for (int i = 0; i < 2; i++) { + auto status = getClient()->setValues(getCallbackClient(), + SetValueRequests{.payloads = {request1}}); + ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage(); + + status = getClient()->setValues(getCallbackClient(), + SetValueRequests{.payloads = {request2, request3}}); + ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage(); + + ASSERT_TRUE(getCallback()->waitForOnPropertyEventResults(/*size=*/1, + /*timeoutInNano=*/1'000'000'000)) + << "not received enough property change events before timeout"; + + auto maybeResults = getCallback()->nextOnPropertyEventResults(); + ASSERT_TRUE(maybeResults.has_value()) << "no results in callback"; + ASSERT_THAT(maybeResults.value().payloads, UnorderedElementsAre(testValue1, testValue2)) + << "results mismatch, expect 2 batched on change events"; + ASSERT_FALSE(getCallback()->nextOnPropertyEventResults().has_value()) + << "more results than expected"; + } +} + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleCallback.cpp b/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleCallback.cpp new file mode 100644 index 0000000000000000000000000000000000000000..72c5dc54b370ff1b60e28f701cb245e736d52e38 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleCallback.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2021 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 "MockVehicleCallback.h" + +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +namespace { + +using ::aidl::android::hardware::automotive::vehicle::GetValueResults; +using ::aidl::android::hardware::automotive::vehicle::PropIdAreaId; +using ::aidl::android::hardware::automotive::vehicle::SetValueResults; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropErrors; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValues; +using ::android::base::ScopedLockAssertion; +using ::ndk::ScopedAStatus; +using ::ndk::ScopedFileDescriptor; + +template +static ScopedAStatus storeResults(const T& results, std::list* storedResults) { + T resultsCopy{ + .payloads = results.payloads, + }; + int fd = results.sharedMemoryFd.get(); + if (fd != -1) { + resultsCopy.sharedMemoryFd = ScopedFileDescriptor(dup(fd)); + } + storedResults->push_back(std::move(resultsCopy)); + return ScopedAStatus::ok(); +} + +} // namespace + +ScopedAStatus MockVehicleCallback::onGetValues(const GetValueResults& results) { + ScopedAStatus result; + { + std::scoped_lock lockGuard(mLock); + result = storeResults(results, &mGetValueResults); + } + mCond.notify_all(); + return result; +} + +ScopedAStatus MockVehicleCallback::onSetValues(const SetValueResults& results) { + ScopedAStatus result; + { + std::scoped_lock lockGuard(mLock); + result = storeResults(results, &mSetValueResults); + } + mCond.notify_all(); + return result; +} + +ScopedAStatus MockVehicleCallback::onPropertyEvent(const VehiclePropValues& results, + int32_t sharedMemoryFileCount) { + ScopedAStatus result; + { + std::scoped_lock lockGuard(mLock); + mSharedMemoryFileCount = sharedMemoryFileCount; + result = storeResults(results, &mOnPropertyEventResults); + } + mCond.notify_all(); + return result; +} + +ScopedAStatus MockVehicleCallback::onPropertySetError(const VehiclePropErrors& results) { + ScopedAStatus result; + { + std::scoped_lock lockGuard(mLock); + result = storeResults(results, &mOnPropertySetErrorResults); + } + mCond.notify_all(); + return result; +} + +ScopedAStatus MockVehicleCallback::onSupportedValueChange(const std::vector&) { + // TODO(b/381020465): Add relevant implementation. + return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +} + +std::optional MockVehicleCallback::nextGetValueResults() { + std::scoped_lock lockGuard(mLock); + return pop(mGetValueResults); +} + +std::optional MockVehicleCallback::nextSetValueResults() { + std::scoped_lock lockGuard(mLock); + return pop(mSetValueResults); +} + +std::optional MockVehicleCallback::nextOnPropertyEventResults() { + std::scoped_lock lockGuard(mLock); + return pop(mOnPropertyEventResults); +} + +size_t MockVehicleCallback::countOnPropertyEventResults() { + std::scoped_lock lockGuard(mLock); + return mOnPropertyEventResults.size(); +} + +std::optional MockVehicleCallback::nextOnPropertySetErrorResults() { + std::scoped_lock lockGuard(mLock); + return pop(mOnPropertySetErrorResults); +} + +size_t MockVehicleCallback::countOnPropertySetErrorResults() { + std::scoped_lock lockGuard(mLock); + return mOnPropertySetErrorResults.size(); +} + +bool MockVehicleCallback::waitForSetValueResults(size_t size, size_t timeoutInNano) { + std::unique_lock lk(mLock); + return mCond.wait_for(lk, std::chrono::nanoseconds(timeoutInNano), [this, size] { + ScopedLockAssertion lockAssertion(mLock); + return mSetValueResults.size() >= size; + }); +} + +bool MockVehicleCallback::waitForGetValueResults(size_t size, size_t timeoutInNano) { + std::unique_lock lk(mLock); + return mCond.wait_for(lk, std::chrono::nanoseconds(timeoutInNano), [this, size] { + ScopedLockAssertion lockAssertion(mLock); + return mGetValueResults.size() >= size; + }); +} + +bool MockVehicleCallback::waitForOnPropertyEventResults(size_t size, size_t timeoutInNano) { + std::unique_lock lk(mLock); + return mCond.wait_for(lk, std::chrono::nanoseconds(timeoutInNano), [this, size] { + ScopedLockAssertion lockAssertion(mLock); + return mOnPropertyEventResults.size() >= size; + }); +} + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleCallback.h b/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleCallback.h new file mode 100644 index 0000000000000000000000000000000000000000..81a85ff7370863ff623d9321d201c5abd3505893 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleCallback.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_aidl_impl_vhal_test_MockVehicleCallback_H_ +#define android_hardware_automotive_vehicle_aidl_impl_vhal_test_MockVehicleCallback_H_ + +#include + +#include +#include + +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +template +std::optional pop(std::list& items) { + if (items.size() > 0) { + auto item = std::move(items.front()); + items.pop_front(); + return item; + } + return std::nullopt; +} + +// MockVehicleCallback is a mock VehicleCallback implementation that simply stores the results. +class MockVehicleCallback final + : public aidl::android::hardware::automotive::vehicle::BnVehicleCallback { + public: + ndk::ScopedAStatus onGetValues( + const aidl::android::hardware::automotive::vehicle::GetValueResults& results) override; + ndk::ScopedAStatus onSetValues( + const aidl::android::hardware::automotive::vehicle::SetValueResults& results) override; + ndk::ScopedAStatus onPropertyEvent( + const aidl::android::hardware::automotive::vehicle::VehiclePropValues&, + int32_t) override; + ndk::ScopedAStatus onPropertySetError( + const aidl::android::hardware::automotive::vehicle::VehiclePropErrors&) override; + ndk::ScopedAStatus onSupportedValueChange( + const std::vector&) + override; + + // Test functions + std::optional + nextGetValueResults(); + std::optional + nextSetValueResults(); + std::optional + nextOnPropertyEventResults(); + size_t countOnPropertySetErrorResults(); + std::optional + nextOnPropertySetErrorResults(); + size_t countOnPropertyEventResults(); + bool waitForSetValueResults(size_t size, size_t timeoutInNano); + bool waitForGetValueResults(size_t size, size_t timeoutInNano); + bool waitForOnPropertyEventResults(size_t size, size_t timeoutInNano); + + private: + std::mutex mLock; + std::condition_variable mCond; + std::list mGetValueResults + GUARDED_BY(mLock); + std::list mSetValueResults + GUARDED_BY(mLock); + std::list + mOnPropertyEventResults GUARDED_BY(mLock); + int32_t mSharedMemoryFileCount GUARDED_BY(mLock); + std::list + mOnPropertySetErrorResults GUARDED_BY(mLock); +}; + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_aidl_impl_vhal_test_MockVehicleCallback_H_ diff --git a/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleHardware.cpp b/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleHardware.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e796ce56f56e344a2112352c79079ed6329afe04 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleHardware.cpp @@ -0,0 +1,358 @@ +/* + * Copyright (C) 2021 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 "MockVehicleHardware.h" +#include "MockVehicleCallback.h" + +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +using ::aidl::android::hardware::automotive::vehicle::GetValueRequest; +using ::aidl::android::hardware::automotive::vehicle::GetValueResult; +using ::aidl::android::hardware::automotive::vehicle::SetValueRequest; +using ::aidl::android::hardware::automotive::vehicle::SetValueResult; +using ::aidl::android::hardware::automotive::vehicle::StatusCode; +using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; + +MockVehicleHardware::MockVehicleHardware() { + mRecurrentTimer = std::make_unique(); +} + +MockVehicleHardware::~MockVehicleHardware() { + std::unique_lock lk(mLock); + mCv.wait(lk, [this] { return mThreadCount == 0; }); + mRecurrentTimer.reset(); +} + +std::vector MockVehicleHardware::getAllPropertyConfigs() const { + std::scoped_lock lockGuard(mLock); + mGetAllPropertyConfigsCalled = true; + return mPropertyConfigs; +} + +std::optional MockVehicleHardware::getPropertyConfig(int32_t propId) const { + std::scoped_lock lockGuard(mLock); + for (const auto& config : mPropertyConfigs) { + if (config.prop == propId) { + return config; + } + } + return std::nullopt; +} + +StatusCode MockVehicleHardware::setValues(std::shared_ptr callback, + const std::vector& requests) { + std::scoped_lock lockGuard(mLock); + if (StatusCode status = handleRequestsLocked(__func__, callback, requests, &mSetValueRequests, + &mSetValueResponses); + status != StatusCode::OK) { + return status; + } + if (mPropertyChangeCallback == nullptr) { + return StatusCode::OK; + } + std::vector values; + for (auto& request : requests) { + values.push_back(request.value); + } + (*mPropertyChangeCallback)(values); + return StatusCode::OK; +} + +StatusCode MockVehicleHardware::getValues(std::shared_ptr callback, + const std::vector& requests) const { + std::scoped_lock lockGuard(mLock); + if (mGetValueResponder != nullptr) { + return mGetValueResponder(callback, requests); + } + return handleRequestsLocked(__func__, callback, requests, &mGetValueRequests, + &mGetValueResponses); +} + +void MockVehicleHardware::setDumpResult(DumpResult result) { + mDumpResult = result; +} + +DumpResult MockVehicleHardware::dump(const std::vector&) { + return mDumpResult; +} + +StatusCode MockVehicleHardware::checkHealth() { + return StatusCode::OK; +} + +StatusCode MockVehicleHardware::subscribe(SubscribeOptions options) { + { + std::scoped_lock lockGuard(mLock); + mSubscribeOptions.push_back(options); + } + for (int32_t areaId : options.areaIds) { + if (auto status = subscribePropIdAreaId(options.propId, areaId, options.sampleRate); + status != StatusCode::OK) { + return status; + } + } + return StatusCode::OK; +} + +std::vector MockVehicleHardware::getSubscribeOptions() { + std::scoped_lock lockGuard(mLock); + return mSubscribeOptions; +} + +void MockVehicleHardware::clearSubscribeOptions() { + std::scoped_lock lockGuard(mLock); + mSubscribeOptions.clear(); +} + +StatusCode MockVehicleHardware::subscribePropIdAreaId(int32_t propId, int32_t areaId, + float sampleRateHz) { + if (sampleRateHz == 0) { + // on-change property. + std::scoped_lock lockGuard(mLock); + mSubOnChangePropIdAreaIds.insert(std::pair(propId, areaId)); + return StatusCode::OK; + } + + // continuous property. + std::shared_ptr> action; + + { + std::scoped_lock lockGuard(mLock); + if (mRecurrentActions[propId][areaId] != nullptr) { + // Remove the previous action register for this [propId, areaId]. + mRecurrentTimer->unregisterTimerCallback(mRecurrentActions[propId][areaId]); + } + + // We are sure 'propertyChangeCallback' would be alive because we would unregister timer + // before destroying 'this' which owns mPropertyChangeCallback. + const PropertyChangeCallback* propertyChangeCallback = mPropertyChangeCallback.get(); + action = std::make_shared>([propertyChangeCallback, propId, areaId] { + std::vector values = { + { + .areaId = areaId, + .prop = propId, + }, + }; + (*propertyChangeCallback)(values); + }); + // Store the action in a map so that we could remove the action later. + mRecurrentActions[propId][areaId] = action; + } + + // In mock implementation, we generate a new property change event for this property at sample + // rate. + int64_t interval = static_cast(1'000'000'000. / sampleRateHz); + mRecurrentTimer->registerTimerCallback(interval, action); + return StatusCode::OK; +} + +StatusCode MockVehicleHardware::unsubscribe(int32_t propId, int32_t areaId) { + std::scoped_lock lockGuard(mLock); + // For on-change property. + mSubOnChangePropIdAreaIds.erase(std::make_pair(propId, areaId)); + // for continuous property. + if (mRecurrentActions[propId][areaId] != nullptr) { + // Remove the previous action register for this [propId, areaId]. + mRecurrentTimer->unregisterTimerCallback(mRecurrentActions[propId][areaId]); + mRecurrentActions[propId].erase(areaId); + if (mRecurrentActions[propId].empty()) { + mRecurrentActions.erase(propId); + } + } + return StatusCode::OK; +} + +std::set> MockVehicleHardware::getSubscribedOnChangePropIdAreaIds() { + std::scoped_lock lockGuard(mLock); + std::set> propIdAreaIds; + propIdAreaIds = mSubOnChangePropIdAreaIds; + return propIdAreaIds; +} + +std::set> MockVehicleHardware::getSubscribedContinuousPropIdAreaIds() { + std::scoped_lock lockGuard(mLock); + std::set> propIdAreaIds; + for (const auto& [propId, actionByAreaId] : mRecurrentActions) { + for (const auto& [areaId, _] : actionByAreaId) { + propIdAreaIds.insert(std::make_pair(propId, areaId)); + } + } + return propIdAreaIds; +} + +void MockVehicleHardware::registerOnPropertyChangeEvent( + std::unique_ptr callback) { + std::scoped_lock lockGuard(mLock); + mPropertyChangeCallback = std::move(callback); +} + +void MockVehicleHardware::registerOnPropertySetErrorEvent( + std::unique_ptr callback) { + std::scoped_lock lockGuard(mLock); + mPropertySetErrorCallback = std::move(callback); +} + +void MockVehicleHardware::setPropertyConfigs(const std::vector& configs) { + std::scoped_lock lockGuard(mLock); + mPropertyConfigs = configs; +} + +void MockVehicleHardware::addGetValueResponses(const std::vector& responses) { + std::scoped_lock lockGuard(mLock); + mGetValueResponses.push_back(responses); +} + +void MockVehicleHardware::addSetValueResponses(const std::vector& responses) { + std::scoped_lock lockGuard(mLock); + mSetValueResponses.push_back(responses); +} + +void MockVehicleHardware::setGetValueResponder( + std::function, + const std::vector&)>&& responder) { + std::scoped_lock lockGuard(mLock); + mGetValueResponder = responder; +} + +std::vector MockVehicleHardware::nextGetValueRequests() { + std::scoped_lock lockGuard(mLock); + std::optional> request = pop(mGetValueRequests); + if (!request.has_value()) { + return std::vector(); + } + return std::move(request.value()); +} + +std::vector MockVehicleHardware::nextSetValueRequests() { + std::scoped_lock lockGuard(mLock); + std::optional> request = pop(mSetValueRequests); + if (!request.has_value()) { + return std::vector(); + } + return std::move(request.value()); +} + +void MockVehicleHardware::setStatus(const char* functionName, StatusCode status) { + std::scoped_lock lockGuard(mLock); + mStatusByFunctions[functionName] = status; +} + +void MockVehicleHardware::setSleepTime(int64_t timeInNano) { + std::scoped_lock lockGuard(mLock); + mSleepTime = timeInNano; +} + +void MockVehicleHardware::setPropertyOnChangeEventBatchingWindow(std::chrono::nanoseconds window) { + std::scoped_lock lockGuard(mLock); + mEventBatchingWindow = window; +} + +std::chrono::nanoseconds MockVehicleHardware::getPropertyOnChangeEventBatchingWindow() { + std::scoped_lock lockGuard(mLock); + return mEventBatchingWindow; +} + +template +StatusCode MockVehicleHardware::returnResponse( + std::shared_ptr)>> callback, + std::list>* storedResponses) const { + if (storedResponses->size() > 0) { + (*callback)(std::move(storedResponses->front())); + storedResponses->pop_front(); + return StatusCode::OK; + } else { + ALOGE("no more response"); + return StatusCode::INTERNAL_ERROR; + } +} + +template StatusCode MockVehicleHardware::returnResponse( + std::shared_ptr)>> callback, + std::list>* storedResponses) const; + +template StatusCode MockVehicleHardware::returnResponse( + std::shared_ptr)>> callback, + std::list>* storedResponses) const; + +template +StatusCode MockVehicleHardware::handleRequestsLocked( + const char* functionName, + std::shared_ptr)>> callback, + const std::vector& requests, + std::list>* storedRequests, + std::list>* storedResponses) const { + storedRequests->push_back(requests); + if (auto it = mStatusByFunctions.find(functionName); it != mStatusByFunctions.end()) { + if (StatusCode status = it->second; status != StatusCode::OK) { + return status; + } + } + + if (mSleepTime != 0) { + int64_t sleepTime = mSleepTime; + mThreadCount++; + std::thread t([this, callback, sleepTime, storedResponses]() { + std::this_thread::sleep_for(std::chrono::nanoseconds(sleepTime)); + returnResponse(callback, storedResponses); + mThreadCount--; + mCv.notify_one(); + }); + // Detach the thread here so we do not have to maintain the thread object. mThreadCount + // and mCv make sure we wait for all threads to end before we exit. + t.detach(); + return StatusCode::OK; + + } else { + return returnResponse(callback, storedResponses); + } +} + +template StatusCode MockVehicleHardware::handleRequestsLocked( + const char* functionName, + std::shared_ptr)>> callback, + const std::vector& requests, + std::list>* storedRequests, + std::list>* storedResponses) const; + +template StatusCode MockVehicleHardware::handleRequestsLocked( + const char* functionName, + std::shared_ptr)>> callback, + const std::vector& requests, + std::list>* storedRequests, + std::list>* storedResponses) const; + +void MockVehicleHardware::sendOnPropertySetErrorEvent( + const std::vector& errorEvents) { + std::scoped_lock lockGuard(mLock); + (*mPropertySetErrorCallback)(errorEvents); +} + +bool MockVehicleHardware::getAllPropertyConfigsCalled() { + std::scoped_lock lockGuard(mLock); + return mGetAllPropertyConfigsCalled; +} + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleHardware.h b/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleHardware.h new file mode 100644 index 0000000000000000000000000000000000000000..06e01a8ec085e596d55c1a7b0c96b152224321bd --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleHardware.h @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_aidl_impl_vhal_test_MockVehicleHardware_H_ +#define android_hardware_automotive_vehicle_aidl_impl_vhal_test_MockVehicleHardware_H_ + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +class MockVehicleHardware final : public IVehicleHardware { + public: + MockVehicleHardware(); + + ~MockVehicleHardware(); + + std::vector + getAllPropertyConfigs() const override; + std::optional + getPropertyConfig(int32_t propId) const override; + aidl::android::hardware::automotive::vehicle::StatusCode setValues( + std::shared_ptr callback, + const std::vector& + requests) override; + aidl::android::hardware::automotive::vehicle::StatusCode getValues( + std::shared_ptr callback, + const std::vector& + requests) const override; + DumpResult dump(const std::vector&) override; + aidl::android::hardware::automotive::vehicle::StatusCode checkHealth() override; + void registerOnPropertyChangeEvent( + std::unique_ptr callback) override; + void registerOnPropertySetErrorEvent(std::unique_ptr) override; + aidl::android::hardware::automotive::vehicle::StatusCode subscribe( + aidl::android::hardware::automotive::vehicle::SubscribeOptions options) override; + aidl::android::hardware::automotive::vehicle::StatusCode unsubscribe(int32_t propId, + int32_t areaId) override; + std::chrono::nanoseconds getPropertyOnChangeEventBatchingWindow() override; + + // Test functions. + void setPropertyConfigs( + const std::vector& + configs); + void addGetValueResponses( + const std::vector& + responses); + void addSetValueResponses( + const std::vector& + responses); + void setGetValueResponder( + std::function, + const std::vector< + aidl::android::hardware::automotive::vehicle::GetValueRequest>&)>&& + responder); + std::vector + nextGetValueRequests(); + std::vector + nextSetValueRequests(); + void setStatus(const char* functionName, + aidl::android::hardware::automotive::vehicle::StatusCode status); + void setSleepTime(int64_t timeInNano); + void setDumpResult(DumpResult result); + void sendOnPropertySetErrorEvent(const std::vector& errorEvents); + void setPropertyOnChangeEventBatchingWindow(std::chrono::nanoseconds window); + + std::set> getSubscribedOnChangePropIdAreaIds(); + std::set> getSubscribedContinuousPropIdAreaIds(); + std::vector + getSubscribeOptions(); + void clearSubscribeOptions(); + // Whether getAllPropertyConfigs() has been called, which blocks all all property configs + // being ready. + bool getAllPropertyConfigsCalled(); + + private: + mutable std::mutex mLock; + mutable std::condition_variable mCv; + mutable std::atomic mThreadCount; + std::vector mPropertyConfigs + GUARDED_BY(mLock); + mutable std::list> + mGetValueRequests GUARDED_BY(mLock); + mutable std::list> + mGetValueResponses GUARDED_BY(mLock); + mutable std::list> + mSetValueRequests GUARDED_BY(mLock); + mutable std::list> + mSetValueResponses GUARDED_BY(mLock); + std::unordered_map + mStatusByFunctions GUARDED_BY(mLock); + int64_t mSleepTime GUARDED_BY(mLock) = 0; + std::unique_ptr mPropertyChangeCallback GUARDED_BY(mLock); + std::unique_ptr mPropertySetErrorCallback GUARDED_BY(mLock); + std::function, + const std::vector&)> + mGetValueResponder GUARDED_BY(mLock); + std::chrono::nanoseconds mEventBatchingWindow GUARDED_BY(mLock) = std::chrono::nanoseconds(0); + std::set> mSubOnChangePropIdAreaIds GUARDED_BY(mLock); + std::vector mSubscribeOptions + GUARDED_BY(mLock); + + template + aidl::android::hardware::automotive::vehicle::StatusCode returnResponse( + std::shared_ptr)>> callback, + std::list>* storedResponses) const; + template + aidl::android::hardware::automotive::vehicle::StatusCode handleRequestsLocked( + const char* functionName, + std::shared_ptr)>> callback, + const std::vector& requests, + std::list>* storedRequests, + std::list>* storedResponses) const REQUIRES(mLock); + aidl::android::hardware::automotive::vehicle::StatusCode subscribePropIdAreaId( + int32_t propId, int32_t areaId, float sampleRateHz); + + DumpResult mDumpResult; + + mutable bool mGetAllPropertyConfigsCalled GUARDED_BY(mLock) = false; + + // RecurrentTimer is thread-safe. + std::shared_ptr mRecurrentTimer; + std::unordered_map>>> + mRecurrentActions GUARDED_BY(mLock); +}; + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_aidl_impl_vhal_test_MockVehicleHardware_H_ diff --git a/automotive/vehicle/aidl/impl/current/vhal/test/SubscriptionManagerTest.cpp b/automotive/vehicle/aidl/impl/current/vhal/test/SubscriptionManagerTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5d58de5e6f7915c2abbe95c9cca3c711278ade22 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/vhal/test/SubscriptionManagerTest.cpp @@ -0,0 +1,889 @@ +/* + * Copyright (C) 2021 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 "SubscriptionManager.h" + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +using ::aidl::android::hardware::automotive::vehicle::BnVehicleCallback; +using ::aidl::android::hardware::automotive::vehicle::GetValueResults; +using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback; +using ::aidl::android::hardware::automotive::vehicle::SetValueResults; +using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropErrors; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValues; +using ::ndk::ScopedAStatus; +using ::ndk::SpAIBinder; +using ::testing::Contains; +using ::testing::ElementsAre; +using ::testing::UnorderedElementsAre; + +class PropertyCallback final : public BnVehicleCallback { + public: + ScopedAStatus onGetValues(const GetValueResults&) override { return ScopedAStatus::ok(); } + + ScopedAStatus onSetValues(const SetValueResults&) override { return ScopedAStatus::ok(); } + + ScopedAStatus onPropertyEvent(const VehiclePropValues& values, int32_t) override { + std::scoped_lock lockGuard(mLock); + for (const auto& value : values.payloads) { + mEvents.push_back(value); + } + return ScopedAStatus::ok(); + } + + ScopedAStatus onPropertySetError(const VehiclePropErrors&) override { + return ScopedAStatus::ok(); + } + + ScopedAStatus onSupportedValueChange( + const std::vector<::aidl::android::hardware::automotive::vehicle::PropIdAreaId>&) + override { + return ScopedAStatus::ok(); + } + + // Test functions. + std::list getEvents() { + std::scoped_lock lockGuard(mLock); + return mEvents; + } + + void clearEvents() { + std::scoped_lock lockGuard(mLock); + mEvents.clear(); + } + + private: + std::mutex mLock; + std::list mEvents GUARDED_BY(mLock); +}; + +class SubscriptionManagerTest : public testing::Test { + public: + void SetUp() override { + mHardware = std::make_shared(); + mManager = std::make_unique(mHardware.get()); + mCallback = ndk::SharedRefBase::make(); + // Keep the local binder alive. + mBinder = mCallback->asBinder(); + mCallbackClient = IVehicleCallback::fromBinder(mBinder); + std::shared_ptr callbackClient = mCallbackClient; + mHardware->registerOnPropertyChangeEvent( + std::make_unique( + [callbackClient](std::vector updatedValues) { + VehiclePropValues values = { + .payloads = std::move(updatedValues), + }; + callbackClient->onPropertyEvent(values, 0); + })); + } + + SubscriptionManager* getManager() { return mManager.get(); } + + std::shared_ptr getCallbackClient() { return mCallbackClient; } + + PropertyCallback* getCallback() { return mCallback.get(); } + + std::list getEvents() { return getCallback()->getEvents(); } + + void clearEvents() { return getCallback()->clearEvents(); } + + std::shared_ptr getHardware() { return mHardware; } + + private: + std::unique_ptr mManager; + std::shared_ptr mCallback; + std::shared_ptr mCallbackClient; + std::shared_ptr mHardware; + SpAIBinder mBinder; +}; + +TEST_F(SubscriptionManagerTest, testSubscribeGlobalContinuous) { + std::vector options = {{ + .propId = 0, + .areaIds = {0}, + .sampleRate = 10.0, + }}; + + auto result = getManager()->subscribe(getCallbackClient(), options, true); + ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message(); + + ASSERT_THAT(getHardware()->getSubscribedContinuousPropIdAreaIds(), + UnorderedElementsAre(std::pair(0, 0))); + + std::this_thread::sleep_for(std::chrono::seconds(1)); + + // Theoretically trigger 10 times, but check for at least 9 times to be stable. + ASSERT_GE(getEvents().size(), static_cast(9)); + EXPECT_EQ(getEvents().back().prop, 0); + EXPECT_EQ(getEvents().back().areaId, 0); +} + +TEST_F(SubscriptionManagerTest, testSubscribeMultiplePropsGlobalContinuous) { + std::vector options = {{ + .propId = 0, + .areaIds = {0}, + .sampleRate = 10.0, + }, + { + .propId = 1, + .areaIds = {0}, + .sampleRate = 20.0, + }}; + + auto result = getManager()->subscribe(getCallbackClient(), options, true); + ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message(); + + std::this_thread::sleep_for(std::chrono::seconds(1)); + + size_t event0Count = 0; + size_t event1Count = 0; + + for (const auto& event : getEvents()) { + if (event.prop == 0) { + event0Count++; + } else { + event1Count++; + } + } + + // Theoretically trigger 10 times, but check for at least 9 times to be stable. + EXPECT_GE(event0Count, static_cast(9)); + // Theoretically trigger 20 times, but check for at least 15 times to be stable. + EXPECT_GE(event1Count, static_cast(15)); +} + +TEST_F(SubscriptionManagerTest, testOverrideSubscriptionContinuous) { + std::vector options = {{ + .propId = 0, + .areaIds = {0}, + .sampleRate = 20.0, + }}; + + auto result = getManager()->subscribe(getCallbackClient(), options, true); + ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message(); + + // Override sample rate to be 10.0. + options[0].sampleRate = 10.0; + result = getManager()->subscribe(getCallbackClient(), options, true); + ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message(); + + std::this_thread::sleep_for(std::chrono::seconds(1)); + + // Theoretically trigger 10 times, but check for at least 9 times to be stable. + EXPECT_GE(getEvents().size(), static_cast(9)); + EXPECT_LE(getEvents().size(), static_cast(15)); +} + +TEST_F(SubscriptionManagerTest, testSubscribeMultipleAreasContinuous) { + std::vector options = { + { + .propId = 0, + .areaIds = {0, 1}, + .sampleRate = 10.0, + }, + }; + + auto result = getManager()->subscribe(getCallbackClient(), options, true); + ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message(); + + std::this_thread::sleep_for(std::chrono::seconds(1)); + + size_t area0Count = 0; + size_t area1Count = 0; + + for (const auto& event : getEvents()) { + if (event.areaId == 0) { + area0Count++; + } else { + area1Count++; + } + } + + // Theoretically trigger 10 times, but check for at least 9 times to be stable. + EXPECT_GE(area0Count, static_cast(9)); + // Theoretically trigger 10 times, but check for at least 9 times to be stable. + EXPECT_GE(area1Count, static_cast(9)); +} + +TEST_F(SubscriptionManagerTest, testUnsubscribeGlobalContinuous) { + std::vector options = {{ + .propId = 0, + .areaIds = {0}, + .sampleRate = 100.0, + }}; + + auto result = getManager()->subscribe(getCallbackClient(), options, true); + ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message(); + + result = getManager()->unsubscribe(getCallbackClient()->asBinder().get()); + ASSERT_TRUE(result.ok()) << "failed to unsubscribe: " << result.error().message(); + + ASSERT_EQ(getHardware()->getSubscribedContinuousPropIdAreaIds().size(), 0u); + + // Wait for the last events to come. + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + clearEvents(); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + ASSERT_TRUE(getEvents().empty()); +} + +TEST_F(SubscriptionManagerTest, testUnsubscribeMultipleAreas) { + std::vector options = { + { + .propId = 0, + .areaIds = {0, 1, 2, 3, 4}, + .sampleRate = 10.0, + }, + { + .propId = 1, + .areaIds = {0}, + .sampleRate = 10.0, + }, + }; + + auto result = getManager()->subscribe(getCallbackClient(), options, true); + ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message(); + + result = getManager()->unsubscribe(getCallbackClient()->asBinder().get(), + std::vector({0})); + ASSERT_TRUE(result.ok()) << "failed to unsubscribe: " << result.error().message(); + + // Wait for the last events to come. + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + clearEvents(); + + std::this_thread::sleep_for(std::chrono::seconds(1)); + + // Theoretically trigger 10 times, but check for at least 9 times to be stable. + EXPECT_GE(getEvents().size(), static_cast(9)); + + for (const auto& event : getEvents()) { + EXPECT_EQ(event.prop, 1); + } +} + +TEST_F(SubscriptionManagerTest, testUnsubscribeByCallback) { + std::vector options = { + { + .propId = 0, + .areaIds = {0, 1, 2, 3, 4}, + .sampleRate = 10.0, + }, + { + .propId = 1, + .areaIds = {0}, + .sampleRate = 10.0, + }, + }; + + auto result = getManager()->subscribe(getCallbackClient(), options, true); + ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message(); + + result = getManager()->unsubscribe(getCallbackClient()->asBinder().get()); + ASSERT_TRUE(result.ok()) << "failed to unsubscribe: " << result.error().message(); + + // Wait for the last events to come. + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + clearEvents(); + + std::this_thread::sleep_for(std::chrono::seconds(1)); + + EXPECT_TRUE(getEvents().empty()); +} + +TEST_F(SubscriptionManagerTest, testUnsubscribeUnsubscribedPropId) { + std::vector options = { + { + .propId = 0, + .areaIds = {0, 1, 2, 3, 4}, + }, + { + .propId = 1, + .areaIds = {0}, + }, + }; + + auto result = getManager()->subscribe(getCallbackClient(), options, false); + ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message(); + + // Property ID: 2 was not subscribed. + result = getManager()->unsubscribe(getCallbackClient()->asBinder().get(), + std::vector({0, 1, 2})); + ASSERT_TRUE(result.ok()) << "unsubscribe an unsubscribed property must do nothing"; + + std::vector updatedValues = { + { + .prop = 0, + .areaId = 0, + }, + { + .prop = 1, + .areaId = 0, + }, + }; + auto clients = getManager()->getSubscribedClients(std::vector(updatedValues)); + + ASSERT_EQ(clients.size(), 0u) << "all subscribed properties must be unsubscribed"; +} + +TEST_F(SubscriptionManagerTest, testSubscribeOnchange) { + std::vector options1 = { + { + .propId = 0, + .areaIds = {0, 1}, + }, + { + .propId = 1, + .areaIds = {0}, + }, + }; + std::vector options2 = { + { + .propId = 0, + .areaIds = {0}, + }, + }; + + SpAIBinder binder1 = ndk::SharedRefBase::make()->asBinder(); + std::shared_ptr client1 = IVehicleCallback::fromBinder(binder1); + SpAIBinder binder2 = ndk::SharedRefBase::make()->asBinder(); + std::shared_ptr client2 = IVehicleCallback::fromBinder(binder2); + auto result = getManager()->subscribe(client1, options1, false); + ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message(); + result = getManager()->subscribe(client2, options2, false); + ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message(); + ASSERT_THAT(getHardware()->getSubscribedOnChangePropIdAreaIds(), + UnorderedElementsAre(std::pair(0, 0), + std::pair(0, 1), + std::pair(1, 0))); + ASSERT_EQ(getHardware()->getSubscribedContinuousPropIdAreaIds().size(), 0u); + + std::vector updatedValues = { + { + .prop = 0, + .areaId = 0, + }, + { + .prop = 0, + .areaId = 1, + }, + { + .prop = 1, + .areaId = 0, + }, + { + .prop = 1, + .areaId = 1, + }, + }; + auto clients = getManager()->getSubscribedClients(std::vector(updatedValues)); + + ASSERT_THAT(clients[client1], + UnorderedElementsAre(updatedValues[0], updatedValues[1], updatedValues[2])); + ASSERT_THAT(clients[client2], ElementsAre(updatedValues[0])); +} + +TEST_F(SubscriptionManagerTest, testSubscribeInvalidOption) { + std::vector options = { + { + .propId = 0, + .areaIds = {0, 1, 2, 3, 4}, + // invalid sample rate. + .sampleRate = 0.0, + }, + { + .propId = 1, + .areaIds = {0}, + .sampleRate = 10.0, + }, + }; + + auto result = getManager()->subscribe(getCallbackClient(), options, true); + ASSERT_FALSE(result.ok()) << "subscribe with invalid sample rate must fail"; + ASSERT_TRUE(getManager() + ->getSubscribedClients({{ + .prop = 0, + .areaId = 0, + }, + { + .prop = 1, + .areaId = 0, + }}) + .empty()) + << "no property should be subscribed if error is returned"; +} + +TEST_F(SubscriptionManagerTest, testSubscribeNoAreaIds) { + std::vector options = { + { + .propId = 0, + .areaIds = {}, + .sampleRate = 1.0, + }, + { + .propId = 1, + .areaIds = {0}, + .sampleRate = 10.0, + }, + }; + + auto result = getManager()->subscribe(getCallbackClient(), options, true); + ASSERT_FALSE(result.ok()) << "subscribe with invalid sample rate must fail"; + ASSERT_TRUE(getManager() + ->getSubscribedClients({{ + .prop = 1, + .areaId = 0, + }}) + .empty()) + << "no property should be subscribed if error is returned"; +} + +TEST_F(SubscriptionManagerTest, testUnsubscribeOnchange) { + std::vector options = { + { + .propId = 0, + .areaIds = {0, 1}, + }, + { + .propId = 1, + .areaIds = {0}, + }, + }; + + auto result = getManager()->subscribe(getCallbackClient(), options, false); + ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message(); + + result = getManager()->unsubscribe(getCallbackClient()->asBinder().get(), + std::vector({0})); + ASSERT_TRUE(result.ok()) << "failed to unsubscribe: " << result.error().message(); + + std::vector updatedValues = { + { + .prop = 0, + .areaId = 0, + }, + { + .prop = 1, + .areaId = 0, + }, + }; + auto clients = getManager()->getSubscribedClients(std::vector(updatedValues)); + + ASSERT_THAT(clients[getCallbackClient()], ElementsAre(updatedValues[1])); + ASSERT_THAT(getHardware()->getSubscribedOnChangePropIdAreaIds(), + UnorderedElementsAre(std::pair(1, 0))); +} + +TEST_F(SubscriptionManagerTest, testCheckSampleRateHzValid) { + ASSERT_TRUE(SubscriptionManager::checkSampleRateHz(1.0)); +} + +TEST_F(SubscriptionManagerTest, testCheckSampleRateHzInvalidTooSmall) { + ASSERT_FALSE(SubscriptionManager::checkSampleRateHz(FLT_MIN)); +} + +TEST_F(SubscriptionManagerTest, testCheckSampleRateHzInvalidZero) { + ASSERT_FALSE(SubscriptionManager::checkSampleRateHz(0)); +} + +TEST_F(SubscriptionManagerTest, testCheckResolutionValid) { + ASSERT_TRUE(SubscriptionManager::checkResolution(0.0)); + ASSERT_TRUE(SubscriptionManager::checkResolution(0.1)); + ASSERT_TRUE(SubscriptionManager::checkResolution(1.0)); +} + +TEST_F(SubscriptionManagerTest, testCheckResolutionInvalid) { + ASSERT_FALSE(SubscriptionManager::checkResolution(2.0)); +} + +TEST_F(SubscriptionManagerTest, testSubscribe_enableVur) { + std::vector options = {{ + .propId = 0, + .areaIds = {0}, + .sampleRate = 10.0, + .enableVariableUpdateRate = true, + }}; + + auto result = getManager()->subscribe(getCallbackClient(), options, true); + ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message(); + + ASSERT_THAT(getHardware()->getSubscribeOptions(), ElementsAre(options[0])); +} + +TEST_F(SubscriptionManagerTest, testSubscribe_VurStateChange) { + std::vector options = {{ + .propId = 0, + .areaIds = {0}, + .sampleRate = 10.0, + .enableVariableUpdateRate = true, + }}; + + auto result = getManager()->subscribe(getCallbackClient(), options, true); + ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message(); + + ASSERT_THAT(getHardware()->getSubscribeOptions(), ElementsAre(options[0])); + + getHardware()->clearSubscribeOptions(); + result = getManager()->subscribe(getCallbackClient(), options, true); + ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message(); + + ASSERT_TRUE(getHardware()->getSubscribeOptions().empty()); + + std::vector newOptions = {{ + .propId = 0, + .areaIds = {0}, + .sampleRate = 10.0, + .enableVariableUpdateRate = false, + }}; + result = getManager()->subscribe(getCallbackClient(), newOptions, true); + ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message(); + + ASSERT_THAT(getHardware()->getSubscribeOptions(), ElementsAre(newOptions[0])); +} + +TEST_F(SubscriptionManagerTest, testSubscribe_enableVur_filterUnchangedEvents) { + SpAIBinder binder1 = ndk::SharedRefBase::make()->asBinder(); + std::shared_ptr client1 = IVehicleCallback::fromBinder(binder1); + SpAIBinder binder2 = ndk::SharedRefBase::make()->asBinder(); + std::shared_ptr client2 = IVehicleCallback::fromBinder(binder2); + SubscribeOptions client1Option = { + .propId = 0, + .areaIds = {0}, + .sampleRate = 10.0, + .enableVariableUpdateRate = false, + }; + auto result = getManager()->subscribe(client1, {client1Option}, true); + ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message(); + + ASSERT_THAT(getHardware()->getSubscribeOptions(), UnorderedElementsAre(client1Option)); + + getHardware()->clearSubscribeOptions(); + SubscribeOptions client2Option = { + .propId = 0, + .areaIds = {0, 1}, + .sampleRate = 20.0, + .enableVariableUpdateRate = true, + }; + + result = getManager()->subscribe(client2, {client2Option}, true); + ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message(); + + ASSERT_THAT(getHardware()->getSubscribeOptions(), + UnorderedElementsAre( + SubscribeOptions{ + .propId = 0, + .areaIds = {0}, + .sampleRate = 20.0, + // This is enabled for client2, but disabled for client1. + .enableVariableUpdateRate = false, + }, + SubscribeOptions{ + .propId = 0, + .areaIds = {1}, + .sampleRate = 20.0, + .enableVariableUpdateRate = true, + })); + + std::vector propertyEvents = {{ + .prop = 0, + .areaId = 0, + .value = {.int32Values = {0}}, + .timestamp = 1, + }, + { + .prop = 0, + .areaId = 1, + .value = {.int32Values = {1}}, + .timestamp = 1, + }}; + auto clients = + getManager()->getSubscribedClients(std::vector(propertyEvents)); + + ASSERT_THAT(clients[client1], UnorderedElementsAre(propertyEvents[0])); + ASSERT_THAT(clients[client2], UnorderedElementsAre(propertyEvents[0], propertyEvents[1])); + + // If the same property events happen again with a new timestamp. + // VUR is disabled for client1, enabled for client2. + clients = getManager()->getSubscribedClients({{ + .prop = 0, + .areaId = 0, + .value = {.int32Values = {0}}, + .timestamp = 2, + }}); + + ASSERT_FALSE(clients.find(client1) == clients.end()) + << "Must not filter out property events if VUR is not enabled"; + ASSERT_TRUE(clients.find(client2) == clients.end()) + << "Must filter out property events if VUR is enabled"; +} + +TEST_F(SubscriptionManagerTest, testSubscribe_enableVur_filterUnchangedEvents_withResolution) { + SpAIBinder binder1 = ndk::SharedRefBase::make()->asBinder(); + std::shared_ptr client1 = IVehicleCallback::fromBinder(binder1); + SpAIBinder binder2 = ndk::SharedRefBase::make()->asBinder(); + std::shared_ptr client2 = IVehicleCallback::fromBinder(binder2); + SubscribeOptions client1Option = { + .propId = 0, + .areaIds = {0}, + .sampleRate = 10.0, + .resolution = 0.01, + .enableVariableUpdateRate = false, + }; + auto result = getManager()->subscribe(client1, {client1Option}, true); + ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message(); + + ASSERT_THAT(getHardware()->getSubscribeOptions(), UnorderedElementsAre(client1Option)); + + getHardware()->clearSubscribeOptions(); + SubscribeOptions client2Option = { + .propId = 0, + .areaIds = {0, 1}, + .sampleRate = 20.0, + .resolution = 0.1, + .enableVariableUpdateRate = true, + }; + + result = getManager()->subscribe(client2, {client2Option}, true); + ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message(); + + ASSERT_THAT(getHardware()->getSubscribeOptions(), + UnorderedElementsAre( + SubscribeOptions{ + .propId = 0, + .areaIds = {0}, + .sampleRate = 20.0, + .resolution = 0.01, + // This is enabled for client2, but disabled for client1. + .enableVariableUpdateRate = false, + }, + SubscribeOptions{ + .propId = 0, + .areaIds = {1}, + .sampleRate = 20.0, + .resolution = 0.1, + .enableVariableUpdateRate = true, + })); + + std::vector propertyEvents = {{ + .prop = 0, + .areaId = 0, + .value = {.floatValues = {1.0}}, + .timestamp = 1, + }, + { + .prop = 0, + .areaId = 1, + .value = {.floatValues = {1.0}}, + .timestamp = 1, + }}; + auto clients = + getManager()->getSubscribedClients(std::vector(propertyEvents)); + + ASSERT_THAT(clients[client1], UnorderedElementsAre(propertyEvents[0])); + ASSERT_THAT(clients[client2], UnorderedElementsAre(propertyEvents[0], propertyEvents[1])); + + clients = getManager()->getSubscribedClients({{ + .prop = 0, + .areaId = 0, + .value = {.floatValues = {1.01}}, + .timestamp = 2, + }}); + + ASSERT_FALSE(clients.find(client1) == clients.end()) + << "Must not filter out property events if VUR is not enabled"; + ASSERT_TRUE(clients.find(client2) == clients.end()) + << "Must filter out property events if VUR is enabled and change is too small"; + ASSERT_TRUE(abs(clients[client1][0].value.floatValues[0] - 1.01) < 0.0000001) + << "Expected property value == 1.01, instead got " + << clients[client1][0].value.floatValues[0]; + + clients = getManager()->getSubscribedClients({{ + .prop = 0, + .areaId = 1, + .value = {.floatValues = {1.06}}, + .timestamp = 3, + }}); + + ASSERT_TRUE(clients.find(client1) == clients.end()) + << "Must not get property events for an areaId that the client hasn't subscribed to"; + ASSERT_FALSE(clients.find(client2) == clients.end()) + << "Must get property events significant changes"; + ASSERT_TRUE(abs(clients[client2][0].value.floatValues[0] - 1.1) < 0.0000001) + << "Expected property value == 1.1, instead got " + << clients[client2][0].value.floatValues[0]; +} + +TEST_F(SubscriptionManagerTest, testSubscribe_enableVur_mustNotFilterStatusChange) { + SpAIBinder binder1 = ndk::SharedRefBase::make()->asBinder(); + std::shared_ptr client1 = IVehicleCallback::fromBinder(binder1); + SpAIBinder binder2 = ndk::SharedRefBase::make()->asBinder(); + std::shared_ptr client2 = IVehicleCallback::fromBinder(binder2); + SubscribeOptions client1Option = { + .propId = 0, + .areaIds = {0}, + .sampleRate = 10.0, + .enableVariableUpdateRate = false, + }; + auto result = getManager()->subscribe(client1, {client1Option}, true); + ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message(); + + ASSERT_THAT(getHardware()->getSubscribeOptions(), UnorderedElementsAre(client1Option)); + + getHardware()->clearSubscribeOptions(); + SubscribeOptions client2Option = { + .propId = 0, + .areaIds = {0, 1}, + .sampleRate = 20.0, + .enableVariableUpdateRate = true, + }; + + result = getManager()->subscribe(client2, {client2Option}, true); + ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message(); + + ASSERT_THAT(getHardware()->getSubscribeOptions(), + UnorderedElementsAre( + SubscribeOptions{ + .propId = 0, + .areaIds = {0}, + .sampleRate = 20.0, + // This is enabled for client2, but disabled for client1. + .enableVariableUpdateRate = false, + }, + SubscribeOptions{ + .propId = 0, + .areaIds = {1}, + .sampleRate = 20.0, + .enableVariableUpdateRate = true, + })); + + VehiclePropValue propValue1 = { + .prop = 0, + .areaId = 0, + .value = {.int32Values = {0}}, + .timestamp = 1, + }; + auto clients = getManager()->getSubscribedClients(std::vector({propValue1})); + + ASSERT_THAT(clients[client1], UnorderedElementsAre(propValue1)); + + // A new event with the same value, but different status must not be filtered out. + VehiclePropValue propValue2 = { + .prop = 0, + .areaId = 0, + .value = {.int32Values = {0}}, + .status = VehiclePropertyStatus::UNAVAILABLE, + .timestamp = 2, + }; + clients = getManager()->getSubscribedClients({propValue2}); + + ASSERT_THAT(clients[client1], UnorderedElementsAre(propValue2)) + << "Must not filter out property events that has status change"; +} + +TEST_F(SubscriptionManagerTest, testSubscribe_enableVur_timestampUpdated_filterOutdatedEvent) { + SpAIBinder binder1 = ndk::SharedRefBase::make()->asBinder(); + std::shared_ptr client1 = IVehicleCallback::fromBinder(binder1); + SpAIBinder binder2 = ndk::SharedRefBase::make()->asBinder(); + std::shared_ptr client2 = IVehicleCallback::fromBinder(binder2); + std::vector options = {{ + .propId = 0, + .areaIds = {0}, + .sampleRate = 10.0, + .enableVariableUpdateRate = true, + }}; + + // client1 subscribe with VUR enabled. + auto result = getManager()->subscribe(client1, options, true); + ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message(); + + // Let client2 subscribe with VUR disabled so that we enabled VUR in DefaultVehicleHal layer. + result = getManager()->subscribe(client2, + {{ + .propId = 0, + .areaIds = {0}, + .sampleRate = 10.0, + .enableVariableUpdateRate = false, + }}, + true); + ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message(); + + VehiclePropValue value0 = { + .prop = 0, + .areaId = 0, + .value = {.int32Values = {0}}, + .timestamp = 1, + }; + auto clients = getManager()->getSubscribedClients({value0}); + + ASSERT_THAT(clients[client1], UnorderedElementsAre(value0)); + + // A new event with the same value arrived. This must update timestamp to 3. + VehiclePropValue value1 = { + .prop = 0, + .areaId = 0, + .value = {.int32Values = {0}}, + .timestamp = 3, + }; + clients = getManager()->getSubscribedClients({value1}); + + ASSERT_TRUE(clients.find(client1) == clients.end()) + << "Must filter out duplicate property events if VUR is enabled"; + + // The latest timestamp is 3, so even though the value is not the same, this is outdated and + // must be ignored. + VehiclePropValue value2 = { + .prop = 0, + .areaId = 0, + .value = {.int32Values = {1}}, + .timestamp = 2, + }; + clients = getManager()->getSubscribedClients({value1}); + + ASSERT_TRUE(clients.find(client1) == clients.end()) + << "Must filter out outdated property events if VUR is enabled"; +} + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/current/vhal/vhal-default-service.rc b/automotive/vehicle/aidl/impl/current/vhal/vhal-default-service.rc new file mode 100644 index 0000000000000000000000000000000000000000..761053f46aee40f7b8f640caf2e6fcf0bc90190d --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/vhal/vhal-default-service.rc @@ -0,0 +1,4 @@ +service vendor.vehicle-hal-default /vendor/bin/hw/android.hardware.automotive.vehicle@V4-default-service + class early_hal + user vehicle_network + group system inet diff --git a/automotive/vehicle/aidl/impl/current/vhal/vhal-default-service.xml b/automotive/vehicle/aidl/impl/current/vhal/vhal-default-service.xml new file mode 100644 index 0000000000000000000000000000000000000000..4695bf7d9373d0d728fa13f8c48de41bab655564 --- /dev/null +++ b/automotive/vehicle/aidl/impl/current/vhal/vhal-default-service.xml @@ -0,0 +1,7 @@ + + + android.hardware.automotive.vehicle + 4 + IVehicle/default + + diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/prop.json b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/prop.json deleted file mode 100644 index b88110923742998f2c904c5d96f217dbdf190ca6..0000000000000000000000000000000000000000 --- a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/prop.json +++ /dev/null @@ -1,26 +0,0 @@ -[ - { - "timestamp": 1000000, - "areaId": 0, - "value": 8, - "prop": 289408000 - }, - { - "timestamp": 2000000, - "areaId": 0, - "value": 4, - "prop": 289408000 - }, - { - "timestamp": 3000000, - "areaId": 0, - "value": 16, - "prop": 289408000 - }, - { - "timestamp": 4000000, - "areaId": 0, - "value": 10, - "prop": 289408000 - } -] diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/prop_different_types.json b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/prop_different_types.json deleted file mode 100644 index 0363ebd131ba8503820aaf5b6e9bba7982fe3783..0000000000000000000000000000000000000000 --- a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/prop_different_types.json +++ /dev/null @@ -1,58 +0,0 @@ -[ - { - "timestamp": 1000000, - "areaId": 0, - "value": 1, - "prop": 287310600 - }, - { - "timestamp": 1000000, - "areaId": 0, - "value": 2, - "prop": 289408000 - }, - { - "timestamp": 1000000, - "areaId": 0, - "value": 3.3, - "prop": 291504905 - }, - { - "timestamp": 1000000, - "areaId": 0, - "value": 4, - "prop": 290457096 - }, - { - "timestamp": 1000000, - "areaId": 0, - "value": "test", - "prop": 286265094 - }, - { - "timestamp": 1000000, - "areaId": 0, - "value": [1, 2], - "prop": 289476368 - }, - { - "timestamp": 1000000, - "areaId": 0, - "value": { - "int32Values": [1, 2], - "int64Values": [3, 4], - "floatValues": [5.5, 6.6], - "stringValue": "test" - }, - "prop": 299896626 - }, - { - "timestamp": 1000000, - "areaId": 0, - "value": { - "int32Values": [1], - "floatValues": [1] - }, - "prop": 299896064 - } -] \ No newline at end of file diff --git a/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/EvConnectorType.aidl b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/EvConnectorType.aidl index b469578e7756dfb0344f8272c7a12c0ced4c17b2..768e97ead6e9d477f33a5b9eac1077320961fc37 100644 --- a/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/EvConnectorType.aidl +++ b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/EvConnectorType.aidl @@ -46,5 +46,7 @@ enum EvConnectorType { TESLA_SUPERCHARGER = 9, GBT_AC = 10, GBT_DC = 11, + SAE_J3400_AC = 8, + SAE_J3400_DC = 9, OTHER = 101, } diff --git a/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleProperty.aidl b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleProperty.aidl index 4c5dad23c8febaff73b4874ca6bbd1222efc506c..6188dd982489f08742f766a271f0296e7d826f3f 100644 --- a/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleProperty.aidl +++ b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleProperty.aidl @@ -48,11 +48,15 @@ enum VehicleProperty { INFO_DRIVER_SEAT = (((0x010A + 0x10000000) + 0x05000000) + 0x00400000) /* 356516106 */, INFO_EXTERIOR_DIMENSIONS = (((0x010B + 0x10000000) + 0x01000000) + 0x00410000) /* 289472779 */, INFO_MULTI_EV_PORT_LOCATIONS = (((0x010C + 0x10000000) + 0x01000000) + 0x00410000) /* 289472780 */, + INFO_MODEL_TRIM = (((0x010D + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.STRING) /* 286261517 */, + INFO_VEHICLE_SIZE_CLASS = (((0x010E + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32_VEC) /* 289472782 */, PERF_ODOMETER = (((0x0204 + 0x10000000) + 0x01000000) + 0x00600000) /* 291504644 */, PERF_VEHICLE_SPEED = (((0x0207 + 0x10000000) + 0x01000000) + 0x00600000) /* 291504647 */, PERF_VEHICLE_SPEED_DISPLAY = (((0x0208 + 0x10000000) + 0x01000000) + 0x00600000) /* 291504648 */, PERF_STEERING_ANGLE = (((0x0209 + 0x10000000) + 0x01000000) + 0x00600000) /* 291504649 */, PERF_REAR_STEERING_ANGLE = (((0x0210 + 0x10000000) + 0x01000000) + 0x00600000) /* 291504656 */, + INSTANTANEOUS_FUEL_ECONOMY = (((0x0211 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.FLOAT) /* 291504657 */, + INSTANTANEOUS_EV_EFFICIENCY = (((0x0212 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.FLOAT) /* 291504658 */, ENGINE_COOLANT_TEMP = (((0x0301 + 0x10000000) + 0x01000000) + 0x00600000) /* 291504897 */, ENGINE_OIL_LEVEL = (((0x0303 + 0x10000000) + 0x01000000) + 0x00400000) /* 289407747 */, ENGINE_OIL_TEMP = (((0x0304 + 0x10000000) + 0x01000000) + 0x00600000) /* 291504900 */, @@ -69,8 +73,14 @@ enum VehicleProperty { EV_BATTERY_AVERAGE_TEMPERATURE = (((0x030E + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.FLOAT) /* 291504910 */, TIRE_PRESSURE = (((0x0309 + 0x10000000) + 0x07000000) + 0x00600000) /* 392168201 */, CRITICALLY_LOW_TIRE_PRESSURE = (((0x030A + 0x10000000) + 0x07000000) + 0x00600000) /* 392168202 */, + ACCELERATOR_PEDAL_COMPRESSION_PERCENTAGE = (((0x030F + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.FLOAT) /* 291504911 */, + BRAKE_PEDAL_COMPRESSION_PERCENTAGE = (((0x0310 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.FLOAT) /* 291504912 */, + BRAKE_PAD_WEAR_PERCENTAGE = (((0x0311 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.WHEEL) + android.hardware.automotive.vehicle.VehiclePropertyType.FLOAT) /* 392168209 */, + BRAKE_FLUID_LEVEL_LOW = (((0x0312 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.BOOLEAN) /* 287310610 */, + VEHICLE_PASSIVE_SUSPENSION_HEIGHT = (((0x0313 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.WHEEL) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32) /* 390071059 */, ENGINE_IDLE_AUTO_STOP_ENABLED = (((0x0320 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.BOOLEAN) /* 287310624 */, IMPACT_DETECTED = (((0x0330 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32) /* 289407792 */, + VEHICLE_HORN_ENGAGED = (((0x0340 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.BOOLEAN) /* 287310656 */, GEAR_SELECTION = (((0x0400 + 0x10000000) + 0x01000000) + 0x00400000) /* 289408000 */, CURRENT_GEAR = (((0x0401 + 0x10000000) + 0x01000000) + 0x00400000) /* 289408001 */, PARKING_BRAKE_ON = (((0x0402 + 0x10000000) + 0x01000000) + 0x00200000) /* 287310850 */, @@ -85,6 +95,8 @@ enum VehicleProperty { EV_STOPPING_MODE = (((0x040D + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32) /* 289408013 */, ELECTRONIC_STABILITY_CONTROL_ENABLED = (((0x040E + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.BOOLEAN) /* 287310862 */, ELECTRONIC_STABILITY_CONTROL_STATE = (((0x040F + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32) /* 289408015 */, + TURN_SIGNAL_LIGHT_STATE = (((0x0410 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32) /* 289408016 */, + TURN_SIGNAL_SWITCH = (((0x0411 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32) /* 289408017 */, HVAC_FAN_SPEED = (((0x0500 + 0x10000000) + 0x05000000) + 0x00400000) /* 356517120 */, HVAC_FAN_DIRECTION = (((0x0501 + 0x10000000) + 0x05000000) + 0x00400000) /* 356517121 */, HVAC_TEMPERATURE_CURRENT = (((0x0502 + 0x10000000) + 0x05000000) + 0x00600000) /* 358614274 */, @@ -261,6 +273,7 @@ enum VehicleProperty { VEHICLE_IN_USE = (((0x0F4A + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.BOOLEAN) /* 287313738 */, CLUSTER_HEARTBEAT = (((0x0F4B + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.MIXED) /* 299896651 */, VEHICLE_DRIVING_AUTOMATION_CURRENT_LEVEL = (((0x0F4C + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32) /* 289410892 */, + VEHICLE_DRIVING_AUTOMATION_TARGET_LEVEL = (((0x0F4F + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32) /* 289410895 */, CAMERA_SERVICE_CURRENT_STATE = (((0x0F4D + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32_VEC) /* 289476429 */, PER_DISPLAY_MAX_BRIGHTNESS = (((0x0F4E + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.INT32_VEC) /* 289476430 */, AUTOMATIC_EMERGENCY_BRAKING_ENABLED = (((0x1000 + android.hardware.automotive.vehicle.VehiclePropertyGroup.SYSTEM) + android.hardware.automotive.vehicle.VehicleArea.GLOBAL) + android.hardware.automotive.vehicle.VehiclePropertyType.BOOLEAN) /* 287313920 */, diff --git a/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleSizeClass.aidl b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleSizeClass.aidl new file mode 100644 index 0000000000000000000000000000000000000000..6817124b49013c55d724f221fa197a8b9ec76af1 --- /dev/null +++ b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleSizeClass.aidl @@ -0,0 +1,72 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.vehicle; +@Backing(type="int") @VintfStability +enum VehicleSizeClass { + EPA_TWO_SEATER = 0x100, + EPA_MINICOMPACT = 0x101, + EPA_SUBCOMPACT = 0x102, + EPA_COMPACT = 0x103, + EPA_MIDSIZE = 0x104, + EPA_LARGE = 0x105, + EPA_SMALL_STATION_WAGON = 0x106, + EPA_MIDSIZE_STATION_WAGON = 0x107, + EPA_LARGE_STATION_WAGON = 0x108, + EPA_SMALL_PICKUP_TRUCK = 0x109, + EPA_STANDARD_PICKUP_TRUCK = 0x10A, + EPA_VAN = 0x10B, + EPA_MINIVAN = 0x10C, + EPA_SMALL_SUV = 0x10D, + EPA_STANDARD_SUV = 0x10E, + EU_A_SEGMENT = 0x200, + EU_B_SEGMENT = 0x201, + EU_C_SEGMENT = 0x202, + EU_D_SEGMENT = 0x203, + EU_E_SEGMENT = 0x204, + EU_F_SEGMENT = 0x205, + EU_J_SEGMENT = 0x206, + EU_M_SEGMENT = 0x207, + EU_S_SEGMENT = 0x208, + JPN_KEI = 0x300, + JPN_SMALL_SIZE = 0x301, + JPN_NORMAL_SIZE = 0x302, + US_GVWR_CLASS_1_CV = 0x400, + US_GVWR_CLASS_2_CV = 0x401, + US_GVWR_CLASS_3_CV = 0x402, + US_GVWR_CLASS_4_CV = 0x403, + US_GVWR_CLASS_5_CV = 0x404, + US_GVWR_CLASS_6_CV = 0x405, + US_GVWR_CLASS_7_CV = 0x406, + US_GVWR_CLASS_8_CV = 0x407, +} diff --git a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/EvConnectorType.aidl b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/EvConnectorType.aidl index 7891dd93367deec3288d3928fd36ca805a511105..5738d21440c4e199e5e60f51d1a8e383a034324d 100644 --- a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/EvConnectorType.aidl +++ b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/EvConnectorType.aidl @@ -72,12 +72,15 @@ enum EvConnectorType { TESLA_ROADSTER = 7, /** * DO NOT USE - * Use TESLA_SUPERCHARGER instead. + * Use SAE_J3400_AC instead. * * High Power Wall Charger of Tesla. */ TESLA_HPWC = 8, /** + * DO NOT USE + * Use SAE_J3400_DC instead. + * * SAE J3400 connector * * Also known as the "North American Charging Standard" (NACS) @@ -88,6 +91,32 @@ enum EvConnectorType { GBT_AC = 10, /** GBT_DC Fast Charging Standard */ GBT_DC = 11, + /** + * SAE J3400 connector - AC Charging. + * + * Also known as the "North American Charging Standard" (NACS). + * + * This enum must be used if the vehicle specifically supports AC charging. If the vehicle + * supports both AC and DC, INFO_EV_CONNECTOR_TYPE should be populated with both SAE_J3400_AC + * and SAE_J3400_DC. If the vehicle only supports AC charging, it should only be populated with + * SAE_J3400_AC. + * + * This is equivalent to TESLA_HPWC enum. + */ + SAE_J3400_AC = 8, + /** + * SAE J3400 connector - DC Charging. + * + * Also known as the "North American Charging Standard" (NACS). + * + * This enum must be used if the vehicle specifically supports DC charging. If the vehicle + * supports both AC and DC, INFO_EV_CONNECTOR_TYPE should be populated with both SAE_J3400_AC + * and SAE_J3400_DC. If the vehicle only supports DC charging, it should only be populated with + * SAE_J3400_DC. + * + * This is equivalent to TESLA_SUPERCHARGER enum. + */ + SAE_J3400_DC = 9, /** * Connector type to use when no other types apply. Before using this * value, work with Google to see if the EvConnectorType enum can be diff --git a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl index e5c09b09bec074aa94c5525324753f3d25f3ab30..43675ff8f582b218d0a0507dedaf53a457b50d28 100644 --- a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl +++ b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl @@ -231,6 +231,45 @@ enum VehicleProperty { */ INFO_MULTI_EV_PORT_LOCATIONS = 0x010C + 0x10000000 + 0x01000000 + 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC + /** + * Public trim name of the vehicle. + * + * This property must communicate the vehicle's public trim name. + * + * For example, say an OEM manufactures two different versions of a vehicle model: + * "makeName modelName" and + * "makeName modelName Sport" + * This property must be empty for the first vehicle (i.e. base model), and set to "Sport" for + * the second vehicle. + * + * @change_mode VehiclePropertyChangeMode.STATIC + * @access VehiclePropertyAccess.READ + * @version 4 + */ + INFO_MODEL_TRIM = + 0x010D + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.STRING, + /** + * Vehicle Size Class. + * + * This property must communicate an integer array that contains the size classifications + * followed by the vehicle as enumerated in VehicleSizeClass.aidl. If the vehicle follows a + * single standard, then the array size of the property's value should be 1. If the vehicle + * follows multiple standards that the OEM wants to communicate, this may be communicated as + * additional values in the array. + * + * For example, suppose a vehicle model follows the VehicleSizeClass.EU_A_SEGMENT standard in + * the EU and the VehicleSizeClass.JPN_KEI standard in Japan. In this scenario this property + * must return an intArray = [VehicleSizeClass.EU_A_SEGMENT, VehicleSizeClass.JPN_KEI]. If this + * vehicle only followed the VehicleSizeClass.EU_A_SEGMENT standard, then we expect intArray = + * [VehicleSizeClass.EU_A_SEGMENT]. + * + * @change_mode VehiclePropertyChangeMode.STATIC + * @access VehiclePropertyAccess.READ + * @data_enum VehicleSizeClass + * @version 4 + */ + INFO_VEHICLE_SIZE_CLASS = 0x010E + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + + VehiclePropertyType.INT32_VEC, /** * Current odometer value of the vehicle * @@ -302,6 +341,38 @@ enum VehicleProperty { */ PERF_REAR_STEERING_ANGLE = 0x0210 + 0x10000000 + 0x01000000 + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT + /** + * Instantaneous Fuel Economy in L/100km. + * + * This property must communicate the instantaneous fuel economy of the vehicle in units of + * L/100km. The property's value is independent of DISTANCE_DISPLAY_UNITS, + * FUEL_VOLUME_DISPLAY_UNITS, and FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME property i.e. this + * property must always communicate the value in L/100km. + * + * For the EV version of this property, see INSTANTANEOUS_EV_EFFICIENCY. + * + * @change_mode VehiclePropertyChangeMode.CONTINUOUS + * @access VehiclePropertyAccess.READ + * @version 4 + */ + INSTANTANEOUS_FUEL_ECONOMY = + 0x0211 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.FLOAT, + /** + * Instantaneous EV efficiency in km/kWh. + * + * This property must communicate the instantaneous EV battery efficiency of the vehicle in + * units of km/kWh. The property's value is independent of the DISTANCE_DISPLAY_UNITS and + * EV_BATTERY_DISPLAY_UNITS properties i.e. this property must always communicate the value in + * km/kWh. + * + * For the fuel version of this property, see INSTANTANEOUS_FUEL_ECONOMY. + * + * @change_mode VehiclePropertyChangeMode.CONTINUOUS + * @access VehiclePropertyAccess.READ + * @version 4 + */ + INSTANTANEOUS_EV_EFFICIENCY = + 0x0212 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.FLOAT, /** * Temperature of engine coolant * @@ -525,16 +596,27 @@ enum VehicleProperty { /** * Tire pressure * - * Each tires is identified by its areaConfig.areaId config and their - * minFloatValue/maxFloatValue are used to store OEM recommended pressure - * range. The minFloatValue and maxFloatValue in VehicleAreaConfig must be defined. - * The minFloatValue in the areaConfig data represents the lower bound of - * the recommended tire pressure. - * The maxFloatValue in the areaConfig data represents the upper bound of - * the recommended tire pressure. + * {@code HasSupportedValueInfo.hasMinSupportedValue} and + * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for all areas. + * + * {@code MinMaxSupportedValueResult.minSupportedValue} represents the lower bound of the + * recommended tire pressure for the tire at the specified area ID. + * + * {@code MinMaxSupportedValueResult.maxSupportedValue} represents the upper bound of the + * recommended tire pressure for the tire at the specified area ID. + * + * For example, if the recommended tire pressure of left_front tire is from 200.0 KILOPASCAL to + * 240.0 KILOPASCAL, {@code getMinMaxSupportedValue} for + * [propId=TIRE_PRESSURE, areaId=VehicleAreaWheel::LEFT_FRONT] must return a + * {@code MinMaxSupportedValueResult} with OK status, 200.0 as minSupportedValue, 240.0 as + * maxSupportedValue. + * + * For backward compatibility, minFloatValue and maxFloatValue in {@code VehicleAreaConfig} + * must be set to the same as minSupportedValue and maxSupportedValue at boot time. + * + * Each tire is identified by its areaConfig.areaId config. + * * For example: - * The following areaConfig indicates the recommended tire pressure - * of left_front tire is from 200.0 KILOPASCAL to 240.0 KILOPASCAL. * .areaConfigs = { * VehicleAreaConfig { * .areaId = VehicleAreaWheel::LEFT_FRONT, @@ -545,6 +627,7 @@ enum VehicleProperty { * * @change_mode VehiclePropertyChangeMode.CONTINUOUS * @access VehiclePropertyAccess.READ + * @require_min_max_supported_value * @unit VehicleUnit.KILOPASCAL * @version 2 */ @@ -566,6 +649,100 @@ enum VehicleProperty { */ CRITICALLY_LOW_TIRE_PRESSURE = 0x030A + 0x10000000 + 0x07000000 + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:WHEEL,VehiclePropertyType:FLOAT + /** + * Accelerator pedal compression percentage. + * + * This property must communicate the percentage that the physical accelerator pedal in the + * vehicle is compressed. This property must return a float value from 0 to 100. + * + * 0 indicates the pedal is not compressed. + * 100 indicates the pedal is maximally compressed. + * + * @change_mode VehiclePropertyChangeMode.CONTINUOUS + * @access VehiclePropertyAccess.READ + * @version 4 + */ + ACCELERATOR_PEDAL_COMPRESSION_PERCENTAGE = + 0x030F + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.FLOAT, + /** + * Brake pedal compression percentage. + * + * This property must communicate the percentage that the physical brake pedal in the vehicle is + * compressed. This property must return a float value from 0 to 100. + * + * 0 indicates the pedal is not compressed. + * 100 indicates the pedal is maximally compressed. + * + * @change_mode VehiclePropertyChangeMode.CONTINUOUS + * @access VehiclePropertyAccess.READ + * @version 4 + */ + BRAKE_PEDAL_COMPRESSION_PERCENTAGE = + 0x0310 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.FLOAT, + /** + * Brake pad wear percentage. + * + * This property must communicate the amount of brake pad wear accumulated by the vehicle as a + * percentage. This property return a float value from 0 to 100. + * + * 0 indicates the brake pad has no wear. + * 100 indicates the brake pad is maximally worn. + * + * @change_mode VehiclePropertyChangeMode.ON_CHANGE + * @access VehiclePropertyAccess.READ + * @version 4 + */ + BRAKE_PAD_WEAR_PERCENTAGE = + 0x0311 + VehiclePropertyGroup.SYSTEM + VehicleArea.WHEEL + VehiclePropertyType.FLOAT, + /** + * Brake fluid low. + * + * This property must communicate that the brake fluid level in the vehicle is low according to + * the OEM. This property must match the vehicle's brake fluid level status as displayed on the + * instrument cluster. If the brake fluid level is low, this property must be set to true. If + * not, it must be set to false. + * + * @change_mode VehiclePropertyChangeMode.ON_CHANGE + * @access VehiclePropertyAccess.READ + * @version 4 + */ + BRAKE_FLUID_LEVEL_LOW = + 0x0312 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN, + /** + * Vehicle Passive Suspension Height in mm. + * + * This property must communicate the real-time suspension displacement of the vehicle relative + * to its neutral position, given in mm. In other words, the displacement of the suspension at + * any given point in time relative to the suspension's position when the vehicle is on a flat + * surface with no passengers or cargo. When the suspension is compressed in comparison to the + * neutral position, the value should be negative. When the suspension is decompressed in + * comparison to the neutral position, the value should be positive. + * + * Examples for further clarity: + * 1) Suppose the user is driving on a smooth flat surface, and all wheels are currently + * compressed by 2 cm in comparison to the default suspension height. In this scenario, this + * property must be set to -20 for all wheels. + * 2) Suppose the user drives over a pothole. While the front left wheel is over the pothole, + * it's decompressed by 3 cm in comparison to the rest of the wheels, or 1 cm in comparison to + * the default suspension height. All the others are still compressed by 2 cm. In this + * scenario, this property must be set to -20 for all wheels except for the front left, which + * must be set to 10. + * + * HasSupportedValueInfo.hasMinSupportedValue and HasSupportedValueInfo.hasMaxSupportedValue + * must be true for all areas. + * + * MinMaxSupportedValueResult.minSupportedValue represents the lower bound of the suspension + * height for the wheel at the specified area ID. + * + * MinMaxSupportedValueResult.maxSupportedValue represents the upper bound of the suspension + * height for the wheel at the specified area ID. + * + * @change_mode VehiclePropertyChangeMode.CONTINUOUS + * @access VehiclePropertyAccess.READ + * @version 4 + */ + VEHICLE_PASSIVE_SUSPENSION_HEIGHT = + 0x0313 + VehiclePropertyGroup.SYSTEM + VehicleArea.WHEEL + VehiclePropertyType.INT32, /** * Represents feature for engine idle automatic stop. * @@ -589,8 +766,12 @@ enum VehicleProperty { * of the vehicle as described through the ImpactSensorLocation enum. As a bit flag property, * this property can be set to multiple ORed together values of the enum when necessary. * - * For the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined - * unless all bit flags of ImpactSensorLocation are supported. + * For the global area ID (0), {@code getSupportedValuesList} + * must return a {@code SupportedValuesListResult} that contains supported values unless all bit + * flags of ImpactSensorLocation are supported. + * + * For backward compatibility, if {@code SupportedValuesListResult} is defined, + * {@code VehicleAreaConfig#supportedEnumValues} must be set to the same values. * * @change_mode VehiclePropertyChangeMode.ON_CHANGE * @access VehiclePropertyAccess.READ @@ -599,23 +780,47 @@ enum VehicleProperty { */ IMPACT_DETECTED = 0x0330 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32, + /** + * Vehicle horn engaged. + * + * This property must communicate if the vehicle's horn is currently engaged or not. If true, + * the horn is engaged. If false, the horn is disengaged. + * + * @change_mode VehiclePropertyChangeMode.ON_CHANGE + * @access VehiclePropertyAccess.READ_WRITE + * @access VehiclePropertyAccess.READ + * @version 4 + */ + VEHICLE_HORN_ENGAGED = + 0x0340 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN, /** * Currently selected gear * * This is the gear selected by the user. * - * Values in the config data must represent the list of supported gears for this vehicle. For - * example, config data for an automatic transmission must contain {GEAR_NEUTRAL, GEAR_REVERSE, - * GEAR_PARK, GEAR_DRIVE, GEAR_1, GEAR_2,...} and for manual transmission the list must be - * {GEAR_NEUTRAL, GEAR_REVERSE, GEAR_1, GEAR_2,...} + * {@code VehicleAreaConfig.HasSupportedValueInfo.hasSupportedValuesList} for the global area ID + * (0) must be {@code true}. + * + * {@code getSupportedValuesList} for [GEAR_SELECTION, areaId=0] must return a + * {@code SupportedValuesListResult} that contains non-null {@code supportedValuesList}. + * + * The supportedValues must represent the list of supported gears for this vehicle. For example, + * for an automatic transmission, the list can be {GEAR_NEUTRAL, GEAR_REVERSE, GEAR_PARK, + * GEAR_DRIVE, GEAR_1, GEAR_2,...} and for manual transmission it can be {GEAR_NEUTRAL, + * GEAR_REVERSE, GEAR_1, GEAR_2,...}. * * In the case of an automatic transmission vehicle that allows the driver to select specific * gears on demand (i.e. "manual mode"), GEAR_SELECTION's value must be set to the specific gear * selected by the driver instead of simply GEAR_DRIVE. * + * For backward compatibility, config array for this property must be a list of values + * same as the supported values at boot-time. + * * @change_mode VehiclePropertyChangeMode.ON_CHANGE * @access VehiclePropertyAccess.READ * @data_enum VehicleGear + * @require_supported_values_list + * @legacy_supported_values_in_config * @version 2 */ GEAR_SELECTION = 0x0400 + 0x10000000 + 0x01000000 @@ -626,16 +831,27 @@ enum VehicleProperty { * the current gear will be one of GEAR_1, GEAR_2 etc, which reflects * the actual gear the transmission is currently running in. * - * Values in the config data must represent the list of supported gears - * for this vehicle. For example, config data for an automatic transmission - * must contain {GEAR_NEUTRAL, GEAR_REVERSE, GEAR_PARK, GEAR_1, GEAR_2,...} - * and for manual transmission the list must be + * {@code VehicleAreaConfig.HasSupportedValueInfo.hasSupportedValuesList} for the global area ID + * (0) must be {@code true}. + * + * {@code getSupportedValuesList} for [GEAR_SELECTION, areaId=0] must return a + * {@code SupportedValuesListResult} that contains non-null {@code supportedValuesList}. + * + * The supported values list must represent the list of supported gears + * for this vehicle. For example, for an automatic transmission, this list can be + * {GEAR_NEUTRAL, GEAR_REVERSE, GEAR_PARK, GEAR_1, GEAR_2,...} + * and for manual transmission the list can be * {GEAR_NEUTRAL, GEAR_REVERSE, GEAR_1, GEAR_2,...}. This list need not be the * same as that of the supported gears reported in GEAR_SELECTION. * + * For backward compatibility, config array for this property must be a list of values + * same as the supported values at boot-time. + * * @change_mode VehiclePropertyChangeMode.ON_CHANGE * @access VehiclePropertyAccess.READ * @data_enum VehicleGear + * @require_supported_values_list + * @legacy_supported_values_in_config * @version 2 */ CURRENT_GEAR = 0x0401 + 0x10000000 + 0x01000000 @@ -673,11 +889,19 @@ enum VehicleProperty { /** * Regenerative braking level of a electronic vehicle * - * The maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All values between - * minInt32Value and maxInt32Value must be supported. The minInt32Value must be 0. + * {@code HasSupportedValueInfo.hasMinSupportedValue} and + * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for global area ID(0) + * + * {@code MinMaxSupportedValueResult.minSupportedValue} must be 0. + * + * {@code MinMaxSupportedValueResult.maxSupportedValue} indicates the setting for the maximum + * amount of energy regenerated from braking. The minSupportedValue indicates the setting for no + * regenerative braking. * - * The maxInt32Value indicates the setting for the maximum amount of energy regenerated from - * braking. The minInt32Value indicates the setting for no regenerative braking. + * All values between min and max supported value must be supported. + * + * For backward compatibility, minInt32Value and maxInt32Value in {@code VehicleAreaConfig} + * must be set to the same as minSupportedValue and maxSupportedValue at boot time. * * This property is a more granular form of EV_REGENERATIVE_BRAKING_STATE. It allows the user to * set a more specific level of regenerative braking if the states in EvRegenerativeBrakingState @@ -689,6 +913,7 @@ enum VehicleProperty { * @change_mode VehiclePropertyChangeMode.ON_CHANGE * @access VehiclePropertyAccess.READ_WRITE * @access VehiclePropertyAccess.READ + * @require_min_max_supported_value * @version 2 */ EV_BRAKE_REGENERATION_LEVEL = @@ -726,7 +951,12 @@ enum VehicleProperty { NIGHT_MODE = 0x0407 + 0x10000000 + 0x01000000 + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN /** - * State of the vehicles turn signals + * (Deprecated) State of the vehicles turn signals + * + * This property has been deprecated as it ambiguously defines the state of the vehicle turn + * signals without making clear if it means the state of the turn signal lights or the state of + * the turn signal switch. The introduction of TURN_SIGNAL_LIGHT_STATE and TURN_SIGNAL_SWITCH + * rectifies this problem. * * @change_mode VehiclePropertyChangeMode.ON_CHANGE * @access VehiclePropertyAccess.READ @@ -774,8 +1004,12 @@ enum VehicleProperty { /** * Represents property for the current stopping mode of the vehicle. * - * For the global area ID (0), the VehicleAreaConfig#supportedEnumValues must be defined unless - * all enum values of EvStoppingMode are supported. + * For the global area ID (0), {@code getSupportedValuesList} + * must return a {@code SupportedValuesListResult} that contains supported values unless all + * enum values of EvStoppingMode are supported. + * + * For backward compatibility, if {@code SupportedValuesListResult} is defined, + * {@code VehicleAreaConfig#supportedEnumValues} must be set to the same values. * * The EvStoppingMode enum may be extended to include more states in the future. * @@ -819,10 +1053,14 @@ enum VehicleProperty { * ElectronicStabilityControlState or ErrorState. It must not surface errors through StatusCode * and must use the supported error states instead. * - * For the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined - * unless all states of both ElectronicStabilityControlState (including OTHER, which is not + * For the global area ID (0), {@code getSupportedValuesList} + * must return a {@code SupportedValuesListResult} that contains supported values unless all + * states of both ElectronicStabilityControlState (including OTHER, which is not * recommended) and ErrorState are supported. * + * For backward compatibility, if {@code SupportedValuesListResult} is defined, + * {@code VehicleAreaConfig#supportedEnumValues} must be set to the same values. + * * @change_mode VehiclePropertyChangeMode.ON_CHANGE * @access VehiclePropertyAccess.READ * @data_enum ElectronicStabilityControlState @@ -831,6 +1069,60 @@ enum VehicleProperty { */ ELECTRONIC_STABILITY_CONTROL_STATE = 0x040F + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32, + /** + * Turn signal light state. + * + * This property must communicate the actual state of the turn signal lights. + * + * Examples: + * 1) Left turn signal light is currently pulsing, right turn signal light is currently off. + * This property must return VehicleTurnSignal.LEFT while the light is on during the pulse, + * and VehicleTurnSignal.NONE when it is off during the pulse. + * 2) Right turn signal light is currently pulsing, left turn signal light is currently off. + * This property must return VehicleTurnSignal.RIGHT while the light is on during the pulse, + * and VehicleTurnSignal.NONE when it is off during the pulse. + * 3) Both turn signal lights are currently pulsing (e.g. when hazard lights switch is on). + * This property must return VehicleTurnSignal.LEFT | VehicleTurnSignal.RIGHT while the lights + * are on during the pulse, and VehicleTurnSignal.NONE when they are off during the pulse. + * + * Note that this property uses VehicleTurnSignal as a bit flag, unlike TURN_SIGNAL_SWITCH, + * which uses it like a regular enum. This means this property can support ORed together values + * in VehicleTurnSignal. + * + * This is different from the function of TURN_SIGNAL_SWITCH, which must communicate the state + * of the turn signal lever/switch. + * + * This property is a replacement to the TURN_SIGNAL_STATE property, which is now deprecated. + * + * @change_mode VehiclePropertyChangeMode.ON_CHANGE + * @access VehiclePropertyAccess.READ + * @data_enum VehicleTurnSignal + * @version 4 + */ + TURN_SIGNAL_LIGHT_STATE = + 0x0410 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32, + /** + * Turn signal switch. + * + * This property must communicate the state of the turn signal lever/switch. This is different + * from the function of TURN_SIGNAL_LIGHT_STATE, which must communicate the actual state of the + * turn signal lights. + * + * Note that this property uses VehicleTurnSignal as a regular enum, unlike + * TURN_SIGNAL_LIGHT_STATE, which uses it like a bit flag. This means this property cannot + * support ORed together values in VehicleTurnSignal. + * + * This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to + * implement it as VehiclePropertyAccess.READ only. + * + * @change_mode VehiclePropertyChangeMode.ON_CHANGE + * @access VehiclePropertyAccess.READ_WRITE + * @access VehiclePropertyAccess.READ + * @data_enum VehicleTurnSignal + * @version 4 + */ + TURN_SIGNAL_SWITCH = + 0x0411 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32, /** * HVAC Properties * @@ -904,6 +1196,10 @@ enum VehicleProperty { * This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to * implement it as VehiclePropertyAccess.READ only. * + * The supported hvac fan direction is exposed through {@code HVAC_FAN_DIRECTION_AVAILABLE} + * property. Caller should not call {@code getSupportedValuesList}, or use + * {@code VehicleAreaConfig#supportedEnumValues}. + * * @change_mode VehiclePropertyChangeMode.ON_CHANGE * @access VehiclePropertyAccess.READ_WRITE * @access VehiclePropertyAccess.READ @@ -1544,8 +1840,15 @@ enum VehicleProperty { * * Indicates type of units the car is using to display speed to user. Eg. m/s, km/h, or mph. * - * VehiclePropConfig.configArray is used to indicate the supported speed display units. - * Pressure units are defined in VehicleUnit. + * {@code VehicleAreaConfig.HasSupportedValueInfo.hasSupportedValuesList} for the global area ID + * (0) must be {@code true}. + * + * {@code getSupportedValuesLists} for [VEHICLE_SPEED_DISPLAY_UNITS, areaId=0] must return a + * {@code SupportedValuesListResult} that contains non-null {@code supportedValuesList}, + * e.g. [METER_PER_SEC, MILES_PER_HOUR, KILOMETERS_PER_HOUR]. + * + * For backward compatibility, config array for this property must contain the same values as + * supported values at boot time. * For example: configArray[0] = METER_PER_SEC * configArray[1] = MILES_PER_HOUR * configArray[2] = KILOMETERS_PER_HOUR @@ -1559,6 +1862,9 @@ enum VehicleProperty { * @change_mode VehiclePropertyChangeMode.ON_CHANGE * @access VehiclePropertyAccess.READ_WRITE * @access VehiclePropertyAccess.READ + * @data_enum VehicleUnit + * @require_supported_values_list + * @legacy_supported_values_in_config * @version 2 */ VEHICLE_SPEED_DISPLAY_UNITS = 0x0605 + 0x10000000 + 0x01000000 @@ -5187,9 +5493,7 @@ enum VehicleProperty { * * Defines the level of autonomy currently engaged in the vehicle from the J3016_202104 revision * of the SAE standard levels 0-5, with 0 representing no autonomy and 5 representing full - * driving automation. These levels should be used in accordance with the standards defined in - * https://www.sae.org/standards/content/j3016_202104/ and - * https://www.sae.org/blog/sae-j3016-update + * driving automation. * * For the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined * unless all states of VehicleAutonomousState are supported. @@ -5201,7 +5505,35 @@ enum VehicleProperty { */ VEHICLE_DRIVING_AUTOMATION_CURRENT_LEVEL = 0x0F4C + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32, - + /** + * Target state of vehicle autonomy. + * + * Defines the level of autonomy being targeted by the vehicle from the J3016_202104 revision of + * the SAE standard levels 0-5, with 0 representing no autonomy and 5 representing full driving + * automation. + * + * For example, suppose the vehicle is currently in a Level 3 state of automation and wants to + * give the driver full manual control (i.e. Level 0) as soon as it's safe to do so. In this + * scenario, this property must be set to VehicleAutonomousState.LEVEL_0. Similarly, if the + * vehicle is currently in Level 1 state of automation and wants to go up to Level 2, this + * property must be set to VehicleAutonomousState.LEVEL_2. If the vehicle has already reached + * and is currently in the target level of autonomy, this property must be equal to the value of + * VEHICLE_DRIVING_AUTOMATION_CURRENT_LEVEL. + * + * For the global area ID (0), the SupportedValuesListResult#supportedValuesList array must be + * defined unless all states of VehicleAutonomousState are supported. These values must match + * the values in supportedValuesList of VEHICLE_DRIVING_AUTOMATION_CURRENT_LEVEL. + * + * For the property that communicates the current state of autonomy, see + * VEHICLE_DRIVING_AUTOMATION_CURRENT_LEVEL. + * + * @change_mode VehiclePropertyChangeMode.ON_CHANGE + * @access VehiclePropertyAccess.READ + * @data_enum VehicleAutonomousState + * @version 4 + */ + VEHICLE_DRIVING_AUTOMATION_TARGET_LEVEL = + 0x0F4F + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32, /** * Reports current state of CarEvsService types. * diff --git a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleSizeClass.aidl b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleSizeClass.aidl new file mode 100644 index 0000000000000000000000000000000000000000..1915c4a1f6e208a312e834cb631539e981fc3b23 --- /dev/null +++ b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleSizeClass.aidl @@ -0,0 +1,212 @@ +/* + * 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. + */ + +package android.hardware.automotive.vehicle; + +/** + * Used to enumerate the various size classes of vehicles. + * + * This enum can be extended in future releases to include additional values. + */ +@VintfStability +@Backing(type="int") +enum VehicleSizeClass { + /** + * Represents two-seaters as defined by the EPA standard of size classes for vehicles in the + * United States. + * + * The current implementation of EPA-standard enums follows the classification defined in + * Federal Regulation, Title 40—Protection of Environment, Section 600.315-08 "Classes of + * comparable automobiles". + */ + EPA_TWO_SEATER = 0x100, + /** + * Represents minicompact cars as defined by the EPA standard of size classes for vehicles in + * the United States. + */ + EPA_MINICOMPACT = 0x101, + /** + * Represents subcompact cars as defined by the EPA standard of size classes for vehicles in the + * United States. + */ + EPA_SUBCOMPACT = 0x102, + /** + * Represents compact cars as defined by the EPA standard of size classes for vehicles in the + * United States. + */ + EPA_COMPACT = 0x103, + /** + * Represents midsize cars as defined by the EPA standard of size classes for vehicles in the + * United States. + */ + EPA_MIDSIZE = 0x104, + /** + * Represents large cars as defined by the EPA standard of size classes for vehicles in the + * United States. + */ + EPA_LARGE = 0x105, + /** + * Represents small station wagons as defined by the EPA standard of size classes for vehicles + * in the United States. + */ + EPA_SMALL_STATION_WAGON = 0x106, + /** + * Represents midsize station wagons as defined by the EPA standard of size classes for vehicles + * in the United States. + */ + EPA_MIDSIZE_STATION_WAGON = 0x107, + /** + * Represents large station wagons as defined by the EPA standard of size classes for vehicles + * in the United States. + */ + EPA_LARGE_STATION_WAGON = 0x108, + /** + * Represents small pickup trucks as defined by the EPA standard of size classes for vehicles + * in the United States. + */ + EPA_SMALL_PICKUP_TRUCK = 0x109, + /** + * Represents standard pickup trucks as defined by the EPA standard of size classes for vehicles + * in the United States. + */ + EPA_STANDARD_PICKUP_TRUCK = 0x10A, + /** + * Represents vans as defined by the EPA standard of size classes for vehicles in the United + * States. + */ + EPA_VAN = 0x10B, + /** + * Represents minivans as defined by the EPA standard of size classes for vehicles in the United + * States. + */ + EPA_MINIVAN = 0x10C, + /** + * Represents small sport utility vehicles (SUVs) as defined by the EPA standard of size classes + * for vehicles in the United States. + */ + EPA_SMALL_SUV = 0x10D, + /** + * Represents standard sport utility vehicles (SUVs) as defined by the EPA standard of size + * classes for vehicles in the United States. + */ + EPA_STANDARD_SUV = 0x10E, + /** + * Represents A-segment vehicle size class, commonly called "mini" cars or "city" cars, as + * classified in the EU. + * + * The current implementation of the EU Car Segment enums follows the classification first + * described in Case No COMP/M.1406 Hyundai / Kia Regulation (EEC) No 4064/89 Merger Procedure. + */ + EU_A_SEGMENT = 0x200, + /** + * Represents B-segment vehicle size class, commonly called "small" cars, as classified in the + * EU. + */ + EU_B_SEGMENT = 0x201, + /** + * Represents C-segment vehicle size class, commonly called "medium" cars, as classified in the + * EU. + */ + EU_C_SEGMENT = 0x202, + /** + * Represents D-segment vehicle size class, commonly called "large" cars, as classified in the + * EU. + */ + EU_D_SEGMENT = 0x203, + /** + * Represents E-segment vehicle size class, commonly called "executive" cars, as classified in + * the EU. + */ + EU_E_SEGMENT = 0x204, + /** + * Represents F-segment vehicle size class, commonly called "luxury" cars, as classified in the + * EU. + */ + EU_F_SEGMENT = 0x205, + /** + * Represents J-segment vehicle size class, commonly associated with SUVs and off-road vehicles, + * as classified in the EU. + */ + EU_J_SEGMENT = 0x206, + /** + * Represents M-segment vehicle size class, commonly called "multi-purpose" cars, as classified + * in the EU. + */ + EU_M_SEGMENT = 0x207, + /** + * Represents S-segment vehicle size class, commonly called "sports" cars, as classified in the + * EU. + */ + EU_S_SEGMENT = 0x208, + /** + * Represents keijidosha or "kei" cars as defined by the Japanese standard of size classes for + * vehicles. + * + * The current implementation of Japan-standard enums follows the classification defined in the + * Japanese Government's Road Vehicle Act of 1951. + */ + JPN_KEI = 0x300, + /** + * Represents small-size passenger vehicles as defined by the Japanese standard of size classes + * for vehicles. + */ + JPN_SMALL_SIZE = 0x301, + /** + * Represents normal-size passenger vehicles as defined by the Japanese standard of size classes + * for vehicles. + */ + JPN_NORMAL_SIZE = 0x302, + /** + * Represents Class 1 trucks following the US GVWR classification of commercial vehicles. This + * is classified under "Light duty" vehicles by the US Federal Highway Association. + */ + US_GVWR_CLASS_1_CV = 0x400, + /** + * Represents Class 2 trucks following the US GVWR classification of commercial vehicles. This + * is classified under "Light duty" vehicles by the US Federal Highway Association. + */ + US_GVWR_CLASS_2_CV = 0x401, + /** + * Represents Class 3 trucks following the US GVWR classification of commercial vehicles. This + * is classified under "Medium duty" vehicles by the US Federal Highway Association. + */ + US_GVWR_CLASS_3_CV = 0x402, + /** + * Represents Class 4 trucks following the US GVWR classification of commercial vehicles. This + * is classified under "Medium duty" vehicles by the US Federal Highway Association. + */ + US_GVWR_CLASS_4_CV = 0x403, + /** + * Represents Class 5 trucks following the US GVWR classification of commercial vehicles. This + * is classified under "Medium duty" vehicles by the US Federal Highway Association. + */ + US_GVWR_CLASS_5_CV = 0x404, + /** + * Represents Class 6 trucks following the US GVWR classification of commercial vehicles. This + * is classified under "Medium duty" vehicles by the US Federal Highway Association. + */ + US_GVWR_CLASS_6_CV = 0x405, + /** + * Represents Class 7 trucks following the US GVWR classification of commercial vehicles. This + * is classified under "Heavy duty" vehicles by the US Federal Highway Association. + */ + US_GVWR_CLASS_7_CV = 0x406, + /** + * Represents Class 8 trucks following the US GVWR classification of commercial vehicles. This + * is classified under "Heavy duty" vehicles by the US Federal Highway Association. + */ + US_GVWR_CLASS_8_CV = 0x407, +} diff --git a/automotive/vehicle/tools/translate_aidl_enums.py b/automotive/vehicle/tools/translate_aidl_enums.py index a7c1808250753dfd8008f9b47cec6fc59a0961c9..53afef30af23cdc2140a0a56f829d8582259236e 100644 --- a/automotive/vehicle/tools/translate_aidl_enums.py +++ b/automotive/vehicle/tools/translate_aidl_enums.py @@ -21,14 +21,16 @@ ENUM_NAMETest.java files in cts/tests/tests/car/src/android/car/cts and packages/services/Car/tests/android_car_api_test/src/android/car/apitest + Also needs a flag name e.g. FLAG_ANDROID_VIC_VEHICLE_PROPERTIES + Usage: - $ python translate_aidl_enums.py ENUM_NAME.aidl + $ python translate_aidl_enums.py ENUM_NAME.aidl FLAG_NAME """ import os import sys LICENSE = """/* - * Copyright (C) 2023 The Android Open Source Project + * 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. @@ -45,15 +47,20 @@ LICENSE = """/* """ class EnumParser: - def __init__(self, file_path, file_name): + def __init__(self, file_path, file_name, flag_name): self.filePath = file_path self.fileName = file_name + self.flagName = flag_name self.lowerFileName = self.fileName[0].lower() + self.fileName[1:] + self.enumNames = [] self.enums = [] self.outputMsg = [] self.outputMsg.append(LICENSE) self.outputMsg.append("\npackage android.car.hardware.property;\n") self.outputMsg.append(""" +import static android.car.feature.Flags.{}; + +import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; @@ -61,26 +68,61 @@ import com.android.car.internal.util.ConstantDebugUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -""") +""".format(self.flagName)) + + comment_block = [] + in_comment = False with open(self.filePath, 'r') as f: - for line in f.readlines()[16:]: - if line in ["package android.hardware.automotive.vehicle;\n", - "@VintfStability\n", - '@Backing(type="int")\n']: + lines = f.readlines() + for line in lines: + line = line.rstrip('\n') + if line.strip() in ["package android.hardware.automotive.vehicle;", + "@VintfStability", + '@Backing(type="int")']: + continue + + if line.strip().startswith('/**') or line.strip().startswith('/*'): + in_comment = True + comment_block.append(line + '\n') + continue + elif in_comment: + comment_block.append(line + '\n') + if line.strip().endswith('*/'): + in_comment = False + continue + elif line.strip().startswith('*'): + comment_block.append(line + '\n') continue - msg = line + msg = line + '\n' msgSplit = msg.strip().split() if len(msgSplit) > 0 and msgSplit[0] == "enum": + if comment_block: + self.outputMsg.extend(comment_block) + comment_block = [] + self.outputMsg.append("@FlaggedApi({})\n".format(self.flagName)) msgSplit[0] = "public final class" msg = " ".join(msgSplit) + "\n" + self.outputMsg.append(msg) elif len(msgSplit) > 1 and msgSplit[1] == '=': + if comment_block: + indented_comment_block = [line for line in comment_block] + self.outputMsg.extend(indented_comment_block) + comment_block = [] msgSplit.insert(0, " public static final int") - self.enums.append(msgSplit[1]) - msgSplit[-1] = msgSplit[-1][:-1] + ";\n" - msg = " ".join(msgSplit) - elif msg == "}\n": + enum_name = msgSplit[1].strip() + self.enumNames.append(enum_name) + enum = msgSplit[3].strip(",") + self.enums.append(enum) + if msgSplit[-1].endswith(','): + msgSplit[-1] = msgSplit[-1][:-1] + ";" + msg = " ".join(msgSplit) + "\n" + self.outputMsg.append(msg) + elif line.strip() == '}': + if comment_block: + self.outputMsg.extend(comment_block) + comment_block = [] self.outputMsg.append(""" private {2}() {{}} @@ -101,17 +143,23 @@ import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.SOURCE) public @interface {2}Int {{}}\n""".format(self.lowerFileName, "{" + ", ".join(self.enums) + "}", self.fileName)) - self.outputMsg.append(msg) - self.outputMsg.append("TODO: delete this line and manually update this file with app-facing documentation and necessary tags.\n") + self.outputMsg.append("}") self.outputMsgApiTest = [] self.outputMsgApiTest.append(LICENSE) self.outputMsgApiTest.append("""package android.car.apitest; +import static android.car.feature.Flags.{1}; + import static com.google.common.truth.Truth.assertWithMessage; +import android.platform.test.annotations.RequiresFlagsEnabled; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; + import androidx.test.filters.SmallTest; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -122,6 +170,8 @@ import java.util.Collection; @SmallTest @RunWith(Parameterized.class) public class {0}Test {{ + @Rule + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); private final int mJavaConstantValue; private final int mHalConstantValue; @@ -133,56 +183,68 @@ public class {0}Test {{ @Parameterized.Parameters public static Collection constantValues() {{ return Arrays.asList( - new Object[][] {{""".format(self.fileName)) - for enum in self.enums: + new Object[][] {{""".format(self.fileName, self.flagName)) + for enum in self.enumNames: self.outputMsgApiTest.append(""" {{ android.car.hardware.property.{0}.{1}, android.hardware.automotive.vehicle.{0}.{1} }},""".format(self.fileName, enum)) self.outputMsgApiTest.append(""" - }); - } + }}); + }} @Test - public void testMatchWithVehicleHal() { + @RequiresFlagsEnabled({}) + public void testMatchWithVehicleHal() {{ assertWithMessage("Java constant") .that(mJavaConstantValue) .isEqualTo(mHalConstantValue); - } -} -""") + }} +}} +""".format(self.flagName)) self.outputMsgCtsTest = [] self.outputMsgCtsTest.append(LICENSE) self.outputMsgCtsTest.append(""" package android.car.cts; +import static android.car.feature.Flags.{1}; + import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import android.car.cts.utils.VehiclePropertyUtils; import android.car.hardware.property.{0}; +import android.platform.test.annotations.RequiresFlagsEnabled; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; +import org.junit.Rule; import org.junit.Test; import java.util.List; public class {0}Test {{ + @Rule + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); @Test - public void testToString() {{""".format(self.fileName)) - for enum in self.enums: + @RequiresFlagsEnabled({1}) + public void testToString() {{""".format(self.fileName, self.flagName)) + for enum in self.enumNames: self.outputMsgCtsTest.append(""" assertThat({0}.toString( {0}.{1})) .isEqualTo("{1}");""".format(self.fileName, enum)) + max_enum_value = len(self.enums) self.outputMsgCtsTest.append(""" assertThat({0}.toString({1})).isEqualTo("{2}"); assertThat({0}.toString(12)).isEqualTo("0xc"); }} @Test + @RequiresFlagsEnabled({4}) public void testAll{0}sAreMappedInToString() {{ List {3}s = VehiclePropertyUtils.getIntegersFromDataEnums({0}.class); @@ -194,11 +256,11 @@ public class {0}Test {{ }} }} }} -""".format(self.fileName, len(self.enums), hex(len(self.enums)), self.lowerFileName)) +""".format(self.fileName, len(self.enums), hex(len(self.enums)), self.lowerFileName, self.flagName)) def main(): - if len(sys.argv) != 2: - print("Usage: {} enum_aidl_file".format(sys.argv[0])) + if len(sys.argv) != 3: + print("Usage: {} enum_aidl_file ALL_CAPS_FLAG_NAME".format(sys.argv[0])) sys.exit(1) print("WARNING: This file only generates the base enum values in the framework layer. The " + "generated files must be reviewed by you and edited if any additional changes are " @@ -207,12 +269,14 @@ def main(): + "the new property is system API") file_path = sys.argv[1] file_name = file_path.split('/')[-1][:-5] - parser = EnumParser(file_path, file_name) + flag_name = sys.argv[2] + parser = EnumParser(file_path, file_name, flag_name) android_top = os.environ['ANDROID_BUILD_TOP'] if not android_top: print('ANDROID_BUILD_TOP is not in environmental variable, please run source and lunch ' + 'at the android root') + sys.exit(1) with open(android_top + "/packages/services/Car/car-lib/src/android/car/hardware/property/" + file_name + ".java", 'w') as f: diff --git a/automotive/vehicle/vhal_static_cpp_lib.mk b/automotive/vehicle/vhal_static_cpp_lib.mk index 9371453b37b52ffad1db5aa2d7391978a7a9303e..7ab34f495d3ce784b048f2bb3cebe6a2b3a220b8 100644 --- a/automotive/vehicle/vhal_static_cpp_lib.mk +++ b/automotive/vehicle/vhal_static_cpp_lib.mk @@ -16,5 +16,5 @@ # interface and VHAL properties. LOCAL_STATIC_LIBRARIES += \ - android.hardware.automotive.vehicle-V3-ndk \ + android.hardware.automotive.vehicle-V4-ndk \ android.hardware.automotive.vehicle.property-V4-ndk diff --git a/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp b/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp index fb3c8cddd24595fe72ef1122e761c28fe93f2791..02a9830af490bfaf2ff1125ee3c5cdfb37e80b97 100644 --- a/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp +++ b/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp @@ -1376,6 +1376,84 @@ TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyLowSpeedAutomaticEmergencyBrakin VehiclePropertyGroup::SYSTEM, VehicleArea::GLOBAL, VehiclePropertyType::INT32); } +TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyInfoModelTrimConfig) { + verifyProperty(VehicleProperty::INFO_MODEL_TRIM, VehiclePropertyAccess::READ, + VehiclePropertyChangeMode::STATIC, VehiclePropertyGroup::SYSTEM, + VehicleArea::GLOBAL, VehiclePropertyType::STRING); +} + +TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyInfoVehicleSizeClassConfig) { + verifyProperty(VehicleProperty::INFO_VEHICLE_SIZE_CLASS, VehiclePropertyAccess::READ, + VehiclePropertyChangeMode::STATIC, VehiclePropertyGroup::SYSTEM, + VehicleArea::GLOBAL, VehiclePropertyType::INT32_VEC); +} + +TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyTurnSignalLightStateConfig) { + verifyProperty(VehicleProperty::TURN_SIGNAL_LIGHT_STATE, VehiclePropertyAccess::READ, + VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM, + VehicleArea::GLOBAL, VehiclePropertyType::INT32); +} + +TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyTurnSignalSwitchConfig) { + verifyProperty(VehicleProperty::TURN_SIGNAL_SWITCH, VehiclePropertyAccess::READ_WRITE, + VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM, + VehicleArea::GLOBAL, VehiclePropertyType::INT32); +} + +TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyInstantaneousFuelEconomyConfig) { + verifyProperty(VehicleProperty::INSTANTANEOUS_FUEL_ECONOMY, VehiclePropertyAccess::READ, + VehiclePropertyChangeMode::CONTINUOUS, VehiclePropertyGroup::SYSTEM, + VehicleArea::GLOBAL, VehiclePropertyType::FLOAT); +} + +TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyInstantaneousEvEfficiencyConfig) { + verifyProperty(VehicleProperty::INSTANTANEOUS_EV_EFFICIENCY, VehiclePropertyAccess::READ, + VehiclePropertyChangeMode::CONTINUOUS, VehiclePropertyGroup::SYSTEM, + VehicleArea::GLOBAL, VehiclePropertyType::FLOAT); +} + +TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyVehicleHornEngagedConfig) { + verifyProperty(VehicleProperty::VEHICLE_HORN_ENGAGED, VehiclePropertyAccess::READ_WRITE, + VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM, + VehicleArea::GLOBAL, VehiclePropertyType::BOOLEAN); +} + +TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyVehicleDrivingAutomationTargetLevelConfig) { + verifyProperty(VehicleProperty::VEHICLE_DRIVING_AUTOMATION_TARGET_LEVEL, + VehiclePropertyAccess::READ, VehiclePropertyChangeMode::ON_CHANGE, + VehiclePropertyGroup::SYSTEM, VehicleArea::GLOBAL, VehiclePropertyType::INT32); +} + +TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyAcceleratorPedalCompressionPercentageConfig) { + verifyProperty(VehicleProperty::ACCELERATOR_PEDAL_COMPRESSION_PERCENTAGE, + VehiclePropertyAccess::READ, VehiclePropertyChangeMode::CONTINUOUS, + VehiclePropertyGroup::SYSTEM, VehicleArea::GLOBAL, VehiclePropertyType::FLOAT); +} + +TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyBrakePedalCompressionPercentageConfig) { + verifyProperty(VehicleProperty::BRAKE_PEDAL_COMPRESSION_PERCENTAGE, VehiclePropertyAccess::READ, + VehiclePropertyChangeMode::CONTINUOUS, VehiclePropertyGroup::SYSTEM, + VehicleArea::GLOBAL, VehiclePropertyType::FLOAT); +} + +TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyBrakePadWearPercentageConfig) { + verifyProperty(VehicleProperty::BRAKE_PAD_WEAR_PERCENTAGE, VehiclePropertyAccess::READ, + VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM, + VehicleArea::WHEEL, VehiclePropertyType::FLOAT); +} + +TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyBrakeFluidLevelLowConfig) { + verifyProperty(VehicleProperty::BRAKE_FLUID_LEVEL_LOW, VehiclePropertyAccess::READ, + VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM, + VehicleArea::GLOBAL, VehiclePropertyType::BOOLEAN); +} + +TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyVehiclePassiveSuspensionHeightConfig) { + verifyProperty(VehicleProperty::VEHICLE_PASSIVE_SUSPENSION_HEIGHT, VehiclePropertyAccess::READ, + VehiclePropertyChangeMode::CONTINUOUS, VehiclePropertyGroup::SYSTEM, + VehicleArea::WHEEL, VehiclePropertyType::INT32); +} + bool VtsHalAutomotiveVehicleTargetTest::checkIsSupported(int32_t propertyId) { auto result = mVhalClient->getPropConfigs({propertyId}); return result.ok(); diff --git a/broadcastradio/aidl/Android.bp b/broadcastradio/aidl/Android.bp index 82ee9495ab11c8b4c4278ecd9016f7e9247e8c90..081bae359c8ea87a21d71d9accbd901a541b1067 100644 --- a/broadcastradio/aidl/Android.bp +++ b/broadcastradio/aidl/Android.bp @@ -51,12 +51,12 @@ aidl_interface { }, ], - frozen: true, + frozen: false, } // Note: This should always be one version ahead of the last frozen version -latest_android_hardware_broadcastradio = "android.hardware.broadcastradio-V2" +latest_android_hardware_broadcastradio = "android.hardware.broadcastradio-V3" cc_defaults { name: "latest_android_hardware_broadcastradio_ndk_static", diff --git a/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/Alert.aidl b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/Alert.aidl new file mode 100644 index 0000000000000000000000000000000000000000..7e02f703b39662bf034dda5bb6289df933dfcbec --- /dev/null +++ b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/Alert.aidl @@ -0,0 +1,40 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.broadcastradio; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable Alert { + android.hardware.broadcastradio.AlertStatus status; + android.hardware.broadcastradio.AlertMessageType messageType; + android.hardware.broadcastradio.AlertInfo[] infoArray; +} diff --git a/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertArea.aidl b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertArea.aidl new file mode 100644 index 0000000000000000000000000000000000000000..aa828d03c1823867864cb7c07a593c2829fc043f --- /dev/null +++ b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertArea.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.broadcastradio; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable AlertArea { + android.hardware.broadcastradio.Polygon[] polygons; + android.hardware.broadcastradio.Geocode[] geocodes; +} diff --git a/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertCategory.aidl b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertCategory.aidl new file mode 100644 index 0000000000000000000000000000000000000000..f493e7588e05e114d190c94bb32a08ca97128250 --- /dev/null +++ b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertCategory.aidl @@ -0,0 +1,49 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.broadcastradio; +@Backing(type="int") @JavaDerive(equals=true, toString=true) @VintfStability +enum AlertCategory { + GEO, + MET, + SAFETY, + SECURITY, + RESCUE, + FIRE, + HEALTH, + ENV, + TRANSPORT, + INFRA, + CBRNE, + OTHER, +} diff --git a/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertCertainty.aidl b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertCertainty.aidl new file mode 100644 index 0000000000000000000000000000000000000000..dcf283a3add0f5e18cdb2e92b563df3880905c68 --- /dev/null +++ b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertCertainty.aidl @@ -0,0 +1,42 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.broadcastradio; +@Backing(type="int") @JavaDerive(equals=true, toString=true) @VintfStability +enum AlertCertainty { + OBSERVED, + LIKELY, + POSSIBLE, + UNLIKELY, + UNKNOWN, +} diff --git a/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertInfo.aidl b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..da08c9aa14740b1f5c1cc3d887974bdc7c8ad9d6 --- /dev/null +++ b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertInfo.aidl @@ -0,0 +1,44 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.broadcastradio; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable AlertInfo { + android.hardware.broadcastradio.AlertCategory[] categoryArray; + android.hardware.broadcastradio.AlertUrgency urgency; + android.hardware.broadcastradio.AlertSeverity severity; + android.hardware.broadcastradio.AlertCertainty certainty; + String description; + android.hardware.broadcastradio.AlertArea[] areas; + @nullable String language; +} diff --git a/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertMessageType.aidl b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertMessageType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..2b89c92f2e0fa4d24c967de1e58a7fa8335e4de9 --- /dev/null +++ b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertMessageType.aidl @@ -0,0 +1,40 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.broadcastradio; +@Backing(type="int") @JavaDerive(equals=true, toString=true) @VintfStability +enum AlertMessageType { + ALERT, + UPDATE, + CANCEL, +} diff --git a/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertSeverity.aidl b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertSeverity.aidl new file mode 100644 index 0000000000000000000000000000000000000000..5c91abd55b54f01cdde9c794cf3d8f9ae6498cf3 --- /dev/null +++ b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertSeverity.aidl @@ -0,0 +1,42 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.broadcastradio; +@Backing(type="int") @JavaDerive(equals=true, toString=true) @VintfStability +enum AlertSeverity { + EXTREME, + SEVERE, + MODERATE, + MINOR, + UNKNOWN, +} diff --git a/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertStatus.aidl b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertStatus.aidl new file mode 100644 index 0000000000000000000000000000000000000000..8ce69b5a2ee152795f7b49742175f935b59d170f --- /dev/null +++ b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertStatus.aidl @@ -0,0 +1,40 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.broadcastradio; +@Backing(type="int") @JavaDerive(equals=true, toString=true) @VintfStability +enum AlertStatus { + ACTUAL, + EXERCISE, + TEST, +} diff --git a/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertUrgency.aidl b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertUrgency.aidl new file mode 100644 index 0000000000000000000000000000000000000000..fd0491d2b6686a19be6ecdbd28bd6d8c0bab8df8 --- /dev/null +++ b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertUrgency.aidl @@ -0,0 +1,42 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.broadcastradio; +@Backing(type="int") @JavaDerive(equals=true, toString=true) @VintfStability +enum AlertUrgency { + IMMEDIATE, + EXPECTED, + FUTURE, + PAST, + UNKNOWN, +} diff --git a/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/Coordinate.aidl b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/Coordinate.aidl new file mode 100644 index 0000000000000000000000000000000000000000..b303986b23e34cdcdbe12d05ccd7b44a3ad84fa4 --- /dev/null +++ b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/Coordinate.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.broadcastradio; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable Coordinate { + double latitude; + double longitude; +} diff --git a/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/Geocode.aidl b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/Geocode.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a07e1c0be979721ff0a4506ca9c70091dbd57467 --- /dev/null +++ b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/Geocode.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.broadcastradio; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable Geocode { + String valueName; + String value; +} diff --git a/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/Polygon.aidl b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/Polygon.aidl new file mode 100644 index 0000000000000000000000000000000000000000..4d4d78da38b59ab1b1b27c5b183c2169cdff2c04 --- /dev/null +++ b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/Polygon.aidl @@ -0,0 +1,38 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.broadcastradio; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable Polygon { + android.hardware.broadcastradio.Coordinate[] coordinates; +} diff --git a/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/ProgramInfo.aidl b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/ProgramInfo.aidl index 997cdd7dd0ddf63b49840d84184277d24a9a35b9..dd579019c89a985a8cfef053e3ab42478739a7aa 100644 --- a/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/ProgramInfo.aidl +++ b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/ProgramInfo.aidl @@ -42,6 +42,7 @@ parcelable ProgramInfo { int signalQuality; android.hardware.broadcastradio.Metadata[] metadata; android.hardware.broadcastradio.VendorKeyValue[] vendorInfo; + @nullable android.hardware.broadcastradio.Alert emergencyAlert; const int FLAG_LIVE = (1 << 0) /* 1 */; const int FLAG_MUTED = (1 << 1) /* 2 */; const int FLAG_TRAFFIC_PROGRAM = (1 << 2) /* 4 */; diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/Alert.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/Alert.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a307ccc0c0cf5a818445a7acba6c140a60581077 --- /dev/null +++ b/broadcastradio/aidl/android/hardware/broadcastradio/Alert.aidl @@ -0,0 +1,46 @@ +/* + * 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. + */ + +package android.hardware.broadcastradio; + +import android.hardware.broadcastradio.AlertInfo; +import android.hardware.broadcastradio.AlertMessageType; +import android.hardware.broadcastradio.AlertStatus; + +/** + * Emergency Alert Message. + * + *

Alert message can be sent from a radio station of technologies such as HD radio to + * the radio users for some emergency events (see ITU-T X.1303 bis for more info). + */ +@VintfStability +@JavaDerive(equals=true, toString=true) +parcelable Alert { + /** + * The status of the alert message. + */ + AlertStatus status; + + /** + * The message type of the alert message. + */ + AlertMessageType messageType; + + /** + * Array of alert information. + */ + AlertInfo[] infoArray; +} diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/AlertArea.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/AlertArea.aidl new file mode 100644 index 0000000000000000000000000000000000000000..b3f07b372f38be8e339a691803176c0a2876f5f1 --- /dev/null +++ b/broadcastradio/aidl/android/hardware/broadcastradio/AlertArea.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ + +package android.hardware.broadcastradio; + +import android.hardware.broadcastradio.Geocode; +import android.hardware.broadcastradio.Polygon; + +/** + * The geographic area that delineates the affected area of the alert message + * + *

(see ITU-T X.1303 bis for more info). + */ +@VintfStability +@JavaDerive(equals=true, toString=true) +parcelable AlertArea { + /** + * Polygons that delineate the affected area of the alert message. + */ + Polygon[] polygons; + + /** + * Geographic code delineating the affected area of the alert message. + */ + Geocode[] geocodes; +} diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/AlertCategory.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/AlertCategory.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a24361a650277fbcceed670f9b1442b62c980b80 --- /dev/null +++ b/broadcastradio/aidl/android/hardware/broadcastradio/AlertCategory.aidl @@ -0,0 +1,88 @@ +/* + * 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. + */ + +package android.hardware.broadcastradio; + +/** + * The category of the subject event of the emergency alert message. + * + *

(see ITU-T X.1303 bis for more info). + */ +@VintfStability +@Backing(type="int") +@JavaDerive(equals=true, toString=true) +enum AlertCategory { + /** + * Alert category related to geophysical (inc. landslide). + */ + GEO, + + /** + * Alert category related to meteorological (inc. flood). + */ + MET, + + /** + * Alert category related to general emergency and public safety. + */ + SAFETY, + + /** + * Alert category related to law enforcement, military, homeland and local/private security. + */ + SECURITY, + + /** + * Alert category related to rescue and recovery. + */ + RESCUE, + + /** + * Alert category related to fire suppression and rescue. + */ + FIRE, + + /** + * Alert category related to medical and public health. + */ + HEALTH, + + /** + * Alert category related to pollution and other environmental. + */ + ENV, + + /** + * Alert category related to public and private transportation. + */ + TRANSPORT, + + /** + * Utility, telecommunication, other non-transport infrastructure. + */ + INFRA, + + /** + * Alert category related to chemical, biological, radiological, nuclear or high-yield + * explosive threat or attack. + */ + CBRNE, + + /** + * Alert category related to other events. + */ + OTHER, +} diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/AlertCertainty.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/AlertCertainty.aidl new file mode 100644 index 0000000000000000000000000000000000000000..11f069e19ff92da16171658bd3c939779fa3ba68 --- /dev/null +++ b/broadcastradio/aidl/android/hardware/broadcastradio/AlertCertainty.aidl @@ -0,0 +1,52 @@ +/* + * 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. + */ + +package android.hardware.broadcastradio; + +/** + * The certainty of the subject event of the emergency alert message + * + *

(see ITU-T X.1303 bis for more info). + */ +@VintfStability +@Backing(type="int") +@JavaDerive(equals=true, toString=true) +enum AlertCertainty { + /** + * Certainty indicating that the event is determined to have occurred or to be ongoing. + */ + OBSERVED, + + /** + * Certainty indicating that the event is likely (probability > ~50%). + */ + LIKELY, + + /** + * Certainty indicating that the event is possible but not likely (probability <= ~50%). + */ + POSSIBLE, + + /** + * Certainty indicating that the event is not expected to occur (probability ~ 0). + */ + UNLIKELY, + + /** + * Unknown certainty. + */ + UNKNOWN, +} diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/AlertInfo.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/AlertInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ab2e6f7a9fa528676df110dddc1c849f6b76fa3d --- /dev/null +++ b/broadcastradio/aidl/android/hardware/broadcastradio/AlertInfo.aidl @@ -0,0 +1,77 @@ +/* + * 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. + */ + +package android.hardware.broadcastradio; + +import android.hardware.broadcastradio.AlertArea; +import android.hardware.broadcastradio.AlertCategory; +import android.hardware.broadcastradio.AlertCertainty; +import android.hardware.broadcastradio.AlertSeverity; +import android.hardware.broadcastradio.AlertUrgency; + +/** + * Alert information. + * + *

(see ITU-T X.1303 bis for more info). + */ +@VintfStability +@JavaDerive(equals=true, toString=true) +parcelable AlertInfo { + /** + * Array of categories of the subject event of the alert info. + * + *

According to ITU-T X.1303, a single alert info block may contains multiple categories. + */ + AlertCategory[] categoryArray; + + /** + * The urgency of the subject event of the alert info. + * + *

Urgency represents the time available to prepare for the alert. + */ + AlertUrgency urgency; + + /** + * The severity of the subject event of the alert info. + * + *

Severity represents the intensity of impact. + */ + AlertSeverity severity; + + /** + * The certainty of the subject event of the alert info. + * + *

Certainty represents confidence in the observation or prediction. + */ + AlertCertainty certainty; + + /** + * Textual descriptions of the subject event. + */ + String description; + + /** + * The array of geographic areas to which the alert info segment in which it appears applies. + */ + AlertArea[] areas; + + /** + * The IETF RFC 3066 language code donating the language of the alert message. + * + *

This field is optional. + */ + @nullable String language; +} diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/AlertMessageType.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/AlertMessageType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..1dd4e2bed265d91de25552e0738599c68706b4b8 --- /dev/null +++ b/broadcastradio/aidl/android/hardware/broadcastradio/AlertMessageType.aidl @@ -0,0 +1,43 @@ +/* + * 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. + */ + +package android.hardware.broadcastradio; + +/** + * The emergency alert message type + * + *

The message type indicates the emergency alert message nature. + * (see ITU-T X.1303 bis for more info). + */ +@VintfStability +@Backing(type="int") +@JavaDerive(equals=true, toString=true) +enum AlertMessageType { + /** + * Initial information requiring attention by targeted recipients. + */ + ALERT, + + /** + * Updates and supersedes the earlier message(s). + */ + UPDATE, + + /** + * Cancels the earlier message(s). + */ + CANCEL, +} diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/AlertSeverity.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/AlertSeverity.aidl new file mode 100644 index 0000000000000000000000000000000000000000..acc11c489feb77d87b47374a713b5f01677d5f9d --- /dev/null +++ b/broadcastradio/aidl/android/hardware/broadcastradio/AlertSeverity.aidl @@ -0,0 +1,52 @@ +/* + * 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. + */ + +package android.hardware.broadcastradio; + +/** + * The severity of the subject event of the emergency alert message + * + *

(see ITU-T X.1303 bis for more info). + */ +@VintfStability +@Backing(type="int") +@JavaDerive(equals=true, toString=true) +enum AlertSeverity { + /** + * Severity indicating extraordinary threat to life or property. + */ + EXTREME, + + /** + * Severity indicating significant threat to life or property. + */ + SEVERE, + + /** + * Severity indicating possible threat to life or property. + */ + MODERATE, + + /** + * Severity indicating minimal to no known threat to life or property. + */ + MINOR, + + /** + * Unknown severity. + */ + UNKNOWN, +} diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/AlertStatus.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/AlertStatus.aidl new file mode 100644 index 0000000000000000000000000000000000000000..8b0c9170d23ae8dd6f2af3412de79b2bb084cdc6 --- /dev/null +++ b/broadcastradio/aidl/android/hardware/broadcastradio/AlertStatus.aidl @@ -0,0 +1,42 @@ +/* + * 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. + */ + +package android.hardware.broadcastradio; + +/** + * The status of the alert message + * + *

Status is the appropriate handling of the alert message (see ITU-T X.1303 bis for more info). + */ +@VintfStability +@Backing(type="int") +@JavaDerive(equals=true, toString=true) +enum AlertStatus { + /** + * Actionable by all targeted recipients. + */ + ACTUAL, + + /** + * Actionable only by designated exercise participants. + */ + EXERCISE, + + /** + * Technical testing only, all recipients disregard. + */ + TEST, +} diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/AlertUrgency.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/AlertUrgency.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c7bfdbcef88d9b46dc5e1141ec8c7dd12db89dda --- /dev/null +++ b/broadcastradio/aidl/android/hardware/broadcastradio/AlertUrgency.aidl @@ -0,0 +1,52 @@ +/* + * 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. + */ + +package android.hardware.broadcastradio; + +/** + * The severity of the subject event of the emergency alert message. + * + *

(see ITU-T X.1303 bis for more info). + */ +@VintfStability +@Backing(type="int") +@JavaDerive(equals=true, toString=true) +enum AlertUrgency { + /** + * Urgency indicating that responsive action should be taken immediately. + */ + IMMEDIATE, + + /** + * Urgency indicating that responsive action should be taken soon. + */ + EXPECTED, + + /** + * Urgency indicating that responsive action should be taken in the near future. + */ + FUTURE, + + /** + * Urgency indicating that responsive action is no longer required. + */ + PAST, + + /** + * Unknown urgency. + */ + UNKNOWN, +} diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/Coordinate.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/Coordinate.aidl new file mode 100644 index 0000000000000000000000000000000000000000..9c9680b6c7488358402958a4ba861d655ef67371 --- /dev/null +++ b/broadcastradio/aidl/android/hardware/broadcastradio/Coordinate.aidl @@ -0,0 +1,40 @@ +/* + * 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. + */ + +package android.hardware.broadcastradio; + +/** + * Coordinate reprensenting the geographic location in alert message + * + *

(see ITU-T X.1303 bis for more info). + */ +@VintfStability +@JavaDerive(equals=true, toString=true) +parcelable Coordinate { + /** + * Latitude of the cooridinate. + * + *

Latitude is in the range of -90 to 90. + */ + double latitude; + + /** + * Longitude of the cooridinate. + * + *

Longitude is in the range of -180 to 180. + */ + double longitude; +} diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/Geocode.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/Geocode.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ca9815485cfb187b0d1568c53e13dd94e45c99f4 --- /dev/null +++ b/broadcastradio/aidl/android/hardware/broadcastradio/Geocode.aidl @@ -0,0 +1,40 @@ +/* + * 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. + */ + +package android.hardware.broadcastradio; + +/** + * Geographic code reprensenting location in alert message. + * + *

Geocode is mainly for information display instead of parsing on radio application side. See + * ITU-T X.1303 bis for more info. + */ +@VintfStability +@JavaDerive(equals=true, toString=true) +parcelable Geocode { + /** + * Value name of a geographic code. + * + *

Value name are acronyms should be represented in all capital + * letters without periods (e.g., SAME, FIPS, ZIP). + */ + String valueName; + + /** + * Value of a geographic code. + */ + String value; +} diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/Polygon.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/Polygon.aidl new file mode 100644 index 0000000000000000000000000000000000000000..12bd2cd82b1488e44f1cd9fe9f88170286a3ca64 --- /dev/null +++ b/broadcastradio/aidl/android/hardware/broadcastradio/Polygon.aidl @@ -0,0 +1,36 @@ +/* + * 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. + */ + +package android.hardware.broadcastradio; + +import android.hardware.broadcastradio.Coordinate; + +/** + * The array of coordinates defining a polygon + * + *

(see ITU-T X.1303 bis for more info). + */ +@VintfStability +@JavaDerive(equals=true, toString=true) +parcelable Polygon { + /** + * Cooridinates of points defining a polygon. + * + *

A minimum of 4 coordinates MUST be present and the first and last + * coordinates must be the same. See WGS 84 for more information. + */ + Coordinate[] coordinates; +} diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/ProgramInfo.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/ProgramInfo.aidl index d4ccd01bc3ca4dc13400b968dee4f2f8de8044fe..0b5abe2ce76d1f79005aa5e543f203646b750c17 100644 --- a/broadcastradio/aidl/android/hardware/broadcastradio/ProgramInfo.aidl +++ b/broadcastradio/aidl/android/hardware/broadcastradio/ProgramInfo.aidl @@ -16,6 +16,7 @@ package android.hardware.broadcastradio; +import android.hardware.broadcastradio.Alert; import android.hardware.broadcastradio.Metadata; import android.hardware.broadcastradio.ProgramIdentifier; import android.hardware.broadcastradio.ProgramSelector; @@ -192,4 +193,12 @@ parcelable ProgramInfo { * for example: paid-service=true; bitrate=320kbps. */ VendorKeyValue[] vendorInfo; + + /** + * Emergency alert message. + * + *

Alert message can be sent from a radio station of technologies such as HD radio to + * the radio users for some emergency events. + */ + @nullable Alert emergencyAlert; } diff --git a/broadcastradio/aidl/default/BroadcastRadio.cpp b/broadcastradio/aidl/default/BroadcastRadio.cpp index 4d6d81dc1d4582a1d34e215951c0656bfa9683a5..015cae02c73611953f98db2c61e03888903150cf 100644 --- a/broadcastradio/aidl/default/BroadcastRadio.cpp +++ b/broadcastradio/aidl/default/BroadcastRadio.cpp @@ -17,11 +17,9 @@ #include "BroadcastRadio.h" #include #include +#include #include "resources.h" -#include -#include - #include #include @@ -47,6 +45,8 @@ inline constexpr std::chrono::milliseconds kStepDelayTimeMs = 100ms; inline constexpr std::chrono::milliseconds kTuneDelayTimeMs = 150ms; inline constexpr std::chrono::seconds kListDelayTimeS = 1s; +const string kAlertAreaDelimiter = "+"; +const string kAlertCoordinateGeocodeDelimiter = ","; // clang-format off const AmFmBandRange kFmFullBandRange = {65000, 108000, 10, 0}; const AmFmBandRange kAmFullBandRange = {150, 30000, 1, 0}; @@ -142,6 +142,30 @@ ProgramInfo makeSampleProgramInfo(const ProgramSelector& selector) { return info; } +static Alert createSampleAlert() { + Polygon polygon = {{{-38.47, -120.14}, + {38.34, -119.95}, + {38.52, -119.74}, + {38.62, -119.89}, + {-38.47, -120.14}}}; + AlertArea alertArea1 = {{polygon}, {{"SAME", "006109"}, {"SAME", "006209"}}}; + AlertArea alertArea2 = {{}, {{"SAME", "006009"}}}; + AlertInfo alertInfo; + alertInfo.categoryArray = {AlertCategory::GEO, AlertCategory::TRANSPORT}; + alertInfo.urgency = AlertUrgency::FUTURE; + alertInfo.severity = AlertSeverity::SEVERE; + alertInfo.certainty = AlertCertainty::POSSIBLE; + alertInfo.description = "Sample radio alert."; + alertInfo.language = "en-US"; + alertInfo.areas.push_back(alertArea1); + alertInfo.areas.push_back(alertArea2); + Alert alert; + alert.status = AlertStatus::ACTUAL; + alert.messageType = AlertMessageType::ALERT; + alert.infoArray.push_back(alertInfo); + return alert; +} + static bool checkDumpCallerHasWritePermissions(int fd) { uid_t uid = AIBinder_getCallingUid(); if (uid == AID_ROOT || uid == AID_SHELL || uid == AID_SYSTEM) { @@ -151,6 +175,87 @@ static bool checkDumpCallerHasWritePermissions(int fd) { return false; } +static bool parseGeocode(int fd, const string& geocodeString, Geocode& parsedGeocode) { + vector geocodeStringPair = + ::android::base::Split(geocodeString, kAlertCoordinateGeocodeDelimiter); + if (geocodeStringPair.size() != 2) { + dprintf(fd, "Geocode is not of \"VALUE_NAME,VALUE\" format: %s\n", geocodeString.c_str()); + return false; + } + parsedGeocode.valueName = geocodeStringPair[0]; + parsedGeocode.value = geocodeStringPair[1]; + return true; +} + +static bool parsePolygon(int fd, const string& polygonString, Polygon& parsedPolygon) { + vector coordinates; + vector coordinateStrings = + ::android::base::Split(polygonString, kAlertCoordinateGeocodeDelimiter); + if (coordinateStrings.size() % 2) { + dprintf(fd, "Incomplete \"LATITUDE,LONGITUDE\" coordinate pairs separated by \",\": %s\n", + polygonString.c_str()); + return false; + } + for (size_t i = 0; i < coordinateStrings.size(); i += 2) { + double latitude; + double longitude; + if (!utils::parseArgDouble(coordinateStrings[i], &latitude) || + !utils::parseArgDouble(coordinateStrings[i + 1], &longitude)) { + dprintf(fd, "Value of \"LATITUDE,LONGITUDE\" coordinate pair is not double-type: %s\n", + coordinateStrings[i].c_str()); + return false; + } + coordinates.push_back(Coordinate(latitude, longitude)); + } + parsedPolygon.coordinates = coordinates; + return true; +} + +static bool parseAreaString(int fd, const string& areaString, AlertArea& parsedAlertArea) { + vector areaEntryStrings = ::android::base::Split(areaString, "_"); + for (const auto& areaEntryString : areaEntryStrings) { + vector areaTypeValuePair = ::android::base::Split(areaEntryString, ":"); + if (areaTypeValuePair.size() != 2) { + dprintf(fd, "Area is not of \":\" format: %s\n", areaEntryString.c_str()); + return false; + } + if (EqualsIgnoreCase(areaTypeValuePair[0], "polygon")) { + Polygon parsedPolygon; + if (!parsePolygon(fd, areaTypeValuePair[1], parsedPolygon)) { + return false; + } + parsedAlertArea.polygons.push_back(parsedPolygon); + } else if (EqualsIgnoreCase(areaTypeValuePair[0], "geocode")) { + Geocode parsedGeocode; + if (!parseGeocode(fd, areaTypeValuePair[1], parsedGeocode)) { + return false; + } + parsedAlertArea.geocodes.push_back(parsedGeocode); + } else { + dprintf(fd, "Invalid area other than \"polygon\" and \"geocode\": %s\n", + areaTypeValuePair[0].c_str()); + return false; + } + } + return true; +} + +static bool parseAreaListString(int fd, const string& areaListString, + vector& parsedAlertAreas) { + if (EqualsIgnoreCase(areaListString, kAlertAreaDelimiter)) { + return true; + } + vector areaStrings = ::android::base::Split(areaListString, kAlertAreaDelimiter); + for (const auto& areaString : areaStrings) { + AlertArea parsedArea; + if (!parseAreaString(fd, areaString, parsedArea)) { + return false; + } + parsedAlertAreas.push_back(parsedArea); + } + return true; +} + } // namespace BroadcastRadio::BroadcastRadio(const VirtualRadio& virtualRadio) @@ -162,9 +267,9 @@ BroadcastRadio::BroadcastRadio(const VirtualRadio& virtualRadio) ProgramSelector sel = utils::makeSelectorAmfm(ranges[0].lowerBound); VirtualProgram virtualProgram = {}; if (mVirtualRadio.getProgram(sel, &virtualProgram)) { - mCurrentProgram = virtualProgram.selector; + mCurrentProgramSelector = virtualProgram.selector; } else { - mCurrentProgram = sel; + mCurrentProgramSelector = sel; } adjustAmFmRangeLocked(); } @@ -230,13 +335,13 @@ ProgramInfo BroadcastRadio::tuneInternalLocked(const ProgramSelector& sel) { isDigitalProgramAllowed(sel, isConfigFlagSetLocked(ConfigFlag::FORCE_ANALOG_FM), isConfigFlagSetLocked(ConfigFlag::FORCE_ANALOG_AM)); if (isProgramAllowed && mVirtualRadio.getProgram(sel, &virtualProgram)) { - mCurrentProgram = virtualProgram.selector; + mCurrentProgramSelector = virtualProgram.selector; programInfo = virtualProgram; } else { if (!isProgramAllowed) { - mCurrentProgram = utils::makeSelectorAmfm(utils::getAmFmFrequency(sel)); + mCurrentProgramSelector = utils::makeSelectorAmfm(utils::getAmFmFrequency(sel)); } else { - mCurrentProgram = sel; + mCurrentProgramSelector = sel; } programInfo = makeSampleProgramInfo(sel); } @@ -277,6 +382,10 @@ ScopedAStatus BroadcastRadio::unsetTunerCallback() { void BroadcastRadio::handleProgramInfoUpdateRadioCallback( ProgramInfo programInfo, const std::shared_ptr& callback) { callback->onCurrentProgramInfoChanged(programInfo); + { + lock_guard lk(mMutex); + mCurrentProgramInfo = programInfo; + } if (programInfo.selector.primaryId.type != IdentifierType::HD_STATION_ID_EXT) { return; } @@ -285,12 +394,14 @@ void BroadcastRadio::handleProgramInfoUpdateRadioCallback( programInfo.infoFlags |= ProgramInfo::FLAG_HD_SIS_ACQUISITION; auto sisAcquiredTask = [this, callback, programInfo, cancelTask]() { callback->onCurrentProgramInfoChanged(programInfo); + mCurrentProgramInfo = programInfo; auto audioAcquiredTask = [this, callback, programInfo]() { ProgramInfo hdProgramInfoWithAudio = programInfo; hdProgramInfoWithAudio.infoFlags |= ProgramInfo::FLAG_HD_AUDIO_ACQUISITION; callback->onCurrentProgramInfoChanged(hdProgramInfoWithAudio); lock_guard lk(mMutex); mIsTuneCompleted = true; + mCurrentProgramInfo = hdProgramInfoWithAudio; }; lock_guard lk(mMutex); mTuningThread->schedule(audioAcquiredTask, cancelTask, kTuneDelayTimeMs); @@ -481,7 +592,8 @@ ScopedAStatus BroadcastRadio::seek(bool directionUp, bool skipSubChannel) { auto cancelTask = [callback]() { callback->onTuneFailed(Result::CANCELED, {}); }; VirtualProgram nextProgram = {}; - bool foundNext = findNextLocked(mCurrentProgram, directionUp, skipSubChannel, &nextProgram); + bool foundNext = + findNextLocked(mCurrentProgramSelector, directionUp, skipSubChannel, &nextProgram); mIsTuneCompleted = false; if (!foundNext) { auto task = [callback]() { @@ -520,10 +632,10 @@ ScopedAStatus BroadcastRadio::step(bool directionUp) { cancelLocked(); int64_t stepTo; - if (utils::hasId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY_KHZ)) { - stepTo = utils::getId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY_KHZ); - } else if (mCurrentProgram.primaryId.type == IdentifierType::HD_STATION_ID_EXT) { - stepTo = utils::getHdFrequency(mCurrentProgram); + if (utils::hasId(mCurrentProgramSelector, IdentifierType::AMFM_FREQUENCY_KHZ)) { + stepTo = utils::getId(mCurrentProgramSelector, IdentifierType::AMFM_FREQUENCY_KHZ); + } else if (mCurrentProgramSelector.primaryId.type == IdentifierType::HD_STATION_ID_EXT) { + stepTo = utils::getHdFrequency(mCurrentProgramSelector); } else { LOG(WARNING) << __func__ << ": can't step in anything else than AM/FM"; return ScopedAStatus::fromServiceSpecificErrorWithMessage( @@ -568,7 +680,7 @@ void BroadcastRadio::cancelLocked() { LOG(DEBUG) << __func__ << ": cancelling current tuning operations..."; mTuningThread->cancelAll(); - if (mCurrentProgram.primaryId.type != IdentifierType::INVALID) { + if (mCurrentProgramSelector.primaryId.type != IdentifierType::INVALID) { mIsTuneCompleted = true; } } @@ -692,13 +804,13 @@ ScopedAStatus BroadcastRadio::getParameters([[maybe_unused]] const vector(utils::getAmFmFrequency(mCurrentProgram)); + int32_t freq = static_cast(utils::getAmFmFrequency(mCurrentProgramSelector)); for (const auto& range : mAmFmConfig.ranges) { if (range.lowerBound <= freq && range.upperBound >= freq) { bool isBandChanged = hasBandBefore ? *mCurrentAmFmBandRange != range : true; @@ -711,6 +823,24 @@ bool BroadcastRadio::adjustAmFmRangeLocked() { return !hasBandBefore; } +void BroadcastRadio::updateCurrentProgramInfoWithAlert(std::optional& alert) { + std::shared_ptr callback; + ProgramInfo currentProgramInfo; + { + lock_guard lk(mMutex); + if (mCallback == nullptr) { + return; + } + if (mCurrentProgramInfo.selector.primaryId.type == IdentifierType::INVALID) { + return; + } + callback = mCallback; + currentProgramInfo = mCurrentProgramInfo; + } + currentProgramInfo.emergencyAlert = alert.value(); + callback->onCurrentProgramInfoChanged(currentProgramInfo); +} + ScopedAStatus BroadcastRadio::registerAnnouncementListener( [[maybe_unused]] const std::shared_ptr& listener, const vector& enabled, std::shared_ptr* returnCloseHandle) { @@ -745,6 +875,8 @@ binder_status_t BroadcastRadio::dump(int fd, const char** args, uint32_t numArgs return cmdStartProgramListUpdates(fd, args, numArgs); } else if (EqualsIgnoreCase(option, "--stopProgramListUpdates")) { return cmdStopProgramListUpdates(fd, numArgs); + } else if (EqualsIgnoreCase(option, "--simulateAlert")) { + return cmdSimulateAlert(fd, args, numArgs); } dprintf(fd, "Invalid option: %s\n", option.c_str()); return STATUS_BAD_VALUE; @@ -767,7 +899,7 @@ binder_status_t BroadcastRadio::dumpsys(int fd) { } else { dprintf(fd, "ITunerCallback registered\n"); } - dprintf(fd, "CurrentProgram: %s \n", mCurrentProgram.toString().c_str()); + dprintf(fd, "CurrentProgram: %s \n", mCurrentProgramSelector.toString().c_str()); return STATUS_OK; } @@ -798,13 +930,41 @@ binder_status_t BroadcastRadio::cmdHelp(int fd) const { "excludeModifications (string, should be either \"true\" or \"false\")\n"); dprintf(fd, "--stopProgramListUpdates: stop current pending program list updates\n"); dprintf(fd, - "Note on for --startProgramList command: it is int for identifier type. " + "\t: it is int for identifier type. " "Please see broadcastradio/aidl/android/hardware/broadcastradio/IdentifierType.aidl " "for its definition.\n"); dprintf(fd, - "Note on for --startProgramList command: it is long type for identifier value. " + "\t: it is long type for identifier value. " "Please see broadcastradio/aidl/android/hardware/broadcastradio/IdentifierType.aidl " "for its value.\n"); + dprintf(fd, + "--simulateAlert " + " : simulate emergency alert on current " + "program; if no arguments following \"--simulateAlert\", the default alert message" + "is applied.\n"); + dprintf(fd, "\t: string representation of alert scope.\n"); + dprintf(fd, "\t: string representation of alert message type.\n"); + dprintf(fd, + "\t: string representation of alert categories separated by " + "\",\".\n"); + dprintf(fd, "\t: string representation of alert urgency type.\n"); + dprintf(fd, "\t: string representation of alert severity type.\n"); + dprintf(fd, "\t: string representation of alert certainty type.\n"); + dprintf(fd, "\t: description of alert message within quotation mark(\"\").\n"); + dprintf(fd, "\t: language code of alert message, \"null\" if unspecified.\n"); + dprintf(fd, + "\t: :_:_...+:_:_... " + "which represents list of affected areas of the alert separated by \"|\". " + "If no area, this field should be: |\n" + "Each area may contains multiple entries separated by \";\" where " + " can be either \"polygon\" or \"geocode\". If is polygon, is a " + "series of coordinates of \"LATITUDE,LONGITUDE\" format separated by \",\"; if " + " is geocode, is of \"VALUE_NAME,VALUE\" format.\n"); + dprintf(fd, + "Example: --simulateAlert actual alert geo,transport future severe" + " possible \"alert message for testing\" en-US geocode:SAME,006109_geocode:SAME,006209" + "_polygon:-38.47,-120.14,38.34,-119.95,38.52,-119.74,38.62,-119.89,-38.47,-120.14" + "+geocode:SAME,006009\n"); return STATUS_OK; } @@ -1038,4 +1198,71 @@ binder_status_t BroadcastRadio::cmdStopProgramListUpdates(int fd, uint32_t numAr return STATUS_OK; } +binder_status_t BroadcastRadio::cmdSimulateAlert(int fd, const char** args, uint32_t numArgs) { + if (!checkDumpCallerHasWritePermissions(fd)) { + return STATUS_PERMISSION_DENIED; + } + std::optional alertOpt; + if (numArgs == 1) { + alertOpt.emplace(createSampleAlert()); + updateCurrentProgramInfoWithAlert(alertOpt); + return STATUS_OK; + } + if (numArgs != 10) { + dprintf(fd, + "Invalid number of arguments: please provide --simulateAlert " + " " + " , provided: %d\n", + numArgs); + return STATUS_BAD_VALUE; + } + Alert parsedAlert; + if (!utils::parseAlertStatus(args[1], parsedAlert.status)) { + dprintf(fd, "Unknown alert status type: %s\n", args[2]); + return STATUS_BAD_VALUE; + } + if (!utils::parseAlertMessageType(args[2], parsedAlert.messageType)) { + dprintf(fd, "Unknown alert message type: %s\n", args[3]); + return STATUS_BAD_VALUE; + } + AlertInfo parsedAlertInfo; + vector categoryStrings = ::android::base::Split(args[3], ","); + for (const auto& categoryString : categoryStrings) { + AlertCategory category; + if (!utils::parseAlertCategory(categoryString, category)) { + dprintf(fd, "Unknown alert category type: %s\n", args[3]); + return STATUS_BAD_VALUE; + } + parsedAlertInfo.categoryArray.push_back(category); + } + if (!utils::parseAlertUrgency(args[4], parsedAlertInfo.urgency)) { + dprintf(fd, "Unknown alert urgency type: %s\n", args[4]); + return STATUS_BAD_VALUE; + } + if (!utils::parseAlertSeverity(args[5], parsedAlertInfo.severity)) { + dprintf(fd, "Unknown alert severity type: %s\n", args[5]); + return STATUS_BAD_VALUE; + } + if (!utils::parseAlertCertainty(args[6], parsedAlertInfo.certainty)) { + dprintf(fd, "Unknown alert certainty type: %s\n", args[6]); + return STATUS_BAD_VALUE; + } + parsedAlertInfo.description = string(args[7]); + string languageStr = string(args[8]); + if (!EqualsIgnoreCase(languageStr, "null")) { + parsedAlertInfo.language.emplace(languageStr); + } + string areaListString = string(args[9]); + vector areaList; + if (!parseAreaListString(fd, areaListString, areaList)) { + return STATUS_BAD_VALUE; + } + parsedAlertInfo.areas = areaList; + parsedAlert.infoArray = {parsedAlertInfo}; + LOG(INFO) << "Simulate alert: " << parsedAlert.toString().c_str(); + alertOpt.emplace(parsedAlert); + updateCurrentProgramInfoWithAlert(alertOpt); + return STATUS_OK; +} + } // namespace aidl::android::hardware::broadcastradio diff --git a/broadcastradio/aidl/default/BroadcastRadio.h b/broadcastradio/aidl/default/BroadcastRadio.h index 60ea90743ae14d0f18ea815338cc5d3007e9d63e..a4cba3b412d168d47d8e992f0b0383dc07e9e9ab 100644 --- a/broadcastradio/aidl/default/BroadcastRadio.h +++ b/broadcastradio/aidl/default/BroadcastRadio.h @@ -78,7 +78,8 @@ class BroadcastRadio final : public BnBroadcastRadio { std::unique_ptr<::android::WorkerThread>(new ::android::WorkerThread()); bool mIsTuneCompleted GUARDED_BY(mMutex) = true; Properties mProperties GUARDED_BY(mMutex); - ProgramSelector mCurrentProgram GUARDED_BY(mMutex) = {}; + ProgramSelector mCurrentProgramSelector GUARDED_BY(mMutex) = {}; + ProgramInfo mCurrentProgramInfo GUARDED_BY(mMutex) = {}; std::vector mProgramList GUARDED_BY(mMutex) = {}; std::optional mCurrentAmFmBandRange GUARDED_BY(mMutex); std::shared_ptr mCallback GUARDED_BY(mMutex); @@ -99,6 +100,7 @@ class BroadcastRadio final : public BnBroadcastRadio { void jumpToFirstSubChannelLocked(std::vector::const_iterator& it) const REQUIRES(mMutex); bool isConfigFlagSetLocked(ConfigFlag flag) const REQUIRES(mMutex); + void updateCurrentProgramInfoWithAlert(std::optional& alert); binder_status_t cmdHelp(int fd) const; binder_status_t cmdTune(int fd, const char** args, uint32_t numArgs); @@ -107,6 +109,7 @@ class BroadcastRadio final : public BnBroadcastRadio { binder_status_t cmdCancel(int fd, uint32_t numArgs); binder_status_t cmdStartProgramListUpdates(int fd, const char** args, uint32_t numArgs); binder_status_t cmdStopProgramListUpdates(int fd, uint32_t numArgs); + binder_status_t cmdSimulateAlert(int fd, const char** args, uint32_t numArgs); binder_status_t dumpsys(int fd) EXCLUDES(mMutex); }; diff --git a/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp b/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp index 4627ec97aaa3638f96922b0c9f0dcc4709b95720..508d8f1d121209587367235b8a06d18682f2f0ed 100644 --- a/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp +++ b/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp @@ -16,6 +16,7 @@ #define EGMOCK_VERBOSE 1 +#include #include #include #include @@ -76,12 +77,13 @@ const ConfigFlag kConfigFlagValues[] = { constexpr int32_t kAidlVersion1 = 1; constexpr int32_t kAidlVersion2 = 2; +constexpr int32_t kAidlVersion3 = 3; bool isValidAmFmFreq(int64_t freq, int aidlVersion) { ProgramIdentifier id = bcutils::makeIdentifier(IdentifierType::AMFM_FREQUENCY_KHZ, freq); if (aidlVersion == kAidlVersion1) { return bcutils::isValid(id); - } else if (aidlVersion == kAidlVersion2) { + } else if (aidlVersion >= kAidlVersion2) { return bcutils::isValidV2(id); } LOG(ERROR) << "Unknown AIDL version " << aidlVersion; @@ -105,6 +107,41 @@ bool supportsFM(const AmFmRegionConfig& config) { return false; } +void validateMetadata(const ProgramInfo& info, int32_t aidlVersion) { + for (const auto& metadataItem : info.metadata) { + bool validMetadata = false; + if (aidlVersion == kAidlVersion1) { + validMetadata = bcutils::isValidMetadata(metadataItem); + } else { + validMetadata = bcutils::isValidMetadataV2(metadataItem); + } + EXPECT_TRUE(validMetadata) << "Invalid metadata " << metadataItem.toString().c_str(); + } +} + +void validateAlert(const ProgramInfo& info, int32_t aidlVersion) { + if (aidlVersion < kAidlVersion3 || !info.emergencyAlert.has_value()) { + return; + } + Alert alert = info.emergencyAlert.value(); + ASSERT_FALSE(alert.infoArray.empty()); + for (const auto& alertInfo : alert.infoArray) { + ASSERT_FALSE(alertInfo.categoryArray.empty()); + if (alertInfo.areas.empty()) { + continue; + } + for (const auto& area : alertInfo.areas) { + if (area.polygons.empty()) { + continue; + } + for (const auto& polygon : area.polygons) { + ASSERT_GE(polygon.coordinates.size(), 4); + EXPECT_EQ(polygon.coordinates.front(), polygon.coordinates.back()); + } + } + } +} + } // namespace class CallbackFlag final { @@ -250,15 +287,9 @@ ScopedAStatus TunerCallbackImpl::onCurrentProgramInfoChanged(const ProgramInfo& } } - for (const auto& metadataItem : info.metadata) { - bool validMetadata = false; - if (mCallbackAidlVersion == kAidlVersion1) { - validMetadata = bcutils::isValidMetadata(metadataItem); - } else { - validMetadata = bcutils::isValidMetadataV2(metadataItem); - } - EXPECT_TRUE(validMetadata) << "Invalid metadata " << metadataItem.toString().c_str(); - } + validateMetadata(info, mCallbackAidlVersion); + + validateAlert(info, mCallbackAidlVersion); { std::lock_guard lk(mLock); @@ -349,7 +380,7 @@ void BroadcastRadioHalTest::SetUp() { // get AIDL HAL version ASSERT_TRUE(mModule->getInterfaceVersion(&mAidlVersion).isOk()); EXPECT_GE(mAidlVersion, kAidlVersion1); - EXPECT_LE(mAidlVersion, kAidlVersion2); + EXPECT_LE(mAidlVersion, kAidlVersion3); // set callback mCallback = SharedRefBase::make(mAidlVersion); @@ -1124,12 +1155,22 @@ TEST_P(BroadcastRadioHalTest, SetConfigFlags) { * Verifies that: * - startProgramListUpdates either succeeds or returns NOT_SUPPORTED; * - the complete list is fetched within kProgramListScanTimeoutMs; - * - stopProgramListUpdates does not crash. + * - stopProgramListUpdates does not crash; + * - metadata of program info in the program list is valid; + * - alert message is valid if it exists in the program list. */ TEST_P(BroadcastRadioHalTest, GetProgramListFromEmptyFilter) { LOG(DEBUG) << "GetProgramListFromEmptyFilter Test"; - getProgramList(); + std::optional completeList = getProgramList(); + + if (!completeList || mAidlVersion < kAidlVersion3) { + return; + } + for (const auto& program : *completeList) { + validateMetadata(program, mAidlVersion); + validateAlert(program, mAidlVersion); + } } /** diff --git a/broadcastradio/common/utilsaidl/Android.bp b/broadcastradio/common/utilsaidl/Android.bp index d88081fae1b4966bd8b97d367339cd49378c853b..22454927efdd26b2306a7e2bdf5f3e6cb2a9deb0 100644 --- a/broadcastradio/common/utilsaidl/Android.bp +++ b/broadcastradio/common/utilsaidl/Android.bp @@ -24,7 +24,7 @@ package { default_applicable_licenses: ["hardware_interfaces_license"], } -cc_library_static { +cc_library { name: "android.hardware.broadcastradio@common-utils-aidl-lib", defaults: [ "BroadcastRadioUtilsDefaults", @@ -34,7 +34,7 @@ cc_library_static { ], } -cc_library_static { +cc_library { name: "android.hardware.broadcastradio@common-utils-aidl-lib-V2", defaults: [ "BroadcastRadioUtilsDefaults", @@ -47,7 +47,21 @@ cc_library_static { ], } -cc_library_static { +cc_library { + name: "android.hardware.broadcastradio@common-utils-aidl-lib-V3", + defaults: [ + "BroadcastRadioUtilsDefaults", + ], + srcs: [ + "src/UtilsV2.cpp", + "src/UtilsV3.cpp", + ], + shared_libs: [ + "android.hardware.broadcastradio-V3-ndk", + ], +} + +cc_library { name: "android.hardware.broadcastradio@common-utils-aidl-lib-latest", defaults: [ "BroadcastRadioUtilsDefaults", @@ -55,6 +69,7 @@ cc_library_static { ], srcs: [ "src/UtilsV2.cpp", + "src/UtilsV3.cpp", ], } diff --git a/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h b/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h index a34ee105076ade45c7d183ffd0f26d744f3a5d52..f5b71b2d24837e477ea4918c006369c723142ac3 100644 --- a/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h +++ b/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h @@ -197,6 +197,8 @@ bool parseArgInt(const std::string& s, int* out); bool parseArgLong(const std::string& s, long* out); +bool parseArgDouble(const std::string& s, double* out); + bool parseArgBool(const std::string& s, bool* out); bool parseArgDirection(const std::string& s, bool* out); diff --git a/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/UtilsV3.h b/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/UtilsV3.h new file mode 100644 index 0000000000000000000000000000000000000000..250e217212bfcedc9ef214a4642bc3aab2a654c9 --- /dev/null +++ b/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/UtilsV3.h @@ -0,0 +1,37 @@ +/* + * 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. + */ + +#pragma once + +#include + +namespace aidl::android::hardware::broadcastradio { + +namespace utils { + +bool parseAlertStatus(const std::string& s, AlertStatus& out); + +bool parseAlertMessageType(const std::string& s, AlertMessageType& out); + +bool parseAlertCategory(const std::string& s, AlertCategory& out); + +bool parseAlertUrgency(const std::string& s, AlertUrgency& out); + +bool parseAlertSeverity(const std::string& s, AlertSeverity& out); + +bool parseAlertCertainty(const std::string& s, AlertCertainty& out); +} // namespace utils +} // namespace aidl::android::hardware::broadcastradio \ No newline at end of file diff --git a/broadcastradio/common/utilsaidl/src/Utils.cpp b/broadcastradio/common/utilsaidl/src/Utils.cpp index 3de18660ebe990e62dd09b25b5378785d341e600..bfa93a541152a667fb5fd75d4c565ee6d799885d 100644 --- a/broadcastradio/common/utilsaidl/src/Utils.cpp +++ b/broadcastradio/common/utilsaidl/src/Utils.cpp @@ -19,6 +19,7 @@ #include "broadcastradio-utils-aidl/Utils.h" #include +#include #include #include @@ -631,6 +632,10 @@ bool parseArgLong(const std::string& s, long* out) { return ::android::base::ParseInt(s, out); } +bool parseArgDouble(const std::string& s, double* out) { + return ::android::base::ParseDouble(s, out); +} + bool parseArgBool(const std::string& s, bool* out) { if (EqualsIgnoreCase(s, "true")) { *out = true; diff --git a/broadcastradio/common/utilsaidl/src/UtilsV3.cpp b/broadcastradio/common/utilsaidl/src/UtilsV3.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bf694da3b9a32e48501ef852930cb51189ecd95b --- /dev/null +++ b/broadcastradio/common/utilsaidl/src/UtilsV3.cpp @@ -0,0 +1,142 @@ +/* + * 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. + */ + +#define LOG_TAG "BcRadioAidlDef.utilsV3" + +#include "broadcastradio-utils-aidl/Utils.h" + +#include + +namespace aidl::android::hardware::broadcastradio { + +namespace utils { + +namespace { + +using ::android::base::EqualsIgnoreCase; +using ::std::vector; +} // namespace + +bool parseAlertStatus(const std::string& s, AlertStatus& out) { + if (EqualsIgnoreCase(s, toString(AlertStatus::ACTUAL))) { + out = AlertStatus::ACTUAL; + } else if (EqualsIgnoreCase(s, toString(AlertStatus::EXERCISE))) { + out = AlertStatus::EXERCISE; + } else if (EqualsIgnoreCase(s, toString(AlertStatus::TEST))) { + out = AlertStatus::TEST; + } else { + return false; + } + return true; +} + +bool parseAlertMessageType(const std::string& s, AlertMessageType& out) { + if (EqualsIgnoreCase(s, toString(AlertMessageType::ALERT))) { + out = AlertMessageType::ALERT; + } else if (EqualsIgnoreCase(s, toString(AlertMessageType::UPDATE))) { + out = AlertMessageType::UPDATE; + } else if (EqualsIgnoreCase(s, toString(AlertMessageType::CANCEL))) { + out = AlertMessageType::CANCEL; + } else { + return false; + } + return true; +} + +bool parseAlertCategory(const std::string& s, AlertCategory& out) { + if (EqualsIgnoreCase(s, toString(AlertCategory::GEO))) { + out = AlertCategory::GEO; + } else if (EqualsIgnoreCase(s, toString(AlertCategory::MET))) { + out = AlertCategory::MET; + } else if (EqualsIgnoreCase(s, toString(AlertCategory::SAFETY))) { + out = AlertCategory::SAFETY; + } else if (EqualsIgnoreCase(s, toString(AlertCategory::SECURITY))) { + out = AlertCategory::SECURITY; + } else if (EqualsIgnoreCase(s, toString(AlertCategory::RESCUE))) { + out = AlertCategory::RESCUE; + } else if (EqualsIgnoreCase(s, toString(AlertCategory::FIRE))) { + out = AlertCategory::FIRE; + } else if (EqualsIgnoreCase(s, toString(AlertCategory::HEALTH))) { + out = AlertCategory::HEALTH; + } else if (EqualsIgnoreCase(s, toString(AlertCategory::ENV))) { + out = AlertCategory::ENV; + } else if (EqualsIgnoreCase(s, toString(AlertCategory::TRANSPORT))) { + out = AlertCategory::TRANSPORT; + } else if (EqualsIgnoreCase(s, toString(AlertCategory::INFRA))) { + out = AlertCategory::INFRA; + } else if (EqualsIgnoreCase(s, toString(AlertCategory::CBRNE))) { + out = AlertCategory::CBRNE; + } else if (EqualsIgnoreCase(s, toString(AlertCategory::OTHER))) { + out = AlertCategory::OTHER; + } else { + return false; + } + return true; +} + +bool parseAlertUrgency(const std::string& s, AlertUrgency& out) { + if (EqualsIgnoreCase(s, toString(AlertUrgency::IMMEDIATE))) { + out = AlertUrgency::IMMEDIATE; + } else if (EqualsIgnoreCase(s, toString(AlertUrgency::EXPECTED))) { + out = AlertUrgency::EXPECTED; + } else if (EqualsIgnoreCase(s, toString(AlertUrgency::FUTURE))) { + out = AlertUrgency::FUTURE; + } else if (EqualsIgnoreCase(s, toString(AlertUrgency::PAST))) { + out = AlertUrgency::PAST; + } else if (EqualsIgnoreCase(s, toString(AlertUrgency::UNKNOWN))) { + out = AlertUrgency::UNKNOWN; + } else { + return false; + } + return true; +} + +bool parseAlertSeverity(const std::string& s, AlertSeverity& out) { + if (EqualsIgnoreCase(s, toString(AlertSeverity::EXTREME))) { + out = AlertSeverity::EXTREME; + } else if (EqualsIgnoreCase(s, toString(AlertSeverity::SEVERE))) { + out = AlertSeverity::SEVERE; + } else if (EqualsIgnoreCase(s, toString(AlertSeverity::MODERATE))) { + out = AlertSeverity::MODERATE; + } else if (EqualsIgnoreCase(s, toString(AlertSeverity::MINOR))) { + out = AlertSeverity::MINOR; + } else if (EqualsIgnoreCase(s, toString(AlertSeverity::UNKNOWN))) { + out = AlertSeverity::UNKNOWN; + } else { + return false; + } + return true; +} + +bool parseAlertCertainty(const std::string& s, AlertCertainty& out) { + if (EqualsIgnoreCase(s, toString(AlertCertainty::OBSERVED))) { + out = AlertCertainty::OBSERVED; + } else if (EqualsIgnoreCase(s, toString(AlertCertainty::LIKELY))) { + out = AlertCertainty::LIKELY; + } else if (EqualsIgnoreCase(s, toString(AlertCertainty::POSSIBLE))) { + out = AlertCertainty::POSSIBLE; + } else if (EqualsIgnoreCase(s, toString(AlertCertainty::UNLIKELY))) { + out = AlertCertainty::UNLIKELY; + } else if (EqualsIgnoreCase(s, toString(AlertCertainty::UNKNOWN))) { + out = AlertCertainty::UNKNOWN; + } else { + return false; + } + return true; +} + +} // namespace utils +} // namespace aidl::android::hardware::broadcastradio diff --git a/camera/metadata/aidl/Android.bp b/camera/metadata/aidl/Android.bp index a9c1a1a195e4ef680f553ac984d84ad08699c7e0..d7303fcce72b90ac97dfeb7adffb41113603b9fc 100644 --- a/camera/metadata/aidl/Android.bp +++ b/camera/metadata/aidl/Android.bp @@ -13,7 +13,7 @@ aidl_interface { host_supported: true, vendor_available: true, srcs: ["android/hardware/camera/metadata/*.aidl"], - frozen: true, + frozen: false, stability: "vintf", backend: { cpp: { diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataSection.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataSection.aidl index 138101b4cb2e437ca593385317995871d4d9bb16..49243dd077ba2ca2121d1413ce8c79a3533aeb27 100644 --- a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataSection.aidl +++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataSection.aidl @@ -72,5 +72,7 @@ enum CameraMetadataSection { ANDROID_AUTOMOTIVE_LENS, ANDROID_EXTENSION, ANDROID_JPEGR, + ANDROID_SHARED_SESSION, + ANDROID_DESKTOP_EFFECTS, VENDOR_SECTION = 0x8000, } diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataSectionStart.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataSectionStart.aidl index 85eee08a454aca382a02beecf663f039ba8013a0..588179fe13a3cdac3c5e699fdcb20c676bf1cb10 100644 --- a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataSectionStart.aidl +++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataSectionStart.aidl @@ -72,5 +72,7 @@ enum CameraMetadataSectionStart { ANDROID_AUTOMOTIVE_LENS_START = (android.hardware.camera.metadata.CameraMetadataSection.ANDROID_AUTOMOTIVE_LENS << 16) /* 2031616 */, ANDROID_EXTENSION_START = (android.hardware.camera.metadata.CameraMetadataSection.ANDROID_EXTENSION << 16) /* 2097152 */, ANDROID_JPEGR_START = (android.hardware.camera.metadata.CameraMetadataSection.ANDROID_JPEGR << 16) /* 2162688 */, + ANDROID_SHARED_SESSION_START = (android.hardware.camera.metadata.CameraMetadataSection.ANDROID_SHARED_SESSION << 16) /* 2228224 */, + ANDROID_DESKTOP_EFFECTS_START = (android.hardware.camera.metadata.CameraMetadataSection.ANDROID_DESKTOP_EFFECTS << 16) /* 2293760 */, VENDOR_SECTION_START = (android.hardware.camera.metadata.CameraMetadataSection.VENDOR_SECTION << 16) /* -2147483648 */, } diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataTag.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataTag.aidl index 9321ec0e37c2fc2d783133da286477c5342edbbe..c3cb3f7178fccb03f74520f25a13de2cc2d3fe2b 100644 --- a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataTag.aidl +++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataTag.aidl @@ -43,6 +43,10 @@ enum CameraMetadataTag { ANDROID_COLOR_CORRECTION_GAINS, ANDROID_COLOR_CORRECTION_ABERRATION_MODE, ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES, + ANDROID_COLOR_CORRECTION_COLOR_TEMPERATURE, + ANDROID_COLOR_CORRECTION_COLOR_TINT, + ANDROID_COLOR_CORRECTION_COLOR_TEMPERATURE_RANGE, + ANDROID_COLOR_CORRECTION_AVAILABLE_MODES, ANDROID_CONTROL_AE_ANTIBANDING_MODE = android.hardware.camera.metadata.CameraMetadataSectionStart.ANDROID_CONTROL_START /* 65536 */, ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION, ANDROID_CONTROL_AE_LOCK, @@ -100,6 +104,8 @@ enum CameraMetadataTag { ANDROID_CONTROL_AUTOFRAMING_STATE, ANDROID_CONTROL_LOW_LIGHT_BOOST_INFO_LUMINANCE_RANGE, ANDROID_CONTROL_LOW_LIGHT_BOOST_STATE, + ANDROID_CONTROL_AE_PRIORITY_MODE = 65597, + ANDROID_CONTROL_AE_AVAILABLE_PRIORITY_MODES, ANDROID_DEMOSAIC_MODE = android.hardware.camera.metadata.CameraMetadataSectionStart.ANDROID_DEMOSAIC_START /* 131072 */, ANDROID_EDGE_MODE = android.hardware.camera.metadata.CameraMetadataSectionStart.ANDROID_EDGE_START /* 196608 */, ANDROID_EDGE_STRENGTH, @@ -343,14 +349,27 @@ enum CameraMetadataTag { ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION, ANDROID_HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION, ANDROID_HEIC_AVAILABLE_HEIC_STALL_DURATIONS_MAXIMUM_RESOLUTION, + ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_STREAM_CONFIGURATIONS, + ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_MIN_FRAME_DURATIONS, + ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_STALL_DURATIONS, + ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION, + ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION, + ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_STALL_DURATIONS_MAXIMUM_RESOLUTION, ANDROID_HEIC_INFO_SUPPORTED = android.hardware.camera.metadata.CameraMetadataSectionStart.ANDROID_HEIC_INFO_START /* 1900544 */, ANDROID_HEIC_INFO_MAX_JPEG_APP_SEGMENTS_COUNT, ANDROID_AUTOMOTIVE_LOCATION = android.hardware.camera.metadata.CameraMetadataSectionStart.ANDROID_AUTOMOTIVE_START /* 1966080 */, ANDROID_AUTOMOTIVE_LENS_FACING = android.hardware.camera.metadata.CameraMetadataSectionStart.ANDROID_AUTOMOTIVE_LENS_START /* 2031616 */, + ANDROID_EXTENSION_NIGHT_MODE_INDICATOR = 2097154, ANDROID_JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS = android.hardware.camera.metadata.CameraMetadataSectionStart.ANDROID_JPEGR_START /* 2162688 */, ANDROID_JPEGR_AVAILABLE_JPEG_R_MIN_FRAME_DURATIONS, ANDROID_JPEGR_AVAILABLE_JPEG_R_STALL_DURATIONS, ANDROID_JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION, ANDROID_JPEGR_AVAILABLE_JPEG_R_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION, ANDROID_JPEGR_AVAILABLE_JPEG_R_STALL_DURATIONS_MAXIMUM_RESOLUTION, + ANDROID_DESKTOP_EFFECTS_CAPABILITIES = android.hardware.camera.metadata.CameraMetadataSectionStart.ANDROID_DESKTOP_EFFECTS_START /* 2293760 */, + ANDROID_DESKTOP_EFFECTS_BACKGROUND_BLUR_MODES, + ANDROID_DESKTOP_EFFECTS_BACKGROUND_BLUR_MODE, + ANDROID_DESKTOP_EFFECTS_FACE_RETOUCH_MODE, + ANDROID_DESKTOP_EFFECTS_FACE_RETOUCH_STRENGTH, + ANDROID_DESKTOP_EFFECTS_PORTRAIT_RELIGHT_MODE, } diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/ColorCorrectionMode.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/ColorCorrectionMode.aidl index 23816057195e172e7586304db5f1dca7408750d3..69f0f5faa601e28f837945ee08962ff6e1444bda 100644 --- a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/ColorCorrectionMode.aidl +++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/ColorCorrectionMode.aidl @@ -41,4 +41,5 @@ enum ColorCorrectionMode { ANDROID_COLOR_CORRECTION_MODE_TRANSFORM_MATRIX, ANDROID_COLOR_CORRECTION_MODE_FAST, ANDROID_COLOR_CORRECTION_MODE_HIGH_QUALITY, + ANDROID_COLOR_CORRECTION_MODE_CCT, } diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/ControlAePriorityMode.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/ControlAePriorityMode.aidl new file mode 100644 index 0000000000000000000000000000000000000000..eac214794df3260cd3aae872e3db9476400238cd --- /dev/null +++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/ControlAePriorityMode.aidl @@ -0,0 +1,44 @@ +/* + * 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. + *//* + * Autogenerated from camera metadata definitions in + * /system/media/camera/docs/metadata_definitions.xml + * *** DO NOT EDIT BY HAND *** + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.camera.metadata; +@Backing(type="int") @VintfStability +enum ControlAePriorityMode { + ANDROID_CONTROL_AE_PRIORITY_MODE_OFF, + ANDROID_CONTROL_AE_PRIORITY_MODE_SENSOR_SENSITIVITY_PRIORITY, + ANDROID_CONTROL_AE_PRIORITY_MODE_SENSOR_EXPOSURE_TIME_PRIORITY, +} diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/DesktopEffectsBackgroundBlurMode.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/DesktopEffectsBackgroundBlurMode.aidl new file mode 100644 index 0000000000000000000000000000000000000000..36da888422655eade26ad4fbb2ef895c1ecd43c6 --- /dev/null +++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/DesktopEffectsBackgroundBlurMode.aidl @@ -0,0 +1,44 @@ +/* + * 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. + *//* + * Autogenerated from camera metadata definitions in + * /system/media/camera/docs/metadata_definitions.xml + * *** DO NOT EDIT BY HAND *** + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.camera.metadata; +@Backing(type="int") @VintfStability +enum DesktopEffectsBackgroundBlurMode { + ANDROID_DESKTOP_EFFECTS_BACKGROUND_BLUR_MODE_OFF, + ANDROID_DESKTOP_EFFECTS_BACKGROUND_BLUR_MODE_LIGHT, + ANDROID_DESKTOP_EFFECTS_BACKGROUND_BLUR_MODE_FULL, +} diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/DesktopEffectsCapabilities.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/DesktopEffectsCapabilities.aidl new file mode 100644 index 0000000000000000000000000000000000000000..d16ef99368c5e4e2cbe271d793803ce5f9c20bfc --- /dev/null +++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/DesktopEffectsCapabilities.aidl @@ -0,0 +1,44 @@ +/* + * 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. + *//* + * Autogenerated from camera metadata definitions in + * /system/media/camera/docs/metadata_definitions.xml + * *** DO NOT EDIT BY HAND *** + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.camera.metadata; +@Backing(type="int") @VintfStability +enum DesktopEffectsCapabilities { + ANDROID_DESKTOP_EFFECTS_CAPABILITIES_BACKGROUND_BLUR, + ANDROID_DESKTOP_EFFECTS_CAPABILITIES_FACE_RETOUCH, + ANDROID_DESKTOP_EFFECTS_CAPABILITIES_PORTRAIT_RELIGHT, +} diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/DesktopEffectsFaceRetouchMode.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/DesktopEffectsFaceRetouchMode.aidl new file mode 100644 index 0000000000000000000000000000000000000000..8004b918230924225b96eea5ba8933dd5bc3cd8e --- /dev/null +++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/DesktopEffectsFaceRetouchMode.aidl @@ -0,0 +1,43 @@ +/* + * 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. + *//* + * Autogenerated from camera metadata definitions in + * /system/media/camera/docs/metadata_definitions.xml + * *** DO NOT EDIT BY HAND *** + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.camera.metadata; +@Backing(type="int") @VintfStability +enum DesktopEffectsFaceRetouchMode { + ANDROID_DESKTOP_EFFECTS_FACE_RETOUCH_MODE_OFF, + ANDROID_DESKTOP_EFFECTS_FACE_RETOUCH_MODE_ON, +} diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/DesktopEffectsPortraitRelightMode.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/DesktopEffectsPortraitRelightMode.aidl new file mode 100644 index 0000000000000000000000000000000000000000..abd06a7f1fb3e72e029e1377d440245d6ab44206 --- /dev/null +++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/DesktopEffectsPortraitRelightMode.aidl @@ -0,0 +1,43 @@ +/* + * 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. + *//* + * Autogenerated from camera metadata definitions in + * /system/media/camera/docs/metadata_definitions.xml + * *** DO NOT EDIT BY HAND *** + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.camera.metadata; +@Backing(type="int") @VintfStability +enum DesktopEffectsPortraitRelightMode { + ANDROID_DESKTOP_EFFECTS_PORTRAIT_RELIGHT_MODE_OFF, + ANDROID_DESKTOP_EFFECTS_PORTRAIT_RELIGHT_MODE_ON, +} diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/ExtensionNightModeIndicator.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/ExtensionNightModeIndicator.aidl new file mode 100644 index 0000000000000000000000000000000000000000..6cfdc02d82ff311178e3d0bb05c2db94b17c02a3 --- /dev/null +++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/ExtensionNightModeIndicator.aidl @@ -0,0 +1,44 @@ +/* + * 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. + *//* + * Autogenerated from camera metadata definitions in + * /system/media/camera/docs/metadata_definitions.xml + * *** DO NOT EDIT BY HAND *** + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.camera.metadata; +@Backing(type="int") @VintfStability +enum ExtensionNightModeIndicator { + ANDROID_EXTENSION_NIGHT_MODE_INDICATOR_UNKNOWN, + ANDROID_EXTENSION_NIGHT_MODE_INDICATOR_OFF, + ANDROID_EXTENSION_NIGHT_MODE_INDICATOR_ON, +} diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/HeicAvailableHeicUltraHdrStreamConfigurations.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/HeicAvailableHeicUltraHdrStreamConfigurations.aidl new file mode 100644 index 0000000000000000000000000000000000000000..339d2fa6ebc16026621c3d1c0989b16cabca07c4 --- /dev/null +++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/HeicAvailableHeicUltraHdrStreamConfigurations.aidl @@ -0,0 +1,43 @@ +/* + * 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. + *//* + * Autogenerated from camera metadata definitions in + * /system/media/camera/docs/metadata_definitions.xml + * *** DO NOT EDIT BY HAND *** + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.camera.metadata; +@Backing(type="int") @VintfStability +enum HeicAvailableHeicUltraHdrStreamConfigurations { + ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_STREAM_CONFIGURATIONS_OUTPUT, + ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_STREAM_CONFIGURATIONS_INPUT, +} diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/HeicAvailableHeicUltraHdrStreamConfigurationsMaximumResolution.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/HeicAvailableHeicUltraHdrStreamConfigurationsMaximumResolution.aidl new file mode 100644 index 0000000000000000000000000000000000000000..775506982107205c18f4d1da90e5f37f4831e53e --- /dev/null +++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/HeicAvailableHeicUltraHdrStreamConfigurationsMaximumResolution.aidl @@ -0,0 +1,43 @@ +/* + * 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. + *//* + * Autogenerated from camera metadata definitions in + * /system/media/camera/docs/metadata_definitions.xml + * *** DO NOT EDIT BY HAND *** + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.camera.metadata; +@Backing(type="int") @VintfStability +enum HeicAvailableHeicUltraHdrStreamConfigurationsMaximumResolution { + ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_OUTPUT, + ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_INPUT, +} diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/SensorReadoutTimestamp.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/SensorReadoutTimestamp.aidl index 35dc1a976f8460116da7b4a9f36e8036f45117cc..11be18ef063a724c8b67b8c6b95e4ac6e1b3317c 100644 --- a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/SensorReadoutTimestamp.aidl +++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/SensorReadoutTimestamp.aidl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 The Android Open Source Project + * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataSection.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataSection.aidl index 73bcc12ad4e2e87c4acbd515d0a0bd25a2f9969f..b7edaf2a7d518304905c649ddf3e9c1e0b37f3ca 100644 --- a/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataSection.aidl +++ b/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataSection.aidl @@ -63,5 +63,7 @@ enum CameraMetadataSection { ANDROID_AUTOMOTIVE_LENS, ANDROID_EXTENSION, ANDROID_JPEGR, + ANDROID_SHARED_SESSION, + ANDROID_DESKTOP_EFFECTS, VENDOR_SECTION = 0x8000, } diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataSectionStart.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataSectionStart.aidl index 75e791531b57e359001d7fa6d580306a0a6d30fb..b36a433ccec2d413ac78cc35dbadd41a14be0e33 100644 --- a/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataSectionStart.aidl +++ b/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataSectionStart.aidl @@ -65,5 +65,7 @@ enum CameraMetadataSectionStart { ANDROID_AUTOMOTIVE_LENS_START = CameraMetadataSection.ANDROID_AUTOMOTIVE_LENS << 16, ANDROID_EXTENSION_START = CameraMetadataSection.ANDROID_EXTENSION << 16, ANDROID_JPEGR_START = CameraMetadataSection.ANDROID_JPEGR << 16, + ANDROID_SHARED_SESSION_START = CameraMetadataSection.ANDROID_SHARED_SESSION << 16, + ANDROID_DESKTOP_EFFECTS_START = CameraMetadataSection.ANDROID_DESKTOP_EFFECTS << 16, VENDOR_SECTION_START = CameraMetadataSection.VENDOR_SECTION << 16, } diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl index 236bcaf5a37521416385ec45c03f2275a13782e7..8b2ac7234373c2b87442e81d7d1b1ab8d7798e93 100644 --- a/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl +++ b/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl @@ -69,6 +69,38 @@ enum CameraMetadataTag { * @see ANDROID_COLOR_CORRECTION_ABERRATION_MODE */ ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES, + /** + * android.colorCorrection.colorTemperature [dynamic, int32, public] + * + *

Specifies the color temperature for CCT mode in Kelvin + * to adjust the white balance of the image.

+ */ + ANDROID_COLOR_CORRECTION_COLOR_TEMPERATURE, + /** + * android.colorCorrection.colorTint [dynamic, int32, public] + * + *

Specifies the color tint for CCT mode to adjust the white + * balance of the image.

+ */ + ANDROID_COLOR_CORRECTION_COLOR_TINT, + /** + * android.colorCorrection.colorTemperatureRange [static, int32[], public] + * + *

The range of supported color temperature values for + * ANDROID_COLOR_CORRECTION_COLOR_TEMPERATURE.

+ * + * @see ANDROID_COLOR_CORRECTION_COLOR_TEMPERATURE + */ + ANDROID_COLOR_CORRECTION_COLOR_TEMPERATURE_RANGE, + /** + * android.colorCorrection.availableModes [static, byte[], public] + * + *

List of color correction modes for ANDROID_COLOR_CORRECTION_MODE that are + * supported by this camera device.

+ * + * @see ANDROID_COLOR_CORRECTION_MODE + */ + ANDROID_COLOR_CORRECTION_AVAILABLE_MODES, /** * android.control.aeAntibandingMode [dynamic, enum, public] * @@ -501,6 +533,21 @@ enum CameraMetadataTag { *

Current state of the low light boost AE mode.

*/ ANDROID_CONTROL_LOW_LIGHT_BOOST_STATE, + /** + * android.control.aePriorityMode [dynamic, enum, public] + * + *

Turn on AE priority mode.

+ */ + ANDROID_CONTROL_AE_PRIORITY_MODE = 65597, + /** + * android.control.aeAvailablePriorityModes [static, byte[], public] + * + *

List of auto-exposure priority modes for ANDROID_CONTROL_AE_PRIORITY_MODE + * that are supported by this camera device.

+ * + * @see ANDROID_CONTROL_AE_PRIORITY_MODE + */ + ANDROID_CONTROL_AE_AVAILABLE_PRIORITY_MODES, /** * android.demosaic.mode [controls, enum, system] * @@ -2345,6 +2392,62 @@ enum CameraMetadataTag { * @see ANDROID_SENSOR_PIXEL_MODE */ ANDROID_HEIC_AVAILABLE_HEIC_STALL_DURATIONS_MAXIMUM_RESOLUTION, + /** + * android.heic.availableHeicUltraHdrStreamConfigurations [static, enum[], ndk_public] + * + *

The available HEIC (ISO/IEC 23008-12/24) UltraHDR stream + * configurations that this camera device supports + * (i.e. format, width, height, output/input stream).

+ */ + ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_STREAM_CONFIGURATIONS, + /** + * android.heic.availableHeicUltraHdrMinFrameDurations [static, int64[], ndk_public] + * + *

This lists the minimum frame duration for each + * format/size combination for HEIC UltraHDR output formats.

+ */ + ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_MIN_FRAME_DURATIONS, + /** + * android.heic.availableHeicUltraHdrStallDurations [static, int64[], ndk_public] + * + *

This lists the maximum stall duration for each + * output format/size combination for HEIC UltraHDR streams.

+ */ + ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_STALL_DURATIONS, + /** + * android.heic.availableHeicUltraHdrStreamConfigurationsMaximumResolution [static, enum[], ndk_public] + * + *

The available HEIC (ISO/IEC 23008-12/24) UltraHDR stream + * configurations that this camera device supports + * (i.e. format, width, height, output/input stream) for CaptureRequests where + * ANDROID_SENSOR_PIXEL_MODE is set to + * CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION.

+ * + * @see ANDROID_SENSOR_PIXEL_MODE + */ + ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION, + /** + * android.heic.availableHeicUltraHdrMinFrameDurationsMaximumResolution [static, int64[], ndk_public] + * + *

This lists the minimum frame duration for each + * format/size combination for HEIC UltraHDR output formats for CaptureRequests where + * ANDROID_SENSOR_PIXEL_MODE is set to + * CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION.

+ * + * @see ANDROID_SENSOR_PIXEL_MODE + */ + ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION, + /** + * android.heic.availableHeicUltraHdrStallDurationsMaximumResolution [static, int64[], ndk_public] + * + *

This lists the maximum stall duration for each + * output format/size combination for HEIC UltraHDR streams for CaptureRequests where + * ANDROID_SENSOR_PIXEL_MODE is set to + * CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION.

+ * + * @see ANDROID_SENSOR_PIXEL_MODE + */ + ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_STALL_DURATIONS_MAXIMUM_RESOLUTION, /** * android.heic.info.supported [static, enum, system] * @@ -2374,6 +2477,13 @@ enum CameraMetadataTag { * passenger seats.

*/ ANDROID_AUTOMOTIVE_LENS_FACING = CameraMetadataSectionStart.ANDROID_AUTOMOTIVE_LENS_START, + /** + * android.extension.nightModeIndicator [dynamic, enum, public] + * + *

Indicates when to activate Night Mode Camera Extension for high-quality + * still captures in low-light conditions.

+ */ + ANDROID_EXTENSION_NIGHT_MODE_INDICATOR = 2097154, /** * android.jpegr.availableJpegRStreamConfigurations [static, enum[], ndk_public] * @@ -2426,4 +2536,50 @@ enum CameraMetadataTag { * @see ANDROID_SENSOR_PIXEL_MODE */ ANDROID_JPEGR_AVAILABLE_JPEG_R_STALL_DURATIONS_MAXIMUM_RESOLUTION, + /** + * android.desktopEffects.capabilities [static, enum[], system] + * + *

List of special effects supported by the camera device.

+ */ + ANDROID_DESKTOP_EFFECTS_CAPABILITIES = CameraMetadataSectionStart.ANDROID_DESKTOP_EFFECTS_START, + /** + * android.desktopEffects.backgroundBlurModes [static, byte[], system] + * + *

List of background blur modes supported by the camera device. The key will only exist + * if BACKGROUND_BLUR is listed by ANDROID_DESKTOP_EFFECTS_CAPABILITIES.

+ * + * @see ANDROID_DESKTOP_EFFECTS_CAPABILITIES + */ + ANDROID_DESKTOP_EFFECTS_BACKGROUND_BLUR_MODES, + /** + * android.desktopEffects.backgroundBlurMode [controls, enum, system] + * + *

Control how the background should be blurred. Supported modes are listed in + * ANDROID_DESKTOP_EFFECTS_BACKGROUND_BLUR_MODES by the camera device.

+ * + * @see ANDROID_DESKTOP_EFFECTS_BACKGROUND_BLUR_MODES + */ + ANDROID_DESKTOP_EFFECTS_BACKGROUND_BLUR_MODE, + /** + * android.desktopEffects.faceRetouchMode [controls, enum, system] + * + *

Whether to enable face retouch effect.

+ */ + ANDROID_DESKTOP_EFFECTS_FACE_RETOUCH_MODE, + /** + * android.desktopEffects.faceRetouchStrength [controls, byte, system] + * + *

Control the strength of face retouch applied to the frames. If + * ANDROID_DESKTOP_EFFECTS_FACE_RETOUCH_MODE in ON without a faceRetouchStrength, + * a default will be set by the camera device.

+ * + * @see ANDROID_DESKTOP_EFFECTS_FACE_RETOUCH_MODE + */ + ANDROID_DESKTOP_EFFECTS_FACE_RETOUCH_STRENGTH, + /** + * android.desktopEffects.portraitRelightMode [controls, enum, system] + * + *

Whether to enable portrait relighting effect.

+ */ + ANDROID_DESKTOP_EFFECTS_PORTRAIT_RELIGHT_MODE, } diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/ColorCorrectionMode.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/ColorCorrectionMode.aidl index 2a51bfcfc0acc70b615df4cf0c94318911ef7bca..f12b6f6c12c3a6ff970ec42b570c7c32e3a7e93d 100644 --- a/camera/metadata/aidl/android/hardware/camera/metadata/ColorCorrectionMode.aidl +++ b/camera/metadata/aidl/android/hardware/camera/metadata/ColorCorrectionMode.aidl @@ -33,4 +33,5 @@ enum ColorCorrectionMode { ANDROID_COLOR_CORRECTION_MODE_TRANSFORM_MATRIX, ANDROID_COLOR_CORRECTION_MODE_FAST, ANDROID_COLOR_CORRECTION_MODE_HIGH_QUALITY, + ANDROID_COLOR_CORRECTION_MODE_CCT, } diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/ControlAePriorityMode.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/ControlAePriorityMode.aidl new file mode 100644 index 0000000000000000000000000000000000000000..fd4f53182446ea9d456f12c571045a4b872b328e --- /dev/null +++ b/camera/metadata/aidl/android/hardware/camera/metadata/ControlAePriorityMode.aidl @@ -0,0 +1,36 @@ +/* + * 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. + */ + +/* + * Autogenerated from camera metadata definitions in + * /system/media/camera/docs/metadata_definitions.xml + * *** DO NOT EDIT BY HAND *** + */ + +package android.hardware.camera.metadata; + +/** + * android.control.aePriorityMode enumeration values + * @see ANDROID_CONTROL_AE_PRIORITY_MODE + * See system/media/camera/docs/metadata_definitions.xml for details. + */ +@VintfStability +@Backing(type="int") +enum ControlAePriorityMode { + ANDROID_CONTROL_AE_PRIORITY_MODE_OFF, + ANDROID_CONTROL_AE_PRIORITY_MODE_SENSOR_SENSITIVITY_PRIORITY, + ANDROID_CONTROL_AE_PRIORITY_MODE_SENSOR_EXPOSURE_TIME_PRIORITY, +} diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/DesktopEffectsBackgroundBlurMode.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/DesktopEffectsBackgroundBlurMode.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e8b2180fe2fb263eac34d99a31ad50972dd3f072 --- /dev/null +++ b/camera/metadata/aidl/android/hardware/camera/metadata/DesktopEffectsBackgroundBlurMode.aidl @@ -0,0 +1,36 @@ +/* + * 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. + */ + +/* + * Autogenerated from camera metadata definitions in + * /system/media/camera/docs/metadata_definitions.xml + * *** DO NOT EDIT BY HAND *** + */ + +package android.hardware.camera.metadata; + +/** + * android.desktopEffects.backgroundBlurMode enumeration values + * @see ANDROID_DESKTOP_EFFECTS_BACKGROUND_BLUR_MODE + * See system/media/camera/docs/metadata_definitions.xml for details. + */ +@VintfStability +@Backing(type="int") +enum DesktopEffectsBackgroundBlurMode { + ANDROID_DESKTOP_EFFECTS_BACKGROUND_BLUR_MODE_OFF, + ANDROID_DESKTOP_EFFECTS_BACKGROUND_BLUR_MODE_LIGHT, + ANDROID_DESKTOP_EFFECTS_BACKGROUND_BLUR_MODE_FULL, +} diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/DesktopEffectsCapabilities.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/DesktopEffectsCapabilities.aidl new file mode 100644 index 0000000000000000000000000000000000000000..45cb78ede9d4c016d6b02861ebcfab405c2a01d5 --- /dev/null +++ b/camera/metadata/aidl/android/hardware/camera/metadata/DesktopEffectsCapabilities.aidl @@ -0,0 +1,36 @@ +/* + * 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. + */ + +/* + * Autogenerated from camera metadata definitions in + * /system/media/camera/docs/metadata_definitions.xml + * *** DO NOT EDIT BY HAND *** + */ + +package android.hardware.camera.metadata; + +/** + * android.desktopEffects.capabilities enumeration values + * @see ANDROID_DESKTOP_EFFECTS_CAPABILITIES + * See system/media/camera/docs/metadata_definitions.xml for details. + */ +@VintfStability +@Backing(type="int") +enum DesktopEffectsCapabilities { + ANDROID_DESKTOP_EFFECTS_CAPABILITIES_BACKGROUND_BLUR, + ANDROID_DESKTOP_EFFECTS_CAPABILITIES_FACE_RETOUCH, + ANDROID_DESKTOP_EFFECTS_CAPABILITIES_PORTRAIT_RELIGHT, +} diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/DesktopEffectsFaceRetouchMode.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/DesktopEffectsFaceRetouchMode.aidl new file mode 100644 index 0000000000000000000000000000000000000000..d8c8101a1802d5bb4fed2514240de3fd70d4031e --- /dev/null +++ b/camera/metadata/aidl/android/hardware/camera/metadata/DesktopEffectsFaceRetouchMode.aidl @@ -0,0 +1,35 @@ +/* + * 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. + */ + +/* + * Autogenerated from camera metadata definitions in + * /system/media/camera/docs/metadata_definitions.xml + * *** DO NOT EDIT BY HAND *** + */ + +package android.hardware.camera.metadata; + +/** + * android.desktopEffects.faceRetouchMode enumeration values + * @see ANDROID_DESKTOP_EFFECTS_FACE_RETOUCH_MODE + * See system/media/camera/docs/metadata_definitions.xml for details. + */ +@VintfStability +@Backing(type="int") +enum DesktopEffectsFaceRetouchMode { + ANDROID_DESKTOP_EFFECTS_FACE_RETOUCH_MODE_OFF, + ANDROID_DESKTOP_EFFECTS_FACE_RETOUCH_MODE_ON, +} diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/DesktopEffectsPortraitRelightMode.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/DesktopEffectsPortraitRelightMode.aidl new file mode 100644 index 0000000000000000000000000000000000000000..4a1d43868faa98df6f5f8f80a8e1a4f7578d1b61 --- /dev/null +++ b/camera/metadata/aidl/android/hardware/camera/metadata/DesktopEffectsPortraitRelightMode.aidl @@ -0,0 +1,35 @@ +/* + * 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. + */ + +/* + * Autogenerated from camera metadata definitions in + * /system/media/camera/docs/metadata_definitions.xml + * *** DO NOT EDIT BY HAND *** + */ + +package android.hardware.camera.metadata; + +/** + * android.desktopEffects.portraitRelightMode enumeration values + * @see ANDROID_DESKTOP_EFFECTS_PORTRAIT_RELIGHT_MODE + * See system/media/camera/docs/metadata_definitions.xml for details. + */ +@VintfStability +@Backing(type="int") +enum DesktopEffectsPortraitRelightMode { + ANDROID_DESKTOP_EFFECTS_PORTRAIT_RELIGHT_MODE_OFF, + ANDROID_DESKTOP_EFFECTS_PORTRAIT_RELIGHT_MODE_ON, +} diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/ExtensionNightModeIndicator.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/ExtensionNightModeIndicator.aidl new file mode 100644 index 0000000000000000000000000000000000000000..3c3bdf573f4752e611508733611050a8dd8516ba --- /dev/null +++ b/camera/metadata/aidl/android/hardware/camera/metadata/ExtensionNightModeIndicator.aidl @@ -0,0 +1,36 @@ +/* + * 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. + */ + +/* + * Autogenerated from camera metadata definitions in + * /system/media/camera/docs/metadata_definitions.xml + * *** DO NOT EDIT BY HAND *** + */ + +package android.hardware.camera.metadata; + +/** + * android.extension.nightModeIndicator enumeration values + * @see ANDROID_EXTENSION_NIGHT_MODE_INDICATOR + * See system/media/camera/docs/metadata_definitions.xml for details. + */ +@VintfStability +@Backing(type="int") +enum ExtensionNightModeIndicator { + ANDROID_EXTENSION_NIGHT_MODE_INDICATOR_UNKNOWN, + ANDROID_EXTENSION_NIGHT_MODE_INDICATOR_OFF, + ANDROID_EXTENSION_NIGHT_MODE_INDICATOR_ON, +} diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/HeicAvailableHeicUltraHdrStreamConfigurations.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/HeicAvailableHeicUltraHdrStreamConfigurations.aidl new file mode 100644 index 0000000000000000000000000000000000000000..56761b968ccb9fe12c7ddb49f7b3af570e9ced36 --- /dev/null +++ b/camera/metadata/aidl/android/hardware/camera/metadata/HeicAvailableHeicUltraHdrStreamConfigurations.aidl @@ -0,0 +1,35 @@ +/* + * 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. + */ + +/* + * Autogenerated from camera metadata definitions in + * /system/media/camera/docs/metadata_definitions.xml + * *** DO NOT EDIT BY HAND *** + */ + +package android.hardware.camera.metadata; + +/** + * android.heic.availableHeicUltraHdrStreamConfigurations enumeration values + * @see ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_STREAM_CONFIGURATIONS + * See system/media/camera/docs/metadata_definitions.xml for details. + */ +@VintfStability +@Backing(type="int") +enum HeicAvailableHeicUltraHdrStreamConfigurations { + ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_STREAM_CONFIGURATIONS_OUTPUT, + ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_STREAM_CONFIGURATIONS_INPUT, +} diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/HeicAvailableHeicUltraHdrStreamConfigurationsMaximumResolution.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/HeicAvailableHeicUltraHdrStreamConfigurationsMaximumResolution.aidl new file mode 100644 index 0000000000000000000000000000000000000000..7fb19dc4686fe5cc16ccea9e867da12006befdb3 --- /dev/null +++ b/camera/metadata/aidl/android/hardware/camera/metadata/HeicAvailableHeicUltraHdrStreamConfigurationsMaximumResolution.aidl @@ -0,0 +1,35 @@ +/* + * 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. + */ + +/* + * Autogenerated from camera metadata definitions in + * /system/media/camera/docs/metadata_definitions.xml + * *** DO NOT EDIT BY HAND *** + */ + +package android.hardware.camera.metadata; + +/** + * android.heic.availableHeicUltraHdrStreamConfigurationsMaximumResolution enumeration values + * @see ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION + * See system/media/camera/docs/metadata_definitions.xml for details. + */ +@VintfStability +@Backing(type="int") +enum HeicAvailableHeicUltraHdrStreamConfigurationsMaximumResolution { + ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_OUTPUT, + ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_INPUT, +} diff --git a/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp b/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp index 9fa4df2cf4b09751140aa7bc2175cf4993222ba8..ec61eec679eba520a4f73e8fd1ed31cbbba208df 100644 --- a/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp +++ b/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp @@ -118,7 +118,8 @@ TEST_P(CameraAidlTest, setCallback) { ScopedAStatus ret = mProvider->setCallback(cb); ASSERT_TRUE(ret.isOk()); ret = mProvider->setCallback(nullptr); - ASSERT_EQ(static_cast(Status::ILLEGAL_ARGUMENT), ret.getServiceSpecificError()); + ASSERT_TRUE(static_cast(Status::ILLEGAL_ARGUMENT) == ret.getServiceSpecificError() || + EX_NULL_POINTER == ret.getExceptionCode()); } // Test if ICameraProvider::getCameraDeviceInterface returns Status::OK and non-null device diff --git a/camera/provider/aidl/vts/camera_aidl_test.cpp b/camera/provider/aidl/vts/camera_aidl_test.cpp index 6ecd45186cfca0e90b50d8142dbe97850b3266b4..44af306c91961d1ae55f8277974d5d7c59f8d620 100644 --- a/camera/provider/aidl/vts/camera_aidl_test.cpp +++ b/camera/provider/aidl/vts/camera_aidl_test.cpp @@ -2590,8 +2590,7 @@ ndk::ScopedAStatus CameraAidlTest::configureStreams(std::shared_ptr= 3)) { + if (bufferManagerType == BufferManagerType::SESSION && interfaceVersion >= 3) { ret = session->configureStreamsV2(config, &aidl_return); } else { ret = session->configureStreams(config, halStreams); @@ -2599,12 +2598,11 @@ ndk::ScopedAStatus CameraAidlTest::configureStreams(std::shared_ptrinsert(halStream.id); } diff --git a/compatibility_matrices/compatibility_matrix.202504.xml b/compatibility_matrices/compatibility_matrix.202504.xml index 8338e1351c60a7e0a1b78d9fd419004e484cb576..8d5a50a44a235dde8c291f1e5961fba7b2fbd61f 100644 --- a/compatibility_matrices/compatibility_matrix.202504.xml +++ b/compatibility_matrices/compatibility_matrix.202504.xml @@ -171,7 +171,7 @@ android.hardware.broadcastradio - 1-2 + 1-3 IBroadcastRadio .* @@ -233,7 +233,7 @@ android.hardware.gnss - 2-4 + 2-5 IGnss default @@ -257,7 +257,7 @@ android.hardware.health - 3 + 3-4 IHealth default @@ -380,7 +380,7 @@ android.hardware.power - 5 + 5-6 IPower default @@ -543,7 +543,7 @@ android.hardware.sensors - 2 + 2-3 ISensors default @@ -567,7 +567,7 @@ android.hardware.thermal - 2 + 3 IThermal default @@ -607,7 +607,7 @@ android.hardware.tv.tuner - 1-2 + 1-3 ITuner default @@ -615,7 +615,7 @@ android.hardware.tv.input - 1-2 + 1-3 ITvInput default @@ -671,7 +671,7 @@ android.hardware.wifi - 1-2 + 2-3 IWifi default @@ -701,6 +701,14 @@ default + + android.hardware.tv.mediaquality + 1 + + IMediaQuality + default + + mapper diff --git a/compatibility_matrices/exclude/fcm_exclude.cpp b/compatibility_matrices/exclude/fcm_exclude.cpp index 1d5b2bdefd8f97caea904e23e6f618544b6a2529..57e039c0305c4f4eeb6b21f36dd19a7cabab1028 100644 --- a/compatibility_matrices/exclude/fcm_exclude.cpp +++ b/compatibility_matrices/exclude/fcm_exclude.cpp @@ -140,6 +140,7 @@ bool ShouldCheckMissingAidlHalsInFcm(const std::string& packageAndVersion) { "android.hardware.camera.common@", "android.hardware.common@", "android.hardware.common.fmq@", + "android.hardware.gnss.gnss_assistance@", "android.hardware.gnss.measurement_corrections@", "android.hardware.gnss.visibility_control@", "android.hardware.graphics.common@", diff --git a/contexthub/aidl/android/hardware/contexthub/IContextHub.aidl b/contexthub/aidl/android/hardware/contexthub/IContextHub.aidl index 24192a1e4bbace34667dfa5bf7124ad371bc5507..83f73c3a9eed0f7474e3de380ecc0f6266b7c05b 100644 --- a/contexthub/aidl/android/hardware/contexthub/IContextHub.aidl +++ b/contexthub/aidl/android/hardware/contexthub/IContextHub.aidl @@ -323,9 +323,6 @@ interface IContextHub { * (nullable). Null indicates a fully custom marshalling scheme. The value should match * a published descriptor for both destination and initiator. * - * @return An integer identifying the session, the integer can be used to present - * the tuple of (destination, initiator, serviceDescriptor). - * * @throws EX_ILLEGAL_ARGUMENT if any of the arguments are invalid, or the combination of the * arguments is invalid. * @throws EX_SERVICE_SPECIFIC on other errors diff --git a/contexthub/aidl/default/Android.bp b/contexthub/aidl/default/Android.bp index da173f925deeb45677a4425c48e7cbb5940ae626..c0b147c2d50062d1b9c87a553552654ac8b00557 100644 --- a/contexthub/aidl/default/Android.bp +++ b/contexthub/aidl/default/Android.bp @@ -30,6 +30,7 @@ cc_library_static { shared_libs: [ "libbase", "libbinder_ndk", + "liblog", "android.hardware.contexthub-V4-ndk", ], export_include_dirs: ["include"], @@ -51,6 +52,7 @@ cc_binary { shared_libs: [ "libbase", "libbinder_ndk", + "liblog", "android.hardware.contexthub-V4-ndk", ], static_libs: [ diff --git a/contexthub/aidl/default/ContextHub.cpp b/contexthub/aidl/default/ContextHub.cpp index 5713a1bf0825d902937f60eab7f62769034b3dd6..4ae9c09213b4d646272712287a34ba65d7215d44 100644 --- a/contexthub/aidl/default/ContextHub.cpp +++ b/contexthub/aidl/default/ContextHub.cpp @@ -16,10 +16,54 @@ #include "contexthub-impl/ContextHub.h" -namespace aidl::android::hardware::contexthub { +#ifndef LOG_TAG +#define LOG_TAG "CHRE" +#endif + +#include +#include using ::ndk::ScopedAStatus; +namespace aidl::android::hardware::contexthub { + +namespace { + +constexpr uint64_t kMockVendorHubId = 0x1234567812345678; +constexpr uint64_t kMockVendorHub2Id = 0x0EADBEEFDEADBEEF; + +// Mock endpoints for the default implementation. +// These endpoints just echo back any messages sent to them. +constexpr size_t kMockEndpointCount = 4; +const EndpointInfo kMockEndpointInfos[kMockEndpointCount] = { + { + .id = {.hubId = kMockVendorHubId, .id = UINT64_C(0x1)}, + .type = EndpointInfo::EndpointType::GENERIC, + .name = "Mock Endpoint 1", + .version = 1, + }, + { + .id = {.hubId = kMockVendorHubId, .id = UINT64_C(0x2)}, + .type = EndpointInfo::EndpointType::GENERIC, + .name = "Mock Endpoint 2", + .version = 2, + }, + { + .id = {.hubId = kMockVendorHub2Id, .id = UINT64_C(0x1)}, + .type = EndpointInfo::EndpointType::GENERIC, + .name = "Mock Endpoint 3", + .version = 1, + }, + { + .id = {.hubId = kMockVendorHub2Id, .id = UINT64_C(0x2)}, + .type = EndpointInfo::EndpointType::GENERIC, + .name = "Mock Endpoint 4", + .version = 2, + }, +}; + +} // anonymous namespace + ScopedAStatus ContextHub::getContextHubs(std::vector* out_contextHubInfos) { ContextHubInfo hub = {}; hub.name = "Mock Context Hub"; @@ -112,7 +156,13 @@ ScopedAStatus ContextHub::sendMessageToHub(int32_t in_contextHubId, } } -ScopedAStatus ContextHub::setTestMode(bool /* enable */) { +ScopedAStatus ContextHub::setTestMode(bool enable) { + if (enable) { + std::unique_lock lock(mEndpointMutex); + mEndpoints.clear(); + mEndpointSessions.clear(); + mEndpointCallback = nullptr; + } return ScopedAStatus::ok(); } @@ -137,6 +187,10 @@ ScopedAStatus ContextHub::sendMessageDeliveryStatusToHub( } ScopedAStatus ContextHub::getHubs(std::vector* _aidl_return) { + if (_aidl_return == nullptr) { + return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + ContextHubInfo hub = {}; hub.name = "Mock Context Hub"; hub.vendor = "AOSP"; @@ -158,61 +212,217 @@ ScopedAStatus ContextHub::getHubs(std::vector* _aidl_return) { vendorHub.version = 42; HubInfo hubInfo2 = {}; - hubInfo1.hubId = UINT64_C(0x1234567812345678); - hubInfo1.hubDetails = + hubInfo2.hubId = kMockVendorHubId; + hubInfo2.hubDetails = HubInfo::HubDetails::make(vendorHub); + VendorHubInfo vendorHub2 = {}; + vendorHub2.name = "Mock Vendor Hub 2"; + vendorHub2.version = 24; + + HubInfo hubInfo3 = {}; + hubInfo3.hubId = kMockVendorHub2Id; + hubInfo3.hubDetails = + HubInfo::HubDetails::make(vendorHub2); + _aidl_return->push_back(hubInfo1); _aidl_return->push_back(hubInfo2); + _aidl_return->push_back(hubInfo3); return ScopedAStatus::ok(); }; -ScopedAStatus ContextHub::getEndpoints(std::vector* /* _aidl_return */) { - return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +ScopedAStatus ContextHub::getEndpoints(std::vector* _aidl_return) { + if (_aidl_return == nullptr) { + return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + + Service echoService; + echoService.format = Service::RpcFormat::CUSTOM; + echoService.serviceDescriptor = "ECHO"; + echoService.majorVersion = 1; + echoService.minorVersion = 0; + + for (const EndpointInfo& endpoint : kMockEndpointInfos) { + EndpointInfo endpointWithService(endpoint); + endpointWithService.services.push_back(echoService); + _aidl_return->push_back(std::move(endpointWithService)); + } + + return ScopedAStatus::ok(); }; -ScopedAStatus ContextHub::registerEndpoint(const EndpointInfo& /* in_endpoint */) { - return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +ScopedAStatus ContextHub::registerEndpoint(const EndpointInfo& in_endpoint) { + std::unique_lock lock(mEndpointMutex); + + for (const EndpointInfo& endpoint : mEndpoints) { + if ((endpoint.id.id == in_endpoint.id.id && endpoint.id.hubId == in_endpoint.id.hubId) || + endpoint.name == in_endpoint.name) { + return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + } + mEndpoints.push_back(in_endpoint); + return ScopedAStatus::ok(); }; -ScopedAStatus ContextHub::unregisterEndpoint(const EndpointInfo& /* in_endpoint */) { - return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +ScopedAStatus ContextHub::unregisterEndpoint(const EndpointInfo& in_endpoint) { + std::unique_lock lock(mEndpointMutex); + + for (auto it = mEndpoints.begin(); it != mEndpoints.end(); ++it) { + if (it->id.id == in_endpoint.id.id && it->id.hubId == in_endpoint.id.hubId) { + mEndpoints.erase(it); + return ScopedAStatus::ok(); + } + } + return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); }; ScopedAStatus ContextHub::registerEndpointCallback( - const std::shared_ptr& /* in_callback */) { - return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + const std::shared_ptr& in_callback) { + std::unique_lock lock(mEndpointMutex); + + mEndpointCallback = in_callback; + return ScopedAStatus::ok(); }; -ScopedAStatus ContextHub::requestSessionIdRange(int32_t /* in_size */, - std::vector* /* _aidl_return */) { - return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +ScopedAStatus ContextHub::requestSessionIdRange(int32_t in_size, + std::vector* _aidl_return) { + constexpr int32_t kMaxSize = 1024; + if (in_size > kMaxSize || _aidl_return == nullptr) { + return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + + { + std::lock_guard lock(mEndpointMutex); + mMaxValidSessionId = in_size; + } + + _aidl_return->push_back(0); + _aidl_return->push_back(in_size); + return ScopedAStatus::ok(); }; ScopedAStatus ContextHub::openEndpointSession( - int32_t /* in_sessionId */, const EndpointId& /* in_destination */, - const EndpointId& /* in_initiator */, - const std::optional& /* in_serviceDescriptor */) { - return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + int32_t in_sessionId, const EndpointId& in_destination, const EndpointId& in_initiator, + const std::optional& in_serviceDescriptor) { + // We are not calling onCloseEndpointSession on failure because the remote endpoints (our + // mock endpoints) always accept the session. + + std::shared_ptr callback = nullptr; + { + std::unique_lock lock(mEndpointMutex); + if (in_sessionId > mMaxValidSessionId) { + ALOGE("openEndpointSession: session ID %" PRId32 " is invalid", in_sessionId); + return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + + for (const EndpointSession& session : mEndpointSessions) { + bool sessionAlreadyExists = + (session.initiator == in_destination && session.peer == in_initiator) || + (session.peer == in_destination && session.initiator == in_initiator); + if (sessionAlreadyExists) { + ALOGD("openEndpointSession: session ID %" PRId32 " already exists", in_sessionId); + return (session.sessionId == in_sessionId && + session.serviceDescriptor == in_serviceDescriptor) + ? ScopedAStatus::ok() + : ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } else if (session.sessionId == in_sessionId) { + ALOGE("openEndpointSession: session ID %" PRId32 " is invalid: endpoint mismatch", + in_sessionId); + return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + } + + // Verify the initiator and destination are valid endpoints + bool initiatorIsValid = findEndpoint(in_initiator, mEndpoints.begin(), mEndpoints.end()); + if (!initiatorIsValid) { + ALOGE("openEndpointSession: initiator %" PRIu64 ":%" PRIu64 " is invalid", + in_initiator.id, in_initiator.hubId); + return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + bool destinationIsValid = findEndpoint(in_destination, &kMockEndpointInfos[0], + &kMockEndpointInfos[kMockEndpointCount]); + if (!destinationIsValid) { + ALOGE("openEndpointSession: destination %" PRIu64 ":%" PRIu64 " is invalid", + in_destination.id, in_destination.hubId); + return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + + mEndpointSessions.push_back({ + .sessionId = in_sessionId, + .initiator = in_initiator, + .peer = in_destination, + .serviceDescriptor = in_serviceDescriptor, + }); + + if (mEndpointCallback != nullptr) { + callback = mEndpointCallback; + } + } + + if (callback != nullptr) { + callback->onEndpointSessionOpenComplete(in_sessionId); + } + return ScopedAStatus::ok(); }; -ScopedAStatus ContextHub::sendMessageToEndpoint(int32_t /* in_sessionId */, - const Message& /* in_msg */) { - return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +ScopedAStatus ContextHub::sendMessageToEndpoint(int32_t in_sessionId, const Message& in_msg) { + bool foundSession = false; + std::shared_ptr callback = nullptr; + { + std::unique_lock lock(mEndpointMutex); + + for (const EndpointSession& session : mEndpointSessions) { + if (session.sessionId == in_sessionId) { + foundSession = true; + break; + } + } + + if (mEndpointCallback != nullptr) { + callback = mEndpointCallback; + } + } + + if (!foundSession) { + ALOGE("sendMessageToEndpoint: session ID %" PRId32 " is invalid", in_sessionId); + return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + + if (callback != nullptr) { + if (in_msg.flags & Message::FLAG_REQUIRES_DELIVERY_STATUS) { + MessageDeliveryStatus msgStatus = {}; + msgStatus.messageSequenceNumber = in_msg.sequenceNumber; + msgStatus.errorCode = ErrorCode::OK; + callback->onMessageDeliveryStatusReceived(in_sessionId, msgStatus); + } + + // Echo the message back + callback->onMessageReceived(in_sessionId, in_msg); + } + return ScopedAStatus::ok(); }; ScopedAStatus ContextHub::sendMessageDeliveryStatusToEndpoint( int32_t /* in_sessionId */, const MessageDeliveryStatus& /* in_msgStatus */) { - return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + return ScopedAStatus::ok(); }; -ScopedAStatus ContextHub::closeEndpointSession(int32_t /* in_sessionId */, Reason /* in_reason */) { - return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +ScopedAStatus ContextHub::closeEndpointSession(int32_t in_sessionId, Reason /* in_reason */) { + std::unique_lock lock(mEndpointMutex); + + for (auto it = mEndpointSessions.begin(); it != mEndpointSessions.end(); ++it) { + if (it->sessionId == in_sessionId) { + mEndpointSessions.erase(it); + return ScopedAStatus::ok(); + } + } + ALOGE("closeEndpointSession: session ID %" PRId32 " is invalid", in_sessionId); + return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); }; ScopedAStatus ContextHub::endpointSessionOpenComplete(int32_t /* in_sessionId */) { - return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + return ScopedAStatus::ok(); }; } // namespace aidl::android::hardware::contexthub diff --git a/contexthub/aidl/default/include/contexthub-impl/ContextHub.h b/contexthub/aidl/default/include/contexthub-impl/ContextHub.h index 5680a779a60c152c9a02e586d4c98a3ed519570c..49688786c1e07023479e2e98ac7c2c8a3cab1a74 100644 --- a/contexthub/aidl/default/include/contexthub-impl/ContextHub.h +++ b/contexthub/aidl/default/include/contexthub-impl/ContextHub.h @@ -18,6 +18,7 @@ #include +#include #include #include @@ -72,10 +73,37 @@ class ContextHub : public BnContextHub { ::ndk::ScopedAStatus endpointSessionOpenComplete(int32_t in_sessionId) override; private: + struct EndpointSession { + int32_t sessionId; + EndpointId initiator; + EndpointId peer; + std::optional serviceDescriptor; + }; + static constexpr uint32_t kMockHubId = 0; + + //! Finds an endpoint in the range defined by the endpoints + //! @return whether the endpoint was found + template + bool findEndpoint(const EndpointId& target, const Iter& begin, const Iter& end) { + for (auto iter = begin; iter != end; ++iter) { + if (iter->id.id == target.id && iter->id.hubId == target.hubId) { + return true; + } + } + return false; + } + std::shared_ptr mCallback; std::unordered_set mConnectedHostEndpoints; + + //! Endpoint storage and information + std::mutex mEndpointMutex; + std::vector mEndpoints; + std::vector mEndpointSessions; + std::shared_ptr mEndpointCallback; + int32_t mMaxValidSessionId = 0; }; } // namespace contexthub diff --git a/contexthub/aidl/vts/Android.bp b/contexthub/aidl/vts/Android.bp index 62a319ec6bacb86c52d482e942f759d8593b2dcf..a19b6fd700030ec2370401dbd329890e6eca9b21 100644 --- a/contexthub/aidl/vts/Android.bp +++ b/contexthub/aidl/vts/Android.bp @@ -33,7 +33,7 @@ cc_test { "libbinder", ], static_libs: [ - "android.hardware.contexthub-V3-cpp", + "android.hardware.contexthub-V4-cpp", "VtsHalContexthubUtils", ], test_suites: [ diff --git a/contexthub/aidl/vts/VtsAidlHalContextHubTargetTest.cpp b/contexthub/aidl/vts/VtsAidlHalContextHubTargetTest.cpp index fa427a56a926510f56ffcbd70f8b97211e4c09f5..95a96cd77894625bf074d8ee723b717063d8676b 100644 --- a/contexthub/aidl/vts/VtsAidlHalContextHubTargetTest.cpp +++ b/contexthub/aidl/vts/VtsAidlHalContextHubTargetTest.cpp @@ -20,8 +20,10 @@ #include #include +#include #include #include +#include #include #include #include @@ -34,18 +36,25 @@ using ::android::sp; using ::android::String16; using ::android::binder::Status; using ::android::hardware::contexthub::AsyncEventType; +using ::android::hardware::contexthub::BnEndpointCallback; using ::android::hardware::contexthub::ContextHubInfo; using ::android::hardware::contexthub::ContextHubMessage; +using ::android::hardware::contexthub::EndpointId; +using ::android::hardware::contexthub::EndpointInfo; using ::android::hardware::contexthub::ErrorCode; using ::android::hardware::contexthub::HostEndpointInfo; +using ::android::hardware::contexthub::HubInfo; using ::android::hardware::contexthub::IContextHub; using ::android::hardware::contexthub::IContextHubCallbackDefault; +using ::android::hardware::contexthub::Message; using ::android::hardware::contexthub::MessageDeliveryStatus; using ::android::hardware::contexthub::NanoappBinary; using ::android::hardware::contexthub::NanoappInfo; using ::android::hardware::contexthub::NanoappRpcService; using ::android::hardware::contexthub::NanSessionRequest; using ::android::hardware::contexthub::NanSessionStateUpdate; +using ::android::hardware::contexthub::Reason; +using ::android::hardware::contexthub::Service; using ::android::hardware::contexthub::Setting; using ::android::hardware::contexthub::vts_utils::kNonExistentAppId; using ::android::hardware::contexthub::vts_utils::waitForCallback; @@ -61,8 +70,14 @@ class ContextHubAidl : public testing::TestWithParam( String16(std::get<0>(GetParam()).c_str())); ASSERT_NE(contextHub, nullptr); + + // Best effort enable test mode - this may not be supported on older HALS, so we + // ignore the return value. + contextHub->setTestMode(/* enable= */ true); } + virtual void TearDown() override { contextHub->setTestMode(/* enable= */ false); } + uint32_t getHubId() { return std::get<1>(GetParam()); } void testSettingChanged(Setting setting); @@ -465,6 +480,290 @@ TEST_P(ContextHubAidl, TestSendMessageDeliveryStatusToHub) { } } +class TestEndpointCallback : public BnEndpointCallback { + public: + Status onEndpointStarted(const std::vector& /* endpointInfos */) override { + return Status::ok(); + } + + Status onEndpointStopped(const std::vector& /* endpointIds */, + Reason /* reason */) override { + return Status::ok(); + } + + Status onMessageReceived(int32_t /* sessionId */, const Message& message) override { + mMessages.push_back(message); + return Status::ok(); + } + + Status onMessageDeliveryStatusReceived(int32_t /* sessionId */, + const MessageDeliveryStatus& /* msgStatus */) override { + return Status::ok(); + } + + Status onEndpointSessionOpenRequest( + int32_t /* sessionId */, const EndpointId& /* destination */, + const EndpointId& /* initiator */, + const std::optional& /* serviceDescriptor */) override { + return Status::ok(); + } + + Status onCloseEndpointSession(int32_t /* sessionId */, Reason /* reason */) override { + return Status::ok(); + } + + Status onEndpointSessionOpenComplete(int32_t /* sessionId */) override { + mWasOnEndpointSessionOpenCompleteCalled = true; + return Status::ok(); + } + + std::vector getMessages() { return mMessages; } + + bool wasOnEndpointSessionOpenCompleteCalled() { + return mWasOnEndpointSessionOpenCompleteCalled; + } + void resetWasOnEndpointSessionOpenCompleteCalled() { + mWasOnEndpointSessionOpenCompleteCalled = false; + } + + private: + std::vector mMessages; + bool mWasOnEndpointSessionOpenCompleteCalled = false; +}; + +TEST_P(ContextHubAidl, RegisterEndpoint) { + EndpointInfo endpointInfo; + endpointInfo.id.id = 1; + endpointInfo.id.hubId = 0xCAFECAFECAFECAFE; + endpointInfo.type = EndpointInfo::EndpointType::NATIVE; + endpointInfo.name = String16("Test host endpoint 1"); + endpointInfo.version = 42; + + Status status = contextHub->registerEndpoint(endpointInfo); + if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION || + status.transactionError() == android::UNKNOWN_TRANSACTION) { + GTEST_SKIP() << "Not supported -> old API; or not implemented"; + } else { + EXPECT_TRUE(status.isOk()); + } +} + +TEST_P(ContextHubAidl, RegisterEndpointSameNameFailure) { + EndpointInfo endpointInfo; + endpointInfo.id.id = 2; + endpointInfo.id.hubId = 0xCAFECAFECAFECAFE; + endpointInfo.type = EndpointInfo::EndpointType::NATIVE; + endpointInfo.name = String16("Test host endpoint 2"); + endpointInfo.version = 42; + + EndpointInfo endpointInfo2; + endpointInfo2.id.id = 3; + endpointInfo2.id.hubId = 0xCAFECAFECAFECAFE; + endpointInfo2.type = EndpointInfo::EndpointType::NATIVE; + endpointInfo2.name = String16("Test host endpoint 2"); + endpointInfo2.version = 42; + + Status status = contextHub->registerEndpoint(endpointInfo); + if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION || + status.transactionError() == android::UNKNOWN_TRANSACTION) { + GTEST_SKIP() << "Not supported -> old API; or not implemented"; + } else { + EXPECT_TRUE(status.isOk()); + } + + EXPECT_FALSE(contextHub->registerEndpoint(endpointInfo2).isOk()); +} + +TEST_P(ContextHubAidl, RegisterEndpointSameIdFailure) { + EndpointInfo endpointInfo; + endpointInfo.id.id = 4; + endpointInfo.id.hubId = 0xCAFECAFECAFECAFE; + endpointInfo.type = EndpointInfo::EndpointType::NATIVE; + endpointInfo.name = String16("Test host endpoint 4"); + endpointInfo.version = 42; + + EndpointInfo endpointInfo2; + endpointInfo2.id.id = 4; + endpointInfo2.id.hubId = 0xCAFECAFECAFECAFE; + endpointInfo2.type = EndpointInfo::EndpointType::NATIVE; + endpointInfo2.name = String16("Test host endpoint - same ID test"); + endpointInfo2.version = 42; + + Status status = contextHub->registerEndpoint(endpointInfo); + if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION || + status.transactionError() == android::UNKNOWN_TRANSACTION) { + GTEST_SKIP() << "Not supported -> old API; or not implemented"; + } else { + EXPECT_TRUE(status.isOk()); + } + + EXPECT_FALSE(contextHub->registerEndpoint(endpointInfo2).isOk()); +} + +TEST_P(ContextHubAidl, UnregisterEndpoint) { + EndpointInfo endpointInfo; + endpointInfo.id.id = 6; + endpointInfo.id.hubId = 0xCAFECAFECAFECAFE; + endpointInfo.type = EndpointInfo::EndpointType::NATIVE; + endpointInfo.name = String16("Test host endpoint 6"); + endpointInfo.version = 42; + + Status status = contextHub->registerEndpoint(endpointInfo); + if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION || + status.transactionError() == android::UNKNOWN_TRANSACTION) { + GTEST_SKIP() << "Not supported -> old API; or not implemented"; + } else { + EXPECT_TRUE(status.isOk()); + } + + EXPECT_TRUE(contextHub->unregisterEndpoint(endpointInfo).isOk()); +} + +TEST_P(ContextHubAidl, UnregisterEndpointNonexistent) { + EndpointInfo endpointInfo; + endpointInfo.id.id = 100; + endpointInfo.id.hubId = 0xCAFECAFECAFECAFE; + endpointInfo.type = EndpointInfo::EndpointType::NATIVE; + endpointInfo.name = String16("Test host endpoint 100"); + endpointInfo.version = 42; + + Status status = contextHub->unregisterEndpoint(endpointInfo); + if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION || + status.transactionError() == android::UNKNOWN_TRANSACTION) { + GTEST_SKIP() << "Not supported -> old API; or not implemented"; + } else { + EXPECT_FALSE(status.isOk()); + } +} + +TEST_P(ContextHubAidl, RegisterCallback) { + auto cb = sp::make(); + Status status = contextHub->registerEndpointCallback(cb); + if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION || + status.transactionError() == android::UNKNOWN_TRANSACTION) { + GTEST_SKIP() << "Not supported -> old API; or not implemented"; + } else { + EXPECT_TRUE(status.isOk()); + } +} + +TEST_P(ContextHubAidl, OpenEndpointSessionInvalidRange) { + auto cb = sp::make(); + Status status = contextHub->registerEndpointCallback(cb); + if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION || + status.transactionError() == android::UNKNOWN_TRANSACTION) { + GTEST_SKIP() << "Not supported -> old API; or not implemented"; + } else { + EXPECT_TRUE(status.isOk()); + } + + // Register the endpoint + EndpointInfo initiatorEndpoint; + initiatorEndpoint.id.id = 7; + initiatorEndpoint.id.hubId = 0xCAFECAFECAFECAFE; + initiatorEndpoint.type = EndpointInfo::EndpointType::NATIVE; + initiatorEndpoint.name = String16("Test host endpoint 7"); + initiatorEndpoint.version = 42; + EXPECT_TRUE(contextHub->registerEndpoint(initiatorEndpoint).isOk()); + + // Find the destination, if it exists + std::vector endpoints; + EXPECT_TRUE(contextHub->getEndpoints(&endpoints).isOk()); + const EndpointInfo* destinationEndpoint = nullptr; + for (const EndpointInfo& endpoint : endpoints) { + for (const Service& service : endpoint.services) { + if (service.serviceDescriptor == String16("ECHO")) { + destinationEndpoint = &endpoint; + break; + } + } + } + if (destinationEndpoint == nullptr) { + return; // no echo service endpoint -> just return + } + + // Request the range + constexpr int32_t requestedRange = 100; + std::vector range; + ASSERT_TRUE(contextHub->requestSessionIdRange(requestedRange, &range).isOk()); + EXPECT_EQ(range.size(), 2); + EXPECT_GE(range[1] - range[0] + 1, requestedRange); + + // Open the session + cb->resetWasOnEndpointSessionOpenCompleteCalled(); + int32_t sessionId = range[1] + 10; // invalid + EXPECT_FALSE(contextHub + ->openEndpointSession(sessionId, destinationEndpoint->id, + initiatorEndpoint.id, + /* in_serviceDescriptor= */ String16("ECHO")) + .isOk()); + EXPECT_FALSE(cb->wasOnEndpointSessionOpenCompleteCalled()); +} + +TEST_P(ContextHubAidl, OpenEndpointSessionAndSendMessageEchoesBack) { + auto cb = sp::make(); + Status status = contextHub->registerEndpointCallback(cb); + if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION || + status.transactionError() == android::UNKNOWN_TRANSACTION) { + GTEST_SKIP() << "Not supported -> old API; or not implemented"; + } else { + EXPECT_TRUE(status.isOk()); + } + + // Register the endpoint + EndpointInfo initiatorEndpoint; + initiatorEndpoint.id.id = 8; + initiatorEndpoint.id.hubId = 0xCAFECAFECAFECAFE; + initiatorEndpoint.type = EndpointInfo::EndpointType::NATIVE; + initiatorEndpoint.name = String16("Test host endpoint 7"); + initiatorEndpoint.version = 42; + EXPECT_TRUE(contextHub->registerEndpoint(initiatorEndpoint).isOk()); + + // Find the destination, if it exists + std::vector endpoints; + EXPECT_TRUE(contextHub->getEndpoints(&endpoints).isOk()); + const EndpointInfo* destinationEndpoint = nullptr; + for (const EndpointInfo& endpoint : endpoints) { + for (const Service& service : endpoint.services) { + if (service.serviceDescriptor == String16("ECHO")) { + destinationEndpoint = &endpoint; + break; + } + } + } + if (destinationEndpoint == nullptr) { + return; // no echo service endpoint -> just return + } + + // Request the range + constexpr int32_t requestedRange = 100; + std::vector range; + ASSERT_TRUE(contextHub->requestSessionIdRange(requestedRange, &range).isOk()); + EXPECT_EQ(range.size(), 2); + EXPECT_GE(range[1] - range[0] + 1, requestedRange); + + // Open the session + cb->resetWasOnEndpointSessionOpenCompleteCalled(); + int32_t sessionId = range[0]; + ASSERT_TRUE(contextHub + ->openEndpointSession(sessionId, destinationEndpoint->id, + initiatorEndpoint.id, + /* in_serviceDescriptor= */ String16("ECHO")) + .isOk()); + EXPECT_TRUE(cb->wasOnEndpointSessionOpenCompleteCalled()); + + // Send the message + Message message; + message.flags = 0; + message.sequenceNumber = 0; + message.content.push_back(42); + ASSERT_TRUE(contextHub->sendMessageToEndpoint(sessionId, message).isOk()); + + // Check for echo + EXPECT_FALSE(cb->getMessages().empty()); + EXPECT_EQ(cb->getMessages().back().content.back(), 42); +} + std::string PrintGeneratedTest(const testing::TestParamInfo& info) { return std::string("CONTEXT_HUB_ID_") + std::to_string(std::get<1>(info.param)); } diff --git a/gnss/1.1/default/Android.bp b/gnss/1.1/default/Android.bp index 697cb91f4f9ca675094137d62a67fdd8f15ce82a..6c338bdcf584d7238053c1be13d22799d824b02d 100644 --- a/gnss/1.1/default/Android.bp +++ b/gnss/1.1/default/Android.bp @@ -27,7 +27,7 @@ cc_binary { "android.hardware.gnss@2.0", "android.hardware.gnss@1.1", "android.hardware.gnss@1.0", - "android.hardware.gnss-V4-ndk", + "android.hardware.gnss-V5-ndk", ], static_libs: [ "android.hardware.gnss@common-default-lib", diff --git a/gnss/1.1/vts/functional/Android.bp b/gnss/1.1/vts/functional/Android.bp index 65c752c97739292122a70a8501d85a6d4ca513cc..1398462939756c986ba35bc04c32e05e61da6323 100644 --- a/gnss/1.1/vts/functional/Android.bp +++ b/gnss/1.1/vts/functional/Android.bp @@ -37,7 +37,7 @@ cc_test { "android.hardware.gnss@1.1", "android.hardware.gnss@2.0", "android.hardware.gnss@common-vts-lib", - "android.hardware.gnss-V4-cpp", + "android.hardware.gnss-V5-cpp", ], shared_libs: [ "android.hardware.gnss.measurement_corrections@1.0", diff --git a/gnss/2.0/default/Android.bp b/gnss/2.0/default/Android.bp index 35c2e376ac74189f27634fdc1419399362623651..6a4965b648fad00f5bbd1642f7e8557af612eb37 100644 --- a/gnss/2.0/default/Android.bp +++ b/gnss/2.0/default/Android.bp @@ -50,7 +50,7 @@ cc_binary { "android.hardware.gnss@2.0", "android.hardware.gnss@1.1", "android.hardware.gnss@1.0", - "android.hardware.gnss-V4-ndk", + "android.hardware.gnss-V5-ndk", ], static_libs: [ "android.hardware.gnss@common-default-lib", diff --git a/gnss/2.0/vts/functional/Android.bp b/gnss/2.0/vts/functional/Android.bp index 4ca30630e81e308558aa8995c45b4bcd98197317..08d4cb3316ec310a04c12bc3945bac83cd5989f4 100644 --- a/gnss/2.0/vts/functional/Android.bp +++ b/gnss/2.0/vts/functional/Android.bp @@ -40,7 +40,7 @@ cc_test { "android.hardware.gnss@2.0", "android.hardware.gnss@2.1", "android.hardware.gnss@common-vts-lib", - "android.hardware.gnss-V4-cpp", + "android.hardware.gnss-V5-cpp", ], test_suites: [ "general-tests", diff --git a/gnss/2.1/default/Android.bp b/gnss/2.1/default/Android.bp index 1bb75121139b31698b59af18666ae3c941c5ab08..a2e652eaf6a96b602bb672735757bdac9c76e614 100644 --- a/gnss/2.1/default/Android.bp +++ b/gnss/2.1/default/Android.bp @@ -44,7 +44,7 @@ cc_binary { "android.hardware.gnss@1.0", "android.hardware.gnss@1.1", "android.hardware.gnss@2.0", - "android.hardware.gnss-V4-ndk", + "android.hardware.gnss-V5-ndk", ], static_libs: [ "android.hardware.gnss@common-default-lib", diff --git a/gnss/2.1/vts/functional/Android.bp b/gnss/2.1/vts/functional/Android.bp index af660378d9f8b505b16d12ea5c5532a217a19d2d..8a8fa93bc1a06d53d30c8dad9cf97ba0439d25c8 100644 --- a/gnss/2.1/vts/functional/Android.bp +++ b/gnss/2.1/vts/functional/Android.bp @@ -41,7 +41,7 @@ cc_test { "android.hardware.gnss@2.0", "android.hardware.gnss@2.1", "android.hardware.gnss@common-vts-lib", - "android.hardware.gnss-V4-cpp", + "android.hardware.gnss-V5-cpp", ], shared_libs: [ "libvintf", diff --git a/gnss/aidl/Android.bp b/gnss/aidl/Android.bp index 47fc3af6d0c9bf174e1f652cdfdff4983fb792ef..6e159a154b59435bb95db0a7ffdfd0626fdfbf1e 100644 --- a/gnss/aidl/Android.bp +++ b/gnss/aidl/Android.bp @@ -30,6 +30,7 @@ aidl_interface { "android/hardware/gnss/*.aidl", "android/hardware/gnss/measurement_corrections/*.aidl", "android/hardware/gnss/visibility_control/*.aidl", + "android/hardware/gnss/gnss_assistance/*.aidl", ], stability: "vintf", backend: { @@ -56,6 +57,6 @@ aidl_interface { }, ], - frozen: true, + frozen: false, } diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl index d1aaf2c4578eceffab6b8d477dda0b1b1e91f4be..fc746127353b4df81293dd8ade68b9a517e366f1 100644 --- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl @@ -61,6 +61,7 @@ interface IGnss { void stopSvStatus(); void startNmea(); void stopNmea(); + android.hardware.gnss.gnss_assistance.IGnssAssistanceInterface getExtensionGnssAssistanceInterface(); const int ERROR_INVALID_ARGUMENT = 1; const int ERROR_ALREADY_INIT = 2; const int ERROR_GENERIC = 3; diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/BeidouSatelliteEphemeris.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/BeidouSatelliteEphemeris.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ec517e60b157a445be522bc88379622b40516113 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/BeidouSatelliteEphemeris.aidl @@ -0,0 +1,47 @@ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss.gnss_assistance; +/* @hide */ +@VintfStability +parcelable BeidouSatelliteEphemeris { + int prn; + android.hardware.gnss.gnss_assistance.BeidouSatelliteEphemeris.BeidouSatelliteClockModel satelliteClockModel; + android.hardware.gnss.gnss_assistance.KeplerianOrbitModel satelliteOrbitModel; + android.hardware.gnss.gnss_assistance.BeidouSatelliteEphemeris.BeidouSatelliteHealth satelliteHealth; + android.hardware.gnss.gnss_assistance.BeidouSatelliteEphemeris.BeidouSatelliteEphemerisTime satelliteEphemerisTime; + @VintfStability + parcelable BeidouSatelliteClockModel { + long timeOfClockSeconds; + double af0; + double af1; + double af2; + double tgd1; + double tgd2; + int aodc; + } + parcelable BeidouSatelliteHealth { + int satH1; + double svAccur; + } + parcelable BeidouSatelliteEphemerisTime { + int aode; + int weekNumber; + int toeSeconds; + } +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/GalileoIonosphericModel.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/GalileoIonosphericModel.aidl new file mode 100644 index 0000000000000000000000000000000000000000..6d8040bb859269128016735e6541a9cd4643e873 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/GalileoIonosphericModel.aidl @@ -0,0 +1,41 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss.gnss_assistance; +/* @hide */ +@VintfStability +parcelable GalileoIonosphericModel { + double ai0; + double ai1; + double ai2; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/GalileoSatelliteEphemeris.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/GalileoSatelliteEphemeris.aidl new file mode 100644 index 0000000000000000000000000000000000000000..1bac08e55ff64e1520010f44dcd83c679e97b382 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/GalileoSatelliteEphemeris.aidl @@ -0,0 +1,68 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss.gnss_assistance; +/* @hide */ +@VintfStability +parcelable GalileoSatelliteEphemeris { + int satelliteCodeNumber; + android.hardware.gnss.gnss_assistance.GalileoSatelliteEphemeris.GalileoSatelliteClockModel[] satelliteClockModel; + android.hardware.gnss.gnss_assistance.KeplerianOrbitModel satelliteOrbitModel; + android.hardware.gnss.gnss_assistance.GalileoSatelliteEphemeris.GalileoSvHealth svHealth; + android.hardware.gnss.gnss_assistance.SatelliteEphemerisTime satelliteEphemerisTime; + @VintfStability + parcelable GalileoSatelliteClockModel { + long timeOfClockSeconds; + double af0; + double af1; + double af2; + double bgdSeconds; + double sisaMeters; + android.hardware.gnss.gnss_assistance.GalileoSatelliteEphemeris.GalileoSatelliteClockModel.SatelliteClockType satelliteClockType; + @Backing(type="int") @VintfStability + enum SatelliteClockType { + UNDEFINED = 0, + GALILEO_FNAV_CLOCK = 1, + GALILEO_INAV_CLOCK = 2, + } + } + @VintfStability + parcelable GalileoSvHealth { + int dataValidityStatusE1b; + int signalHealthStatusE1b; + int dataValidityStatusE5a; + int signalHealthStatusE5a; + int dataValidityStatusE5b; + int signalHealthStatusE5b; + } +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/GlonassAlmanac.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/GlonassAlmanac.aidl new file mode 100644 index 0000000000000000000000000000000000000000..55621ab7fcdb8b7c9e5484bc85e33827487462db --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/GlonassAlmanac.aidl @@ -0,0 +1,39 @@ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss.gnss_assistance; +/* @hide */ +@VintfStability +parcelable GlonassAlmanac { + long issueDateMs; + android.hardware.gnss.gnss_assistance.GlonassAlmanac.GlonassSatelliteAlmanac[] satelliteAlmanac; + @VintfStability + parcelable GlonassSatelliteAlmanac { + int slotNumber; + int svHealth; + int frequencyChannel; + double tau; + double tLambda; + double lambda; + double deltaI; + double deltaT; + double deltaTDot; + double eccentricity; + double omega; + } +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/GlonassSatelliteEphemeris.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/GlonassSatelliteEphemeris.aidl new file mode 100644 index 0000000000000000000000000000000000000000..bbcb3af07e9cf7daec0c4f59732d193bedb5e2f1 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/GlonassSatelliteEphemeris.aidl @@ -0,0 +1,63 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss.gnss_assistance; +/* @hide */ +@VintfStability +parcelable GlonassSatelliteEphemeris { + int slotNumber; + int svHealth; + double frameTimeSeconds; + int ageInDays; + android.hardware.gnss.gnss_assistance.GlonassSatelliteEphemeris.GlonassSatelliteClockModel satelliteClockModel; + android.hardware.gnss.gnss_assistance.GlonassSatelliteEphemeris.GlonassSatelliteOrbitModel satelliteOrbitModel; + @VintfStability + parcelable GlonassSatelliteClockModel { + long timeOfClockSeconds; + double clockBias; + double freqBias; + int freqNumber; + } + @VintfStability + parcelable GlonassSatelliteOrbitModel { + double x; + double xDot; + double xAccel; + double y; + double yDot; + double yAccel; + double z; + double zDot; + double zAccel; + } +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/GnssAlmanac.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/GnssAlmanac.aidl new file mode 100644 index 0000000000000000000000000000000000000000..b986be485affec37c32b5b883083ca4739cb0956 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/GnssAlmanac.aidl @@ -0,0 +1,57 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss.gnss_assistance; +/* @hide */ +@VintfStability +parcelable GnssAlmanac { + long issueDateMs; + int iod; + int weekNumber; + int toaSeconds; + android.hardware.gnss.gnss_assistance.GnssAlmanac.GnssSatelliteAlmanac[] satelliteAlmanac; + @VintfStability + parcelable GnssSatelliteAlmanac { + int svid; + int svHealth; + double eccentricity; + double inclination; + double omega; + double omega0; + double omegaDot; + double rootA; + double m0; + double af0; + double af1; + } +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/GnssAssistance.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/GnssAssistance.aidl new file mode 100644 index 0000000000000000000000000000000000000000..5f8fee778591f974618fc90733db151e898a6474 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/GnssAssistance.aidl @@ -0,0 +1,100 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss.gnss_assistance; +/* @hide */ +@VintfStability +parcelable GnssAssistance { + android.hardware.gnss.gnss_assistance.GnssAssistance.GpsAssistance gpsAssistance; + android.hardware.gnss.gnss_assistance.GnssAssistance.GlonassAssistance glonassAssistance; + android.hardware.gnss.gnss_assistance.GnssAssistance.GalileoAssistance galileoAssistance; + android.hardware.gnss.gnss_assistance.GnssAssistance.BeidouAssistance beidouAssistance; + android.hardware.gnss.gnss_assistance.GnssAssistance.QzssAssistance qzssAssistance; + @VintfStability + parcelable GnssSatelliteCorrections { + int svid; + android.hardware.gnss.gnss_assistance.IonosphericCorrection[] inonosphericCorrections; + } + @VintfStability + parcelable GpsAssistance { + android.hardware.gnss.gnss_assistance.GnssAlmanac almanac; + android.hardware.gnss.gnss_assistance.KlobucharIonosphericModel ionosphericModel; + android.hardware.gnss.gnss_assistance.UtcModel utcModel; + android.hardware.gnss.gnss_assistance.LeapSecondsModel leapSecondsModel; + android.hardware.gnss.gnss_assistance.TimeModel[] timeModels; + android.hardware.gnss.gnss_assistance.GpsSatelliteEphemeris[] satelliteEphemeris; + android.hardware.gnss.gnss_assistance.RealTimeIntegrityModel[] realTimeIntegrityModels; + android.hardware.gnss.gnss_assistance.GnssAssistance.GnssSatelliteCorrections[] satelliteCorrections; + } + @VintfStability + parcelable GalileoAssistance { + android.hardware.gnss.gnss_assistance.GnssAlmanac almanac; + android.hardware.gnss.gnss_assistance.GalileoIonosphericModel ionosphericModel; + android.hardware.gnss.gnss_assistance.UtcModel utcModel; + android.hardware.gnss.gnss_assistance.LeapSecondsModel leapSecondsModel; + android.hardware.gnss.gnss_assistance.TimeModel[] timeModels; + android.hardware.gnss.gnss_assistance.GalileoSatelliteEphemeris[] satelliteEphemeris; + android.hardware.gnss.gnss_assistance.RealTimeIntegrityModel[] realTimeIntegrityModels; + android.hardware.gnss.gnss_assistance.GnssAssistance.GnssSatelliteCorrections[] satelliteCorrections; + } + @VintfStability + parcelable GlonassAssistance { + android.hardware.gnss.gnss_assistance.GlonassAlmanac almanac; + android.hardware.gnss.gnss_assistance.UtcModel utcModel; + android.hardware.gnss.gnss_assistance.TimeModel[] timeModels; + android.hardware.gnss.gnss_assistance.GlonassSatelliteEphemeris[] satelliteEphemeris; + android.hardware.gnss.gnss_assistance.GnssAssistance.GnssSatelliteCorrections[] satelliteCorrections; + } + @VintfStability + parcelable QzssAssistance { + android.hardware.gnss.gnss_assistance.GnssAlmanac almanac; + android.hardware.gnss.gnss_assistance.KlobucharIonosphericModel ionosphericModel; + android.hardware.gnss.gnss_assistance.UtcModel utcModel; + android.hardware.gnss.gnss_assistance.LeapSecondsModel leapSecondsModel; + android.hardware.gnss.gnss_assistance.TimeModel[] timeModels; + android.hardware.gnss.gnss_assistance.QzssSatelliteEphemeris[] satelliteEphemeris; + android.hardware.gnss.gnss_assistance.RealTimeIntegrityModel[] realTimeIntegrityModels; + android.hardware.gnss.gnss_assistance.GnssAssistance.GnssSatelliteCorrections[] satelliteCorrections; + } + @VintfStability + parcelable BeidouAssistance { + android.hardware.gnss.gnss_assistance.GnssAlmanac almanac; + android.hardware.gnss.gnss_assistance.KlobucharIonosphericModel ionosphericModel; + android.hardware.gnss.gnss_assistance.UtcModel utcModel; + android.hardware.gnss.gnss_assistance.LeapSecondsModel leapSecondsModel; + android.hardware.gnss.gnss_assistance.TimeModel[] timeModels; + android.hardware.gnss.gnss_assistance.BeidouSatelliteEphemeris[] satelliteEphemeris; + android.hardware.gnss.gnss_assistance.RealTimeIntegrityModel[] realTimeIntegrityModels; + android.hardware.gnss.gnss_assistance.GnssAssistance.GnssSatelliteCorrections[] satelliteCorrections; + } +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/GnssCorrectionComponent.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/GnssCorrectionComponent.aidl new file mode 100644 index 0000000000000000000000000000000000000000..2d43bb3d633937aba3c4cd73842c08f10f2435b7 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/GnssCorrectionComponent.aidl @@ -0,0 +1,37 @@ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss.gnss_assistance; +/* @hide */ +@VintfStability +parcelable GnssCorrectionComponent { + String sourceKey; + android.hardware.gnss.gnss_assistance.GnssCorrectionComponent.GnssInterval validityInterval; + android.hardware.gnss.gnss_assistance.GnssCorrectionComponent.PseudorangeCorrection pseudorangeCorrection; + @VintfStability + parcelable GnssInterval { + long startMillisSinceGpsEpoch; + long endMillisSinceGpsEpoch; + } + @VintfStability + parcelable PseudorangeCorrection { + double correctionMeters; + double correctionUncertaintyMeters; + double correctionRateMetersPerSecond; + } +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/GpsSatelliteEphemeris.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/GpsSatelliteEphemeris.aidl new file mode 100644 index 0000000000000000000000000000000000000000..721edb409607d86ebb34bd025b133d2a8cae7cca --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/GpsSatelliteEphemeris.aidl @@ -0,0 +1,64 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss.gnss_assistance; +/* @hide */ +@VintfStability +parcelable GpsSatelliteEphemeris { + int prn; + android.hardware.gnss.gnss_assistance.GpsSatelliteEphemeris.GpsL2Params gpsL2Params; + android.hardware.gnss.gnss_assistance.GpsSatelliteEphemeris.GpsSatelliteClockModel satelliteClockModel; + android.hardware.gnss.gnss_assistance.KeplerianOrbitModel satelliteOrbitModel; + android.hardware.gnss.gnss_assistance.GpsSatelliteEphemeris.GpsSatelliteHealth satelliteHealth; + android.hardware.gnss.gnss_assistance.SatelliteEphemerisTime satelliteEphemerisTime; + @VintfStability + parcelable GpsL2Params { + int l2Code; + int l2Flag; + } + @VintfStability + parcelable GpsSatelliteClockModel { + long timeOfClockSeconds; + double af0; + double af1; + double af2; + double tgd; + int iodc; + } + @VintfStability + parcelable GpsSatelliteHealth { + int svHealth; + double svAccur; + double fitInt; + } +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/IGnssAssistanceCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/IGnssAssistanceCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..602a249730dc1a4a518206ffbdfea971a2c06017 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/IGnssAssistanceCallback.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss.gnss_assistance; +/* @hide */ +@VintfStability +interface IGnssAssistanceCallback { + void injectRequestCb(); +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/IGnssAssistanceInterface.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/IGnssAssistanceInterface.aidl new file mode 100644 index 0000000000000000000000000000000000000000..4dd5cf6aa1d4534b6a8bb291fb103f4bee23f4c1 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/IGnssAssistanceInterface.aidl @@ -0,0 +1,40 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss.gnss_assistance; +/* @hide */ +@VintfStability +interface IGnssAssistanceInterface { + void injectGnssAssistance(in android.hardware.gnss.gnss_assistance.GnssAssistance gnssAssistance); + void setCallback(in android.hardware.gnss.gnss_assistance.IGnssAssistanceCallback callback); +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/IonosphericCorrection.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/IonosphericCorrection.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e02d97fd0b886991491a04cb0d17851c9dd1bc9e --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/IonosphericCorrection.aidl @@ -0,0 +1,40 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss.gnss_assistance; +/* @hide */ +@VintfStability +parcelable IonosphericCorrection { + long carrierFrequencyHz; + android.hardware.gnss.gnss_assistance.GnssCorrectionComponent ionosphericCorrection; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/KeplerianOrbitModel.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/KeplerianOrbitModel.aidl new file mode 100644 index 0000000000000000000000000000000000000000..835c6ec43abb664e6faaeaaa90cf0d0b466dd722 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/KeplerianOrbitModel.aidl @@ -0,0 +1,57 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss.gnss_assistance; +/* @hide */ +@VintfStability +parcelable KeplerianOrbitModel { + double rootA; + double eccentricity; + double i0; + double iDot; + double omega; + double omega0; + double omegaDot; + double m0; + double deltaN; + android.hardware.gnss.gnss_assistance.KeplerianOrbitModel.SecondOrderHarmonicPerturbation secondOrderHarmonicPerturbation; + @VintfStability + parcelable SecondOrderHarmonicPerturbation { + double cic; + double cis; + double crc; + double crs; + double cuc; + double cus; + } +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/KlobucharIonosphericModel.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/KlobucharIonosphericModel.aidl new file mode 100644 index 0000000000000000000000000000000000000000..5a0caa5680660f3bb0b82ae0c1bea465da7b9996 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/KlobucharIonosphericModel.aidl @@ -0,0 +1,46 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss.gnss_assistance; +/* @hide */ +@VintfStability +parcelable KlobucharIonosphericModel { + double alpha0; + double alpha1; + double alpha2; + double alpha3; + double beta0; + double beta1; + double beta2; + double beta3; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/LeapSecondsModel.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/LeapSecondsModel.aidl new file mode 100644 index 0000000000000000000000000000000000000000..bc38b9b02013f118dc82d1246d93d453d5e873e4 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/LeapSecondsModel.aidl @@ -0,0 +1,42 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss.gnss_assistance; +/* @hide */ +@VintfStability +parcelable LeapSecondsModel { + int leapSeconds; + int leapSecondsFuture; + int weekNumberLeapSecondsFuture; + int dayNumberLeapSecondsFuture; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/QzssSatelliteEphemeris.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/QzssSatelliteEphemeris.aidl new file mode 100644 index 0000000000000000000000000000000000000000..5bb1c979986cbf6cf00693c40ee6b10428c2ff2d --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/QzssSatelliteEphemeris.aidl @@ -0,0 +1,44 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss.gnss_assistance; +/* @hide */ +@VintfStability +parcelable QzssSatelliteEphemeris { + int prn; + android.hardware.gnss.gnss_assistance.GpsSatelliteEphemeris.GpsL2Params gpsL2Params; + android.hardware.gnss.gnss_assistance.GpsSatelliteEphemeris.GpsSatelliteClockModel satelliteClockModel; + android.hardware.gnss.gnss_assistance.KeplerianOrbitModel satelliteOrbitModel; + android.hardware.gnss.gnss_assistance.GpsSatelliteEphemeris.GpsSatelliteHealth satelliteHealth; + android.hardware.gnss.gnss_assistance.SatelliteEphemerisTime satelliteEphemerisTime; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/RealTimeIntegrityModel.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/RealTimeIntegrityModel.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c7379e1d3fe0b799d6780cd5661c19a324d503ff --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/RealTimeIntegrityModel.aidl @@ -0,0 +1,45 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss.gnss_assistance; +/* @hide */ +@VintfStability +parcelable RealTimeIntegrityModel { + int svid; + boolean usable; + long publishDateSeconds; + long startDateSeconds; + long endDateSeconds; + String advisoryType; + String advisoryNumber; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/SatelliteEphemerisTime.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/SatelliteEphemerisTime.aidl new file mode 100644 index 0000000000000000000000000000000000000000..1e5cd028f08352a26ad2f4716e953137dd0198a0 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/SatelliteEphemerisTime.aidl @@ -0,0 +1,41 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss.gnss_assistance; +/* @hide */ +@VintfStability +parcelable SatelliteEphemerisTime { + int iode; + int weekNumber; + int toeSeconds; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/TimeModel.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/TimeModel.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e1ce8900fece6738d14c5c6e74e13e3f7cc58988 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/TimeModel.aidl @@ -0,0 +1,43 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss.gnss_assistance; +/* @hide */ +@VintfStability +parcelable TimeModel { + android.hardware.gnss.GnssConstellationType toGnss; + double a0; + double a1; + int timeOfWeek; + int weekNumber; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/UtcModel.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/UtcModel.aidl new file mode 100644 index 0000000000000000000000000000000000000000..df754bcd23ba35f9b4e632808ca36f01a1dcc5b4 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/UtcModel.aidl @@ -0,0 +1,42 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss.gnss_assistance; +/* @hide */ +@VintfStability +parcelable UtcModel { + double a0; + double a1; + int timeOfWeek; + int weekNumber; +} diff --git a/gnss/aidl/android/hardware/gnss/IGnss.aidl b/gnss/aidl/android/hardware/gnss/IGnss.aidl index aaafe7f583d5a5c88a7bf2d0989ad7e013e55ff8..5fc8a48bf1f1f9f79d10d9bbc6ce7137d94e66cf 100644 --- a/gnss/aidl/android/hardware/gnss/IGnss.aidl +++ b/gnss/aidl/android/hardware/gnss/IGnss.aidl @@ -29,6 +29,7 @@ import android.hardware.gnss.IGnssMeasurementInterface; import android.hardware.gnss.IGnssNavigationMessageInterface; import android.hardware.gnss.IGnssPowerIndication; import android.hardware.gnss.IGnssPsds; +import android.hardware.gnss.gnss_assistance.IGnssAssistanceInterface; import android.hardware.gnss.measurement_corrections.IMeasurementCorrectionsInterface; import android.hardware.gnss.visibility_control.IGnssVisibilityControl; @@ -343,4 +344,11 @@ interface IGnss { * Stops the NMEA output stream. */ void stopNmea(); + + /** + * This method returns the IGnssAssistanceInterface. + * + * @return Handle to the IGnssAssistanceInterface. + */ + IGnssAssistanceInterface getExtensionGnssAssistanceInterface(); } diff --git a/gnss/aidl/android/hardware/gnss/gnss_assistance/BeidouSatelliteEphemeris.aidl b/gnss/aidl/android/hardware/gnss/gnss_assistance/BeidouSatelliteEphemeris.aidl new file mode 100644 index 0000000000000000000000000000000000000000..bb1f7d9224abbabaace304fd5e873fbfc089db80 --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/gnss_assistance/BeidouSatelliteEphemeris.aidl @@ -0,0 +1,98 @@ +package android.hardware.gnss.gnss_assistance; + +import android.hardware.gnss.gnss_assistance.KeplerianOrbitModel; + +/** + * Contains ephemeris parameters specific to Beidou satellites. + * + * @hide + */ +@VintfStability +parcelable BeidouSatelliteEphemeris { + /* + * Contains the set of parameters needed for Beidou satellite clock + * correction. + * This is defined in BDS-SIS-ICD-B1I-3.0, section 5.2.4.9, 5.2.4.10. + */ + @VintfStability + parcelable BeidouSatelliteClockModel { + /** + * Time of the clock in seconds since Beidou epoch. + * + * Represents the 'Epoch' field within the 'SV/EPOCH/SV CLK' record of GNSS + * navigation message file in RINEX 3.05 Table A14. + */ + long timeOfClockSeconds; + + /** SV clock bias in seconds. */ + double af0; + + /** SV clock drift in seconds per second. */ + double af1; + + /** Clock drift rate in seconds per second squared. */ + double af2; + + /** Group delay differential 1 B1/B3 in seconds. */ + double tgd1; + + /** Group delay differential 2 B2/B3 in seconds. */ + double tgd2; + + /** + * Age of Data Clock and field range is: 0-31. + * This is defined in BDS-SIS-ICD-B1I-3.0 Section 5.2.4.8 Table 5-6. + */ + int aodc; + } + + /** Contains information about Beidou health. */ + parcelable BeidouSatelliteHealth { + /** + * The autonomous satellite health flag (SatH1) occupies 1 bit. “0” means + * broadcasting satellite is good and “1” means not. + * This is defined in BDS-SIS-ICD-B1I-3.0 section 5.2.4.6. + */ + int satH1; + + /** + * SV accuracy in meters. + * This is defined in the "BROADCAST ORBIT - 6" record of RINEX 3.05 + * Table A14, pp.78. + */ + double svAccur; + } + + /** Contains information about time of ephemeris */ + parcelable BeidouSatelliteEphemerisTime { + /** + * AODE Age of Data, Ephemeris. + * This is as defined in BDS-SIS-ICD-B1I-3.0 section 5.2.4.11 Table 5-8. + */ + int aode; + + /** Beidou week number without rollover. */ + int weekNumber; + + /** + * Time of ephemeris in seconds. + * This is defined in BDS-SIS-ICD-B1I-3.0 section 5.2.4.12. + */ + int toeSeconds; + } + + /** The PRN number of the Beidou satellite. */ + int prn; + + /** Satellite clock model. */ + BeidouSatelliteClockModel satelliteClockModel; + + /** Satellite orbit model. */ + KeplerianOrbitModel satelliteOrbitModel; + + /** Satellite health. */ + BeidouSatelliteHealth satelliteHealth; + + /** Satellite ephemeris time. */ + BeidouSatelliteEphemerisTime satelliteEphemerisTime; +} diff --git a/gnss/aidl/android/hardware/gnss/gnss_assistance/GalileoIonosphericModel.aidl b/gnss/aidl/android/hardware/gnss/gnss_assistance/GalileoIonosphericModel.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ced8917b487afbcdde6f4f4538ffd5190f5f06f3 --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/gnss_assistance/GalileoIonosphericModel.aidl @@ -0,0 +1,35 @@ +/* + * 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. + */ + +package android.hardware.gnss.gnss_assistance; + +/** + * Contains Galileo ionospheric model. + * This is Defined in Galileo-OS-SIS-ICD-v2.1, 5.1.6. + * + * @hide + */ +@VintfStability +parcelable GalileoIonosphericModel { + /** Effective ionisation level 1st order parameter in sfu. */ + double ai0; + + /** Effective ionisation level 2nd order parameter in sfu per degree. */ + double ai1; + + /** Effective ionisation level 3nd order parameter in sfu per degree squared. */ + double ai2; +} diff --git a/gnss/aidl/android/hardware/gnss/gnss_assistance/GalileoSatelliteEphemeris.aidl b/gnss/aidl/android/hardware/gnss/gnss_assistance/GalileoSatelliteEphemeris.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e3160ef75987f2dfce6f1ec4e40ab540d3b1fc31 --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/gnss_assistance/GalileoSatelliteEphemeris.aidl @@ -0,0 +1,118 @@ +/* + * 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. + */ + +package android.hardware.gnss.gnss_assistance; + +import android.hardware.gnss.gnss_assistance.KeplerianOrbitModel; +import android.hardware.gnss.gnss_assistance.SatelliteEphemerisTime; + +/** + * Contains ephemeris parameters specific to Galileo satellites. + * + * @hide + */ +@VintfStability +parcelable GalileoSatelliteEphemeris { + /** + * Contains the set of parameters needed for Galileo satellite clock correction. + * This is defined in Galileo-OS-SIS-ICD 5.1.3. + */ + @VintfStability + parcelable GalileoSatelliteClockModel { + /* + * States the type of satellite clock. + */ + @VintfStability + @Backing(type="int") + enum SatelliteClockType { + UNDEFINED = 0, + GALILEO_FNAV_CLOCK = 1, + GALILEO_INAV_CLOCK = 2 + } + + /** + * Time of the clock in seconds since Galileo epoch. + * + * Represents the 'Epoch' field within the 'SV/EPOCH/SV CLK' record of GNSS + * navigation message file in RINEX 3.05 Table A8 (Galileo). + */ + long timeOfClockSeconds; + + /** SV clock bias correction coefficient in seconds. */ + double af0; + + /** SV clock drift correction coefficient in seconds per second. */ + double af1; + + /** SV clock drift rate correction coefficient in seconds per second squared. */ + double af2; + + /** + * Broadcast group delay in seconds. + * This is defined in Galileo-OS-SIS-ICD 5.1.5. + */ + double bgdSeconds; + + /** + * Signal in space accuracy in meters. + * This is defined in Galileo-OS-SIS-ICD 5.1.12. + */ + double sisaMeters; + + /** Type of satellite clock .*/ + SatelliteClockType satelliteClockType; + } + + /** + * Contains satellite health. + * This is defined in Galileo-OS-SIS-ICD 5.1.9.3. + */ + @VintfStability + parcelable GalileoSvHealth { + /** E1-B data validity status. */ + int dataValidityStatusE1b; + + /** E1-B/C signal health status. */ + int signalHealthStatusE1b; + + /** E5a data validity status. */ + int dataValidityStatusE5a; + + /** E5a signal health status. */ + int signalHealthStatusE5a; + + /** E5b data validity status. */ + int dataValidityStatusE5b; + + /** E5b signal health status. */ + int signalHealthStatusE5b; + } + + /** Satellite code number. */ + int satelliteCodeNumber; + + /** Array of satellite clock model. */ + GalileoSatelliteClockModel[] satelliteClockModel; + + /** Satellite orbit model. */ + KeplerianOrbitModel satelliteOrbitModel; + + /** Satellite health. */ + GalileoSvHealth svHealth; + + /** Satellite ephemeris time. */ + SatelliteEphemerisTime satelliteEphemerisTime; +} diff --git a/gnss/aidl/android/hardware/gnss/gnss_assistance/GlonassAlmanac.aidl b/gnss/aidl/android/hardware/gnss/gnss_assistance/GlonassAlmanac.aidl new file mode 100644 index 0000000000000000000000000000000000000000..d4f149dfd297a8eda8bd1d6fbb57c27b2306a1c4 --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/gnss_assistance/GlonassAlmanac.aidl @@ -0,0 +1,56 @@ +package android.hardware.gnss.gnss_assistance; + +/** + * Contains Glonass almanac data. + * This is defined in Glonass ICD v5.1, Section 4.5. + * + * @hide + */ +@VintfStability +parcelable GlonassAlmanac { + /** + * Contains Glonass satellite almanac data. + * This is defined in Glonass ICD v5.1, Section 4.5. + */ + @VintfStability + parcelable GlonassSatelliteAlmanac { + /** Slot number. */ + int slotNumber; + + /** Satellite health (0=healthy, 1=unhealthy). */ + int svHealth; + + /** Frequency channel number. */ + int frequencyChannel; + + /** Coarse value of satellite time correction to GLONASS time in seconds. */ + double tau; + + /** Time of first ascending node passage of satellite in seconds. */ + double tLambda; + + /** Longitude of the first ascending node in semi-circles. */ + double lambda; + + /** Correction to the mean value of inclination in semi-circles. */ + double deltaI; + + /** Correction to the mean value of the draconian period in seconds per orbital period. */ + double deltaT; + + /** Rate of change of draconian period in seconds per orbital period squared. */ + double deltaTDot; + + /** Eccentricity. */ + double eccentricity; + + /** Argument of perigee in radians. */ + double omega; + } + + /** Almanac issue date in milliseconds (UTC). */ + long issueDateMs; + + /** Array of GlonassSatelliteAlmanac. */ + GlonassSatelliteAlmanac[] satelliteAlmanac; +} diff --git a/gnss/aidl/android/hardware/gnss/gnss_assistance/GlonassSatelliteEphemeris.aidl b/gnss/aidl/android/hardware/gnss/gnss_assistance/GlonassSatelliteEphemeris.aidl new file mode 100644 index 0000000000000000000000000000000000000000..bebde51a33f01240196ee5a4d07f23d5e9b338fe --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/gnss_assistance/GlonassSatelliteEphemeris.aidl @@ -0,0 +1,101 @@ +/* + * 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. + */ + +package android.hardware.gnss.gnss_assistance; + +import android.hardware.gnss.gnss_assistance.SatelliteEphemerisTime; + +/** + * Contains ephemeris parameters specific to Glonass satellites. + * This is defined in RINEX 3.05 APPENDIX 10 and Glonass ICD v5.1, section 4.4. + * + * @hide + */ +@VintfStability +parcelable GlonassSatelliteEphemeris { + /** Contains the set of parameters needed for Glonass satellite clock correction. */ + @VintfStability + parcelable GlonassSatelliteClockModel { + /** + * Time of the clock in seconds (UTC). + * + * Represents the 'Epoch' field within the 'SV/EPOCH/SV CLK' record of GNSS + * navigation message file in RINEX 3.05 Table A10. + */ + long timeOfClockSeconds; + + /** Clock bias in seconds (-TauN). */ + double clockBias; + + /** Frequency bias (+GammaN). */ + double freqBias; + + /** Frequency number. */ + int freqNumber; + } + + /** Contains Glonass orbit model parameters in PZ-90 coordinate system. */ + @VintfStability + parcelable GlonassSatelliteOrbitModel { + /** X position in kilometers. */ + double x; + + /** X velocity in kilometers per second. */ + double xDot; + + /** X acceleration in kilometers per second squared. */ + double xAccel; + + /** Y position in kilometers. */ + double y; + + /** Y velocity in kilometers per second. */ + double yDot; + + /** Y acceleration in kilometers per second squared. */ + double yAccel; + + /** Z position in kilometers. */ + double z; + + /** Z velocity in kilometers per second. */ + double zDot; + + /** Z acceleration in kilometers per second squared. */ + double zAccel; + } + + /** + * L1/Satellite system (R), satellite number (slot number in sat. + * constellation). + */ + int slotNumber; + + /** Satellite health (0=healthy, 1=unhealthy). */ + int svHealth; + + /** Message frame time in seconds of the UTC week (tk+nd*86400). */ + double frameTimeSeconds; + + /** Age of current information in days (E). */ + int ageInDays; + + /** Satellite clock model. */ + GlonassSatelliteClockModel satelliteClockModel; + + /** Satellite orbit model. */ + GlonassSatelliteOrbitModel satelliteOrbitModel; +} diff --git a/gnss/aidl/android/hardware/gnss/gnss_assistance/GnssAlmanac.aidl b/gnss/aidl/android/hardware/gnss/gnss_assistance/GnssAlmanac.aidl new file mode 100644 index 0000000000000000000000000000000000000000..08f33738e206a3393ea797b7fd673093162dd538 --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/gnss_assistance/GnssAlmanac.aidl @@ -0,0 +1,128 @@ +/* + * 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. + */ + +package android.hardware.gnss.gnss_assistance; + +/** + * Contains almanac parameters for GPS, QZSS, Galileo, Beidou. + * + * For Beidou, this is defined in BDS-SIS-ICD-B1I-3.0 section 5.2.4.15. + * For GPS, this is defined in IS-GPS-200 section 20.3.3.5.1.2. + * For QZSS, this is defined in IS-QZSS-PNT section 4.1.2.6. + * For Galileo, this is defined in Galileo-OS-SIS-ICD-v2.1 section 5.1.10. + * + * @hide + */ +@VintfStability +parcelable GnssAlmanac { + /** + * Almanac issue date in milliseconds (UTC). + * + * This is unused for GPS/QZSS/Baidou. + */ + long issueDateMs; + + /** + * Almanac issue of data. + * This is defined Galileo-OS-SIS-ICD-v2.1 section 5.1.10. + * This is unused for GPS/QZSS/Baidou. + */ + int iod; + + /** + * Almanac reference week number. + * + * For GPS and QZSS, this is GPS week number (modulo 1024). + * For Beidou, this is Baidou week number (modulo 8192). + * For Galileo, this is modulo 4 representation of the Galileo week number. + */ + int weekNumber; + + /** Almanac reference time in seconds. */ + int toaSeconds; + + /** + * Contains almanac parameters for GPS, QZSS, Galileo, Beidou. + * + * For Beidou, this is defined in BDS-SIS-ICD-B1I-3.0 section 5.2.4.15. + * For GPS, this is defined in IS-GPS-200 section 20.3.3.5.1.2. + * For QZSS, this is defined in IS-QZSS-PNT section 4.1.2.6. + * For Galileo, this is defined in Galileo-OS-SIS-ICD-v2.1 section 5.1.10. + */ + @VintfStability + parcelable GnssSatelliteAlmanac { + /** The PRN number of the GNSS satellite. */ + int svid; + + /** + * Satellite health information. + * + * For GPS, this is satellite subframe 4 and 5, page 25 6-bit health code as defined in + * IS-GPS-200 Table 20-VIII expressed in integer form. + * + * For QZSS, this is the 5-bit health code as defined in IS-QZSS-PNT, Table 4.1.2-5-2 + * expressed in integer form. + * + * For Beidou, this is 1-bit health information. (0=healthy, 1=unhealthy). + * + * For Galileo, this is 6-bit health, bit 0 and 1 is for E5a, bit 2 and 3 is for E5b, bit + * 4 and 5 is for E1b. + */ + int svHealth; + + /** Eccentricity. */ + double eccentricity; + + /** + * Inclination in semi-circles. + * + * For GPS and Galileo, this is the difference between the inclination angle at reference + * time and the nominal inclination in semi-circles. + * + * For Beidou and QZSS, this is the inclination angle at reference time in semi-circles. + */ + double inclination; + + /** Argument of perigee in semi-circles. */ + double omega; + + /** Longitude of ascending node of orbital plane at weekly epoch in semi-circles. */ + double omega0; + + /** Rate of right ascension in semi-circles per second. */ + double omegaDot; + + /** + * Square root of semi-major axis in square root of meters. + * + * For Galileo, this is the difference with respect to the square root of the nominal + * semi-major axis in square root of meters. + */ + double rootA; + + /** Mean anomaly at reference time in semi-circles. */ + double m0; + + /** Satellite clock time bias correction coefficient in seconds. */ + double af0; + + /** Satellite clock time drift correction coefficient in seconds per second. */ + double af1; + } + + /** Array of GnssSatelliteAlmanac. */ + GnssSatelliteAlmanac[] satelliteAlmanac; +} diff --git a/gnss/aidl/android/hardware/gnss/gnss_assistance/GnssAssistance.aidl b/gnss/aidl/android/hardware/gnss/gnss_assistance/GnssAssistance.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ddff848892824bf974e17375766ada03ccebb579 --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/gnss_assistance/GnssAssistance.aidl @@ -0,0 +1,206 @@ +/* + * 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. + */ + +package android.hardware.gnss.gnss_assistance; + +import android.hardware.gnss.gnss_assistance.BeidouSatelliteEphemeris; +import android.hardware.gnss.gnss_assistance.GalileoIonosphericModel; +import android.hardware.gnss.gnss_assistance.GalileoSatelliteEphemeris; +import android.hardware.gnss.gnss_assistance.GlonassAlmanac; +import android.hardware.gnss.gnss_assistance.GlonassSatelliteEphemeris; +import android.hardware.gnss.gnss_assistance.GnssAlmanac; +import android.hardware.gnss.gnss_assistance.GpsSatelliteEphemeris; +import android.hardware.gnss.gnss_assistance.IonosphericCorrection; +import android.hardware.gnss.gnss_assistance.KlobucharIonosphericModel; +import android.hardware.gnss.gnss_assistance.LeapSecondsModel; +import android.hardware.gnss.gnss_assistance.QzssSatelliteEphemeris; +import android.hardware.gnss.gnss_assistance.RealTimeIntegrityModel; +import android.hardware.gnss.gnss_assistance.TimeModel; +import android.hardware.gnss.gnss_assistance.UtcModel; + +/** + * Contains GNSS assistance. + * + * @hide + */ +@VintfStability +parcelable GnssAssistance { + /** GNSS corrections for satellites. */ + @VintfStability + parcelable GnssSatelliteCorrections { + /** + * Pseudo-random or satellite ID number for the satellite, a.k.a. Space Vehicle (SV), or + * OSN number for Glonass. The distinction is made by looking at the constellation field. + * Values must be in the range of: + * + * - GNSS: 1-32 + * - GLONASS: 1-25 + * - QZSS: 183-206 + * - Galileo: 1-36 + * - Beidou: 1-63 + */ + int svid; + + /** Ionospheric corrections */ + IonosphericCorrection[] inonosphericCorrections; + } + + /** Contains GPS assistance. */ + @VintfStability + parcelable GpsAssistance { + /** The GPS almanac. */ + GnssAlmanac almanac; + + /** The Klobuchar ionospheric model. */ + KlobucharIonosphericModel ionosphericModel; + + /** The UTC model. */ + UtcModel utcModel; + + /** The leap seconds model. */ + LeapSecondsModel leapSecondsModel; + + /** The array of time models. */ + TimeModel[] timeModels; + + /** The array of GPS ephemeris. */ + GpsSatelliteEphemeris[] satelliteEphemeris; + + /** The array of real time integrity models. */ + RealTimeIntegrityModel[] realTimeIntegrityModels; + + /** The array of GPS satellite corrections. */ + GnssSatelliteCorrections[] satelliteCorrections; + } + + /** Contains Galileo assistance. */ + @VintfStability + parcelable GalileoAssistance { + /** The Galileo almanac. */ + GnssAlmanac almanac; + + /** The Galileo ionospheric model. */ + GalileoIonosphericModel ionosphericModel; + + /** The UTC model. */ + UtcModel utcModel; + + /** The leap seconds model. */ + LeapSecondsModel leapSecondsModel; + + /** The array of time models. */ + TimeModel[] timeModels; + + /** The array of Galileo ephemeris. */ + GalileoSatelliteEphemeris[] satelliteEphemeris; + + /** The array of real time integrity models. */ + RealTimeIntegrityModel[] realTimeIntegrityModels; + + /** The array of Galileo satellite corrections. */ + GnssSatelliteCorrections[] satelliteCorrections; + } + + /** Contains Glonass assistance. */ + @VintfStability + parcelable GlonassAssistance { + /** The Glonass almanac. */ + GlonassAlmanac almanac; + + /** The UTC model. */ + UtcModel utcModel; + + /** The array of time models. */ + TimeModel[] timeModels; + + /** The array of Glonass ephemeris. */ + GlonassSatelliteEphemeris[] satelliteEphemeris; + + /** The array of Glonass satellite corrections. */ + GnssSatelliteCorrections[] satelliteCorrections; + } + + /** Contains QZSS assistance. */ + @VintfStability + parcelable QzssAssistance { + /** The QZSS almanac. */ + GnssAlmanac almanac; + + /** The Klobuchar ionospheric model. */ + KlobucharIonosphericModel ionosphericModel; + + /** The UTC model. */ + UtcModel utcModel; + + /** The leap seconds model. */ + LeapSecondsModel leapSecondsModel; + + /** The array of time models. */ + TimeModel[] timeModels; + + /** The array of QZSS ephemeris. */ + QzssSatelliteEphemeris[] satelliteEphemeris; + + /** The array of real time integrity models. */ + RealTimeIntegrityModel[] realTimeIntegrityModels; + + /** The array of QZSS satellite corrections. */ + GnssSatelliteCorrections[] satelliteCorrections; + } + + /** Contains Beidou assistance. */ + @VintfStability + parcelable BeidouAssistance { + /** The Beidou almanac. */ + GnssAlmanac almanac; + + /** The Klobuchar ionospheric model. */ + KlobucharIonosphericModel ionosphericModel; + + /** The UTC model. */ + UtcModel utcModel; + + /** The leap seconds model. */ + LeapSecondsModel leapSecondsModel; + + /** The array of time models. */ + TimeModel[] timeModels; + + /** The array of Beidou ephemeris. */ + BeidouSatelliteEphemeris[] satelliteEphemeris; + + /** The array of real time integrity models. */ + RealTimeIntegrityModel[] realTimeIntegrityModels; + + /** The array of Beidou satellite corrections. */ + GnssSatelliteCorrections[] satelliteCorrections; + } + + /** GPS assistance. */ + GpsAssistance gpsAssistance; + + /** Glonass assistance. */ + GlonassAssistance glonassAssistance; + + /** Galileo assistance. */ + GalileoAssistance galileoAssistance; + + /** Beidou assistance. */ + BeidouAssistance beidouAssistance; + + /** QZSS assistance. */ + QzssAssistance qzssAssistance; +} diff --git a/gnss/aidl/android/hardware/gnss/gnss_assistance/GnssCorrectionComponent.aidl b/gnss/aidl/android/hardware/gnss/gnss_assistance/GnssCorrectionComponent.aidl new file mode 100644 index 0000000000000000000000000000000000000000..445727f1a9af6b22328540cbe50439c69ab5d1b3 --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/gnss_assistance/GnssCorrectionComponent.aidl @@ -0,0 +1,64 @@ +package android.hardware.gnss.gnss_assistance; + +/** + * Gnss correction associated with a component (e.g. the Ionospheric error). + * + * @hide + */ +@VintfStability +parcelable GnssCorrectionComponent { + /** + * Uniquely identifies the source of correction (e.g. "Klobuchar" for + * ionospheric corrections). + * Clients should not depend on the value of the source key but, rather, + * can compare before/after to detect changes. + */ + String sourceKey; + + /** + * Time interval referenced against the GPS epoch. The start must be less than + * or equal to the end. When the start equals the end, the interval is empty. + */ + @VintfStability + parcelable GnssInterval { + /** + * Inclusive start of the interval in milliseconds since the GPS epoch. + * A timestamp matching this interval will have to be the same or after the + * start. Required as a reference time for the initial correction value and + * its rate of change over time. + */ + long startMillisSinceGpsEpoch; + + /** + * Exclusive end of the interval in milliseconds since the GPS epoch. If + * specified, a timestamp matching this interval will have to be before the + * end. + */ + long endMillisSinceGpsEpoch; + } + + /** The correction is only applicable during this time interval. */ + GnssInterval validityInterval; + + /** Pseudorange correction. */ + @VintfStability + parcelable PseudorangeCorrection { + /* Correction to be added to the measured pseudorange, in meters. */ + double correctionMeters; + + /* Uncertainty of the correction, in meters. */ + double correctionUncertaintyMeters; + + /** + * Linear approximation of the change in correction over time. Intended + * usage is to adjust the correction using the formula: + * correctionMeters + correctionRateMetersPerSecond * delta_seconds + * Where `delta_seconds` is the number of elapsed seconds since the beginning + * of the correction validity interval. + */ + double correctionRateMetersPerSecond; + } + + /* Pseudorange correction. */ + PseudorangeCorrection pseudorangeCorrection; +} diff --git a/gnss/aidl/android/hardware/gnss/gnss_assistance/GpsSatelliteEphemeris.aidl b/gnss/aidl/android/hardware/gnss/gnss_assistance/GpsSatelliteEphemeris.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ab3803033c6bbdfb014457fd3e6a66daf76af662 --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/gnss_assistance/GpsSatelliteEphemeris.aidl @@ -0,0 +1,109 @@ +/* + * 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. + */ + +package android.hardware.gnss.gnss_assistance; + +import android.hardware.gnss.gnss_assistance.KeplerianOrbitModel; +import android.hardware.gnss.gnss_assistance.SatelliteEphemerisTime; + +/** + * Contains ephemeris parameters specific to GPS satellites. + * This is defined in IS-GPS-200, section 20.3.3.3. + * + * @hide + */ +@VintfStability +parcelable GpsSatelliteEphemeris { + /** Satellite PRN */ + int prn; + + /* Contains information about L2 params. */ + @VintfStability + parcelable GpsL2Params { + /** Code(s) on L2 Channel. */ + int l2Code; + + /** Data Flag for L2 P-Code. */ + int l2Flag; + } + + /** L2 parameters. */ + GpsL2Params gpsL2Params; + + /** Contains the set of parameters needed for GPS satellite clock correction. */ + @VintfStability + parcelable GpsSatelliteClockModel { + /** + * Time of the clock in seconds since GPS epoch. + * + * Represents the 'Epoch' field within the 'SV/EPOCH/SV CLK' record of GNSS + * navigation message file in RINEX 3.05 Table A6. + */ + long timeOfClockSeconds; + + /** SV clock bias in seconds. */ + double af0; + + /** SV clock drift in seconds per second. */ + double af1; + + /** Clock drift rate in seconds per second squared. */ + double af2; + + /** Group delay differential in seconds. */ + double tgd; + + /** Issue of data, clock. */ + int iodc; + } + + /** Clock model. */ + GpsSatelliteClockModel satelliteClockModel; + + /** Orbit model. */ + KeplerianOrbitModel satelliteOrbitModel; + + /** + * Contains information about GPS health. The information is tied to + * Legacy Navigation (LNAV) data, not Civil Navigation (CNAV) data. + */ + @VintfStability + parcelable GpsSatelliteHealth { + /** + * Represents "SV health" in the "BROADCAST ORBIT - 6" + * record of RINEX 3.05. Table A6, pp.68. + */ + int svHealth; + + /** + * Represents "SV accuracy" in meters in the "BROADCAST ORBIT - 6" + * record of RINEX 3.05. Table A6, pp.68. + */ + double svAccur; + + /** + * Represents the "Fit Interval" in hours in the "BROADCAST ORBIT - 7" + * record of RINEX 3.05. Table A6, pp.69. + */ + double fitInt; + } + + /** Satellite health. */ + GpsSatelliteHealth satelliteHealth; + + /** Ephemeris time. */ + SatelliteEphemerisTime satelliteEphemerisTime; +} diff --git a/gnss/aidl/android/hardware/gnss/gnss_assistance/IGnssAssistanceCallback.aidl b/gnss/aidl/android/hardware/gnss/gnss_assistance/IGnssAssistanceCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..883189ce1db8540214164138071becb535110d05 --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/gnss_assistance/IGnssAssistanceCallback.aidl @@ -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. + */ + +package android.hardware.gnss.gnss_assistance; + +/** + * The callback interface for GNSS HAL to request GNSS assistance data + * (ephemeris and ionospheric corrections) from the framework. + * + * @hide + */ +@VintfStability +interface IGnssAssistanceCallback { + /** + * Callback to request the framework to inject GNSS assistance data via + * IGnssAssistanceInterface. + */ + void injectRequestCb(); +} diff --git a/gnss/aidl/android/hardware/gnss/gnss_assistance/IGnssAssistanceInterface.aidl b/gnss/aidl/android/hardware/gnss/gnss_assistance/IGnssAssistanceInterface.aidl new file mode 100644 index 0000000000000000000000000000000000000000..2097e1e0020c105c919fe5aebef61cef0192cffd --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/gnss_assistance/IGnssAssistanceInterface.aidl @@ -0,0 +1,49 @@ +/* + * 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. + */ + +package android.hardware.gnss.gnss_assistance; + +import android.hardware.gnss.gnss_assistance.GnssAssistance; +import android.hardware.gnss.gnss_assistance.IGnssAssistanceCallback; + +/** + * Interface used by the GNSS HAL to request the GNSS assistance data + * (ephemeris and ionospheric corrections) from the framework. + * + * The GNSS chipset uses the injected assistance data in the process of computing + * the user position for satellite position computation and error corrections. + * + * The framework ensures the assistance data is valid. GNSS HAL should request the + * data when it's engine lacks valid assistance data. + * + * @hide + */ +@VintfStability +interface IGnssAssistanceInterface { + /** + * Inject the GNSS assistance into the GNSS receiver. + * + * @param gnssAssistance GNSS assistance. + */ + void injectGnssAssistance(in GnssAssistance gnssAssistance); + + /** + * Provides the callback routines to request the GNSS assistance. + * + * @param callback Handle to the IGnssAssistanceCallback interface. + */ + void setCallback(in IGnssAssistanceCallback callback); +} diff --git a/gnss/aidl/android/hardware/gnss/gnss_assistance/IonosphericCorrection.aidl b/gnss/aidl/android/hardware/gnss/gnss_assistance/IonosphericCorrection.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e8e50bd4e233e388358c4bc523a8e65ece8fc21b --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/gnss_assistance/IonosphericCorrection.aidl @@ -0,0 +1,36 @@ +/* + * 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. + */ + +package android.hardware.gnss.gnss_assistance; + +import android.hardware.gnss.gnss_assistance.GnssCorrectionComponent; + +/** + * Contains Ionospheric correction. + * + * @hide + */ +@VintfStability +parcelable IonosphericCorrection { + /** + * Carrier frequency in Hz to differentiate signals from the same satellite. + * e.g. GPS L1/L5 + */ + long carrierFrequencyHz; + + /** Ionospheric correction. */ + GnssCorrectionComponent ionosphericCorrection; +} diff --git a/gnss/aidl/android/hardware/gnss/gnss_assistance/KeplerianOrbitModel.aidl b/gnss/aidl/android/hardware/gnss/gnss_assistance/KeplerianOrbitModel.aidl new file mode 100644 index 0000000000000000000000000000000000000000..441b61d5def61a97532f933a084e42053f10eac9 --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/gnss_assistance/KeplerianOrbitModel.aidl @@ -0,0 +1,83 @@ +/* + * 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. + */ + +package android.hardware.gnss.gnss_assistance; + +/** + * Contains Keplerian orbit model parameters for GPS/Galileo/QZSS/Beidou. + * For GPS, this is defined in IS-GPS-200 Table 20-II. + * For Galileo, this is defined in Galileo-OS-SIS-ICD-v2.1 5.1.1. + * For QZSS, this is defined in IS-QZSS-PNT section 4.1.2. + * For Baidou, this is defined in BDS-SIS-ICD-B1I-3.0 section 5.2.4.12. + * + * @hide + */ +@VintfStability +parcelable KeplerianOrbitModel { + /** Square root of the semi-major axis in square root of meters. */ + double rootA; + + /** Eccentricity. */ + double eccentricity; + + /** Inclination angle at reference time in radians. */ + double i0; + + /** Rate of change of inclination angle in radians per second. */ + double iDot; + + /** Argument of perigee in radians. */ + double omega; + + /** Longitude of ascending node of orbit plane at beginning of week in radians. */ + double omega0; + + /** Rate of right ascension in radians per second. */ + double omegaDot; + + /** Mean anomaly at reference time in radians. */ + double m0; + + /** Mean motion difference from computed value in radians per second. */ + double deltaN; + + /** + * Contains second-order harmonic perturbations. + */ + @VintfStability + parcelable SecondOrderHarmonicPerturbation { + /** Amplitude of cosine harmonic correction term to angle of inclination in radians. */ + double cic; + + /** Amplitude of sine harmonic correction term to angle of inclination in radians. */ + double cis; + + /** Amplitude of cosine harmonic correction term to the orbit in meters. */ + double crc; + + /** Amplitude of sine harmonic correction term to the orbit in meters. */ + double crs; + + /** Amplitude of cosine harmonic correction term to the argument of latitude in radians. */ + double cuc; + + /** Amplitude of sine harmonic correction term to the argument of latitude in radians. */ + double cus; + } + + /** Second-order harmonic perturbations. */ + SecondOrderHarmonicPerturbation secondOrderHarmonicPerturbation; +} diff --git a/gnss/aidl/android/hardware/gnss/gnss_assistance/KlobucharIonosphericModel.aidl b/gnss/aidl/android/hardware/gnss/gnss_assistance/KlobucharIonosphericModel.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e261e975739d441974e6433c2091c1b49bfc614a --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/gnss_assistance/KlobucharIonosphericModel.aidl @@ -0,0 +1,50 @@ +/* + * 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. + */ + +package android.hardware.gnss.gnss_assistance; + +/** + * Contains Klobuchar ionospheric model coefficients used by GPS, BDS, QZSS. + * This is defined in IS-GPS-200 20.3.3.5.1.7. + * + * @hide + */ +@VintfStability +parcelable KlobucharIonosphericModel { + /** Alpha0 coefficient in seconds. */ + double alpha0; + + /** Alpha1 coefficient in seconds per semi-circle. */ + double alpha1; + + /** Alpha2 coefficient in seconds per semi-circle squared. */ + double alpha2; + + /** Alpha3 coefficient in seconds per semi-circle cubed. */ + double alpha3; + + /** Beta0 coefficient in seconds. */ + double beta0; + + /** Beta1 coefficient in seconds per semi-circle. */ + double beta1; + + /** Beta2 coefficient in seconds per semi-circle squared. */ + double beta2; + + /** Beta3 coefficient in seconds per semi-circle cubed. */ + double beta3; +} diff --git a/gnss/aidl/android/hardware/gnss/gnss_assistance/LeapSecondsModel.aidl b/gnss/aidl/android/hardware/gnss/gnss_assistance/LeapSecondsModel.aidl new file mode 100644 index 0000000000000000000000000000000000000000..0ebd46dd78b6b07d6f978e55cdaed52cfa526cbc --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/gnss_assistance/LeapSecondsModel.aidl @@ -0,0 +1,38 @@ +/* + * 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. + */ + +package android.hardware.gnss.gnss_assistance; + +/** + * Contains the leap seconds set of parameters needed for GNSS time. + * This is defined in RINEX 3.05 "LEAP SECONDS" in table A2. + * + * @hide + */ +@VintfStability +parcelable LeapSecondsModel { + /** Time difference due to leap seconds before the event in seconds. */ + int leapSeconds; + + /** Time difference due to leap seconds after the event in seconds. */ + int leapSecondsFuture; + + /** GNSS week number in which the leap second event will occur. */ + int weekNumberLeapSecondsFuture; + + /** Day number when the next leap second will occur. */ + int dayNumberLeapSecondsFuture; +} diff --git a/gnss/aidl/android/hardware/gnss/gnss_assistance/QzssSatelliteEphemeris.aidl b/gnss/aidl/android/hardware/gnss/gnss_assistance/QzssSatelliteEphemeris.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a5a22d0e77b3f8bf8666d28ecb9cc864699caaae --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/gnss_assistance/QzssSatelliteEphemeris.aidl @@ -0,0 +1,50 @@ +/* + * 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. + */ + +package android.hardware.gnss.gnss_assistance; + +import android.hardware.gnss.gnss_assistance.GpsSatelliteEphemeris.GpsL2Params; +import android.hardware.gnss.gnss_assistance.GpsSatelliteEphemeris.GpsSatelliteClockModel; +import android.hardware.gnss.gnss_assistance.GpsSatelliteEphemeris.GpsSatelliteHealth; +import android.hardware.gnss.gnss_assistance.KeplerianOrbitModel; +import android.hardware.gnss.gnss_assistance.SatelliteEphemerisTime; + +/** + * Contains ephemeris parameters specific to QZSS satellites. + * This is defined in IS-QZSS-PNT, section 4.1.2. + * + * @hide + */ +@VintfStability +parcelable QzssSatelliteEphemeris { + /** Satellite PRN. */ + int prn; + + /** L2 parameters. */ + GpsL2Params gpsL2Params; + + /** Clock model. */ + GpsSatelliteClockModel satelliteClockModel; + + /** Orbit model. */ + KeplerianOrbitModel satelliteOrbitModel; + + /** Satellite health. */ + GpsSatelliteHealth satelliteHealth; + + /** Ephemeris time. */ + SatelliteEphemerisTime satelliteEphemerisTime; +} diff --git a/gnss/aidl/android/hardware/gnss/gnss_assistance/RealTimeIntegrityModel.aidl b/gnss/aidl/android/hardware/gnss/gnss_assistance/RealTimeIntegrityModel.aidl new file mode 100644 index 0000000000000000000000000000000000000000..4a4122c733553f2d2028254971bd44d30a69317e --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/gnss_assistance/RealTimeIntegrityModel.aidl @@ -0,0 +1,69 @@ +/* + * 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. + */ + +package android.hardware.gnss.gnss_assistance; + +/** + * Contains the real time integrity status of a GNSS satellite based on + * notice advisory. + * + * @hide + */ +@VintfStability +parcelable RealTimeIntegrityModel { + /** + * Pseudo-random or satellite ID number for the satellite, a.k.a. Space Vehicle (SV), or + * OSN number for Glonass. The distinction is made by looking at the constellation field. + * Values must be in the range of: + * + * - GNSS: 1-32 + * - GLONASS: 1-25 + * - QZSS: 183-206 + * - Galileo: 1-36 + * - Beidou: 1-63 + */ + int svid; + + /** Indicates whether the satellite is currently usable for navigation. */ + boolean usable; + + /** UTC timestamp (in seconds) when the advisory was published. */ + long publishDateSeconds; + + /** UTC timestamp (in seconds) for the start of the event. */ + long startDateSeconds; + + /** UTC timestamp (in seconds) for the end of the event. */ + long endDateSeconds; + + /** + * Abbreviated type of the advisory, providing a concise summary of the event. + * This field follows different definitions depending on the GNSS constellation: + * - GPS: See NANU type definitions + * (https://www.navcen.uscg.gov/nanu-abbreviations-and-descriptions) + * - Galileo: See NAGU type definitions + * (https://www.gsc-europa.eu/system-service-status/nagu-information) + * - QZSS: See NAQU type definitions (https://sys.qzss.go.jp/dod/en/naqu/type.html) + * - BeiDou: Not used; set to an empty string. + */ + String advisoryType; + + /** + * Unique identifier for the advisory within its constellation's system. + * For BeiDou, this is not used and should be an empty string. + */ + String advisoryNumber; +} diff --git a/gnss/aidl/android/hardware/gnss/gnss_assistance/SatelliteEphemerisTime.aidl b/gnss/aidl/android/hardware/gnss/gnss_assistance/SatelliteEphemerisTime.aidl new file mode 100644 index 0000000000000000000000000000000000000000..8849401d1d7e770a02ade429ac17689d34567eb3 --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/gnss_assistance/SatelliteEphemerisTime.aidl @@ -0,0 +1,36 @@ +/* + * 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. + */ + +package android.hardware.gnss.gnss_assistance; + +/** + * Contains time of ephemeris. + * + * For GPS, this is defined in IS-GPS-200, section 20.3.3.4.1. + * For QZSS, this is defined in IS-QZSS-200, section 4.1.2.4. + * @hide + */ +@VintfStability +parcelable SatelliteEphemerisTime { + /** The issue of ephemeris data. */ + int iode; + + /** The satellite week number without rollover. */ + int weekNumber; + + /** The broadcast time of ephemeris in GNSS time of week in seconds. */ + int toeSeconds; +} diff --git a/gnss/aidl/android/hardware/gnss/gnss_assistance/TimeModel.aidl b/gnss/aidl/android/hardware/gnss/gnss_assistance/TimeModel.aidl new file mode 100644 index 0000000000000000000000000000000000000000..8804f0249989f7d6f4bf4d62d43a87e1cff93705 --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/gnss_assistance/TimeModel.aidl @@ -0,0 +1,46 @@ +/* + * 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. + */ + +package android.hardware.gnss.gnss_assistance; + +import android.hardware.gnss.GnssConstellationType; + +/* + * Contains the GNSS-GNSS system time offset between the GNSS system time. + * This is defined in RINEX 3.05 "TIME SYSTEM CORR" in table A5. + * + * @hide + */ +@VintfStability +parcelable TimeModel { + /* + * Model represents parameters to convert from current GNSS to GNSS system + * time indicated by toGnss. + */ + GnssConstellationType toGnss; + + /** Bias coefficient of GNSS time scale relative to GNSS time scale in seconds. */ + double a0; + + /** Drift coefficient of GNSS time scale relative to GNSS time scale in seconds per second. */ + double a1; + + /** Reference GNSS time of week in seconds. */ + int timeOfWeek; + + /** Reference GNSS week number. */ + int weekNumber; +} diff --git a/gnss/aidl/android/hardware/gnss/gnss_assistance/UtcModel.aidl b/gnss/aidl/android/hardware/gnss/gnss_assistance/UtcModel.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c16a711acf52fe9b9aee9b838dfd08c1532c6c2b --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/gnss_assistance/UtcModel.aidl @@ -0,0 +1,38 @@ +/* + * 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. + */ + +package android.hardware.gnss.gnss_assistance; + +/** + * Contains parameters to convert from current GNSS time to UTC time. + * This is defined in RINEX 3.05 "TIME SYSTEM CORR" in table A5. + * + * @hide + */ +@VintfStability +parcelable UtcModel { + /** Bias coefficient of GNSS time scale relative to UTC time scale in seconds. */ + double a0; + + /** Drift coefficient of GNSS time scale relative to UTC time scale in seconds per second. */ + double a1; + + /** Reference GNSS time of week in seconds. */ + int timeOfWeek; + + /** Reference GNSS week number. */ + int weekNumber; +} diff --git a/gnss/aidl/default/Android.bp b/gnss/aidl/default/Android.bp index 822e8fc882b7af45eebffe643849a6891b620d63..efe2953baab444274869f774deb719749173c16e 100644 --- a/gnss/aidl/default/Android.bp +++ b/gnss/aidl/default/Android.bp @@ -45,13 +45,14 @@ cc_binary { "android.hardware.gnss.measurement_corrections@1.1", "android.hardware.gnss.measurement_corrections@1.0", "android.hardware.gnss.visibility_control@1.0", - "android.hardware.gnss-V4-ndk", + "android.hardware.gnss-V5-ndk", ], srcs: [ "AGnssRil.cpp", "AGnss.cpp", "Gnss.cpp", "GnssAntennaInfo.cpp", + "GnssAssistanceInterface.cpp", "GnssBatching.cpp", "GnssDebug.cpp", "GnssGeofence.cpp", diff --git a/gnss/aidl/default/Gnss.cpp b/gnss/aidl/default/Gnss.cpp index 94d4d000acd074f9c1d8d274b44d723ded2ad60e..41720c0c884840719d561e2e57475a53f0dcaa9f 100644 --- a/gnss/aidl/default/Gnss.cpp +++ b/gnss/aidl/default/Gnss.cpp @@ -25,6 +25,7 @@ #include "DeviceFileReader.h" #include "FixLocationParser.h" #include "GnssAntennaInfo.h" +#include "GnssAssistanceInterface.h" #include "GnssBatching.h" #include "GnssConfiguration.h" #include "GnssDebug.h" @@ -122,10 +123,13 @@ ScopedAStatus Gnss::start() { std::this_thread::sleep_for(std::chrono::milliseconds(TTFF_MILLIS)); mFirstFixReceived = true; } + int reportGnssCount = 0; do { if (!mIsActive) { + ALOGD("Do not report location. mIsActive is false"); break; } + reportGnssCount += 1; if (!mGnssMeasurementEnabled || mMinIntervalMs <= mGnssMeasurementIntervalMs) { this->reportSvStatus(); } @@ -140,6 +144,7 @@ ScopedAStatus Gnss::start() { this->reportLocation(location); } } while (mIsActive && mThreadBlocker.wait_for(std::chrono::milliseconds(mMinIntervalMs))); + ALOGD("reportGnssCount: %d", reportGnssCount); }); return ScopedAStatus::ok(); } @@ -390,6 +395,14 @@ ndk::ScopedAStatus Gnss::getExtensionMeasurementCorrections( return ndk::ScopedAStatus::ok(); } +ndk::ScopedAStatus Gnss::getExtensionGnssAssistanceInterface( + std::shared_ptr* iGnssAssistanceInterface) { + ALOGD("Gnss::getExtensionGnssAssistanceInterface"); + + *iGnssAssistanceInterface = SharedRefBase::make(); + return ndk::ScopedAStatus::ok(); +} + void Gnss::setGnssMeasurementEnabled(const bool enabled) { mGnssMeasurementEnabled = enabled; } diff --git a/gnss/aidl/default/Gnss.h b/gnss/aidl/default/Gnss.h index 73085ef59103a2a04ea5a1df397c2c0bf9790ce5..56fe39979892824029d89786cb7bf69b3493d499 100644 --- a/gnss/aidl/default/Gnss.h +++ b/gnss/aidl/default/Gnss.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -83,6 +84,9 @@ class Gnss : public BnGnss { std::shared_ptr* iMeasurementCorrections) override; + ndk::ScopedAStatus getExtensionGnssAssistanceInterface( + std::shared_ptr* + iGnssAssistanceInterface) override; void reportSvStatus() const; void setGnssMeasurementEnabled(const bool enabled); diff --git a/gnss/aidl/default/GnssAssistanceInterface.cpp b/gnss/aidl/default/GnssAssistanceInterface.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2ef334c1339b05958e6ba66860f87018fb21cf60 --- /dev/null +++ b/gnss/aidl/default/GnssAssistanceInterface.cpp @@ -0,0 +1,45 @@ +/* + * 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. + */ + +#define LOG_TAG "GnssAssistanceInterfaceAidl" + +#include "GnssAssistanceInterface.h" +#include +#include + +namespace aidl::android::hardware::gnss::gnss_assistance { + +std::shared_ptr GnssAssistanceInterface::sCallback = nullptr; + +ndk::ScopedAStatus GnssAssistanceInterface::setCallback( + const std::shared_ptr& callback) { + ALOGD("setCallback"); + std::unique_lock lock(mMutex); + sCallback = callback; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus GnssAssistanceInterface::injectGnssAssistance( + const GnssAssistance& gnssAssistance) { + ALOGD("injectGnssAssistance. %s", gnssAssistance.toString().c_str()); + if (gnssAssistance.gpsAssistance.satelliteEphemeris.size() == 0 && + gnssAssistance.gpsAssistance.satelliteCorrections.size() == 0) { + ALOGE("Empty GnssAssistance"); + return ndk::ScopedAStatus::fromServiceSpecificError(IGnss::ERROR_INVALID_ARGUMENT); + } + return ndk::ScopedAStatus::ok(); +} +} // namespace aidl::android::hardware::gnss::gnss_assistance diff --git a/gnss/aidl/default/GnssAssistanceInterface.h b/gnss/aidl/default/GnssAssistanceInterface.h new file mode 100644 index 0000000000000000000000000000000000000000..9d92975f86b65e0a30794b2d07be580e1f72125b --- /dev/null +++ b/gnss/aidl/default/GnssAssistanceInterface.h @@ -0,0 +1,37 @@ +/* + * 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. + */ + +#pragma once + +#include + +namespace aidl::android::hardware::gnss::gnss_assistance { + +struct GnssAssistanceInterface : public BnGnssAssistanceInterface { + public: + ndk::ScopedAStatus setCallback( + const std::shared_ptr& callback) override; + ndk::ScopedAStatus injectGnssAssistance(const GnssAssistance& gnssAssistance) override; + + private: + // Guarded by mMutex + static std::shared_ptr sCallback; + + // Synchronization lock for sCallback + mutable std::mutex mMutex; +}; + +} // namespace aidl::android::hardware::gnss::gnss_assistance diff --git a/gnss/aidl/default/gnss-default.xml b/gnss/aidl/default/gnss-default.xml index c01069e4fe02ddf1ee68949e59394dde8f2f4ef9..700e2403458c0c51311610cd54d649bef0f2fc9d 100644 --- a/gnss/aidl/default/gnss-default.xml +++ b/gnss/aidl/default/gnss-default.xml @@ -1,7 +1,7 @@ android.hardware.gnss - 4 + 5 IGnss default diff --git a/gnss/aidl/vts/Android.bp b/gnss/aidl/vts/Android.bp index 2bd6f07e95589acddbafd0e8b483376f588ade5d..20cf44f602443624949ba5e20aaef5bd2d64d499 100644 --- a/gnss/aidl/vts/Android.bp +++ b/gnss/aidl/vts/Android.bp @@ -52,7 +52,7 @@ cc_test { "libbinder", ], static_libs: [ - "android.hardware.gnss-V4-cpp", + "android.hardware.gnss-V5-cpp", "android.hardware.gnss@common-vts-lib", ], test_suites: [ diff --git a/gnss/aidl/vts/gnss_hal_test_cases.cpp b/gnss/aidl/vts/gnss_hal_test_cases.cpp index e4890a778e557bd909d27a0ad17c02f027eb9be9..a2e81d1b8db5dad7341202fe8bc2668fb975a945 100644 --- a/gnss/aidl/vts/gnss_hal_test_cases.cpp +++ b/gnss/aidl/vts/gnss_hal_test_cases.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -73,6 +74,8 @@ using android::hardware::gnss::IGnssPsds; using android::hardware::gnss::PsdsType; using android::hardware::gnss::SatellitePvt; using android::hardware::gnss::common::Utils; +using android::hardware::gnss::gnss_assistance::GnssAssistance; +using android::hardware::gnss::gnss_assistance::IGnssAssistanceInterface; using android::hardware::gnss::measurement_corrections::IMeasurementCorrectionsInterface; using android::hardware::gnss::visibility_control::IGnssVisibilityControl; @@ -1877,3 +1880,22 @@ TEST_P(GnssHalTest, TestSvStatusIntervals) { } } } + +/* + * Test GnssAssistanceExtension: + * 1. Gets the GnssAssistanceExtension + * 2. Injects empty GnssAssistance data and verifies that it returns an error. + */ +TEST_P(GnssHalTest, TestGnssAssistanceExtension) { + // Only runs on devices launched in Android 16+ + if (aidl_gnss_hal_->getInterfaceVersion() <= 4) { + return; + } + sp iGnssAssistance; + auto status = aidl_gnss_hal_->getExtensionGnssAssistanceInterface(&iGnssAssistance); + if (status.isOk() && iGnssAssistance != nullptr) { + GnssAssistance gnssAssistance = {}; + status = iGnssAssistance->injectGnssAssistance(gnssAssistance); + ASSERT_FALSE(status.isOk()); + } +} diff --git a/gnss/common/utils/default/Android.bp b/gnss/common/utils/default/Android.bp index 208bc593f36a97012baf1a94c1ff32e05ac7bdca..e8c370a9bb774de58accdcd4f302a9c376921eed 100644 --- a/gnss/common/utils/default/Android.bp +++ b/gnss/common/utils/default/Android.bp @@ -57,6 +57,6 @@ cc_library_static { "android.hardware.gnss@2.1", "android.hardware.gnss.measurement_corrections@1.1", "android.hardware.gnss.measurement_corrections@1.0", - "android.hardware.gnss-V4-ndk", + "android.hardware.gnss-V5-ndk", ], } diff --git a/gnss/common/utils/vts/Android.bp b/gnss/common/utils/vts/Android.bp index ed5674cf99e89a1d7201cb9129777776547b021d..b8b048a53d52295b3dea96e236fe8a786d8e2268 100644 --- a/gnss/common/utils/vts/Android.bp +++ b/gnss/common/utils/vts/Android.bp @@ -44,7 +44,7 @@ cc_library_static { "android.hardware.gnss@2.1", "android.hardware.gnss.measurement_corrections@1.0", "android.hardware.gnss.measurement_corrections@1.1", - "android.hardware.gnss-V4-cpp", + "android.hardware.gnss-V5-cpp", ], static_libs: [ "libgtest", diff --git a/graphics/Android.bp b/graphics/Android.bp index cdeb2e6119efe48d7562f21559e4e3298f5ee4fa..2213f15b1c5af3c14699d62804e771530d80742d 100644 --- a/graphics/Android.bp +++ b/graphics/Android.bp @@ -35,9 +35,13 @@ rust_defaults { cc_defaults { name: "android.hardware.graphics.allocator-ndk_static", - static_libs: [ - "android.hardware.graphics.allocator-V2-ndk", - ], + target: { + linux: { + static_libs: [ + "android.hardware.graphics.allocator-V2-ndk", + ], + }, + }, defaults: [ "android.hardware.graphics.common-ndk_static", ], @@ -45,9 +49,13 @@ cc_defaults { cc_defaults { name: "android.hardware.graphics.allocator-ndk_shared", - shared_libs: [ - "android.hardware.graphics.allocator-V2-ndk", - ], + target: { + linux: { + shared_libs: [ + "android.hardware.graphics.allocator-V2-ndk", + ], + }, + }, defaults: [ "android.hardware.graphics.common-ndk_shared", ], @@ -69,16 +77,24 @@ rust_defaults { cc_defaults { name: "android.hardware.graphics.common-ndk_static", - static_libs: [ - "android.hardware.graphics.common-V6-ndk", - ], + target: { + linux: { + static_libs: [ + "android.hardware.graphics.common-V6-ndk", + ], + }, + }, } cc_defaults { name: "android.hardware.graphics.common-ndk_shared", - shared_libs: [ - "android.hardware.graphics.common-V6-ndk", - ], + target: { + linux: { + shared_libs: [ + "android.hardware.graphics.common-V6-ndk", + ], + }, + }, } aidl_interface_defaults { @@ -90,16 +106,24 @@ aidl_interface_defaults { cc_defaults { name: "android.hardware.graphics.composer3-ndk_static", - static_libs: [ - "android.hardware.drm.common-V1-ndk", - "android.hardware.graphics.composer3-V4-ndk", - ], + target: { + linux: { + static_libs: [ + "android.hardware.drm.common-V1-ndk", + "android.hardware.graphics.composer3-V4-ndk", + ], + }, + }, } cc_defaults { name: "android.hardware.graphics.composer3-ndk_shared", - shared_libs: [ - "android.hardware.drm.common-V1-ndk", - "android.hardware.graphics.composer3-V4-ndk", - ], + target: { + linux: { + shared_libs: [ + "android.hardware.drm.common-V1-ndk", + "android.hardware.graphics.composer3-V4-ndk", + ], + }, + }, } diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Dataspace.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Dataspace.aidl index 6ed5bb2183efbbd2a46854070c1e0f0e369a6c2d..7264a21f31bc41a5045040913bd424d4b295eda4 100644 --- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Dataspace.aidl +++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Dataspace.aidl @@ -97,5 +97,6 @@ enum Dataspace { JPEG_APP_SEGMENTS = 0x1003, HEIF = 0x1004, JPEG_R = 0x1005, + HEIF_ULTRAHDR = 0x1006, BT709_FULL_RANGE = (((1 << 16) | (3 << 22)) | (1 << 27)) /* 146866176 */, } diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/DisplayHotplugEvent.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/DisplayHotplugEvent.aidl index 63dca0aab5d5ae9915215b89aaa772db5a968d23..b18d2bee357cbd305e148b7e8a0a5083fc0868b0 100644 --- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/DisplayHotplugEvent.aidl +++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/DisplayHotplugEvent.aidl @@ -39,4 +39,5 @@ enum DisplayHotplugEvent { ERROR_UNKNOWN = (-1) /* -1 */, ERROR_INCOMPATIBLE_CABLE = (-2) /* -2 */, ERROR_TOO_MANY_DISPLAYS = (-3) /* -3 */, + ERROR_LINK_UNSTABLE = (-4) /* -4 */, } diff --git a/graphics/common/aidl/android/hardware/graphics/common/Dataspace.aidl b/graphics/common/aidl/android/hardware/graphics/common/Dataspace.aidl index 79737eb8856d1c6a604be5e98ff1e0fbf07e0269..8705aef8d8eb779d97b6680157180be3c6955461 100644 --- a/graphics/common/aidl/android/hardware/graphics/common/Dataspace.aidl +++ b/graphics/common/aidl/android/hardware/graphics/common/Dataspace.aidl @@ -702,18 +702,31 @@ enum Dataspace { /** * Ultra HDR * - * JPEG image with embedded 10-bit recovery map following the Ultra HDR specification. + * JPEG image with embedded HDR gain map following the Ultra HDR specification and + * ISO/CD 21496‐1 * * This value must always remain aligned with the public ImageFormat Jpeg/R definition and is * valid with formats: * HAL_PIXEL_FORMAT_BLOB: JPEG image encoded by Ultra HDR encoder according to * the * Ultra HDR Image format specification. - * The image contains a standard SDR JPEG and a recovery map. Ultra HDR decoders can use the - * map to recover the 10-bit input image. + * The image contains a standard SDR JPEG and a gain map. Ultra HDR decoders can use the + * map to boost the brightness of the rendered image. */ JPEG_R = 0x1005, + /** + * ISO/IEC 23008-12:2024 + * + * High Efficiency Image File Format (HEIF) with embedded HDR gain map + * + * This value is valid with formats: + * HAL_PIXEL_FORMAT_BLOB: A HEIC image encoded by HEIC or HEVC encoder + * according to ISO/IEC 23008-12:2024 that includes an HDR gain map and + * metadata according to ISO/CD 21496‐1. + */ + HEIF_ULTRAHDR = 0x1006, + /** * ITU-R Recommendation 709 (BT.709) * diff --git a/graphics/common/aidl/android/hardware/graphics/common/DisplayHotplugEvent.aidl b/graphics/common/aidl/android/hardware/graphics/common/DisplayHotplugEvent.aidl index b35ada5bc9998d1973a7e6e323e52fd47cc5a474..f77910578d6f70a8e0a86e8d8048008253ae75fb 100644 --- a/graphics/common/aidl/android/hardware/graphics/common/DisplayHotplugEvent.aidl +++ b/graphics/common/aidl/android/hardware/graphics/common/DisplayHotplugEvent.aidl @@ -23,24 +23,31 @@ package android.hardware.graphics.common; @Backing(type="int") enum DisplayHotplugEvent { /** - * Display is successfully connected. - * Connected may be called more than once and the behavior of subsequent - * calls is that SurfaceFlinger queries the display properties again. + * Display was successfully connected. + * CONNECTED may be emitted more than once and the behavior of subsequent + * events is that SurfaceFlinger queries the display properties again. */ CONNECTED = 0, - /** Display is successfully disconnected */ + /** Display was successfully disconnected */ DISCONNECTED = 1, - /** Display is plugged in, but an unknown error occurred */ + /** Unknown error occurred */ ERROR_UNKNOWN = -1, - /** Display is plugged in, but incompatible cable error detected */ + /** Display was plugged in, but incompatible cable error detected */ ERROR_INCOMPATIBLE_CABLE = -2, /** - * Display is plugged in, but exceeds the max number of + * Display was plugged in, but exceeds the max number of * displays that can be simultaneously connected */ ERROR_TOO_MANY_DISPLAYS = -3, + + /** + * Display link is unstable, e.g. link training failure (negotiation + * of connection speed failed), and the display needs to be + * reconfigured + */ + ERROR_LINK_UNSTABLE = -4, } diff --git a/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl b/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl index 8cfdae677c28241ab08738b48813c54e72bfa82c..e4da8904d1246e6d2c119ac4ac45e06e39e37784 100644 --- a/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl +++ b/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl @@ -282,7 +282,7 @@ enum StandardMetadataType { * When it is encoded into a byte stream, the total number of Rects is written using * 8 bytes in little endian. It is followed by each Rect. * - * To encode a Rect, write the following fields in this order each as 8 bytes in little endian: + * To encode a Rect, write the following fields in this order each as 4 bytes in little endian: * left, top, right and bottom. */ CROP = 16, diff --git a/graphics/composer/2.2/utils/command-buffer/include/composer-command-buffer/2.2/ComposerCommandBuffer.h b/graphics/composer/2.2/utils/command-buffer/include/composer-command-buffer/2.2/ComposerCommandBuffer.h index cd4737403d946d8b1c09c7c23ffed27fe93c9b8b..5b3a4336018a5ac688cfd8f1cf6d678dadaaea27 100644 --- a/graphics/composer/2.2/utils/command-buffer/include/composer-command-buffer/2.2/ComposerCommandBuffer.h +++ b/graphics/composer/2.2/utils/command-buffer/include/composer-command-buffer/2.2/ComposerCommandBuffer.h @@ -17,19 +17,13 @@ #pragma once #ifndef LOG_TAG -#warn "ComposerCommandBuffer.h included without LOG_TAG" +#warning "ComposerCommandBuffer.h included without LOG_TAG" #endif //#define LOG_NDEBUG 0 -#include -#include -#include #include -#include -#include - #include #include #include @@ -82,7 +76,7 @@ class CommandWriterBase : public V2_1::CommandWriterBase { void setLayerPerFrameMetadata(const hidl_vec& metadataVec) { beginCommand(IComposerClient::Command::SET_LAYER_PER_FRAME_METADATA, - metadataVec.size() * 2); + static_cast(metadataVec.size() * 2)); for (const auto& metadata : metadataVec) { writeSigned(static_cast(metadata.key)); writeFloat(metadata.value); diff --git a/graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h b/graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h index 1a9276ccbdd5a402e139079066c4d4c6813284af..46d8d4a3c428b409b5f329203d3aa81818d04e14 100644 --- a/graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h +++ b/graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h @@ -17,7 +17,7 @@ #pragma once #ifndef LOG_TAG -#warn "ComposerCommandBuffer.h included without LOG_TAG" +#warning "ComposerCommandBuffer.h included without LOG_TAG" #endif //#define LOG_NDEBUG 0 @@ -46,7 +46,7 @@ class CommandWriterBase : public V2_2::CommandWriterBase { public: void setLayerPerFrameMetadata(const hidl_vec& metadataVec) { beginCommand(IComposerClient::Command::SET_LAYER_PER_FRAME_METADATA, - metadataVec.size() * 2); + static_cast(metadataVec.size() * 2)); for (const auto& metadata : metadataVec) { writeSigned(static_cast(metadata.key)); writeFloat(metadata.value); diff --git a/graphics/composer/2.4/utils/command-buffer/include/composer-command-buffer/2.4/ComposerCommandBuffer.h b/graphics/composer/2.4/utils/command-buffer/include/composer-command-buffer/2.4/ComposerCommandBuffer.h index e981da611ffa6f1379e2849d9bf8afbfde842caf..064fc57e33332d78a815d13056d7947a9b30a0be 100644 --- a/graphics/composer/2.4/utils/command-buffer/include/composer-command-buffer/2.4/ComposerCommandBuffer.h +++ b/graphics/composer/2.4/utils/command-buffer/include/composer-command-buffer/2.4/ComposerCommandBuffer.h @@ -17,7 +17,7 @@ #pragma once #ifndef LOG_TAG -#warn "ComposerCommandBuffer.h included without LOG_TAG" +#warning "ComposerCommandBuffer.h included without LOG_TAG" #endif //#define LOG_NDEBUG 0 @@ -63,16 +63,17 @@ class CommandWriterBase : public V2_3::CommandWriterBase { beginCommand(IComposerClient::Command::SET_LAYER_GENERIC_METADATA, static_cast(commandSize)); - write(key.size()); - writeBlob(key.size(), reinterpret_cast(key.c_str())); + write(static_cast(key.size())); + writeBlob(static_cast(key.size()), + reinterpret_cast(key.c_str())); write(mandatory); - write(value.size()); - writeBlob(value.size(), value.data()); + write(static_cast(value.size())); + writeBlob(static_cast(value.size()), value.data()); endCommand(); } protected: - uint32_t sizeToElements(uint32_t size) { return (size + 3) / 4; } + uint32_t sizeToElements(size_t size) { return static_cast((size + 3) / 4); } }; // This class helps parse a command queue. Note that all sizes/lengths are in diff --git a/graphics/composer/aidl/Android.bp b/graphics/composer/aidl/Android.bp index 719318aec232ff00f1e0c234ba2f0565f367410a..655188dadaf29b30d153ddedb7c918bc0d5f8538 100644 --- a/graphics/composer/aidl/Android.bp +++ b/graphics/composer/aidl/Android.bp @@ -77,7 +77,6 @@ aidl_interface { "android.hardware.common-V2", ], }, - ], } diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCapability.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCapability.aidl index 0e2d72bae0b568f00eb34b449363b341e471b1da..955ff898b856ee1dc08892c912b8e3e76f75e454 100644 --- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCapability.aidl +++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCapability.aidl @@ -43,4 +43,5 @@ enum DisplayCapability { SUSPEND = 6, DISPLAY_IDLE_TIMER = 7, MULTI_THREADED_PRESENT = 8, + PICTURE_PROCESSING = 9, } diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCommand.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCommand.aidl index cce35e79ab78edc8a3df45bbc0602399793ec4c9..9e24a2604fda669629c2f2725d36522392dc45fd 100644 --- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCommand.aidl +++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCommand.aidl @@ -46,4 +46,5 @@ parcelable DisplayCommand { boolean presentDisplay; boolean presentOrValidateDisplay; int frameIntervalNs; + long pictureProfileId; } diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayConfiguration.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayConfiguration.aidl index 040afd786651f2beec4d660377dfeb7056e92555..c522188a24f62599c8431aa48b638bf676acb991 100644 --- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayConfiguration.aidl +++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayConfiguration.aidl @@ -41,6 +41,7 @@ parcelable DisplayConfiguration { int configGroup; int vsyncPeriod; @nullable android.hardware.graphics.composer3.VrrConfig vrrConfig; + android.hardware.graphics.composer3.OutputType hdrOutputType; parcelable Dpi { float x; float y; diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayIdentification.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayIdentification.aidl index a0cc9b097b2227a903cd4f1937b31bcb15b389cb..06f2dde538b2bc4501ec9a0f038e905c5a3aa56c 100644 --- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayIdentification.aidl +++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayIdentification.aidl @@ -36,4 +36,5 @@ package android.hardware.graphics.composer3; parcelable DisplayIdentification { byte port; byte[] data; + android.hardware.graphics.composer3.ScreenPartStatus screenPartStatus = android.hardware.graphics.composer3.ScreenPartStatus.UNSUPPORTED; } diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayLuts.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayLuts.aidl index 327e84c1d73ac34047d04c3dc6941686e5dc22cf..42631409bc4b5e94b2e81e6feae20487f6bea6e4 100644 --- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayLuts.aidl +++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayLuts.aidl @@ -38,6 +38,6 @@ parcelable DisplayLuts { android.hardware.graphics.composer3.DisplayLuts.LayerLut[] layerLuts; parcelable LayerLut { long layer; - android.hardware.graphics.composer3.Lut lut; + android.hardware.graphics.composer3.Luts luts; } } diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl index bc27cc7ec4450d44fcac06140904eab15836957f..1e568b967c6b3800664d0de8797ccf8ba915a02a 100644 --- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl +++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl @@ -87,6 +87,9 @@ interface IComposerClient { void setRefreshRateChangedCallbackDebugEnabled(long display, boolean enabled); android.hardware.graphics.composer3.DisplayConfiguration[] getDisplayConfigurations(long display, int maxFrameIntervalNs); oneway void notifyExpectedPresent(long display, in android.hardware.graphics.composer3.ClockMonotonicTimestamp expectedPresentTime, int frameIntervalNs); + int getMaxLayerPictureProfiles(long display); + oneway void startHdcpNegotiation(long display, in android.hardware.drm.HdcpLevels levels); + android.hardware.graphics.composer3.Luts[] getLuts(long display, in android.hardware.graphics.composer3.Buffer[] buffers); const int EX_BAD_CONFIG = 1; const int EX_BAD_DISPLAY = 2; const int EX_BAD_LAYER = 3; @@ -97,5 +100,7 @@ interface IComposerClient { const int EX_UNSUPPORTED = 8; const int EX_SEAMLESS_NOT_ALLOWED = 9; const int EX_SEAMLESS_NOT_POSSIBLE = 10; + const int EX_CONFIG_FAILED = 11; + const int EX_PICTURE_PROFILE_MAX_EXCEEDED = 12; const int INVALID_CONFIGURATION = 0x7fffffff; } diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LayerCommand.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LayerCommand.aidl index 8b2b13caa1d000d06ff62c5ab3846466250d66e2..c26cb158a8bd6d61059fc939ac30255a10fe23a8 100644 --- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LayerCommand.aidl +++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LayerCommand.aidl @@ -57,5 +57,6 @@ parcelable LayerCommand { @nullable int[] bufferSlotsToClear; android.hardware.graphics.composer3.LayerLifecycleBatchCommandType layerLifecycleBatchCommandType; int newBufferSlotCount; - @nullable android.hardware.graphics.composer3.Lut[] luts; + @nullable android.hardware.graphics.composer3.Luts luts; + long pictureProfileId; } diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LutProperties.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LutProperties.aidl index 5edceb5c3534d920d8997ec488669036dc522b0c..95163513cbf7fc5420b07cc3c50982870511f7fd 100644 --- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LutProperties.aidl +++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LutProperties.aidl @@ -35,7 +35,7 @@ package android.hardware.graphics.composer3; @VintfStability parcelable LutProperties { android.hardware.graphics.composer3.LutProperties.Dimension dimension; - long size; + int size; android.hardware.graphics.composer3.LutProperties.SamplingKey[] samplingKeys; @VintfStability enum Dimension { @@ -46,5 +46,6 @@ parcelable LutProperties { enum SamplingKey { RGB, MAX_RGB, + CIE_Y, } } diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Lut.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Luts.aidl similarity index 94% rename from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Lut.aidl rename to graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Luts.aidl index 5fae35be9d8bc08dbb7fc6d8338cf55c6bd0c9c1..2890365f5a949929460feeddd6ba3ce9d331b14c 100644 --- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Lut.aidl +++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Luts.aidl @@ -33,7 +33,8 @@ package android.hardware.graphics.composer3; @VintfStability -parcelable Lut { +parcelable Luts { @nullable ParcelFileDescriptor pfd; - android.hardware.graphics.composer3.LutProperties lutProperties; + @nullable int[] offsets; + android.hardware.graphics.composer3.LutProperties[] lutProperties; } diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/OutputType.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/OutputType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e1149cb28fecf309008ba93e467c841f79464d3b --- /dev/null +++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/OutputType.aidl @@ -0,0 +1,41 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.graphics.composer3; +@Backing(type="int") @VintfStability +enum OutputType { + INVALID = 0, + SYSTEM = 1, + SDR = 2, + HDR10 = 3, +} diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PresentFence.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PresentFence.aidl index 3bb09cdb34022964b5d15073c9b77ffb994ab7e0..5a77e2242ab39004dcfc337ec9143df39a2e548b 100644 --- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PresentFence.aidl +++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PresentFence.aidl @@ -36,4 +36,10 @@ package android.hardware.graphics.composer3; parcelable PresentFence { long display; ParcelFileDescriptor fence; + @nullable android.hardware.graphics.composer3.PresentFence.LayerPresentFence[] layerPresentFences; + parcelable LayerPresentFence { + long layer; + ParcelFileDescriptor bufferFence; + long bufferLatencyNanos; + } } diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ScreenPartStatus.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ScreenPartStatus.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ff55370b5c6a67d9c2ef33b758dca9112e80784e --- /dev/null +++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ScreenPartStatus.aidl @@ -0,0 +1,40 @@ +/** + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.graphics.composer3; +@Backing(type="int") @VintfStability +enum ScreenPartStatus { + UNSUPPORTED = 0, + ORIGINAL = 1, + REPLACED = 2, +} diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCapability.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCapability.aidl index 7154d7449937db28c2d9e5f45c40ef8a5a53efd5..fa58fb7d5308a6826d37f17c2a9a23b184779e60 100644 --- a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCapability.aidl +++ b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCapability.aidl @@ -96,4 +96,10 @@ enum DisplayCapability { * @see DisplayCommand.validateDisplay */ MULTI_THREADED_PRESENT = 8, + /** + * Specifies that the display supports a global picture-processing pipeline. + * + * @see DisplayCommand.pictureProfileId + */ + PICTURE_PROCESSING = 9, } diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCommand.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCommand.aidl index 02c1389de1ea41417326f591c4d5be27b597f5ab..c3fd68eaae422f7611c484bc54a80513e29a8f9a 100644 --- a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCommand.aidl +++ b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCommand.aidl @@ -185,4 +185,21 @@ parcelable DisplayCommand { * close as possible to the cadence. */ int frameIntervalNs; + + /** + * If the display supports DisplayCapability.PICTURE_PROCESSING, then this value is used to look + * up a picture profile which defines the parameters used when configuring a picture-processing + * pipeline applied to the composition result, enhancing the quality of the entire composed + * image. If the server does not recognize the picture profile, it must continue composition + * and ignore this value. If the value is zero, then the server's default picture processing, + * if possible, must be applied. + * + * Note that the client will never send a DisplayCommand.pictureProfileId if + * IComposerClient.getMaxLayerPictureProfiles is non-zero. Picture profiles will only be + * specified on a per-layer basis via LayerCommand.pictureProfileId. + * + * @see IComposerClient.getMaxLayerPictureProfiles + * @see DisplayCommand.pictureProfileId + */ + long pictureProfileId; } diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayConfiguration.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayConfiguration.aidl index 09c42dcc8a4bedb3588fab754fbb78ebac5653e4..80d13377255cbb6c0150a1368509d2a7b892fdf2 100644 --- a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayConfiguration.aidl +++ b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayConfiguration.aidl @@ -15,6 +15,8 @@ */ package android.hardware.graphics.composer3; + +import android.hardware.graphics.composer3.OutputType; import android.hardware.graphics.composer3.VrrConfig; @VintfStability @@ -67,4 +69,9 @@ parcelable DisplayConfiguration { * Non-VRR modes should set this to null. */ @nullable VrrConfig vrrConfig; + + /** + * The HDR output format available. + */ + OutputType hdrOutputType; } diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayIdentification.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayIdentification.aidl index 03ef8e68df9694992322c51fe95a616c32442792..a477eb63be080d5a58c42867b3af34f54c8cad1f 100644 --- a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayIdentification.aidl +++ b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayIdentification.aidl @@ -16,6 +16,7 @@ package android.hardware.graphics.composer3; +import android.hardware.graphics.composer3.ScreenPartStatus; /** * Output parameters for IComposerClient.getDisplayIdentificationData */ @@ -29,4 +30,8 @@ parcelable DisplayIdentification { * The EDID 1.3 blob identifying the display. */ byte[] data; + /** + * Indicator for part originality of the screen + */ + ScreenPartStatus screenPartStatus = ScreenPartStatus.UNSUPPORTED; } diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayLuts.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayLuts.aidl index ac0a60634a1814d271e58c27c4255efc4a7b0ca1..6b59a6f8f7eaec4aa4666e5248eadcae4b067bb7 100644 --- a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayLuts.aidl +++ b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayLuts.aidl @@ -16,7 +16,7 @@ package android.hardware.graphics.composer3; -import android.hardware.graphics.composer3.Lut; +import android.hardware.graphics.composer3.Luts; /** * LUT (Look-Up Table) Interface for Color Transformation. @@ -37,9 +37,9 @@ parcelable DisplayLuts { */ long layer; /** - * A Lut specified by the HWC for given HDR layers that don't have Luts provided. + * Lut(s) specified by the HWC for given HDR layers that don't have Luts provided. */ - Lut lut; + Luts luts; } LayerLut[] layerLuts; diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl index 213e8e941751e76cd99e686be8b722c215775e03..755696232d99eaebbdad183988b2acbb153aac02 100644 --- a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl +++ b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl @@ -16,11 +16,13 @@ package android.hardware.graphics.composer3; +import android.hardware.drm.HdcpLevels; import android.hardware.graphics.common.DisplayDecorationSupport; import android.hardware.graphics.common.Hdr; import android.hardware.graphics.common.HdrConversionCapability; import android.hardware.graphics.common.HdrConversionStrategy; import android.hardware.graphics.common.Transform; +import android.hardware.graphics.composer3.Buffer; import android.hardware.graphics.composer3.ClientTargetProperty; import android.hardware.graphics.composer3.ClockMonotonicTimestamp; import android.hardware.graphics.composer3.ColorMode; @@ -37,6 +39,7 @@ import android.hardware.graphics.composer3.DisplayIdentification; import android.hardware.graphics.composer3.FormatColorComponent; import android.hardware.graphics.composer3.HdrCapabilities; import android.hardware.graphics.composer3.IComposerCallback; +import android.hardware.graphics.composer3.Luts; import android.hardware.graphics.composer3.OverlayProperties; import android.hardware.graphics.composer3.PerFrameMetadataKey; import android.hardware.graphics.composer3.PowerMode; @@ -93,6 +96,18 @@ interface IComposerClient { * Seamless requirements cannot be met Exception */ const int EX_SEAMLESS_NOT_POSSIBLE = 10; + /** + * Proposed configuration failed for undisclosed reasons + */ + const int EX_CONFIG_FAILED = 11; + + /** + * The number of per-layer picture profiles in use is larger than the number of layer-specific + * picture-processing pipelines, as-defined by getMaxLayerPictureProfiles. + * + * @see LayerCommand.pictureProfileId + */ + const int EX_PICTURE_PROFILE_MAX_EXCEEDED = 12; /** * Integer.MAX_VALUE is reserved for the invalid configuration. @@ -558,6 +573,7 @@ interface IComposerClient { * @exception EX_BAD_DISPLAY when an invalid display handle was passed in. * @exception EX_BAD_CONFIG when the configuration handle passed in is not valid * for this display. + * @exception EX_CONFIG_FAILED when the config failed for undisclosed reasons. */ void setActiveConfig(long display, int config); @@ -583,6 +599,7 @@ interface IComposerClient { * achieve the vsync period change without a noticeable visual artifact. When the conditions * change and it may be possible to change the vsync period seamlessly, onSeamlessPossible * callback must be called to indicate that caller should retry. + * @exception EX_CONFIG_FAILED when the config failed for undisclosed reasons. * * @return is the timeline for the vsync period change. */ @@ -913,4 +930,40 @@ interface IComposerClient { */ oneway void notifyExpectedPresent( long display, in ClockMonotonicTimestamp expectedPresentTime, int frameIntervalNs); + + /* + * Returns the number of layer-specific picture-processing profiles that can be referenced from + * multiple LayerCommand.pictureProfileId. If the client passes in more pictureProfileIds whose + * values are larger than zero (indicating none) then the implementation can support, it should + * return EX_PICTURE_PROFILE_MAX_EXCEEDED. + * + * If the implementation only supports one display-wide picture-processing + * pipeline, a value of zero should be returned here. + */ + int getMaxLayerPictureProfiles(long display); + + /** + * Supports HDCP lazy activation. + * + * When SurfaceFlinger detects secure layers, this method is called to instruct HWC side that + * HDCP negotiation process can be started. + * + * When HDCP is successfully started or failed to start, HWC reports the HDCP levels via + * IComposerCallback.onHdcpLevelsChanged(). + * + * @param display is the display whose HDCP negotiation can be started. + * @param levels is the desired HDCP levels. + * + * @see IComposerCallback.onHdcpLevelsChanged + * + */ + oneway void startHdcpNegotiation(long display, in HdcpLevels levels); + + /* + * Returns the Luts based on the buffers. + * + * @param display is the display for which the luts are requested. + * @param buffers is the buffer where the luts can be computed from + */ + Luts[] getLuts(long display, in Buffer[] buffers); } diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/LayerCommand.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/LayerCommand.aidl index bf4f504d01f3b46c7d330a31455b63909aa9fdf4..d7ef4c14404380d8148c094afd0ecb3e490b34c5 100644 --- a/graphics/composer/aidl/android/hardware/graphics/composer3/LayerCommand.aidl +++ b/graphics/composer/aidl/android/hardware/graphics/composer3/LayerCommand.aidl @@ -24,7 +24,7 @@ import android.hardware.graphics.composer3.Buffer; import android.hardware.graphics.composer3.Color; import android.hardware.graphics.composer3.LayerBrightness; import android.hardware.graphics.composer3.LayerLifecycleBatchCommandType; -import android.hardware.graphics.composer3.Lut; +import android.hardware.graphics.composer3.Luts; import android.hardware.graphics.composer3.ParcelableBlendMode; import android.hardware.graphics.composer3.ParcelableComposition; import android.hardware.graphics.composer3.ParcelableDataspace; @@ -284,5 +284,21 @@ parcelable LayerCommand { /** * Sets the lut(s) for the layer. */ - @nullable Lut[] luts; + @nullable Luts luts; + + /** + * If the display has multiple per-layer picture processing pipelines, then this value is used + * to look up a picture profile which defines the parameters used when configuring a + * picture-processing pipeline for this layer, enhancing the quality of the buffer contents. If + * the server doesn't recognize this profile, it must continue with composition and ignore + * this value. If the value is zero, then the no picture processing must be applied. + * + * Note that the client will never send a DisplayCommand.pictureProfileId if + * IComposerClient.getMaxLayerPictureProfiles is non-zero. Picture profiles will only be + * specified on a per-layer basis. + * + * @see IComposerClient.getMaxLayerPictureProfiles + * @see DisplayCommand.pictureProfileId + */ + long pictureProfileId; } diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/LutProperties.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/LutProperties.aidl index 47ec3906704da854448007b1054f5b3e319f4b03..5f436d90705feedc00ecfaaf53b24cdafb49d3cc 100644 --- a/graphics/composer/aidl/android/hardware/graphics/composer3/LutProperties.aidl +++ b/graphics/composer/aidl/android/hardware/graphics/composer3/LutProperties.aidl @@ -32,17 +32,16 @@ parcelable LutProperties { * The size of the Lut. * This refers to the length of a 1D Lut, or the grid size of a 3D one. */ - long size; + int size; /** * SamplingKey is about how a Lut can be sampled. - * A Lut can be sampled in more than one way, - * but only one sampling method is used at one time. + * A Lut can be sampled in more than one key, + * but only one sampling key is used at one time. * * The implementations should use a sampling strategy * at least as good as linear sampling. */ - // TODO(b/358422255): add sampling ways - @VintfStability enum SamplingKey { RGB, MAX_RGB } + @VintfStability enum SamplingKey { RGB, MAX_RGB, CIE_Y } SamplingKey[] samplingKeys; } diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/Lut.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/Luts.aidl similarity index 64% rename from graphics/composer/aidl/android/hardware/graphics/composer3/Lut.aidl rename to graphics/composer/aidl/android/hardware/graphics/composer3/Luts.aidl index abfeb148e62cc8ecdce0f4d8d7d4ed9529936a19..393354e07b2e2c8feabd276fb4cc2de536c727ae 100644 --- a/graphics/composer/aidl/android/hardware/graphics/composer3/Lut.aidl +++ b/graphics/composer/aidl/android/hardware/graphics/composer3/Luts.aidl @@ -26,13 +26,13 @@ import android.hardware.graphics.composer3.LutProperties; */ @VintfStability -parcelable Lut { +parcelable Luts { /** * A handle to a memory region. * If the file descriptor is not set, this means that the HWC doesn't specify a Lut. * * When specifying a Lut, the HWC is required to follow the instructions as below: - * 1. use `memfd_create` to create a shared memory segment + * 1. use `ashmem_create_region` to create a shared memory segment * with the size specified in lutProperties. * 2. use `mmap` to map the shared memory segment into its own virtual address space. * PROT_READ/PROT_WRITE recommended for prot argument. @@ -40,17 +40,31 @@ parcelable Lut { * For data precision, 32-bit float is used to specify a Lut by both the HWC and * the platform. * - * For unflattening/flattening 3D Lut(s), the algorithm below should be observed - * by both the HWC and the platform. * Assuming that we have a 3D array `ORIGINAL[WIDTH, HEIGHT, DEPTH]`, we would turn it into * `FLAT[WIDTH * HEIGHT * DEPTH]` by * * `FLAT[z + DEPTH * (y + HEIGHT * x)] = ORIGINAL[x, y, z]` + * + * Note that 1D Lut(s) should be gain curve ones and 3D Lut(s) should be pure color lookup + * ones. For 3D Luts buffer,the values of the lut buffer should be normalized, ranging from 0.0 + * to 1.0, inclusively and the data is organized in the order of R, G, B channels. + * For 1D Luts, the lut's values should be also normalized for fixed point pixel formats, + * and we now ignore floating point pixel formats + extended range buffers. */ @nullable ParcelFileDescriptor pfd; /** - * The properties of the Lut. + * The offsets store the starting point of each Lut memory of the Lut buffer. + * + * Multiple Luts can be packed into one same `pfd`, and `offsets` is used to pinpoint + * the starting point of each Lut. + */ + @nullable int[] offsets; + + /** + * The properties list of the Luts. + * + * The number of sampling key inside should only be one. */ - LutProperties lutProperties; + LutProperties[] lutProperties; } diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/OutputType.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/OutputType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..bf4a7867e51e0074fe7b99956df006190217806e --- /dev/null +++ b/graphics/composer/aidl/android/hardware/graphics/composer3/OutputType.aidl @@ -0,0 +1,42 @@ +/* + * 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. + */ + +package android.hardware.graphics.composer3; + +/** + * Display output formats for HDR content. + */ +@VintfStability +@Backing(type="int") +enum OutputType { + /** + * Invalid HDR output type + */ + INVALID = 0, + /** + * Display output format will be chosen by the HAL implementation + * and will not adjust to match the content format + */ + SYSTEM = 1, + /** + * Display supports SDR output type + */ + SDR = 2, + /** + * Display supports HDR10 output type + */ + HDR10 = 3, +} diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/PresentFence.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/PresentFence.aidl index b757656e09765193101a3b5b2bfd5927440ba22e..0d8ea7641a0616b4c61d51ff99572a2f6b5ab5e2 100644 --- a/graphics/composer/aidl/android/hardware/graphics/composer3/PresentFence.aidl +++ b/graphics/composer/aidl/android/hardware/graphics/composer3/PresentFence.aidl @@ -27,4 +27,40 @@ parcelable PresentFence { * The present fence for this display. */ ParcelFileDescriptor fence; + + /** + * A LayerPresentFence is provided by the server when a LayerCommand.pictureProfileId, specified + * by the client, results in the buffer being rendered on the display with some latency after + * the rest of the DisplayCommand has been rendered. This can happen due to the picture + * processing pipeline adding additional latency for the buffer, itself. LayerPresentFences are + * intended to arrive in the same order for each buffer submission on that layer. + * + * Note that this violates the SurfaceControl.Transaction API contract and therefore is only + * allowed on TV devices that require this feature to support high quality video playback on + * large displays. + */ + parcelable LayerPresentFence { + /** + * The layer which this fence refers to. + */ + long layer; + + /** + * The present fence for the buffer contents. + * + * If the buffer ends up being dropped by the server and not rendered, this fence should be + * fired at the same time as the next buffer's present fence (or the display fence if + * picture processing for this layer was removed). + */ + ParcelFileDescriptor bufferFence; + + /** + * The latency that is required for applying picture processing to the layer's buffer. + */ + long bufferLatencyNanos; + } + /** + * The LayerPresentFences for the display. + */ + @nullable LayerPresentFence[] layerPresentFences; } diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/ScreenPartStatus.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ScreenPartStatus.aidl new file mode 100644 index 0000000000000000000000000000000000000000..48c127071d870033a4546a39e149eef45696cde3 --- /dev/null +++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ScreenPartStatus.aidl @@ -0,0 +1,37 @@ +/** + * 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. + */ + +package android.hardware.graphics.composer3; + +/** + * Information relating to internal screen panel part originality + */ +@VintfStability +@Backing(type="int") +enum ScreenPartStatus { + /** + * Device cannot differentiate an original screen from a replaced screen. + */ + UNSUPPORTED = 0, + /** + * Device has the original screen it was manufactured with. + */ + ORIGINAL = 1, + /** + * Device has a replaced screen. + */ + REPLACED = 2, +} diff --git a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientReader.h b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientReader.h index 331d717356aeca59f57758315c6d7c45346cc273..21965307c6f57e417eb4e0fa577d9f7b2439c1b1 100644 --- a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientReader.h +++ b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientReader.h @@ -145,6 +145,18 @@ class ComposerClientReader { return std::move(data.releasedLayers); } + // Get and clear saved layer present fences. + std::vector takeLayerPresentFences(int64_t display) { + LOG_ALWAYS_FATAL_IF(mDisplay && display != *mDisplay); + auto found = mReturnData.find(display); + if (found == mReturnData.end()) { + return {}; + } + + ReturnData& data = found->second; + return std::move(data.layerPresentFences); + } + // Get and clear saved present fence. ndk::ScopedFileDescriptor takePresentFence(int64_t display) { LOG_ALWAYS_FATAL_IF(mDisplay && display != *mDisplay); @@ -223,6 +235,14 @@ class ComposerClientReader { LOG_ALWAYS_FATAL_IF(mDisplay && presentFence.display != *mDisplay); auto& data = mReturnData[presentFence.display]; data.presentFence = std::move(presentFence.fence); + + if (presentFence.layerPresentFences.has_value()) { + for (auto& optionalFence : presentFence.layerPresentFences.value()) { + if (optionalFence.has_value()) { + data.layerPresentFences.push_back(std::move(optionalFence.value())); + } + } + } } void parseSetReleaseFences(ReleaseFences&& releaseFences) { @@ -247,11 +267,11 @@ class ComposerClientReader { void parseSetDisplayLuts(DisplayLuts&& displayLuts) { LOG_ALWAYS_FATAL_IF(mDisplay && displayLuts.display != *mDisplay); auto& data = mReturnData[displayLuts.display]; - for (auto& layerLut : displayLuts.layerLuts) { - if (layerLut.lut.pfd.get() >= 0) { + for (auto& [layerId, luts] : displayLuts.layerLuts) { + if (luts.pfd.get() >= 0) { data.layerLuts.push_back( - {layerLut.layer, Lut{ndk::ScopedFileDescriptor(layerLut.lut.pfd.release()), - layerLut.lut.lutProperties}}); + {layerId, Luts{ndk::ScopedFileDescriptor(luts.pfd.release()), luts.offsets, + luts.lutProperties}}); } } } @@ -260,6 +280,7 @@ class ComposerClientReader { DisplayRequest displayRequests; std::vector changedLayers; ndk::ScopedFileDescriptor presentFence; + std::vector layerPresentFences; std::vector releasedLayers; PresentOrValidate::Result presentOrValidateState; diff --git a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h index 02fb3aab28e6244ec58733b968e306c7f90dbf51..71a04f3228dd6b354e347ce5ccf7cf9abce1dd14 100644 --- a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h +++ b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h @@ -25,22 +25,20 @@ #include #include +#include +#include +#include +#include #include #include #include +#include #include #include -#include +#include #include #include -#include - -#include -#include -#include -#include - #include #include @@ -59,6 +57,8 @@ using aidl::android::hardware::common::NativeHandle; namespace aidl::android::hardware::graphics::composer3 { +using PictureProfileId = decltype(LayerCommand().pictureProfileId); + class ComposerClientWriter final { public: static constexpr std::optional kNoTimestamp = std::nullopt; @@ -84,6 +84,10 @@ class ComposerClientWriter final { DisplayBrightness{.brightness = brightness, .brightnessNits = brightnessNits}); } + void setDisplayPictureProfileId(int64_t display, PictureProfileId pictureProfileId) { + getDisplayCommand(display).pictureProfileId = pictureProfileId; + } + void setClientTarget(int64_t display, uint32_t slot, const native_handle_t* target, int acquireFence, Dataspace dataspace, const std::vector& damage, float hdrSdrRatio) { @@ -246,13 +250,13 @@ class ComposerClientWriter final { getLayerCommand(display, layer).blockingRegion.emplace(blocking.begin(), blocking.end()); } - void setLayerLuts(int64_t display, int64_t layer, std::vector& luts) { - std::vector> currentLuts; - for (auto& lut : luts) { - currentLuts.push_back(std::make_optional( - {ndk::ScopedFileDescriptor(lut.pfd.release()), lut.lutProperties})); - } - getLayerCommand(display, layer).luts.emplace(std::move(currentLuts)); + void setLayerLuts(int64_t display, int64_t layer, Luts& luts) { + getLayerCommand(display, layer).luts.emplace(std::move(luts)); + } + + void setLayerPictureProfileId(int64_t display, int64_t layer, + PictureProfileId pictureProfileId) { + getLayerCommand(display, layer).pictureProfileId = pictureProfileId; } std::vector takePendingCommands() { diff --git a/graphics/composer/aidl/libhwc_aidl_test/ComposerClientWrapper.cpp b/graphics/composer/aidl/libhwc_aidl_test/ComposerClientWrapper.cpp index a81af8f6970e3cf3a52caa26a24e395d96a693e3..fe81bdaa03f9e429dcae6af75333a5bd194102a6 100644 --- a/graphics/composer/aidl/libhwc_aidl_test/ComposerClientWrapper.cpp +++ b/graphics/composer/aidl/libhwc_aidl_test/ComposerClientWrapper.cpp @@ -700,4 +700,11 @@ bool ComposerClientWrapper::destroyAllLayers( mDisplayResources.clear(); return true; } + +std::pair ComposerClientWrapper::getMaxLayerPictureProfiles( + int64_t display) { + int32_t outMaxProfiles = 0; + return {mComposerClient->getMaxLayerPictureProfiles(display, &outMaxProfiles), outMaxProfiles}; +} + } // namespace aidl::android::hardware::graphics::composer3::libhwc_aidl_test diff --git a/graphics/composer/aidl/libhwc_aidl_test/include/ComposerClientWrapper.h b/graphics/composer/aidl/libhwc_aidl_test/include/ComposerClientWrapper.h index 2ad081d1a9c148ba65e47e0a1ac0f45875e2d697..73542ec8b4db3166546cea9195b97b90d9514be2 100644 --- a/graphics/composer/aidl/libhwc_aidl_test/include/ComposerClientWrapper.h +++ b/graphics/composer/aidl/libhwc_aidl_test/include/ComposerClientWrapper.h @@ -198,6 +198,8 @@ class ComposerClientWrapper { std::vector takeListOfRefreshRateChangedDebugData(); + std::pair getMaxLayerPictureProfiles(int64_t display); + static constexpr int32_t kMaxFrameIntervalNs = 50000000; // 20fps static constexpr int32_t kNoFrameIntervalNs = 0; diff --git a/graphics/composer/aidl/vts/Android.bp b/graphics/composer/aidl/vts/Android.bp index 8f5c7d20d4cbb3db04f2aa8e6361ebf7845d2e69..bba043fd1b053ffc594dcb01140870777ae3661f 100644 --- a/graphics/composer/aidl/vts/Android.bp +++ b/graphics/composer/aidl/vts/Android.bp @@ -60,6 +60,8 @@ cc_test { "libaidlcommonsupport", "libarect", "libbase", + "libfmq", + "libgmock", "libgtest", "libhwc_aidl_test", "librenderengine", diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp index 77d8cddaac47a28357fc278ddf1d1cf15d92c870..fd8766973912afe1a946906ca868add1a7dd6471 100644 --- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp +++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp @@ -22,15 +22,19 @@ #include #include #include +#include #include #include #include #include #include #include +#include +#include #include #include #include +#include #include #include #include @@ -45,6 +49,8 @@ #undef LOG_TAG #define LOG_TAG "VtsHalGraphicsComposer3_TargetTest" +using testing::Ge; + namespace aidl::android::hardware::graphics::composer3::vts { using namespace std::chrono_literals; @@ -120,6 +126,15 @@ class GraphicsComposerAidlTest : public ::testing::TestWithParam { [&](const Capability& activeCapability) { return activeCapability == capability; }); } + bool hasDisplayCapability(int64_t displayId, DisplayCapability capability) { + const auto& [status, capabilities] = mComposerClient->getDisplayCapabilities(displayId); + EXPECT_TRUE(status.isOk()); + return std::any_of(capabilities.begin(), capabilities.end(), + [&](const DisplayCapability& activeCapability) { + return activeCapability == capability; + }); + } + int getInterfaceVersion() { const auto& [versionStatus, version] = mComposerClient->getInterfaceVersion(); EXPECT_TRUE(versionStatus.isOk()); @@ -1255,6 +1270,16 @@ TEST_P(GraphicsComposerAidlV3Test, GetDisplayConfigurations) { EXPECT_TRUE(status.isOk()); EXPECT_FALSE(displayConfigurations.empty()); + const bool areAllModesARR = + std::all_of(displayConfigurations.cbegin(), displayConfigurations.cend(), + [](const auto& config) { return config.vrrConfig.has_value(); }); + + const bool areAllModesMRR = + std::all_of(displayConfigurations.cbegin(), displayConfigurations.cend(), + [](const auto& config) { return !config.vrrConfig.has_value(); }); + + EXPECT_TRUE(areAllModesARR || areAllModesMRR) << "Mixing MRR and ARR modes is not allowed"; + for (const auto& displayConfig : displayConfigurations) { EXPECT_NE(-1, displayConfig.width); EXPECT_NE(-1, displayConfig.height); @@ -2052,6 +2077,7 @@ TEST_P(GraphicsComposerAidlCommandTest, SetLayerBuffer) { EXPECT_TRUE(layerStatus.isOk()); writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, handle, /*acquireFence*/ -1); execute(); + ASSERT_TRUE(mReader.takeErrors().empty()); } TEST_P(GraphicsComposerAidlCommandTest, SetLayerBufferMultipleTimes) { @@ -3223,6 +3249,168 @@ TEST_P(GraphicsComposerAidlCommandV3Test, frameIntervalChangeAtPresentFrame) { }); } +class GraphicsComposerAidlCommandV4Test : public GraphicsComposerAidlCommandTest { + protected: + void SetUp() override { + GraphicsComposerAidlTest::SetUp(); + if (getInterfaceVersion() <= 3) { + GTEST_SKIP() << "Device interface version is expected to be >= 4"; + } + } +}; + +TEST_P(GraphicsComposerAidlCommandV4Test, getMaxLayerPictureProfiles_success) { + for (auto& display : mDisplays) { + int64_t displayId = display.getDisplayId(); + if (!hasDisplayCapability(displayId, DisplayCapability::PICTURE_PROCESSING)) { + continue; + } + const auto& [status, maxProfiles] = + mComposerClient->getMaxLayerPictureProfiles(displayId); + EXPECT_TRUE(status.isOk()); + EXPECT_THAT(maxProfiles, Ge(0)); + } +} + +TEST_P(GraphicsComposerAidlCommandV4Test, getMaxLayerPictureProfiles_unsupported) { + for (auto& display : mDisplays) { + int64_t displayId = display.getDisplayId(); + if (hasDisplayCapability(displayId, DisplayCapability::PICTURE_PROCESSING)) { + continue; + } + const auto& [status, maxProfiles] = + mComposerClient->getMaxLayerPictureProfiles(displayId); + EXPECT_FALSE(status.isOk()); + EXPECT_NO_FATAL_FAILURE( + assertServiceSpecificError(status, IComposerClient::EX_UNSUPPORTED)); + } +} + +TEST_P(GraphicsComposerAidlCommandV4Test, setDisplayPictureProfileId_success) { + for (auto& display : mDisplays) { + int64_t displayId = display.getDisplayId(); + if (!hasDisplayCapability(displayId, DisplayCapability::PICTURE_PROCESSING)) { + continue; + } + + auto& writer = getWriter(displayId); + const auto layer = createOnScreenLayer(display); + const auto buffer = allocate(::android::PIXEL_FORMAT_RGBA_8888); + ASSERT_NE(nullptr, buffer->handle); + // TODO(b/337330263): Lookup profile IDs from MediaQualityManager + writer.setDisplayPictureProfileId(displayId, PictureProfileId(1)); + writer.setLayerBuffer(displayId, layer, /*slot*/ 0, buffer->handle, + /*acquireFence*/ -1); + execute(); + ASSERT_TRUE(mReader.takeErrors().empty()); + } +} + +TEST_P(GraphicsComposerAidlCommandV4Test, setLayerPictureProfileId_success) { + for (auto& display : mDisplays) { + int64_t displayId = display.getDisplayId(); + if (!hasDisplayCapability(displayId, DisplayCapability::PICTURE_PROCESSING)) { + continue; + } + const auto& [status, maxProfiles] = mComposerClient->getMaxLayerPictureProfiles(displayId); + EXPECT_TRUE(status.isOk()); + if (maxProfiles == 0) { + continue; + } + + auto& writer = getWriter(displayId); + const auto layer = createOnScreenLayer(display); + const auto buffer = allocate(::android::PIXEL_FORMAT_RGBA_8888); + ASSERT_NE(nullptr, buffer->handle); + writer.setLayerBuffer(displayId, layer, /*slot*/ 0, buffer->handle, + /*acquireFence*/ -1); + // TODO(b/337330263): Lookup profile IDs from MediaQualityManager + writer.setLayerPictureProfileId(displayId, layer, PictureProfileId(1)); + execute(); + ASSERT_TRUE(mReader.takeErrors().empty()); + } +} + +TEST_P(GraphicsComposerAidlCommandV4Test, setLayerPictureProfileId_failsWithTooManyProfiles) { + for (auto& display : mDisplays) { + int64_t displayId = display.getDisplayId(); + if (!hasDisplayCapability(displayId, DisplayCapability::PICTURE_PROCESSING)) { + continue; + } + const auto& [status, maxProfiles] = mComposerClient->getMaxLayerPictureProfiles(displayId); + EXPECT_TRUE(status.isOk()); + if (maxProfiles == 0) { + continue; + } + + auto& writer = getWriter(displayId); + for (int profileId = 1; profileId <= maxProfiles + 1; ++profileId) { + const auto layer = createOnScreenLayer(display); + const auto buffer = allocate(::android::PIXEL_FORMAT_RGBA_8888); + ASSERT_NE(nullptr, buffer->handle); + writer.setLayerBuffer(displayId, layer, /*slot*/ 0, buffer->handle, + /*acquireFence*/ -1); + // TODO(b/337330263): Lookup profile IDs from MediaQualityManager + writer.setLayerPictureProfileId(displayId, layer, PictureProfileId(profileId)); + } + execute(); + const auto errors = mReader.takeErrors(); + ASSERT_TRUE(errors.size() == 1 && + errors[0].errorCode == IComposerClient::EX_PICTURE_PROFILE_MAX_EXCEEDED); + } +} + +TEST_P(GraphicsComposerAidlCommandV4Test, SetUnsupportedLayerLuts) { + auto& writer = getWriter(getPrimaryDisplayId()); + const auto& [layerStatus, layer] = + mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer); + EXPECT_TRUE(layerStatus.isOk()); + const auto& [status, properties] = mComposerClient->getOverlaySupport(); + if (!status.isOk() && status.getExceptionCode() == EX_SERVICE_SPECIFIC && + status.getServiceSpecificError() == IComposerClient::EX_UNSUPPORTED) { + GTEST_SUCCEED() << "getOverlaySupport is not supported"; + return; + } + ASSERT_TRUE(status.isOk()); + + // TODO (b/362319189): add Lut VTS enforcement + if (!properties.lutProperties) { + int32_t size = 7; + size_t bufferSize = static_cast(size) * sizeof(float); + int32_t fd = ashmem_create_region("lut_shared_mem", bufferSize); + void* ptr = mmap(nullptr, bufferSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + std::vector buffers = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f}; + memcpy(ptr, buffers.data(), bufferSize); + munmap(ptr, bufferSize); + Luts luts; + luts.offsets = {0}; + luts.lutProperties = { + {LutProperties::Dimension::ONE_D, size, {LutProperties::SamplingKey::RGB}}}; + luts.pfd = ndk::ScopedFileDescriptor(fd); + + writer.setLayerLuts(getPrimaryDisplayId(), layer, luts); + writer.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp, + ComposerClientWrapper::kNoFrameIntervalNs); + execute(); + // change to client composition + ASSERT_FALSE(mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()); + ASSERT_TRUE(mReader.takeErrors().empty()); + } +} + +TEST_P(GraphicsComposerAidlCommandV4Test, GetDisplayConfigurations_hasHdrType) { + for (const auto& display : mDisplays) { + const auto& [status, displayConfigurations] = + mComposerClient->getDisplayConfigurations(display.getDisplayId()); + EXPECT_TRUE(status.isOk()); + EXPECT_FALSE(displayConfigurations.empty()); + + for (const auto& displayConfig : displayConfigurations) { + EXPECT_NE(displayConfig.hdrOutputType, OutputType::INVALID); + } + } +} + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerAidlCommandTest); INSTANTIATE_TEST_SUITE_P( PerInstance, GraphicsComposerAidlCommandTest, @@ -3253,6 +3441,11 @@ INSTANTIATE_TEST_SUITE_P( PerInstance, GraphicsComposerAidlCommandV3Test, testing::ValuesIn(::android::getAidlHalInstanceNames(IComposer::descriptor)), ::android::PrintInstanceNameToString); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerAidlCommandV4Test); +INSTANTIATE_TEST_SUITE_P( + PerInstance, GraphicsComposerAidlCommandV4Test, + testing::ValuesIn(::android::getAidlHalInstanceNames(IComposer::descriptor)), + ::android::PrintInstanceNameToString); } // namespace aidl::android::hardware::graphics::composer3::vts int main(int argc, char** argv) { diff --git a/graphics/mapper/stable-c/Android.bp b/graphics/mapper/stable-c/Android.bp index 82306be0a594d9f4e5ce99b5ee72fa5be45bba84..f4196b99b753211f809f549195097f5a77d5c1f0 100644 --- a/graphics/mapper/stable-c/Android.bp +++ b/graphics/mapper/stable-c/Android.bp @@ -111,7 +111,7 @@ cc_test { "VtsHalTargetTestDefaults", "use_libaidlvintf_gtest_helper_static", "android.hardware.graphics.allocator-ndk_shared", - "android.hardware.graphics.common-ndk_shared", + "android.hardware.graphics.common-ndk_static", ], srcs: [ "vts/VtsHalGraphicsMapperStableC_TargetTest.cpp", diff --git a/health/aidl/Android.bp b/health/aidl/Android.bp index 97de0e2698979e79a2c9ec0c10f0159843041f80..d2ad3b118143eeaa296ecb27feedc3e243441d10 100644 --- a/health/aidl/Android.bp +++ b/health/aidl/Android.bp @@ -50,9 +50,8 @@ aidl_interface { version: "3", imports: [], }, - ], - frozen: true, + frozen: false, } @@ -84,7 +83,7 @@ cc_library { name: "android.hardware.health-translate-ndk", defaults: ["android.hardware.health-translate-ndk_defaults"], shared_libs: [ - "android.hardware.health-V3-ndk", + "android.hardware.health-V4-ndk", ], } @@ -101,7 +100,7 @@ java_library { name: "android.hardware.health-translate-java", srcs: ["android/hardware/health/Translate.java"], libs: [ - "android.hardware.health-V3-java", + "android.hardware.health-V4-java", "android.hardware.health-V2.0-java", "android.hardware.health-V2.1-java", ], diff --git a/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/BatteryPartStatus.aidl b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/BatteryPartStatus.aidl index e013e31a2498a82d745780febc5e1137b364ae67..93037679758bc85a2095ab055d007f59ce85c904 100644 --- a/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/BatteryPartStatus.aidl +++ b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/BatteryPartStatus.aidl @@ -34,7 +34,7 @@ package android.hardware.health; @Backing(type="int") @VintfStability enum BatteryPartStatus { - UNSUPPORTED, - ORIGINAL, - REPLACED, + UNSUPPORTED = 0, + ORIGINAL = 1, + REPLACED = 2, } diff --git a/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/HealthInfo.aidl b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/HealthInfo.aidl index bfa14758f3406edaff15080303652cd10b1e9b03..d993040a3e55a286105fef4d5dd5600f77ce9450 100644 --- a/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/HealthInfo.aidl +++ b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/HealthInfo.aidl @@ -60,5 +60,6 @@ parcelable HealthInfo { android.hardware.health.BatteryChargingState chargingState; android.hardware.health.BatteryChargingPolicy chargingPolicy; @nullable android.hardware.health.BatteryHealthData batteryHealthData; + @nullable android.hardware.health.HingeInfo[] hingeInfos; const int BATTERY_CHARGE_TIME_TO_FULL_NOW_SECONDS_UNSUPPORTED = (-1) /* -1 */; } diff --git a/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/HingeInfo.aidl b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/HingeInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..b3c38ad54f6e6b93fd2061142d4db1718117a848 --- /dev/null +++ b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/HingeInfo.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.health; +@VintfStability +parcelable HingeInfo { + int numTimesFolded; + int expectedHingeLifespan; +} diff --git a/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/IHealth.aidl b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/IHealth.aidl index b49dfffbe44c8af6dad5f052c591c816b064a249..e919f1485eba5c5b15c92dcd15ea2d0b678664fc 100644 --- a/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/IHealth.aidl +++ b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/IHealth.aidl @@ -49,6 +49,7 @@ interface IHealth { void setChargingPolicy(android.hardware.health.BatteryChargingPolicy in_value); android.hardware.health.BatteryChargingPolicy getChargingPolicy(); android.hardware.health.BatteryHealthData getBatteryHealthData(); + android.hardware.health.HingeInfo[] getHingeInfo(); const int STATUS_UNKNOWN = 2; const int STATUS_CALLBACK_DIED = 4; } diff --git a/health/aidl/android/hardware/health/HealthInfo.aidl b/health/aidl/android/hardware/health/HealthInfo.aidl index af84089598280e2846391595854f53dcb84878c1..1c953eef1f1523a913b7768592ed5457ca9e26ca 100644 --- a/health/aidl/android/hardware/health/HealthInfo.aidl +++ b/health/aidl/android/hardware/health/HealthInfo.aidl @@ -24,6 +24,7 @@ import android.hardware.health.BatteryHealthData; import android.hardware.health.BatteryStatus; import android.hardware.health.DiskStats; import android.hardware.health.StorageInfo; +import android.hardware.health.HingeInfo; /** * Health Information. @@ -115,7 +116,6 @@ parcelable HealthInfo { * Battery capacity level. See {@link BatteryCapacityLevel} for more details. */ BatteryCapacityLevel batteryCapacityLevel; - /** * Value of {@link #batteryChargeTimeToFullNowSeconds} if it is not * supported. @@ -148,4 +148,8 @@ parcelable HealthInfo { * Battery health data */ @nullable BatteryHealthData batteryHealthData; + /** + * Information about foldable hinge health. Will be an empty vector if no hinges present + */ + @nullable HingeInfo[] hingeInfos; } diff --git a/health/aidl/android/hardware/health/HingeInfo.aidl b/health/aidl/android/hardware/health/HingeInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ad38821247de9fa79e9673d8efaba09178be8fe0 --- /dev/null +++ b/health/aidl/android/hardware/health/HingeInfo.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ + +package android.hardware.health; + +/* + * Information on foldable hinge health life time estimates, end of life + * information and other attributes. + * + * All integers in this struct must be interpreted as non-negative. + */ +@VintfStability +parcelable HingeInfo { + /** + * returns count of times a given hinge has been folded. + * + * opening fully counts as 1 fold and closing fully counts as another. + * The hinge has to engage in its full range of motion to be considered + * a fold. Partial folds must not be counted. + */ + int numTimesFolded; + /** + * returns the expected lifespan of hinge in units of number of folds + */ + int expectedHingeLifespan; +} diff --git a/health/aidl/android/hardware/health/IHealth.aidl b/health/aidl/android/hardware/health/IHealth.aidl index bdfe07a8d24ad2b7e0942a37997d61ac55533865..c88141ccf4d746e0e3261f3f12e76222a4774b78 100644 --- a/health/aidl/android/hardware/health/IHealth.aidl +++ b/health/aidl/android/hardware/health/IHealth.aidl @@ -23,6 +23,7 @@ import android.hardware.health.DiskStats; import android.hardware.health.HealthInfo; import android.hardware.health.IHealthInfoCallback; import android.hardware.health.StorageInfo; +import android.hardware.health.HingeInfo; /** * IHealth manages health info and posts events on registered callbacks. @@ -242,4 +243,17 @@ interface IHealth { * for other errors. */ BatteryHealthData getBatteryHealthData(); + + /** + * Get Hinge info. + * + * @return vector of HingeInfo structs if successful. + * If error: + * - Return exception with code EX_UNSUPPORTED_OPERATION + * if this property is not supported, + * - Return service specific error with code STATUS_UNKNOWN + * for other errors. + */ + HingeInfo[] getHingeInfo(); + } diff --git a/health/aidl/default/Android.bp b/health/aidl/default/Android.bp index 2071f08f61b2efec43be22985e218c189ec2f29d..cc5d0a05b007d8e7f331c66e701b4c201877838c 100644 --- a/health/aidl/default/Android.bp +++ b/health/aidl/default/Android.bp @@ -29,7 +29,7 @@ cc_defaults { "libcutils", "liblog", "libutils", - "android.hardware.health-V3-ndk", + "android.hardware.health-V4-ndk", // TODO(b/177269435): remove when BatteryMonitor works with AIDL HealthInfo. "libhidlbase", @@ -48,7 +48,7 @@ cc_defaults { name: "libhealth_aidl_charger_defaults", shared_libs: [ // common - "android.hardware.health-V3-ndk", + "android.hardware.health-V4-ndk", "libbase", "libcutils", "liblog", @@ -195,7 +195,7 @@ cc_fuzz { "service_fuzzer_defaults", ], static_libs: [ - "android.hardware.health-V3-ndk", + "android.hardware.health-V4-ndk", "libbase", "liblog", "fuzz_libhealth_aidl_impl", diff --git a/health/aidl/default/Health.cpp b/health/aidl/default/Health.cpp index 37662eacf32493e605938362c2f40a1cec286fea..d0e2dacf6a2de33c06cfde29a6e699604aed778c 100644 --- a/health/aidl/default/Health.cpp +++ b/health/aidl/default/Health.cpp @@ -192,6 +192,12 @@ ndk::ScopedAStatus Health::getStorageInfo(std::vector*) { return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); } +ndk::ScopedAStatus Health::getHingeInfo(std::vector*) { + // This implementation does not support HingeInfo. An implementation may extend this + // class and override this function to support storage info. + return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +} + ndk::ScopedAStatus Health::getHealthInfo(HealthInfo* out) { battery_monitor_.updateValues(); diff --git a/health/aidl/default/android.hardware.health-service.example.xml b/health/aidl/default/android.hardware.health-service.example.xml index 2acaabacbe5ec59f93b586b5b0a701ee55e62f8d..8ddfbdaaeed4a034697da989d0fde0d998458d55 100644 --- a/health/aidl/default/android.hardware.health-service.example.xml +++ b/health/aidl/default/android.hardware.health-service.example.xml @@ -1,7 +1,7 @@ android.hardware.health - 3 + 4 IHealth/default diff --git a/health/aidl/default/include/health-impl/Health.h b/health/aidl/default/include/health-impl/Health.h index 429ae2ab96473c3025c2bee32d93d71e7d67c737..96df5172f921379873944c9402fa5adaeb29b84e 100644 --- a/health/aidl/default/include/health-impl/Health.h +++ b/health/aidl/default/include/health-impl/Health.h @@ -72,6 +72,7 @@ class Health : public BnHealth, public HalHealthLoopCallback { // The default implementations return nothing in |out|. ndk::ScopedAStatus getDiskStats(std::vector* out) override; ndk::ScopedAStatus getStorageInfo(std::vector* out) override; + ndk::ScopedAStatus getHingeInfo(std::vector* out) override; ndk::ScopedAStatus setChargingPolicy(BatteryChargingPolicy in_value) override; ndk::ScopedAStatus getChargingPolicy(BatteryChargingPolicy* out) override; diff --git a/health/aidl/vts/functional/Android.bp b/health/aidl/vts/functional/Android.bp index 25ba5f8721f8e5a80a90bbd2421c320405ba0288..75bec97f6c93d831b3c70d1715842fe21e528ed8 100644 --- a/health/aidl/vts/functional/Android.bp +++ b/health/aidl/vts/functional/Android.bp @@ -40,7 +40,7 @@ cc_test { "libbinder_ndk", ], static_libs: [ - "android.hardware.health-V3-ndk", + "android.hardware.health-V4-ndk", "libgmock", ], header_libs: [ diff --git a/health/aidl/vts/functional/VtsHalHealthTargetTest.cpp b/health/aidl/vts/functional/VtsHalHealthTargetTest.cpp index 45a1e405012813bbd78bea9ef7ce4ee961aa2e24..a44cd5ee539755fbc843244b3d149fbb0d67f2dd 100644 --- a/health/aidl/vts/functional/VtsHalHealthTargetTest.cpp +++ b/health/aidl/vts/functional/VtsHalHealthTargetTest.cpp @@ -359,6 +359,20 @@ TEST_P(HealthAidl, getStorageInfo) { ASSERT_THAT(value, Each(IsValidStorageInfo())); } +/* + * Tests the values returned by getHingeInfo() from interface IHealth. + */ +TEST_P(HealthAidl, getHingeInfo) { + std::vector value; + auto status = health->getHingeInfo(&value); + ASSERT_THAT(status, AnyOf(IsOk(), ExceptionIs(EX_UNSUPPORTED_OPERATION))); + if (!status.isOk()) return; + for (auto& hinge : value) { + ASSERT_TRUE(hinge.expectedHingeLifespan >= 0); + ASSERT_TRUE(hinge.numTimesFolded >= 0); + } +} + /* * Tests the values returned by getDiskStats() from interface IHealth. */ diff --git a/health/utils/libhealthshim/Android.bp b/health/utils/libhealthshim/Android.bp index b0ea743ea6aa9c50758eb39e81cdfae14cc3d245..9f9970f3e21376d30b739851391b03d75f6e402c 100644 --- a/health/utils/libhealthshim/Android.bp +++ b/health/utils/libhealthshim/Android.bp @@ -34,7 +34,7 @@ cc_defaults { "-Werror", ], static_libs: [ - "android.hardware.health-V3-ndk", + "android.hardware.health-V4-ndk", "android.hardware.health-translate-ndk", "android.hardware.health@1.0", "android.hardware.health@2.0", diff --git a/health/utils/libhealthshim/include/health-shim/shim.h b/health/utils/libhealthshim/include/health-shim/shim.h index ff6849b116633d400de365b17d1130716c05a2db..9a6260148d9e21870a4a11a7e97987495007f5d8 100644 --- a/health/utils/libhealthshim/include/health-shim/shim.h +++ b/health/utils/libhealthshim/include/health-shim/shim.h @@ -43,6 +43,7 @@ class HealthShim : public BnHealth { ndk::ScopedAStatus getEnergyCounterNwh(int64_t* _aidl_return) override; ndk::ScopedAStatus getChargeStatus(BatteryStatus* _aidl_return) override; ndk::ScopedAStatus getStorageInfo(std::vector* _aidl_return) override; + ndk::ScopedAStatus getHingeInfo(std::vector* _aidl_return) override; ndk::ScopedAStatus getDiskStats(std::vector* _aidl_return) override; ndk::ScopedAStatus getHealthInfo(HealthInfo* _aidl_return) override; ndk::ScopedAStatus setChargingPolicy(BatteryChargingPolicy in_value) override; diff --git a/health/utils/libhealthshim/shim.cpp b/health/utils/libhealthshim/shim.cpp index a5ba919dd986520492b892b704b2d149c5d9277b..2ddf97e9c9bb00088fe943929c842d6ba24b3f7f 100644 --- a/health/utils/libhealthshim/shim.cpp +++ b/health/utils/libhealthshim/shim.cpp @@ -190,6 +190,10 @@ ScopedAStatus HealthShim::getStorageInfo(std::vector* out) { return ReturnAndResultToStatus(ret, out_result); } +ScopedAStatus HealthShim::getHingeInfo(std::vector* /*out*/) { + return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +} + ScopedAStatus HealthShim::getDiskStats(std::vector* out) { Result out_result = Result::UNKNOWN; auto ret = service_->getDiskStats([out, &out_result](auto result, const auto& value) { diff --git a/power/aidl/Android.bp b/power/aidl/Android.bp index dc5761312b14cc00ff56519c50a05222f5432b73..2c80aab44cc89318224c85801e65943e0a93e5af 100644 --- a/power/aidl/Android.bp +++ b/power/aidl/Android.bp @@ -69,46 +69,53 @@ aidl_interface { "android.hardware.common-V2", ], }, - ], - frozen: true, - + frozen: false, } +power_version = "android.hardware.power-V6" + cc_defaults { name: "android.hardware.power-ndk_shared", shared_libs: [ - "android.hardware.power-V5-ndk", + power_version + "-ndk", ], } cc_defaults { name: "android.hardware.power-ndk_export_shared", shared_libs: [ - "android.hardware.power-V5-ndk", + power_version + "-ndk", ], export_shared_lib_headers: [ - "android.hardware.power-V5-ndk", + power_version + "-ndk", ], } cc_defaults { name: "android.hardware.power-ndk_static", static_libs: [ - "android.hardware.power-V5-ndk", + power_version + "-ndk", ], } java_defaults { name: "android.hardware.power-java_shared", libs: [ - "android.hardware.power-V5-java", + power_version + "-java", ], } java_defaults { name: "android.hardware.power-java_static", static_libs: [ - "android.hardware.power-V5-java", + power_version + "-java", + ], +} + +aidl_interface_defaults { + name: "android.hardware.power-aidl", + imports: [ + power_version, ], } diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/CompositionData.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/CompositionData.aidl new file mode 100644 index 0000000000000000000000000000000000000000..9ab48181d25b6c99e48ef420c5270e3a5fa4deb9 --- /dev/null +++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/CompositionData.aidl @@ -0,0 +1,43 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.power; +@VintfStability +parcelable CompositionData { + long timestampNanos; + long[] scheduledPresentTimestampsNanos; + long latchTimestampNanos; + android.hardware.power.FrameProducer[] producers; + @nullable android.hardware.power.CompositionUpdate updateData; + long[] outputIds; +} diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/CompositionUpdate.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/CompositionUpdate.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a0c4b2111d871cc1c291b4f9e9989ad3eceea239 --- /dev/null +++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/CompositionUpdate.aidl @@ -0,0 +1,40 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.power; +@VintfStability +parcelable CompositionUpdate { + long timestampNanos; + android.hardware.power.FrameProducerUpdate[] producerUpdates; + long[] deadOutputIds; +} diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/CpuHeadroomParams.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/CpuHeadroomParams.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a38156ab31b76ff9111f24492b7fac6d9e29600b --- /dev/null +++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/CpuHeadroomParams.aidl @@ -0,0 +1,44 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.power; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable CpuHeadroomParams { + android.hardware.power.CpuHeadroomParams.CalculationType calculationType = android.hardware.power.CpuHeadroomParams.CalculationType.MIN; + int calculationWindowMillis = 1000; + int[] tids; + enum CalculationType { + MIN, + AVERAGE, + } +} diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/CpuHeadroomResult.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/CpuHeadroomResult.aidl new file mode 100644 index 0000000000000000000000000000000000000000..21b1e69af17fe519fb07ee3bafba4da5c074d6fe --- /dev/null +++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/CpuHeadroomResult.aidl @@ -0,0 +1,38 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.power; +@JavaDerive(equals=true, toString=true) @VintfStability +union CpuHeadroomResult { + float globalHeadroom; +} diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/FrameProducer.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/FrameProducer.aidl new file mode 100644 index 0000000000000000000000000000000000000000..0d9084b65bc25f9ac84d5483f571cf5350fa0dc8 --- /dev/null +++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/FrameProducer.aidl @@ -0,0 +1,43 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.power; +@VintfStability +parcelable FrameProducer { + long producerId; + int uid; + double fps; + @nullable android.hardware.power.LatchedFrameData currentlyLatchedFrame; + boolean cpuDeadlineMissed; + boolean gpuDeadlineMissed; +} diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/FrameProducerUpdate.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/FrameProducerUpdate.aidl new file mode 100644 index 0000000000000000000000000000000000000000..08ea3dc26313c6b50ad2e72a2d2363fad9f09d91 --- /dev/null +++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/FrameProducerUpdate.aidl @@ -0,0 +1,40 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.power; +@VintfStability +parcelable FrameProducerUpdate { + long producerId; + boolean isDead; + int[] sessions; +} diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/GpuHeadroomParams.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/GpuHeadroomParams.aidl new file mode 100644 index 0000000000000000000000000000000000000000..6faa93891cc9032702175c1ed0ce9469591415bd --- /dev/null +++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/GpuHeadroomParams.aidl @@ -0,0 +1,43 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.power; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable GpuHeadroomParams { + android.hardware.power.GpuHeadroomParams.CalculationType calculationType = android.hardware.power.GpuHeadroomParams.CalculationType.MIN; + int calculationWindowMillis = 1000; + enum CalculationType { + MIN, + AVERAGE, + } +} diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/GpuHeadroomResult.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/GpuHeadroomResult.aidl new file mode 100644 index 0000000000000000000000000000000000000000..bbd3d8b0b418e6fa3e9d45de0057be91c40b3129 --- /dev/null +++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/GpuHeadroomResult.aidl @@ -0,0 +1,38 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.power; +@JavaDerive(equals=true, toString=true) @VintfStability +union GpuHeadroomResult { + float globalHeadroom; +} diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPower.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPower.aidl index 8acdaf20143ed466b043f46a31ac88c50d324bb9..080c0bd356d5369ba47bdb2487a4029f932cf0a8 100644 --- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPower.aidl +++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPower.aidl @@ -43,4 +43,9 @@ interface IPower { android.hardware.power.IPowerHintSession createHintSessionWithConfig(in int tgid, in int uid, in int[] threadIds, in long durationNanos, in android.hardware.power.SessionTag tag, out android.hardware.power.SessionConfig config); android.hardware.power.ChannelConfig getSessionChannel(in int tgid, in int uid); oneway void closeSessionChannel(in int tgid, in int uid); + android.hardware.power.SupportInfo getSupportInfo(); + android.hardware.power.CpuHeadroomResult getCpuHeadroom(in android.hardware.power.CpuHeadroomParams params); + android.hardware.power.GpuHeadroomResult getGpuHeadroom(in android.hardware.power.GpuHeadroomParams params); + oneway void sendCompositionData(in android.hardware.power.CompositionData[] data); + oneway void sendCompositionUpdate(in android.hardware.power.CompositionUpdate update); } diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/LatchedFrameData.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/LatchedFrameData.aidl new file mode 100644 index 0000000000000000000000000000000000000000..01ce1573068fd3ef06ccecaa85c5c5fc8f5a895c --- /dev/null +++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/LatchedFrameData.aidl @@ -0,0 +1,43 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.power; +@VintfStability +parcelable LatchedFrameData { + long frameStartTimestampNanos; + long intendedPresentTimestampNanos; + long bufferSubmissionTimestampNanos; + long gpuSignalTimestampNanos; + boolean usedGpu; + @nullable ParcelFileDescriptor gpuAcquireFence; +} diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionHint.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionHint.aidl index df316189a4a5330f7a780ea8e7ec2af063c9ac1c..f6b32d0a82002b9bf8c61edb5a2c3ab72b275600 100644 --- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionHint.aidl +++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionHint.aidl @@ -42,4 +42,6 @@ enum SessionHint { GPU_LOAD_UP = 5, GPU_LOAD_DOWN = 6, GPU_LOAD_RESET = 7, + CPU_LOAD_SPIKE = 8, + GPU_LOAD_SPIKE = 9, } diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionMode.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionMode.aidl index d0ae0bab708f15d33703d8ffb2d5f7742d708baa..448dbb307b6f6ead5b4f15bbf2716f8146a5e9ca 100644 --- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionMode.aidl +++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionMode.aidl @@ -35,4 +35,7 @@ package android.hardware.power; @Backing(type="int") @VintfStability enum SessionMode { POWER_EFFICIENCY, + GRAPHICS_PIPELINE, + AUTO_CPU, + AUTO_GPU, } diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionTag.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionTag.aidl index 862fbc5a07a325c7378ba0a3ff8b018751aa5f0d..71da2d4062dff39c4c3ec93b4b3fea2dcccf5a4e 100644 --- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionTag.aidl +++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionTag.aidl @@ -39,4 +39,5 @@ enum SessionTag { HWUI, GAME, APP, + SYSUI, } diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SupportInfo.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SupportInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c90125cc19600c99f3f3e3a51b365845104068b4 --- /dev/null +++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SupportInfo.aidl @@ -0,0 +1,59 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.power; +@VintfStability +parcelable SupportInfo { + boolean usesSessions; + long boosts; + long modes; + long sessionHints; + long sessionModes; + long sessionTags; + android.hardware.power.SupportInfo.CompositionDataSupportInfo compositionData; + android.hardware.power.SupportInfo.HeadroomSupportInfo headroom; + @VintfStability + parcelable CompositionDataSupportInfo { + boolean isSupported; + boolean disableGpuFences; + int maxBatchSize; + boolean alwaysBatch; + } + @VintfStability + parcelable HeadroomSupportInfo { + boolean isCpuSupported; + boolean isGpuSupported; + int cpuMinIntervalMillis; + int gpuMinIntervalMillis; + } +} diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/WorkDuration.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/WorkDuration.aidl index 45013ddf77f3bd74bd38a44160a0fb15cf5c212b..25a53505d1236466a6af2ddab90fd37003f48607 100644 --- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/WorkDuration.aidl +++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/WorkDuration.aidl @@ -39,4 +39,5 @@ parcelable WorkDuration { long workPeriodStartTimestampNanos; long cpuDurationNanos; long gpuDurationNanos; + long intendedPresentTimestampNanos; } diff --git a/power/aidl/android/hardware/power/CompositionData.aidl b/power/aidl/android/hardware/power/CompositionData.aidl new file mode 100644 index 0000000000000000000000000000000000000000..43c636fcfa2c50b6aa1157620d10c9faf74902d7 --- /dev/null +++ b/power/aidl/android/hardware/power/CompositionData.aidl @@ -0,0 +1,75 @@ +/* + * 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. + */ + +package android.hardware.power; + +import android.hardware.power.CompositionUpdate; +import android.hardware.power.FrameProducer; + +/** + * Object sent to PowerHAL once per frame during commit that contains relevant + * timing data for a given set of frame producers, drawing to a given set of outputs. + * + * This will generally be layer objects drawing to displays, but could also represent + * things like arbitrary graphics buffers drawing into network sockets. All frame + * producers that participated in this composition and have associated + * sessions will be listed under "producers". + * + * All timestamps use SYSTEM_TIME_MONOTONIC clock, at nanosecond resolution. + */ +@VintfStability +parcelable CompositionData { + /** + * Timestamp for when the message was sent, useful to combine and correlate + * composition data with any reported info from sessions. + * + * The latchTime can be used alongside this for chronologically + * ordering events that happened during latching, such as frame drop. + */ + long timestampNanos; + + /** + * Scheduled presentation times for each outputId, corresponding to the outputId + * with the same index. + */ + long[] scheduledPresentTimestampsNanos; + + /** + * The current frame's latch time for buffers targeting its vsync, this serves + * as the effective frame deadline unless the frame latches with GPU unsignaled. + */ + long latchTimestampNanos; + + /** + * The set of frame producers that tried to present this vsync on these outputs, + * ignoring the ones without associated sessions. + */ + FrameProducer[] producers; + + /** + * Optional parcel containing information not bound to a specific frame, + * such as lifecycle updates. These updates can be sent along with CompositionData + * to minimize additional calls, when appropriate. + */ + @nullable CompositionUpdate updateData; + + /** + * A list of IDs corresponding to one or more outputs, such as displays, + * that are the intended recipients of this frame composition. Each output + * ID is guaranteed to be unique for its lifetime. + */ + long[] outputIds; +} diff --git a/power/aidl/android/hardware/power/CompositionUpdate.aidl b/power/aidl/android/hardware/power/CompositionUpdate.aidl new file mode 100644 index 0000000000000000000000000000000000000000..7cd451c12d955123b20baecf16e8ac0ce6e64bd5 --- /dev/null +++ b/power/aidl/android/hardware/power/CompositionUpdate.aidl @@ -0,0 +1,43 @@ +/* + * 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. + */ + +package android.hardware.power; + +import android.hardware.power.FrameProducerUpdate; + +/** + * An update regarding composition objects that might be sent outside of a normal + * sendCompositionData call, such as for lifecycle updates. This object is either + * attached to CompositionData or sent separately, depending on current activity + * and urgency. + */ +@VintfStability +parcelable CompositionUpdate { + /** + * Timestamp for when the message was sent. + */ + long timestampNanos; + + /** + * Update objects for all frame producers that have changed. + */ + FrameProducerUpdate[] producerUpdates; + + /** + * The IDs of any outputs that have disconnected in the framework. + */ + long[] deadOutputIds; +} diff --git a/power/aidl/android/hardware/power/CpuHeadroomParams.aidl b/power/aidl/android/hardware/power/CpuHeadroomParams.aidl new file mode 100644 index 0000000000000000000000000000000000000000..fab8f430d0f04aab4defda47fb22c81aeb101f34 --- /dev/null +++ b/power/aidl/android/hardware/power/CpuHeadroomParams.aidl @@ -0,0 +1,55 @@ +/* + * 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. + */ + +package android.hardware.power; + +@VintfStability +@JavaDerive(equals=true, toString=true) +parcelable CpuHeadroomParams { + /** + * Defines how to calculate the headroom. + */ + enum CalculationType { + // Default to return the minimum headroom in a window. + MIN, + // Returns the average headroom in a window. + AVERAGE, + } + + /** + * The calculation type. + */ + CalculationType calculationType = CalculationType.MIN; + + /** + * The calculation rolling window size in milliseconds. + * The device should support a superset of [50, 10000] and try to use the closest feasible + * window size to the provided value param. + */ + int calculationWindowMillis = 1000; + + /** + * The thread TIDs to track. + * + * If tids are not-empty, return the headrooms only for cores that are available + * to the given tids, otherwise return the headroom(s) for all cores. + * + * This should handle all the cases including but not limited to core affinity and app cpuset + * that change the available CPU cores for the caller. And the HAL should check that the TIDs + * have the same core affinity. + */ + int[] tids; +} diff --git a/power/aidl/android/hardware/power/CpuHeadroomResult.aidl b/power/aidl/android/hardware/power/CpuHeadroomResult.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e7ed8b66ec76b3ac8abfb84fa45b3f0c9ed77324 --- /dev/null +++ b/power/aidl/android/hardware/power/CpuHeadroomResult.aidl @@ -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. + */ + +package android.hardware.power; + +/** + * Headroom value result depending on the request params. + * + * Each value is ranged from [0, 100], where 0 indicates no CPU resources were left + * during the calculation interval and the app may expect low resources to be granted. + */ +@VintfStability +@JavaDerive(equals=true, toString=true) +union CpuHeadroomResult { + /** + * If ALL selection type is requested. + */ + float globalHeadroom; +} diff --git a/power/aidl/android/hardware/power/FrameProducer.aidl b/power/aidl/android/hardware/power/FrameProducer.aidl new file mode 100644 index 0000000000000000000000000000000000000000..9ff77d36a3d18ece00e181e802381a5671cf2da0 --- /dev/null +++ b/power/aidl/android/hardware/power/FrameProducer.aidl @@ -0,0 +1,63 @@ +/* + * 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. + */ + +package android.hardware.power; + +import android.hardware.power.LatchedFrameData; + +/** + * Abstract unit of frame production. Frame production could be for outputs + * such as layers, sets of layers, serial devices, or a network connection. + * Frame producers are associated with one or more sessions that provide timing context + * and thread associations for the producer. + */ +@VintfStability +parcelable FrameProducer { + /** + * ID of the producer, unique per-producer at a given time. + */ + long producerId; + + /** + * UID of the process that owns the producer. + */ + int uid; + + /** + * The framerate of the producer. This parameter will be set when SF is reasonably + * confident it knows what framerate of the frame producer is, and will + * be set to -1 in cases where SF is not sure, or it's rapidly changing. + */ + double fps; + + /** + * Info for the currently latching frame on this producer, + * this value will be null if the producer tried but failed to latch. + */ + @nullable LatchedFrameData currentlyLatchedFrame; + + /** + * True if SF thinks a frame tried to latch for this producer but failed because the + * CPU did not submit a buffer on time; currentlyLatchedFrame is null if this is true. + */ + boolean cpuDeadlineMissed; + + /** + * True if SF thinks a frame tried to latch for this producer, but failed because the + * GPU did not finish on time; currentlyLatchedFrame is null if this is true. + */ + boolean gpuDeadlineMissed; +} diff --git a/power/aidl/android/hardware/power/FrameProducerUpdate.aidl b/power/aidl/android/hardware/power/FrameProducerUpdate.aidl new file mode 100644 index 0000000000000000000000000000000000000000..3075a8e9cf5de364dae54293120d4ecb960da5b8 --- /dev/null +++ b/power/aidl/android/hardware/power/FrameProducerUpdate.aidl @@ -0,0 +1,45 @@ + +/* + * 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. + */ + +package android.hardware.power; + +/** + * A single update for an individual producer object. + */ +@VintfStability +parcelable FrameProducerUpdate { + /** + * The ID of the producer, guaranteed to be unique at a given time. + */ + long producerId; + + /** + * If true, this producer is no longer active and its data can be released. + * "sessions" will be blank in this case, as there are no more associations + * with this producer. + */ + boolean isDead; + + /** + * The IDs of all sessions associated with the producer, corresponding to the + * ID in SessionConfig returned to the framework during session creation. + * + * If an object was created without a Session ID by using an older creation + * method, it is not eligible to be associated to a FrameProducer. + */ + int[] sessions; +} diff --git a/power/aidl/android/hardware/power/GpuHeadroomParams.aidl b/power/aidl/android/hardware/power/GpuHeadroomParams.aidl new file mode 100644 index 0000000000000000000000000000000000000000..68848d817ecad1031d0b0f5095e77dad49c52219 --- /dev/null +++ b/power/aidl/android/hardware/power/GpuHeadroomParams.aidl @@ -0,0 +1,42 @@ +/* + * 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. + */ + +package android.hardware.power; + +@VintfStability +@JavaDerive(equals=true, toString=true) +parcelable GpuHeadroomParams { + /** + * Defines how to calculate the headroom. + */ + enum CalculationType { + // Default to return the minimum headroom in a window. + MIN, + // Returns the average headroom in a window. + AVERAGE, + } + + /** + * The calculation type. + */ + CalculationType calculationType = CalculationType.MIN; + + /** + * The device should support a superset of [50, 10000] and try to use the closest feasible + * window size to the provided value param. + */ + int calculationWindowMillis = 1000; +} diff --git a/power/aidl/android/hardware/power/GpuHeadroomResult.aidl b/power/aidl/android/hardware/power/GpuHeadroomResult.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ef3257dea1461d42fd6c27535d9b29ac3f87f83c --- /dev/null +++ b/power/aidl/android/hardware/power/GpuHeadroomResult.aidl @@ -0,0 +1,29 @@ +/* + * 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. + */ + +package android.hardware.power; + +/** + * Headroom value result depending on the request params. + * + * Each value is ranged from [0, 100], where 0 indicates no GPU resources were left + * during the calculation interval and the app may expect low resources to be granted. + */ +@VintfStability +@JavaDerive(equals=true, toString=true) +union GpuHeadroomResult { + float globalHeadroom; +} diff --git a/power/aidl/android/hardware/power/IPower.aidl b/power/aidl/android/hardware/power/IPower.aidl index e25714fda50efdbc52f78b342d7f53fe2c437bac..ce61af401435cc2ddb138b834b317f05c8abb2bf 100644 --- a/power/aidl/android/hardware/power/IPower.aidl +++ b/power/aidl/android/hardware/power/IPower.aidl @@ -18,10 +18,17 @@ package android.hardware.power; import android.hardware.power.Boost; import android.hardware.power.ChannelConfig; +import android.hardware.power.CompositionData; +import android.hardware.power.CompositionUpdate; +import android.hardware.power.CpuHeadroomParams; +import android.hardware.power.CpuHeadroomResult; +import android.hardware.power.GpuHeadroomParams; +import android.hardware.power.GpuHeadroomResult; import android.hardware.power.IPowerHintSession; import android.hardware.power.Mode; import android.hardware.power.SessionConfig; import android.hardware.power.SessionTag; +import android.hardware.power.SupportInfo; @VintfStability interface IPower { @@ -144,4 +151,50 @@ interface IPower { * @param uid The UID to be associated with this channel. */ oneway void closeSessionChannel(in int tgid, in int uid); + + /** + * Called to get detailed information on the support status of various PowerHAL + * features, such as hint sessions and specific boosts. + * + * @return a SupportInfo giving detailed support information. + */ + SupportInfo getSupportInfo(); + + /** + * Provides an estimate of available CPU headroom the device based on past history. + *

+ * @param params params to customize the CPU headroom calculation + * @throws EX_UNSUPPORTED_OPERATION if the API is unsupported or the request params can't be + * served. + * @throws EX_SECURITY if the TIDs passed in do not belong to the same process. + * @throws EX_ILLEGAL_STATE if the TIDs passed in do not have the same core affinity setting. + */ + CpuHeadroomResult getCpuHeadroom(in CpuHeadroomParams params); + + /** + * Provides an estimate of available GPU headroom the device based on past history. + *

+ * @param params params to customize the GPU headroom calculation + * @throws EX_UNSUPPORTED_OPERATION if the API is unsupported or the request params can't be + * served. + */ + GpuHeadroomResult getGpuHeadroom(in GpuHeadroomParams params); + + /** + * Sent to PowerHAL when there are surface-attached sessions being composed, + * providing FPS and frame timing data that can be used to supplement + * and validate timing sent via reportActual. This call can be batched, + * especially in the case of a steady state or low-intensity workload. + * + * @param data The aggregated composition data object. + */ + oneway void sendCompositionData(in CompositionData[] data); + + /** + * Sent to inform the HAL about important updates outside of the normal + * reporting cycle, such as lifecycle updates for displays or FrameProducers. + * + * @param update The aggregated composition update object. + */ + oneway void sendCompositionUpdate(in CompositionUpdate update); } diff --git a/power/aidl/android/hardware/power/LatchedFrameData.aidl b/power/aidl/android/hardware/power/LatchedFrameData.aidl new file mode 100644 index 0000000000000000000000000000000000000000..064266976c9b354eede7ddf0b1725d1eb72fdcd7 --- /dev/null +++ b/power/aidl/android/hardware/power/LatchedFrameData.aidl @@ -0,0 +1,70 @@ +/* + * 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. + */ + +package android.hardware.power; + +/** + * Frame information for a specific frame producer on a specific composition, used to + * provide timing information and adjust boosting or scheduling strategies for sessions + * associated with that producer to compensate for observed behavior. + * + * All timestamps use SYSTEM_TIME_MONOTONIC clock, at nanosecond resolution. + */ +@VintfStability +parcelable LatchedFrameData { + /** + * Timestamp for the start of this frame, will be set to -1 if unknown. + */ + long frameStartTimestampNanos; + + /** + * Original, intended presentation time of the frame. + * + * This can be used along with the buffer submission timestamp to infer + * if the frame was supposed to present during a previous composition and got delayed. + * + * It can be compared with the "intendedPresentTimestampNanos" on WorkDurations to + * determine which reported duration sessions correspond with which LatchedFrameData, + * for sessions that use both manual reporting and have associated FrameProducers + */ + long intendedPresentTimestampNanos; + + /** + * Timestamp of buffer submission to SF from the CPU. + */ + long bufferSubmissionTimestampNanos; + + /** + * Timestamp where the GPU fence signaled, will be set to -1 if the buffer + * latched unsignaled or if the GPU was not used. + */ + long gpuSignalTimestampNanos; + + /** + * True if this frame used the GPU for rendering. + */ + boolean usedGpu; + + /** + * Optional GPU fence, sent only when the buffer latches unsignaled, and if + * sending fences is configured on the device in SupportInfo. If the updates + * are batched, a fence will only be sent for the most recent update. + * + * Can be used to get accurate gpu completion timestamps, and to boost if it + * looks like a frame might not signal before the deadline. + */ + @nullable ParcelFileDescriptor gpuAcquireFence; +} diff --git a/power/aidl/android/hardware/power/SessionHint.aidl b/power/aidl/android/hardware/power/SessionHint.aidl index 1a8c50557488f57df496e244dcc2268d2a0753d6..1b8a3ddf351968aa82cc4df3a694752105d50eb1 100644 --- a/power/aidl/android/hardware/power/SessionHint.aidl +++ b/power/aidl/android/hardware/power/SessionHint.aidl @@ -72,4 +72,18 @@ enum SessionHint { * baseline to prepare for an arbitrary load, and must wake up if inactive. */ GPU_LOAD_RESET = 7, + + /** + * This hint indicates an upcoming CPU workload that is abnormally large and + * not representative of the workload. This should be used for rare, one-time + * operations and should be ignored by any load tracking or session hysteresis. + */ + CPU_LOAD_SPIKE = 8, + + /** + * This hint indicates an upcoming GPU workload that is abnormally large and + * not representative of the workload. This should be used for rare, one-time + * operations and should be ignored by any load tracking or session hysteresis. + */ + GPU_LOAD_SPIKE = 9, } diff --git a/power/aidl/android/hardware/power/SessionMode.aidl b/power/aidl/android/hardware/power/SessionMode.aidl index f1ee64e7da8f9aa59e298839671e436aeee6bc14..5bd0e152598eb759accf38209aea9d47a7a5e423 100644 --- a/power/aidl/android/hardware/power/SessionMode.aidl +++ b/power/aidl/android/hardware/power/SessionMode.aidl @@ -25,4 +25,27 @@ enum SessionMode { * and can be safely scheduled to prefer power efficiency. */ POWER_EFFICIENCY, + + /** + * This mode indicates that the threads associated with this hint session + * are part of the graphics pipeline, implying that they are on a critical path + * which will be called of higher priority in terms of CPU resources and scheduling. + */ + GRAPHICS_PIPELINE, + + /** + * This mode indicates that the session does not intend to report CPU timing + * information, and that it instead will rely entirely on information from + * SurfaceFlinger. This mode is only supported for sessions that have + * GRAPHICS_PIPELINE enabled. + */ + AUTO_CPU, + + /** + * This mode indicates that the session does not intend to report GPU timing + * information, and that it instead will rely entirely on information from + * SurfaceFlinger. This mode is only supported for sessions that have + * GRAPHICS_PIPELINE enabled. + */ + AUTO_GPU, } diff --git a/power/aidl/android/hardware/power/SessionTag.aidl b/power/aidl/android/hardware/power/SessionTag.aidl index 27bf3e3c6796f6a40f4b5fb6e811bcbe99ef6a1c..e98cc77d77baeac86462f5a6b0c5e3ccca277884 100644 --- a/power/aidl/android/hardware/power/SessionTag.aidl +++ b/power/aidl/android/hardware/power/SessionTag.aidl @@ -46,4 +46,9 @@ enum SessionTag { * instead. */ APP, + + /** + * This tag is used to mark hint sessions created by the system UI. + */ + SYSUI, } diff --git a/power/aidl/android/hardware/power/SupportInfo.aidl b/power/aidl/android/hardware/power/SupportInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..55287cb6364ab2be1c15c7b4b6881094c411c481 --- /dev/null +++ b/power/aidl/android/hardware/power/SupportInfo.aidl @@ -0,0 +1,143 @@ +/* + * 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. + */ + +package android.hardware.power; + +import android.hardware.power.Boost; +import android.hardware.power.Mode; +import android.hardware.power.SessionHint; +import android.hardware.power.SessionMode; + +/** + * Tells clients the status of various PowerHAL features in a single call. + * SupportInfo consists of several bitsets, where each bit from the left + * corresponds to the support status of that same value of that enum index. + * + * For "Boost", having the first bit set would mean "INTERACTION" + * boost is supported, having the second bit set would mean + * "DISPLAY_UPDATE_IMMINENT" is supported, and so on. The expectation + * is that a client should be able to index the bitset like + * "(supportInfo.boosts >> Boost::AUDIO_LAUNCH) % 2" and it should return + * the support value of Boost::AUDIO_LAUNCH. This pattern is the same for + * all four support bitsets. + */ +@VintfStability +parcelable SupportInfo { + /** + * Boolean representing whether hint sessions are supported on this device. + */ + boolean usesSessions; + + /** + * The set of "Boost" enum values that are supported by this device, + * each bit should correspond to a value of the "Boost.aidl" enum. + */ + long boosts; + + /** + * The set of "Mode" enum values that are supported by this device, + * each bit should correspond to a value of the "Mode.aidl" enum. + */ + long modes; + + /** + * The set of "SessionHint" enum values that are supported by this device, + * each bit should correspond to a value of the "SessionHint.aidl" enum. + */ + long sessionHints; + + /** + * The set of "SessionMode" enum values that are supported by this device, + * each bit should correspond to a value of the "SessionMode.aidl" enum. + */ + long sessionModes; + + /** + * The set of "SessionTag" enum values that are supported by this device, + * each bit should correspond to a value of the "SessionTag.aidl" enum. + */ + long sessionTags; + + /** + * Parcel detailing support info for receiving additional frame composition + * data when sessions are associated with frame producers. + */ + CompositionDataSupportInfo compositionData; + + /** + * Parcel detailing support info for headroom information. + */ + HeadroomSupportInfo headroom; + + @VintfStability + parcelable CompositionDataSupportInfo { + /** + * Whether the sendCompositionData and sendCompositionUpdate APIs are + * supported on this device. The rest of the fields on this parcelable + * are ignored if this is false. + */ + boolean isSupported; + + /** + * Whether to disable sending relevant GPU fence file descriptors along with + * timing information when the frame callback happens. + */ + boolean disableGpuFences; + + /** + * The maximum number of updates to batch before sending. This can be ignored + * if "overrideIfUrgent" is set. Setting to a value less than or equal to 1 + * disables batching entirely. + */ + int maxBatchSize; + + /** + * Whether to ignore important notifications such as FPS changes and frame + * deadline misses, and always send maximum size batches. By default, the + * framework will send batches early if these important events happen. + */ + boolean alwaysBatch; + } + + @VintfStability + parcelable HeadroomSupportInfo { + /** + * Whether the CPU headroom feature is supported. + */ + boolean isCpuSupported; + + /** + * Whether the GPU headroom feature is supported. + */ + boolean isGpuSupported; + + /** + * Minimum polling interval for calling getCpuHeadroom in milliseconds + * + * The getCpuHeadroom API may return cached result if called more frequent + * than the interval. + */ + int cpuMinIntervalMillis; + + /** + * Minimum polling interval for calling getGpuHeadroom in milliseconds. + * + * The getGpuHeadroom API may return cached result if called more frequent + * than the interval. + */ + int gpuMinIntervalMillis; + } +} diff --git a/power/aidl/android/hardware/power/WorkDuration.aidl b/power/aidl/android/hardware/power/WorkDuration.aidl index fcd638b77a102dfb1d88bb2131cceef223f806e5..bcf279a2d0a4d21ade24c3079be6b17e3db4d3ea 100644 --- a/power/aidl/android/hardware/power/WorkDuration.aidl +++ b/power/aidl/android/hardware/power/WorkDuration.aidl @@ -19,7 +19,7 @@ package android.hardware.power; @VintfStability parcelable WorkDuration { /** - * Time stamp in nanoseconds based on CLOCK_MONOTONIC when the duration + * Timestamp in nanoseconds based on CLOCK_MONOTONIC when the duration * sample was measured. */ long timeStampNanos; @@ -49,4 +49,21 @@ parcelable WorkDuration { * SDK/NDK reportActualWorkDuration API. */ long gpuDurationNanos; + + /** + * Timestamp indicating the approximate time when this frame is intended to + * present by the app, and will be required for all sessions associated with + * frame producers. This should always be provided if the session is associated + * with a pipeline, even if it is not using the GRAPHICS_PIPELINE mode. + * + * This timestamp is intended to be used for correlating CompositionData timing + * information with reported WorkDurations from apps. WorkDurations for + * sessions associated with a frame producers, without a reasonable value set + * for this field should be discarded. + * + * Intended vsync times can be inferred or retrieved from Choreographer callbacks. + * While this timestamp is not required to be perfectly accurate, it should + * roughly correspond with an expected vsync time, and should be discarded otherwise. + */ + long intendedPresentTimestampNanos; } diff --git a/power/aidl/default/Power.cpp b/power/aidl/default/Power.cpp index 64294e52299887dcd579c77879f3c8e0b78be115..0a9c90f45a3af5f0c0a0fe720d3cdd7846888463 100644 --- a/power/aidl/default/Power.cpp +++ b/power/aidl/default/Power.cpp @@ -33,6 +33,8 @@ using namespace std::chrono_literals; using ::aidl::android::hardware::common::fmq::MQDescriptor; using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite; using ::aidl::android::hardware::power::ChannelMessage; +using ::aidl::android::hardware::power::CompositionData; +using ::aidl::android::hardware::power::CompositionUpdate; using ::android::AidlMessageQueue; using ndk::ScopedAStatus; @@ -41,6 +43,11 @@ const std::vector BOOST_RANGE{ndk::enum_range().begin(), ndk::enum_range().end()}; const std::vector MODE_RANGE{ndk::enum_range().begin(), ndk::enum_range().end()}; +template +constexpr size_t enum_size() { + return static_cast(*(ndk::enum_range().end() - 1)) + 1; +} + ScopedAStatus Power::setMode(Mode type, bool enabled) { LOG(VERBOSE) << "Power setMode: " << static_cast(type) << " to: " << enabled; return ScopedAStatus::ok(); @@ -64,6 +71,14 @@ ScopedAStatus Power::isBoostSupported(Boost type, bool* _aidl_return) { return ScopedAStatus::ok(); } +ndk::ScopedAStatus Power::getCpuHeadroom(const CpuHeadroomParams&, CpuHeadroomResult*) { + return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +} + +ndk::ScopedAStatus Power::getGpuHeadroom(const GpuHeadroomParams&, GpuHeadroomResult*) { + return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +} + ScopedAStatus Power::createHintSession(int32_t, int32_t, const std::vector& tids, int64_t, std::shared_ptr* _aidl_return) { if (tids.size() == 0) { @@ -105,11 +120,50 @@ ndk::ScopedAStatus Power::closeSessionChannel(int32_t, int32_t) { return ndk::ScopedAStatus::ok(); } -ScopedAStatus Power::getHintSessionPreferredRate(int64_t* outNanoseconds) { +ndk::ScopedAStatus Power::getHintSessionPreferredRate(int64_t* outNanoseconds) { *outNanoseconds = std::chrono::nanoseconds(1ms).count(); return ScopedAStatus::ok(); } +template +int64_t bitsForEnum() { + return static_cast(std::bitset()>().set().to_ullong()); +} + +ndk::ScopedAStatus Power::getSupportInfo(SupportInfo* _aidl_return) { + static SupportInfo supportInfo = {.usesSessions = false, + .modes = bitsForEnum(), + .boosts = bitsForEnum(), + .sessionHints = 0, + .sessionModes = 0, + .sessionTags = 0, + .compositionData = { + .isSupported = false, + .disableGpuFences = false, + .maxBatchSize = 1, + .alwaysBatch = false, + }, + .headroom = { + .isCpuSupported = false, + .isGpuSupported = false, + .cpuMinIntervalMillis = 0, + .gpuMinIntervalMillis = 0, + }}; + // Copy the support object into the binder + *_aidl_return = supportInfo; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Power::sendCompositionData(const std::vector&) { + LOG(INFO) << "Composition data received!"; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Power::sendCompositionUpdate(const CompositionUpdate&) { + LOG(INFO) << "Composition update received!"; + return ndk::ScopedAStatus::ok(); +} + } // namespace example } // namespace impl } // namespace power diff --git a/power/aidl/default/Power.h b/power/aidl/default/Power.h index baabaa72713351c0480ba17206c22185ad9e36ce..118097ff2fa45872748b8b8bea0f765d3d557e59 100644 --- a/power/aidl/default/Power.h +++ b/power/aidl/default/Power.h @@ -44,6 +44,14 @@ class Power : public BnPower { ndk::ScopedAStatus getSessionChannel(int32_t tgid, int32_t uid, ChannelConfig* _aidl_return) override; ndk::ScopedAStatus closeSessionChannel(int32_t tgid, int32_t uid) override; + ndk::ScopedAStatus getSupportInfo(SupportInfo* _aidl_return) override; + ndk::ScopedAStatus getCpuHeadroom(const CpuHeadroomParams& params, + CpuHeadroomResult* _aidl_return) override; + + ndk::ScopedAStatus getGpuHeadroom(const GpuHeadroomParams& params, + GpuHeadroomResult* _aidl_return) override; + ndk::ScopedAStatus sendCompositionData(const std::vector& in_data) override; + ndk::ScopedAStatus sendCompositionUpdate(const CompositionUpdate& in_update) override; private: std::vector> mPowerHintSessions; diff --git a/power/aidl/default/power-default.xml b/power/aidl/default/power-default.xml index 418fb83d624da621c6e762657055777a66603fe6..1bb73f30756ba5c8c74bd61fe2cf3a9849db1aaa 100644 --- a/power/aidl/default/power-default.xml +++ b/power/aidl/default/power-default.xml @@ -1,7 +1,7 @@ android.hardware.power - 5 + 6 IPower/default diff --git a/power/aidl/vts/VtsHalPowerTargetTest.cpp b/power/aidl/vts/VtsHalPowerTargetTest.cpp index 272674f1942002676afd99e8a661135e58b6f9e0..87797aedddd206d0c4dbf0ace9e312c971b75101 100644 --- a/power/aidl/vts/VtsHalPowerTargetTest.cpp +++ b/power/aidl/vts/VtsHalPowerTargetTest.cpp @@ -30,21 +30,30 @@ #include #include #include "aidl/android/hardware/common/fmq/SynchronizedReadWrite.h" +#include "aidl/android/hardware/power/CpuHeadroomParams.h" +#include "aidl/android/hardware/power/GpuHeadroomParams.h" namespace aidl::android::hardware::power { namespace { +using namespace std::chrono_literals; + using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite; using ::android::AidlMessageQueue; using ::android::hardware::EventFlag; using android::hardware::power::Boost; using android::hardware::power::ChannelConfig; using android::hardware::power::ChannelMessage; +using android::hardware::power::CpuHeadroomParams; +using android::hardware::power::CpuHeadroomResult; +using android::hardware::power::GpuHeadroomParams; +using android::hardware::power::GpuHeadroomResult; using android::hardware::power::IPower; using android::hardware::power::IPowerHintSession; using android::hardware::power::Mode; using android::hardware::power::SessionHint; using android::hardware::power::SessionMode; +using android::hardware::power::SupportInfo; using android::hardware::power::WorkDuration; using ChannelMessageContents = ChannelMessage::ChannelMessageContents; using ModeSetter = ChannelMessage::ChannelMessageContents::SessionModeSetter; @@ -83,6 +92,16 @@ const std::vector kInvalidSessionModes = { static_cast(static_cast(kSessionModes.back()) + 1), }; +template +constexpr size_t enum_size() { + return static_cast(*(ndk::enum_range().end() - 1)) + 1; +} + +template +bool supportFromBitset(int64_t& supportInt, E type) { + return (supportInt >> static_cast(type)) % 2; +} + class DurationWrapper : public WorkDuration { public: DurationWrapper(int64_t dur, int64_t time) { @@ -126,12 +145,17 @@ class PowerAidl : public testing::TestWithParam { status = power->createHintSession(getpid(), getuid(), kSelfTids, 16666666L, &mSession); mSessionSupport = status.isOk(); } + if (mServiceVersion >= 6) { + mSupportInfo = std::make_optional(); + ASSERT_TRUE(power->getSupportInfo(&(*mSupportInfo)).isOk()); + } } std::shared_ptr power; int32_t mServiceVersion; std::shared_ptr mSession; bool mSessionSupport = false; + std::optional mSupportInfo = std::nullopt; }; class HintSessionAidl : public PowerAidl { @@ -280,6 +304,42 @@ TEST_P(PowerAidl, createHintSessionWithConfig) { ASSERT_NE(nullptr, session); } +TEST_P(PowerAidl, getCpuHeadroom) { + if (mServiceVersion < 6) { + GTEST_SKIP() << "DEVICE not launching with Power V6 and beyond."; + } + CpuHeadroomParams params; + CpuHeadroomResult headroom; + auto ret = power->getCpuHeadroom(params, &headroom); + if (!mSupportInfo->headroom.isCpuSupported) { + ASSERT_EQ(ret.getExceptionCode(), EX_UNSUPPORTED_OPERATION); + GTEST_SKIP() << "power->getCpuHeadroom is not supported"; + } + ASSERT_TRUE(ret.isOk()); + ASSERT_GE(mSupportInfo->headroom.cpuMinIntervalMillis, 0); + ASSERT_EQ(headroom.getTag(), CpuHeadroomResult::globalHeadroom); + ASSERT_GE(headroom.get(), 0.0f); + ASSERT_LE(headroom.get(), 100.00f); +} + +TEST_P(PowerAidl, getGpuHeadroom) { + if (mServiceVersion < 6) { + GTEST_SKIP() << "DEVICE not launching with Power V6 and beyond."; + } + GpuHeadroomParams params; + GpuHeadroomResult headroom; + auto ret = power->getGpuHeadroom(params, &headroom); + if (!mSupportInfo->headroom.isGpuSupported) { + ASSERT_EQ(ret.getExceptionCode(), EX_UNSUPPORTED_OPERATION); + GTEST_SKIP() << "power->getGpuHeadroom is not supported"; + } + ASSERT_TRUE(ret.isOk()); + ASSERT_GE(mSupportInfo->headroom.gpuMinIntervalMillis, 0); + ASSERT_EQ(headroom.getTag(), GpuHeadroomResult::globalHeadroom); + ASSERT_GE(headroom.get(), 0.0f); + ASSERT_LE(headroom.get(), 100.00f); +} + // FIXED_PERFORMANCE mode is required for all devices which ship on Android 11 // or later TEST_P(PowerAidl, hasFixedPerformance) { @@ -288,6 +348,50 @@ TEST_P(PowerAidl, hasFixedPerformance) { ASSERT_TRUE(supported); } +TEST_P(PowerAidl, hasSupportInfo) { + if (mServiceVersion < 6) { + GTEST_SKIP() << "DEVICE not launching with Power V6 and beyond."; + } + ASSERT_TRUE(mSupportInfo.has_value()); + for (Mode mode : kModes) { + bool supported; + power->isModeSupported(mode, &supported); + ASSERT_EQ(supported, supportFromBitset(mSupportInfo->modes, mode)); + } + for (Boost boost : kBoosts) { + bool supported; + power->isBoostSupported(boost, &supported); + ASSERT_EQ(supported, supportFromBitset(mSupportInfo->boosts, boost)); + } +} + +TEST_P(PowerAidl, receivesCompositionData) { + if (mServiceVersion < 6) { + GTEST_SKIP() << "DEVICE not launching with Power V6 and beyond."; + } + if (mSupportInfo->compositionData.isSupported) { + GTEST_SKIP() << "Composition data marked as unsupported."; + } + // Sending an empty object is fine, we just want to confirm it accepts the tx + std::vector out{}; + out.emplace_back(); + auto status = power->sendCompositionData(out); + ASSERT_TRUE(status.isOk()); +} + +TEST_P(PowerAidl, receivesCompositionUpdate) { + if (mServiceVersion < 6) { + GTEST_SKIP() << "DEVICE not launching with Power V6 and beyond."; + } + if (mSupportInfo->compositionData.isSupported) { + GTEST_SKIP() << "Composition data marked as unsupported."; + } + + CompositionUpdate out{}; + auto status = power->sendCompositionUpdate(out); + ASSERT_TRUE(status.isOk()); +} + TEST_P(HintSessionAidl, createAndCloseHintSession) { if (!mSessionSupport) { GTEST_SKIP() << "DEVICE not support Hint Session."; diff --git a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfig.aidl b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfig.aidl index bba6bdd231ad4ff380fdb7dffef1d50a8cb5b44e..ded483539facf96ebf835eada7c2edccbb657c3e 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfig.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfig.aidl @@ -53,4 +53,6 @@ interface IRadioConfig { oneway void setResponseFunctions(in android.hardware.radio.config.IRadioConfigResponse radioConfigResponse, in android.hardware.radio.config.IRadioConfigIndication radioConfigIndication); oneway void setSimSlotsMapping(in int serial, in android.hardware.radio.config.SlotPortMapping[] slotMap); oneway void getSimultaneousCallingSupport(in int serial); + oneway void getSimTypeInfo(in int serial); + oneway void setSimType(in int serial, in android.hardware.radio.config.SimType[] simTypes); } diff --git a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfigResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfigResponse.aidl index 6ff7bd0b1b05394a36b5cfedbfc66b445fa1ca5a..4e0e133c1d1bbd50f947681274886b45c9a0defb 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfigResponse.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfigResponse.aidl @@ -43,4 +43,6 @@ interface IRadioConfigResponse { oneway void setPreferredDataModemResponse(in android.hardware.radio.RadioResponseInfo info); oneway void setSimSlotsMappingResponse(in android.hardware.radio.RadioResponseInfo info); oneway void getSimultaneousCallingSupportResponse(in android.hardware.radio.RadioResponseInfo info, in int[] enabledLogicalSlots); + oneway void getSimTypeInfoResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.config.SimTypeInfo[] simTypeInfo); + oneway void setSimTypeResponse(in android.hardware.radio.RadioResponseInfo info); } diff --git a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SimType.aidl b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SimType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..b27c86fb8520b7b14b50697f7b5e909eceba1451 --- /dev/null +++ b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SimType.aidl @@ -0,0 +1,41 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.radio.config; +/* @hide */ +@Backing(type="int") @JavaDerive(toString=true) @VintfStability +enum SimType { + UNKNOWN = 0, + PHYSICAL = (1 << 0) /* 1 */, + ESIM = (1 << 1) /* 2 */, +} diff --git a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SimTypeInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SimTypeInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..cba5dd9f9d62f00cbc893e09b1bf4c331f95b3f4 --- /dev/null +++ b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SimTypeInfo.aidl @@ -0,0 +1,40 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.radio.config; +/* @hide */ +@JavaDerive(toString=true) @VintfStability +parcelable SimTypeInfo { + android.hardware.radio.config.SimType currentSimType = android.hardware.radio.config.SimType.UNKNOWN; + int supportedSimTypes; +} diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataCallFailCause.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataCallFailCause.aidl index a0ca4bfc542912e74861de407509a9003091341c..1f8cbdce288b9ec29e16b69b264abc332acbef3e 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataCallFailCause.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataCallFailCause.aidl @@ -169,6 +169,9 @@ enum DataCallFailCause { MAX_PPP_INACTIVITY_TIMER_EXPIRED = 0x7FE, IPV6_ADDRESS_TRANSFER_FAILED = 0x7FF, TRAT_SWAP_FAILED = 0x800, + /** + * @deprecated Legacy CDMA is unsupported. + */ EHRPD_TO_HRPD_FALLBACK = 0x801, MIP_CONFIG_FAILURE = 0x802, PDN_INACTIVITY_TIMER_EXPIRED = 0x803, @@ -192,11 +195,29 @@ enum DataCallFailCause { NON_IP_NOT_SUPPORTED = 0x815, PDN_NON_IP_CALL_THROTTLED = 0x816, PDN_NON_IP_CALL_DISALLOWED = 0x817, + /** + * @deprecated Legacy CDMA is unsupported. + */ CDMA_LOCK = 0x818, + /** + * @deprecated Legacy CDMA is unsupported. + */ CDMA_INTERCEPT = 0x819, + /** + * @deprecated Legacy CDMA is unsupported. + */ CDMA_REORDER = 0x81A, + /** + * @deprecated Legacy CDMA is unsupported. + */ CDMA_RELEASE_DUE_TO_SO_REJECTION = 0x81B, + /** + * @deprecated Legacy CDMA is unsupported. + */ CDMA_INCOMING_CALL = 0x81C, + /** + * @deprecated Legacy CDMA is unsupported. + */ CDMA_ALERT_STOP = 0x81D, CHANNEL_ACQUISITION_FAILURE = 0x81E, MAX_ACCESS_PROBE = 0x81F, @@ -204,8 +225,14 @@ enum DataCallFailCause { NO_RESPONSE_FROM_BASE_STATION = 0x821, REJECTED_BY_BASE_STATION = 0x822, CONCURRENT_SERVICES_INCOMPATIBLE = 0x823, + /** + * @deprecated Legacy CDMA is unsupported. + */ NO_CDMA_SERVICE = 0x824, RUIM_NOT_PRESENT = 0x825, + /** + * @deprecated Legacy CDMA is unsupported. + */ CDMA_RETRY_ORDER = 0x826, ACCESS_BLOCK = 0x827, ACCESS_BLOCK_ALL = 0x828, @@ -324,12 +351,33 @@ enum DataCallFailCause { LOWER_LAYER_REGISTRATION_FAILURE = 0x895, DATA_PLAN_EXPIRED = 0x896, UMTS_HANDOVER_TO_IWLAN = 0x897, + /** + * @deprecated Legacy CDMA is unsupported. + */ EVDO_CONNECTION_DENY_BY_GENERAL_OR_NETWORK_BUSY = 0x898, + /** + * @deprecated Legacy CDMA is unsupported. + */ EVDO_CONNECTION_DENY_BY_BILLING_OR_AUTHENTICATION_FAILURE = 0x899, + /** + * @deprecated Legacy CDMA is unsupported. + */ EVDO_HDR_CHANGED = 0x89A, + /** + * @deprecated Legacy CDMA is unsupported. + */ EVDO_HDR_EXITED = 0x89B, + /** + * @deprecated Legacy CDMA is unsupported. + */ EVDO_HDR_NO_SESSION = 0x89C, + /** + * @deprecated Legacy CDMA is unsupported. + */ EVDO_USING_GPS_FIX_INSTEAD_OF_HDR_CALL = 0x89D, + /** + * @deprecated Legacy CDMA is unsupported. + */ EVDO_HDR_CONNECTION_SETUP_TIMEOUT = 0x89E, FAILED_TO_ACQUIRE_COLOCATED_HDR = 0x89F, OTASP_COMMIT_IN_PROGRESS = 0x8A0, diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaBroadcastSmsConfigInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaBroadcastSmsConfigInfo.aidl index abfb308bf902a40d56c9ced785e4ecdb4e536dcb..99ab0ea48787f55524dc8f9c20bd71a21255d51f 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaBroadcastSmsConfigInfo.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaBroadcastSmsConfigInfo.aidl @@ -35,7 +35,16 @@ package android.hardware.radio.messaging; /* @hide */ @JavaDerive(toString=true) @VintfStability parcelable CdmaBroadcastSmsConfigInfo { + /** + * @deprecated Legacy CDMA is unsupported. + */ int serviceCategory; + /** + * @deprecated Legacy CDMA is unsupported. + */ int language; + /** + * @deprecated Legacy CDMA is unsupported. + */ boolean selected; } diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsAck.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsAck.aidl index ee8371c6866983a945e5dd74d234443d05d9615c..00e584b4ea9d8496d24aca754958756068905b93 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsAck.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsAck.aidl @@ -35,6 +35,12 @@ package android.hardware.radio.messaging; /* @hide */ @JavaDerive(toString=true) @VintfStability parcelable CdmaSmsAck { + /** + * @deprecated Legacy CDMA is unsupported. + */ boolean errorClass; + /** + * @deprecated Legacy CDMA is unsupported. + */ int smsCauseCode; } diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsAddress.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsAddress.aidl index 7382b1fd3b0f88e432dfcda49672184dfd148419..6a64595dacbce5214b06292e73f27ad675d1924a 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsAddress.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsAddress.aidl @@ -35,35 +35,128 @@ package android.hardware.radio.messaging; /* @hide */ @JavaDerive(toString=true) @VintfStability parcelable CdmaSmsAddress { + /** + * @deprecated Legacy CDMA is unsupported. + */ int digitMode; + /** + * @deprecated Legacy CDMA is unsupported. + */ boolean isNumberModeDataNetwork; + /** + * @deprecated Legacy CDMA is unsupported. + */ int numberType; + /** + * @deprecated Legacy CDMA is unsupported. + */ int numberPlan; + /** + * @deprecated Legacy CDMA is unsupported. + */ byte[] digits; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int DIGIT_MODE_FOUR_BIT = 0; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int DIGIT_MODE_EIGHT_BIT = 1; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_PLAN_UNKNOWN = 0; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_PLAN_TELEPHONY = 1; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_PLAN_RESERVED_2 = 2; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_PLAN_DATA = 3; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_PLAN_TELEX = 4; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_PLAN_RESERVED_5 = 5; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_PLAN_RESERVED_6 = 6; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_PLAN_RESERVED_7 = 7; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_PLAN_RESERVED_8 = 8; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_PLAN_PRIVATE = 9; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_PLAN_RESERVED_10 = 10; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_PLAN_RESERVED_11 = 11; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_PLAN_RESERVED_12 = 12; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_PLAN_RESERVED_13 = 13; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_PLAN_RESERVED_14 = 14; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_PLAN_RESERVED_15 = 15; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_TYPE_UNKNOWN = 0; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_TYPE_INTERNATIONAL_OR_DATA_IP = 1; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_TYPE_NATIONAL_OR_INTERNET_MAIL = 2; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_TYPE_NETWORK = 3; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_TYPE_SUBSCRIBER = 4; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_TYPE_ALPHANUMERIC = 5; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_TYPE_ABBREVIATED = 6; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_TYPE_RESERVED_7 = 7; } diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsMessage.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsMessage.aidl index 0e98f4b8443a03b455034aa245e70d57d150217f..bbf8983e2ad8f3c15931cdb7236d7805fe3a296f 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsMessage.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsMessage.aidl @@ -35,10 +35,28 @@ package android.hardware.radio.messaging; /* @hide */ @JavaDerive(toString=true) @VintfStability parcelable CdmaSmsMessage { + /** + * @deprecated Legacy CDMA is unsupported. + */ int teleserviceId; + /** + * @deprecated Legacy CDMA is unsupported. + */ boolean isServicePresent; + /** + * @deprecated Legacy CDMA is unsupported. + */ int serviceCategory; + /** + * @deprecated Legacy CDMA is unsupported. + */ android.hardware.radio.messaging.CdmaSmsAddress address; + /** + * @deprecated Legacy CDMA is unsupported. + */ android.hardware.radio.messaging.CdmaSmsSubaddress subAddress; + /** + * @deprecated Legacy CDMA is unsupported. + */ byte[] bearerData; } diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl index 9982395e1e43699f86aeb9aed8fbad2b7f25fa5c..95bfd4cea2eb1a20c835e646a626b28c1e301a1c 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl @@ -35,9 +35,24 @@ package android.hardware.radio.messaging; /* @hide */ @JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability parcelable CdmaSmsSubaddress { + /** + * @deprecated Legacy CDMA is unsupported. + */ int subaddressType; + /** + * @deprecated Legacy CDMA is unsupported. + */ boolean odd; + /** + * @deprecated Legacy CDMA is unsupported. + */ byte[] digits; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int SUBADDRESS_TYPE_NSAP = 0; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int SUBADDRESS_TYPE_USER_SPECIFIED = 1; } diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsWriteArgs.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsWriteArgs.aidl index d6292e7b2e3aadcd76d9cc7a04845e08fefd4309..759407fd1973a772b67fe15fa66761f91019e6e7 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsWriteArgs.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsWriteArgs.aidl @@ -35,10 +35,28 @@ package android.hardware.radio.messaging; /* @hide */ @JavaDerive(toString=true) @VintfStability parcelable CdmaSmsWriteArgs { + /** + * @deprecated Legacy CDMA is unsupported. + */ int status; + /** + * @deprecated Legacy CDMA is unsupported. + */ android.hardware.radio.messaging.CdmaSmsMessage message; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int STATUS_REC_UNREAD = 0; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int STATUS_REC_READ = 1; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int STATUS_STO_UNSENT = 2; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int STATUS_STO_SENT = 3; } diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessaging.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessaging.aidl index bf5fde50454d83e41bc3f778bbcc04057c0a7195..c69fcac845aadcad0bc0de45565967720bedde0c 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessaging.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessaging.aidl @@ -36,26 +36,50 @@ package android.hardware.radio.messaging; @VintfStability interface IRadioMessaging { oneway void acknowledgeIncomingGsmSmsWithPdu(in int serial, in boolean success, in String ackPdu); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void acknowledgeLastIncomingCdmaSms(in int serial, in android.hardware.radio.messaging.CdmaSmsAck smsAck); oneway void acknowledgeLastIncomingGsmSms(in int serial, in boolean success, in android.hardware.radio.messaging.SmsAcknowledgeFailCause cause); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void deleteSmsOnRuim(in int serial, in int index); oneway void deleteSmsOnSim(in int serial, in int index); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void getCdmaBroadcastConfig(in int serial); oneway void getGsmBroadcastConfig(in int serial); oneway void getSmscAddress(in int serial); oneway void reportSmsMemoryStatus(in int serial, in boolean available); oneway void responseAcknowledgement(); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void sendCdmaSms(in int serial, in android.hardware.radio.messaging.CdmaSmsMessage sms); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void sendCdmaSmsExpectMore(in int serial, in android.hardware.radio.messaging.CdmaSmsMessage sms); oneway void sendImsSms(in int serial, in android.hardware.radio.messaging.ImsSmsMessage message); oneway void sendSms(in int serial, in android.hardware.radio.messaging.GsmSmsMessage message); oneway void sendSmsExpectMore(in int serial, in android.hardware.radio.messaging.GsmSmsMessage message); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void setCdmaBroadcastActivation(in int serial, in boolean activate); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void setCdmaBroadcastConfig(in int serial, in android.hardware.radio.messaging.CdmaBroadcastSmsConfigInfo[] configInfo); oneway void setGsmBroadcastActivation(in int serial, in boolean activate); oneway void setGsmBroadcastConfig(in int serial, in android.hardware.radio.messaging.GsmBroadcastSmsConfigInfo[] configInfo); oneway void setResponseFunctions(in android.hardware.radio.messaging.IRadioMessagingResponse radioMessagingResponse, in android.hardware.radio.messaging.IRadioMessagingIndication radioMessagingIndication); oneway void setSmscAddress(in int serial, in String smsc); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void writeSmsToRuim(in int serial, in android.hardware.radio.messaging.CdmaSmsWriteArgs cdmaSms); oneway void writeSmsToSim(in int serial, in android.hardware.radio.messaging.SmsWriteArgs smsWriteArgs); } diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingIndication.aidl index 389fb2659a3ca880d7a0012c7bc6e3e145c9f325..a5cde9ab2d79e6f329dbf313e84ed56859c52830 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingIndication.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingIndication.aidl @@ -35,7 +35,13 @@ package android.hardware.radio.messaging; /* @hide */ @VintfStability interface IRadioMessagingIndication { + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void cdmaNewSms(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.messaging.CdmaSmsMessage msg); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void cdmaRuimSmsStorageFull(in android.hardware.radio.RadioIndicationType type); oneway void newBroadcastSms(in android.hardware.radio.RadioIndicationType type, in byte[] data); oneway void newSms(in android.hardware.radio.RadioIndicationType type, in byte[] pdu); diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingResponse.aidl index 9b1046483767ccbb9ea422881e5c6dd42a69debd..c2403e48cefb0f7c2b6771055e607c9198809eca 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingResponse.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingResponse.aidl @@ -36,25 +36,49 @@ package android.hardware.radio.messaging; @VintfStability interface IRadioMessagingResponse { oneway void acknowledgeIncomingGsmSmsWithPduResponse(in android.hardware.radio.RadioResponseInfo info); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void acknowledgeLastIncomingCdmaSmsResponse(in android.hardware.radio.RadioResponseInfo info); oneway void acknowledgeLastIncomingGsmSmsResponse(in android.hardware.radio.RadioResponseInfo info); oneway void acknowledgeRequest(in int serial); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void deleteSmsOnRuimResponse(in android.hardware.radio.RadioResponseInfo info); oneway void deleteSmsOnSimResponse(in android.hardware.radio.RadioResponseInfo info); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void getCdmaBroadcastConfigResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.messaging.CdmaBroadcastSmsConfigInfo[] configs); oneway void getGsmBroadcastConfigResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.messaging.GsmBroadcastSmsConfigInfo[] configs); oneway void getSmscAddressResponse(in android.hardware.radio.RadioResponseInfo info, in String smsc); oneway void reportSmsMemoryStatusResponse(in android.hardware.radio.RadioResponseInfo info); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void sendCdmaSmsExpectMoreResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.messaging.SendSmsResult sms); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void sendCdmaSmsResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.messaging.SendSmsResult sms); oneway void sendImsSmsResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.messaging.SendSmsResult sms); oneway void sendSmsExpectMoreResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.messaging.SendSmsResult sms); oneway void sendSmsResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.messaging.SendSmsResult sms); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void setCdmaBroadcastActivationResponse(in android.hardware.radio.RadioResponseInfo info); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void setCdmaBroadcastConfigResponse(in android.hardware.radio.RadioResponseInfo info); oneway void setGsmBroadcastActivationResponse(in android.hardware.radio.RadioResponseInfo info); oneway void setGsmBroadcastConfigResponse(in android.hardware.radio.RadioResponseInfo info); oneway void setSmscAddressResponse(in android.hardware.radio.RadioResponseInfo info); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void writeSmsToRuimResponse(in android.hardware.radio.RadioResponseInfo info, in int index); oneway void writeSmsToSimResponse(in android.hardware.radio.RadioResponseInfo info, in int index); } diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/ImsSmsMessage.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/ImsSmsMessage.aidl index ff4a111aa3b2e7ca999ce3adafaded27ef7fd237..3af0f8de3b180ac8fa0eb74cece731d3f3fe680d 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/ImsSmsMessage.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/ImsSmsMessage.aidl @@ -38,6 +38,9 @@ parcelable ImsSmsMessage { android.hardware.radio.RadioTechnologyFamily tech = android.hardware.radio.RadioTechnologyFamily.THREE_GPP; boolean retry; int messageRef; + /** + * @deprecated Legacy CDMA is unsupported. + */ android.hardware.radio.messaging.CdmaSmsMessage[] cdmaMessage; android.hardware.radio.messaging.GsmSmsMessage[] gsmMessage; } diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/SendSmsResult.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/SendSmsResult.aidl index 3f1d120a991cd86761e07eed8c2e518a20fbc07f..ae398a96350f320092ad07740a79c8f0919f17b9 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/SendSmsResult.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/SendSmsResult.aidl @@ -35,7 +35,16 @@ package android.hardware.radio.messaging; /* @hide */ @JavaDerive(toString=true) @VintfStability parcelable SendSmsResult { + /** + * @deprecated Legacy CDMA is unsupported. + */ int messageRef; + /** + * @deprecated Legacy CDMA is unsupported. + */ String ackPDU; + /** + * @deprecated Legacy CDMA is unsupported. + */ int errorCode; } diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ResetNvType.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ResetNvType.aidl index e9937f068c6d33261be7a977d66bed1b3a4e961c..33c0d709774897d0290865a702ad7c4a52d299da 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ResetNvType.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ResetNvType.aidl @@ -36,6 +36,12 @@ package android.hardware.radio.modem; @Backing(type="int") @JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability enum ResetNvType { RELOAD, + /** + * @deprecated NV APIs are deprecated starting from Android U. + */ ERASE, + /** + * @deprecated NV APIs are deprecated starting from Android U. + */ FACTORY_RESET, } diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/AccessTechnologySpecificInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/AccessTechnologySpecificInfo.aidl index 667a8a770a8301213de0c4cfc4382ef7301f1a4d..36b9cdd09938eaf064045d9e76f2251bbeb96f24 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/AccessTechnologySpecificInfo.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/AccessTechnologySpecificInfo.aidl @@ -36,6 +36,9 @@ package android.hardware.radio.network; @JavaDerive(toString=true) @VintfStability union AccessTechnologySpecificInfo { boolean noinit; + /** + * @deprecated Legacy CDMA is unsupported. + */ android.hardware.radio.network.Cdma2000RegistrationInfo cdmaInfo; android.hardware.radio.network.EutranRegistrationInfo eutranInfo; android.hardware.radio.network.NrVopsInfo ngranNrVopsInfo; diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/Cdma2000RegistrationInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/Cdma2000RegistrationInfo.aidl index bc9c0baa2414f72c378608254dfb12f6dd9e7940..5fbd6c4dfb7e5badf64999bce690cce4f1082057 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/Cdma2000RegistrationInfo.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/Cdma2000RegistrationInfo.aidl @@ -35,11 +35,32 @@ package android.hardware.radio.network; /* @hide */ @JavaDerive(toString=true) @VintfStability parcelable Cdma2000RegistrationInfo { + /** + * @deprecated Legacy CDMA is unsupported. + */ boolean cssSupported; + /** + * @deprecated Legacy CDMA is unsupported. + */ int roamingIndicator; + /** + * @deprecated Legacy CDMA is unsupported. + */ int systemIsInPrl; + /** + * @deprecated Legacy CDMA is unsupported. + */ int defaultRoamingIndicator; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int PRL_INDICATOR_NOT_REGISTERED = (-1) /* -1 */; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int PRL_INDICATOR_NOT_IN_PRL = 0; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int PRL_INDICATOR_IN_PRL = 1; } diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CdmaRoamingType.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CdmaRoamingType.aidl index 84532e3842dd1d263d8e4dbe8591a9edfa126708..ed9a9eb94622638be73e62393c919fb4b1de4757 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CdmaRoamingType.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CdmaRoamingType.aidl @@ -35,7 +35,16 @@ package android.hardware.radio.network; /* @hide */ @Backing(type="int") @JavaDerive(toString=true) @VintfStability enum CdmaRoamingType { + /** + * @deprecated Legacy CDMA is unsupported. + */ HOME_NETWORK, + /** + * @deprecated Legacy CDMA is unsupported. + */ AFFILIATED_ROAM, + /** + * @deprecated Legacy CDMA is unsupported. + */ ANY_ROAM, } diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CdmaSignalStrength.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CdmaSignalStrength.aidl index 94430a8760799d9199200671117a30fccc8cf1b1..6e6866570afe7e16ac7b5c737544aaee00632193 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CdmaSignalStrength.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CdmaSignalStrength.aidl @@ -35,6 +35,12 @@ package android.hardware.radio.network; /* @hide */ @JavaDerive(toString=true) @VintfStability parcelable CdmaSignalStrength { + /** + * @deprecated Legacy CDMA is unsupported. + */ int dbm; + /** + * @deprecated Legacy CDMA is unsupported. + */ int ecio; } diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentity.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentity.aidl index ba27b395275621d9fe385b891e9fbcafb240ec0e..dbd157589c0fcda22b9703142261fc0ae06e9702 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentity.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentity.aidl @@ -39,6 +39,9 @@ union CellIdentity { android.hardware.radio.network.CellIdentityGsm gsm; android.hardware.radio.network.CellIdentityWcdma wcdma; android.hardware.radio.network.CellIdentityTdscdma tdscdma; + /** + * @deprecated Legacy CDMA is unsupported. + */ android.hardware.radio.network.CellIdentityCdma cdma; android.hardware.radio.network.CellIdentityLte lte; android.hardware.radio.network.CellIdentityNr nr; diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityCdma.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityCdma.aidl index 63571bb53356c09116538f421d842ea3ff6cb737..548afd23b4ba37730a2ea53434eb56148e923534 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityCdma.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityCdma.aidl @@ -35,10 +35,28 @@ package android.hardware.radio.network; /* @hide */ @JavaDerive(toString=true) @VintfStability parcelable CellIdentityCdma { + /** + * @deprecated Legacy CDMA is unsupported. + */ int networkId; + /** + * @deprecated Legacy CDMA is unsupported. + */ int systemId; + /** + * @deprecated Legacy CDMA is unsupported. + */ int baseStationId; + /** + * @deprecated Legacy CDMA is unsupported. + */ int longitude; + /** + * @deprecated Legacy CDMA is unsupported. + */ int latitude; + /** + * @deprecated Legacy CDMA is unsupported. + */ android.hardware.radio.network.OperatorInfo operatorNames; } diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoCdma.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoCdma.aidl index 6d76a26b82790bbca08fd2213b254f46b1336840..18c94968554144812fd65ecf8d1ec13dd0dfc7ab 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoCdma.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoCdma.aidl @@ -35,7 +35,16 @@ package android.hardware.radio.network; /* @hide */ @JavaDerive(toString=true) @VintfStability parcelable CellInfoCdma { + /** + * @deprecated Legacy CDMA is unsupported. + */ android.hardware.radio.network.CellIdentityCdma cellIdentityCdma; + /** + * @deprecated Legacy CDMA is unsupported. + */ android.hardware.radio.network.CdmaSignalStrength signalStrengthCdma; + /** + * @deprecated Legacy CDMA is unsupported. + */ android.hardware.radio.network.EvdoSignalStrength signalStrengthEvdo; } diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoRatSpecificInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoRatSpecificInfo.aidl index fd3239dbd81334454e8bc442e94503f523fe0a5b..732e70fb7e55492116fe1504059817bb831b0251 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoRatSpecificInfo.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoRatSpecificInfo.aidl @@ -40,5 +40,8 @@ union CellInfoRatSpecificInfo { android.hardware.radio.network.CellInfoTdscdma tdscdma; android.hardware.radio.network.CellInfoLte lte; android.hardware.radio.network.CellInfoNr nr; + /** + * @deprecated Legacy CDMA is unsupported. + */ android.hardware.radio.network.CellInfoCdma cdma; } diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EvdoSignalStrength.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EvdoSignalStrength.aidl index e97e17dab39091b93add7f89f06754cd4e0abe80..2a7eccbbe7bb06a4fb9b37d8d249840d2dff9477 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EvdoSignalStrength.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EvdoSignalStrength.aidl @@ -35,7 +35,16 @@ package android.hardware.radio.network; /* @hide */ @JavaDerive(toString=true) @VintfStability parcelable EvdoSignalStrength { + /** + * @deprecated Legacy CDMA is unsupported. + */ int dbm; + /** + * @deprecated Legacy CDMA is unsupported. + */ int ecio; + /** + * @deprecated Legacy CDMA is unsupported. + */ int signalNoiseRatio; } diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl index 8af617f6fcf3ecec7b056c0c191d50cfaadbca8f..a6fd27a9b8fe3676fe14f578d62f3e17971c5568 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl @@ -39,6 +39,9 @@ interface IRadioNetwork { oneway void getAvailableBandModes(in int serial); oneway void getAvailableNetworks(in int serial); oneway void getBarringInfo(in int serial); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void getCdmaRoamingPreference(in int serial); oneway void getCellInfoList(in int serial); oneway void getDataRegistrationState(in int serial); @@ -57,6 +60,9 @@ interface IRadioNetwork { oneway void setAllowedNetworkTypesBitmap(in int serial, in int networkTypeBitmap); oneway void setBandMode(in int serial, in android.hardware.radio.network.RadioBandMode mode); oneway void setBarringPassword(in int serial, in String facility, in String oldPassword, in String newPassword); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void setCdmaRoamingPreference(in int serial, in android.hardware.radio.network.CdmaRoamingType type); oneway void setCellInfoListRate(in int serial, in int rate); oneway void setIndicationFilter(in int serial, in int indicationFilter); @@ -86,4 +92,7 @@ interface IRadioNetwork { oneway void setCellularIdentifierTransparencyEnabled(in int serial, in boolean enabled); oneway void setSecurityAlgorithmsUpdatedEnabled(in int serial, boolean enable); oneway void isSecurityAlgorithmsUpdatedEnabled(in int serial); + oneway void setSatellitePlmn(in int serial, in int simSlot, in String[] carrierPlmnArray, in String[] allSatellitePlmnArray); + oneway void setSatelliteEnabledForCarrier(in int serial, in int simSlot, boolean satelliteEnabled); + oneway void isSatelliteEnabledForCarrier(in int serial, in int simSlot); } diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkIndication.aidl index 8eea14f422595caedba233957a163678751bf98b..d4d61188b1d2f3dec3db2919c31f3a23f4739ed7 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkIndication.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkIndication.aidl @@ -36,6 +36,9 @@ package android.hardware.radio.network; @VintfStability interface IRadioNetworkIndication { oneway void barringInfoChanged(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.network.CellIdentity cellIdentity, in android.hardware.radio.network.BarringInfo[] barringInfos); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void cdmaPrlChanged(in android.hardware.radio.RadioIndicationType type, in int version); oneway void cellInfoList(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.network.CellInfo[] records); oneway void currentLinkCapacityEstimate(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.network.LinkCapacityEstimate lce); diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl index e7f291879aa8de136b9ab234522cfde6187ab8cf..080b4aaff2edadaf8e29547df8cdacb5df490da7 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl @@ -40,6 +40,9 @@ interface IRadioNetworkResponse { oneway void getAvailableBandModesResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.RadioBandMode[] bandModes); oneway void getAvailableNetworksResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.OperatorInfo[] networkInfos); oneway void getBarringInfoResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.CellIdentity cellIdentity, in android.hardware.radio.network.BarringInfo[] barringInfos); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void getCdmaRoamingPreferenceResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.CdmaRoamingType type); oneway void getCellInfoListResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.CellInfo[] cellInfo); oneway void getDataRegistrationStateResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.RegStateResult dataRegResponse); @@ -57,6 +60,9 @@ interface IRadioNetworkResponse { oneway void setAllowedNetworkTypesBitmapResponse(in android.hardware.radio.RadioResponseInfo info); oneway void setBandModeResponse(in android.hardware.radio.RadioResponseInfo info); oneway void setBarringPasswordResponse(in android.hardware.radio.RadioResponseInfo info); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void setCdmaRoamingPreferenceResponse(in android.hardware.radio.RadioResponseInfo info); oneway void setCellInfoListRateResponse(in android.hardware.radio.RadioResponseInfo info); oneway void setIndicationFilterResponse(in android.hardware.radio.RadioResponseInfo info); @@ -85,4 +91,7 @@ interface IRadioNetworkResponse { oneway void setCellularIdentifierTransparencyEnabledResponse(in android.hardware.radio.RadioResponseInfo info); oneway void setSecurityAlgorithmsUpdatedEnabledResponse(in android.hardware.radio.RadioResponseInfo info); oneway void isSecurityAlgorithmsUpdatedEnabledResponse(in android.hardware.radio.RadioResponseInfo info, in boolean isEnabled); + oneway void setSatellitePlmnResponse(in android.hardware.radio.RadioResponseInfo info); + oneway void setSatelliteEnabledForCarrierResponse(in android.hardware.radio.RadioResponseInfo info); + oneway void isSatelliteEnabledForCarrierResponse(in android.hardware.radio.RadioResponseInfo info, boolean isEnabled); } diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SignalStrength.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SignalStrength.aidl index da7db9a2aeba5cf0ce2d12fd6a48b4f7b668eefb..196ff19277a94b257db5a9e75bd2924f67573462 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SignalStrength.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SignalStrength.aidl @@ -36,7 +36,13 @@ package android.hardware.radio.network; @JavaDerive(toString=true) @VintfStability parcelable SignalStrength { android.hardware.radio.network.GsmSignalStrength gsm; + /** + * @deprecated Legacy CDMA is unsupported. + */ android.hardware.radio.network.CdmaSignalStrength cdma; + /** + * @deprecated Legacy CDMA is unsupported. + */ android.hardware.radio.network.EvdoSignalStrength evdo; android.hardware.radio.network.LteSignalStrength lte; android.hardware.radio.network.TdscdmaSignalStrength tdscdma; diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CardStatus.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CardStatus.aidl index 0d7e48a68ee254ecb3824869c645b0bd82fd719d..788a2dc8488f57d9cbe707652c3fff4b9fa3c378 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CardStatus.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CardStatus.aidl @@ -38,6 +38,9 @@ parcelable CardStatus { int cardState; android.hardware.radio.sim.PinState universalPinState = android.hardware.radio.sim.PinState.UNKNOWN; int gsmUmtsSubscriptionAppIndex; + /** + * @deprecated Legacy CDMA is unsupported. + */ int cdmaSubscriptionAppIndex; int imsSubscriptionAppIndex; android.hardware.radio.sim.AppStatus[] applications; diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CdmaSubscriptionSource.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CdmaSubscriptionSource.aidl index 13b06e7fdb3e66bd522c5a66703ea20cc40bb7b5..d3e8295416739c4efdd5320bcbf5bdc62782a7e1 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CdmaSubscriptionSource.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CdmaSubscriptionSource.aidl @@ -35,6 +35,12 @@ package android.hardware.radio.sim; /* @hide */ @Backing(type="int") @JavaDerive(toString=true) @VintfStability enum CdmaSubscriptionSource { + /** + * @deprecated Legacy CDMA is unsupported. + */ RUIM_SIM, + /** + * @deprecated Legacy CDMA is unsupported. + */ NV, } diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSim.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSim.aidl index 1728e410105a7632294801f6b8f707f07ffd5ece..5a4c5c1f5fe2651d889ebdee534353989d2a57b2 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSim.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSim.aidl @@ -40,7 +40,13 @@ interface IRadioSim { oneway void changeIccPinForApp(in int serial, in String oldPin, in String newPin, in String aid); oneway void enableUiccApplications(in int serial, in boolean enable); oneway void getAllowedCarriers(in int serial); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void getCdmaSubscription(in int serial); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void getCdmaSubscriptionSource(in int serial); oneway void getFacilityLockForApp(in int serial, in String facility, in String password, in int serviceClass, in String appId); oneway void getIccCardStatus(in int serial); @@ -63,6 +69,9 @@ interface IRadioSim { oneway void sendTerminalResponseToSim(in int serial, in String contents); oneway void setAllowedCarriers(in int serial, in android.hardware.radio.sim.CarrierRestrictions carriers, in android.hardware.radio.sim.SimLockMultiSimPolicy multiSimPolicy); oneway void setCarrierInfoForImsiEncryption(in int serial, in android.hardware.radio.sim.ImsiEncryptionInfo imsiEncryptionInfo); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void setCdmaSubscriptionSource(in int serial, in android.hardware.radio.sim.CdmaSubscriptionSource cdmaSub); oneway void setFacilityLockForApp(in int serial, in String facility, in boolean lockState, in String password, in int serviceClass, in String appId); oneway void setResponseFunctions(in android.hardware.radio.sim.IRadioSimResponse radioSimResponse, in android.hardware.radio.sim.IRadioSimIndication radioSimIndication); diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSimIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSimIndication.aidl index a74b65acad1b187dc702a0803acc48a4791d3509..0c4df06b3969376acd25da22d6a6dbf4d171c9cc 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSimIndication.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSimIndication.aidl @@ -36,6 +36,9 @@ package android.hardware.radio.sim; @VintfStability interface IRadioSimIndication { oneway void carrierInfoForImsiEncryption(in android.hardware.radio.RadioIndicationType info); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void cdmaSubscriptionSourceChanged(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.sim.CdmaSubscriptionSource cdmaSource); oneway void simPhonebookChanged(in android.hardware.radio.RadioIndicationType type); oneway void simPhonebookRecordsReceived(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.sim.PbReceivedStatus status, in android.hardware.radio.sim.PhonebookRecordInfo[] records); diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSimResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSimResponse.aidl index c653847706f68f1f03ae12d097ab4bc4045b5df0..a512bae68a1c6431653b7b2d184efe950bfb70c1 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSimResponse.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSimResponse.aidl @@ -41,7 +41,13 @@ interface IRadioSimResponse { oneway void changeIccPinForAppResponse(in android.hardware.radio.RadioResponseInfo info, in int remainingRetries); oneway void enableUiccApplicationsResponse(in android.hardware.radio.RadioResponseInfo info); oneway void getAllowedCarriersResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.sim.CarrierRestrictions carriers, in android.hardware.radio.sim.SimLockMultiSimPolicy multiSimPolicy); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void getCdmaSubscriptionResponse(in android.hardware.radio.RadioResponseInfo info, in String mdn, in String hSid, in String hNid, in String min, in String prl); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void getCdmaSubscriptionSourceResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.sim.CdmaSubscriptionSource source); oneway void getFacilityLockForAppResponse(in android.hardware.radio.RadioResponseInfo info, in int response); oneway void getIccCardStatusResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.sim.CardStatus cardStatus); @@ -63,6 +69,9 @@ interface IRadioSimResponse { oneway void sendTerminalResponseToSimResponse(in android.hardware.radio.RadioResponseInfo info); oneway void setAllowedCarriersResponse(in android.hardware.radio.RadioResponseInfo info); oneway void setCarrierInfoForImsiEncryptionResponse(in android.hardware.radio.RadioResponseInfo info); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void setCdmaSubscriptionSourceResponse(in android.hardware.radio.RadioResponseInfo info); oneway void setFacilityLockForAppResponse(in android.hardware.radio.RadioResponseInfo info, in int retry); oneway void setSimCardPowerResponse(in android.hardware.radio.RadioResponseInfo info); diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/Call.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/Call.aidl index 27130b4eed4ab5ab07c94f8cde9030b22315f81b..33af1fd00cc372bb195c37d3456336c3affa7d0b 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/Call.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/Call.aidl @@ -42,6 +42,9 @@ parcelable Call { boolean isMT; byte als; boolean isVoice; + /** + * @deprecated Legacy CDMA is unsupported. + */ boolean isVoicePrivacy; String number; int numberPresentation; diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaCallWaiting.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaCallWaiting.aidl index 0b36be4ebadf6ee752bcf5e1e9099923b5b5c77e..7eb8c4e1361f2c51680e0f88be9f7950535136d3 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaCallWaiting.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaCallWaiting.aidl @@ -35,24 +35,84 @@ package android.hardware.radio.voice; /* @hide */ @JavaDerive(toString=true) @VintfStability parcelable CdmaCallWaiting { + /** + * @deprecated Legacy CDMA is unsupported. + */ String number; + /** + * @deprecated Legacy CDMA is unsupported. + */ int numberPresentation; + /** + * @deprecated Legacy CDMA is unsupported. + */ String name; + /** + * @deprecated Legacy CDMA is unsupported. + */ android.hardware.radio.voice.CdmaSignalInfoRecord signalInfoRecord; + /** + * @deprecated Legacy CDMA is unsupported. + */ int numberType; + /** + * @deprecated Legacy CDMA is unsupported. + */ int numberPlan; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_PLAN_UNKNOWN = 0; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_PLAN_ISDN = 1; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_PLAN_DATA = 3; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_PLAN_TELEX = 4; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_PLAN_NATIONAL = 8; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_PLAN_PRIVATE = 9; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_PRESENTATION_ALLOWED = 0; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_PRESENTATION_RESTRICTED = 1; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_PRESENTATION_UNKNOWN = 2; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_TYPE_UNKNOWN = 0; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_TYPE_INTERNATIONAL = 1; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_TYPE_NATIONAL = 2; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_TYPE_NETWORK_SPECIFIC = 3; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NUMBER_TYPE_SUBSCRIBER = 4; } diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl index 014279231d4d6c8dc574fb6d4b47e4e243fd113c..a673c93fc1b41e3db1dae6a1e7e5891f7221ffcb 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl @@ -35,6 +35,12 @@ package android.hardware.radio.voice; /* @hide */ @JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability parcelable CdmaDisplayInfoRecord { + /** + * @deprecated Legacy CDMA is unsupported. + */ String alphaBuf; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int CDMA_ALPHA_INFO_BUFFER_LENGTH = 64; } diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaInformationRecord.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaInformationRecord.aidl index c71a8beccb83c9793f1b08a2bedb78cf6cd58a01..143409f8324462b3a252fddbf0a447c1af202cc9 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaInformationRecord.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaInformationRecord.aidl @@ -35,24 +35,84 @@ package android.hardware.radio.voice; /* @hide */ @JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability parcelable CdmaInformationRecord { + /** + * @deprecated Legacy CDMA is unsupported. + */ int name; + /** + * @deprecated Legacy CDMA is unsupported. + */ android.hardware.radio.voice.CdmaDisplayInfoRecord[] display; + /** + * @deprecated Legacy CDMA is unsupported. + */ android.hardware.radio.voice.CdmaNumberInfoRecord[] number; + /** + * @deprecated Legacy CDMA is unsupported. + */ android.hardware.radio.voice.CdmaSignalInfoRecord[] signal; + /** + * @deprecated Legacy CDMA is unsupported. + */ android.hardware.radio.voice.CdmaRedirectingNumberInfoRecord[] redir; + /** + * @deprecated Legacy CDMA is unsupported. + */ android.hardware.radio.voice.CdmaLineControlInfoRecord[] lineCtrl; + /** + * @deprecated Legacy CDMA is unsupported. + */ android.hardware.radio.voice.CdmaT53ClirInfoRecord[] clir; + /** + * @deprecated Legacy CDMA is unsupported. + */ android.hardware.radio.voice.CdmaT53AudioControlInfoRecord[] audioCtrl; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int CDMA_MAX_NUMBER_OF_INFO_RECS = 10; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NAME_DISPLAY = 0; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NAME_CALLED_PARTY_NUMBER = 1; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NAME_CALLING_PARTY_NUMBER = 2; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NAME_CONNECTED_NUMBER = 3; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NAME_SIGNAL = 4; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NAME_REDIRECTING_NUMBER = 5; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NAME_LINE_CONTROL = 6; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NAME_EXTENDED_DISPLAY = 7; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NAME_T53_CLIR = 8; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NAME_T53_RELEASE = 9; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int NAME_T53_AUDIO_CONTROL = 10; } diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaLineControlInfoRecord.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaLineControlInfoRecord.aidl index 4e4a7ee7b761d7d7ecb8c0378c427553e4b9ba5f..6968a8a399112bbc707f28eaab4f83e8620e1167 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaLineControlInfoRecord.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaLineControlInfoRecord.aidl @@ -35,8 +35,20 @@ package android.hardware.radio.voice; /* @hide */ @JavaDerive(toString=true) @VintfStability parcelable CdmaLineControlInfoRecord { + /** + * @deprecated Legacy CDMA is unsupported. + */ byte lineCtrlPolarityIncluded; + /** + * @deprecated Legacy CDMA is unsupported. + */ byte lineCtrlToggle; + /** + * @deprecated Legacy CDMA is unsupported. + */ byte lineCtrlReverse; + /** + * @deprecated Legacy CDMA is unsupported. + */ byte lineCtrlPowerDenial; } diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl index 974e7958961b494966701e075d0d1c475dc22185..684b17111a39a423203a0b0ab7c59f82000bcf76 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl @@ -35,10 +35,28 @@ package android.hardware.radio.voice; /* @hide */ @JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability parcelable CdmaNumberInfoRecord { + /** + * @deprecated Legacy CDMA is unsupported. + */ String number; + /** + * @deprecated Legacy CDMA is unsupported. + */ byte numberType; + /** + * @deprecated Legacy CDMA is unsupported. + */ byte numberPlan; + /** + * @deprecated Legacy CDMA is unsupported. + */ byte pi; + /** + * @deprecated Legacy CDMA is unsupported. + */ byte si; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int CDMA_NUMBER_INFO_BUFFER_LENGTH = 81; } diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaOtaProvisionStatus.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaOtaProvisionStatus.aidl index ae35fbad526f2a41bb550f43420470e0c85d2659..0bf802dfc698c762948f6a8badd00be623b6c785 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaOtaProvisionStatus.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaOtaProvisionStatus.aidl @@ -35,16 +35,52 @@ package android.hardware.radio.voice; /* @hide */ @Backing(type="int") @JavaDerive(toString=true) @VintfStability enum CdmaOtaProvisionStatus { + /** + * @deprecated Legacy CDMA is unsupported. + */ SPL_UNLOCKED, + /** + * @deprecated Legacy CDMA is unsupported. + */ SPC_RETRIES_EXCEEDED, + /** + * @deprecated Legacy CDMA is unsupported. + */ A_KEY_EXCHANGED, + /** + * @deprecated Legacy CDMA is unsupported. + */ SSD_UPDATED, + /** + * @deprecated Legacy CDMA is unsupported. + */ NAM_DOWNLOADED, + /** + * @deprecated Legacy CDMA is unsupported. + */ MDN_DOWNLOADED, + /** + * @deprecated Legacy CDMA is unsupported. + */ IMSI_DOWNLOADED, + /** + * @deprecated Legacy CDMA is unsupported. + */ PRL_DOWNLOADED, + /** + * @deprecated Legacy CDMA is unsupported. + */ COMMITTED, + /** + * @deprecated Legacy CDMA is unsupported. + */ OTAPA_STARTED, + /** + * @deprecated Legacy CDMA is unsupported. + */ OTAPA_STOPPED, + /** + * @deprecated Legacy CDMA is unsupported. + */ OTAPA_ABORTED, } diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl index 818d107426446107685c77b806bc76af3e423d82..ce7c7c62fb57812d42a01f8c9f05b4c1ddb16ead 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl @@ -35,13 +35,40 @@ package android.hardware.radio.voice; /* @hide */ @JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability parcelable CdmaRedirectingNumberInfoRecord { + /** + * @deprecated Legacy CDMA is unsupported. + */ android.hardware.radio.voice.CdmaNumberInfoRecord redirectingNumber; + /** + * @deprecated Legacy CDMA is unsupported. + */ int redirectingReason; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int REDIRECTING_REASON_UNKNOWN = 0; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int REDIRECTING_REASON_CALL_FORWARDING_BUSY = 1; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int REDIRECTING_REASON_CALL_FORWARDING_NO_REPLY = 2; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int REDIRECTING_REASON_CALLED_DTE_OUT_OF_ORDER = 9; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int REDIRECTING_REASON_CALL_FORWARDING_BY_THE_CALLED_DTE = 10; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int REDIRECTING_REASON_CALL_FORWARDING_UNCONDITIONAL = 15; + /** + * @deprecated Legacy CDMA is unsupported. + */ const int REDIRECTING_REASON_RESERVED = 16; } diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaSignalInfoRecord.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaSignalInfoRecord.aidl index 69447b433a7f12d0a330d4fa6e6164f2ced5c9fb..04e7bdcd647c5a3a77fde7ae36006965bd745f25 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaSignalInfoRecord.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaSignalInfoRecord.aidl @@ -35,8 +35,20 @@ package android.hardware.radio.voice; /* @hide */ @JavaDerive(toString=true) @VintfStability parcelable CdmaSignalInfoRecord { + /** + * @deprecated Legacy CDMA is unsupported. + */ boolean isPresent; + /** + * @deprecated Legacy CDMA is unsupported. + */ byte signalType; + /** + * @deprecated Legacy CDMA is unsupported. + */ byte alertPitch; + /** + * @deprecated Legacy CDMA is unsupported. + */ byte signal; } diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaT53AudioControlInfoRecord.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaT53AudioControlInfoRecord.aidl index 69d79aa43ba5a12f746b2cd0e1d463d8950befee..733d82248d1988f7fef5e0004e66ad235a906b3c 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaT53AudioControlInfoRecord.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaT53AudioControlInfoRecord.aidl @@ -35,6 +35,12 @@ package android.hardware.radio.voice; /* @hide */ @JavaDerive(toString=true) @VintfStability parcelable CdmaT53AudioControlInfoRecord { + /** + * @deprecated Legacy CDMA is unsupported. + */ byte upLink; + /** + * @deprecated Legacy CDMA is unsupported. + */ byte downLink; } diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaT53ClirInfoRecord.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaT53ClirInfoRecord.aidl index 83b6fb9af7691238985cc564ff14a9a27d6d484e..9cf931cd3a1e439b7d8fccff09ee2d932792b0d1 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaT53ClirInfoRecord.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaT53ClirInfoRecord.aidl @@ -35,5 +35,8 @@ package android.hardware.radio.voice; /* @hide */ @JavaDerive(toString=true) @VintfStability parcelable CdmaT53ClirInfoRecord { + /** + * @deprecated Legacy CDMA is unsupported. + */ byte cause; } diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoice.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoice.aidl index d0a9451a3668f31d68b4c31b3921226f7b3571f0..d519bd9009fea86feb142da9dc37d821d20c74a7 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoice.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoice.aidl @@ -59,6 +59,9 @@ interface IRadioVoice { oneway void rejectCall(in int serial); oneway void responseAcknowledgement(); oneway void sendBurstDtmf(in int serial, in String dtmf, in int on, in int off); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void sendCdmaFeatureCode(in int serial, in String featureCode); oneway void sendDtmf(in int serial, in String s); oneway void sendUssd(in int serial, in String ussd); diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceIndication.aidl index 4614ee1b391a3db6fc92ef9ba9bd772f2eb29153..fac27f469a8bc35b97e3e83f535efb6c83b2a7d8 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceIndication.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceIndication.aidl @@ -37,8 +37,17 @@ package android.hardware.radio.voice; interface IRadioVoiceIndication { oneway void callRing(in android.hardware.radio.RadioIndicationType type, in boolean isGsm, in android.hardware.radio.voice.CdmaSignalInfoRecord record); oneway void callStateChanged(in android.hardware.radio.RadioIndicationType type); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void cdmaCallWaiting(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.voice.CdmaCallWaiting callWaitingRecord); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void cdmaInfoRec(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.voice.CdmaInformationRecord[] records); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void cdmaOtaProvisionStatus(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.voice.CdmaOtaProvisionStatus status); oneway void currentEmergencyNumberList(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.voice.EmergencyNumber[] emergencyNumberList); oneway void enterEmergencyCallbackMode(in android.hardware.radio.RadioIndicationType type); diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceResponse.aidl index 46927c2f819848f93e1f4b3ce0b83f7ba8ff57a8..8a0af44cdd9092a9f75140461d080865e6be6ba1 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceResponse.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceResponse.aidl @@ -59,6 +59,9 @@ interface IRadioVoiceResponse { oneway void isVoNrEnabledResponse(in android.hardware.radio.RadioResponseInfo info, in boolean enable); oneway void rejectCallResponse(in android.hardware.radio.RadioResponseInfo info); oneway void sendBurstDtmfResponse(in android.hardware.radio.RadioResponseInfo info); + /** + * @deprecated Legacy CDMA is unsupported. + */ oneway void sendCdmaFeatureCodeResponse(in android.hardware.radio.RadioResponseInfo info); oneway void sendDtmfResponse(in android.hardware.radio.RadioResponseInfo info); oneway void sendUssdResponse(in android.hardware.radio.RadioResponseInfo info); diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/LastCallFailCause.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/LastCallFailCause.aidl index 17a039fcf6620259b597d0cbb62100f209e4c09a..e6c223cfc9042b6a1d3fb64aac04fc1838b9c219 100644 --- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/LastCallFailCause.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/LastCallFailCause.aidl @@ -106,15 +106,45 @@ enum LastCallFailCause { RADIO_RELEASE_ABNORMAL = 259, ACCESS_CLASS_BLOCKED = 260, NETWORK_DETACH = 261, + /** + * @deprecated Legacy CDMA is unsupported. + */ CDMA_LOCKED_UNTIL_POWER_CYCLE = 1000, + /** + * @deprecated Legacy CDMA is unsupported. + */ CDMA_DROP = 1001, + /** + * @deprecated Legacy CDMA is unsupported. + */ CDMA_INTERCEPT = 1002, + /** + * @deprecated Legacy CDMA is unsupported. + */ CDMA_REORDER = 1003, + /** + * @deprecated Legacy CDMA is unsupported. + */ CDMA_SO_REJECT = 1004, + /** + * @deprecated Legacy CDMA is unsupported. + */ CDMA_RETRY_ORDER = 1005, + /** + * @deprecated Legacy CDMA is unsupported. + */ CDMA_ACCESS_FAILURE = 1006, + /** + * @deprecated Legacy CDMA is unsupported. + */ CDMA_PREEMPTED = 1007, + /** + * @deprecated Legacy CDMA is unsupported. + */ CDMA_NOT_EMERGENCY = 1008, + /** + * @deprecated Legacy CDMA is unsupported. + */ CDMA_ACCESS_BLOCKED = 1009, OEM_CAUSE_1 = 0xf001, OEM_CAUSE_2 = 0xf002, diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/AccessNetwork.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/AccessNetwork.aidl index 73a267b6d036a97a6340a43f94f00b7c557997ff..c7198468f9ae2b767a6e2bca9d980feb9c963ef1 100644 --- a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/AccessNetwork.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/AccessNetwork.aidl @@ -39,6 +39,9 @@ enum AccessNetwork { GERAN, UTRAN, EUTRAN, + /** + * @deprecated Legacy CDMA is unsupported. + */ CDMA2000, IWLAN, NGRAN, diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioAccessFamily.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioAccessFamily.aidl index 1298ab0f4cdb29edbc8d663ced67358e1ab6a050..471916f13700231b318ef8d8c205684bf167d1de 100644 --- a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioAccessFamily.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioAccessFamily.aidl @@ -39,15 +39,36 @@ enum RadioAccessFamily { GPRS = (1 << android.hardware.radio.RadioTechnology.GPRS) /* 2 */, EDGE = (1 << android.hardware.radio.RadioTechnology.EDGE) /* 4 */, UMTS = (1 << android.hardware.radio.RadioTechnology.UMTS) /* 8 */, + /** + * @deprecated Legacy CDMA is unsupported. + */ IS95A = (1 << android.hardware.radio.RadioTechnology.IS95A) /* 16 */, + /** + * @deprecated Legacy CDMA is unsupported. + */ IS95B = (1 << android.hardware.radio.RadioTechnology.IS95B) /* 32 */, + /** + * @deprecated Legacy CDMA is unsupported. + */ ONE_X_RTT = (1 << android.hardware.radio.RadioTechnology.ONE_X_RTT) /* 64 */, + /** + * @deprecated Legacy CDMA is unsupported. + */ EVDO_0 = (1 << android.hardware.radio.RadioTechnology.EVDO_0) /* 128 */, + /** + * @deprecated Legacy CDMA is unsupported. + */ EVDO_A = (1 << android.hardware.radio.RadioTechnology.EVDO_A) /* 256 */, HSDPA = (1 << android.hardware.radio.RadioTechnology.HSDPA) /* 512 */, HSUPA = (1 << android.hardware.radio.RadioTechnology.HSUPA) /* 1024 */, HSPA = (1 << android.hardware.radio.RadioTechnology.HSPA) /* 2048 */, + /** + * @deprecated Legacy CDMA is unsupported. + */ EVDO_B = (1 << android.hardware.radio.RadioTechnology.EVDO_B) /* 4096 */, + /** + * @deprecated Legacy CDMA is unsupported. + */ EHRPD = (1 << android.hardware.radio.RadioTechnology.EHRPD) /* 8192 */, LTE = (1 << android.hardware.radio.RadioTechnology.LTE) /* 16384 */, HSPAP = (1 << android.hardware.radio.RadioTechnology.HSPAP) /* 32768 */, @@ -59,4 +80,5 @@ enum RadioAccessFamily { */ LTE_CA = (1 << android.hardware.radio.RadioTechnology.LTE_CA) /* 524288 */, NR = (1 << android.hardware.radio.RadioTechnology.NR) /* 1048576 */, + NB_IOT_NTN = (1 << android.hardware.radio.RadioTechnology.NB_IOT_NTN) /* 2097152 */, } diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnology.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnology.aidl index 7c6a657bcd74497a74226cf104d01645b0da1286..201e6947e17fe256c97e82d6661e793a33b518d6 100644 --- a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnology.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnology.aidl @@ -39,15 +39,36 @@ enum RadioTechnology { GPRS, EDGE, UMTS, + /** + * @deprecated Legacy CDMA is unsupported. + */ IS95A, + /** + * @deprecated Legacy CDMA is unsupported. + */ IS95B, + /** + * @deprecated Legacy CDMA is unsupported. + */ ONE_X_RTT, + /** + * @deprecated Legacy CDMA is unsupported. + */ EVDO_0, + /** + * @deprecated Legacy CDMA is unsupported. + */ EVDO_A, HSDPA, HSUPA, HSPA, + /** + * @deprecated Legacy CDMA is unsupported. + */ EVDO_B, + /** + * @deprecated Legacy CDMA is unsupported. + */ EHRPD, LTE, HSPAP, @@ -59,4 +80,5 @@ enum RadioTechnology { */ LTE_CA, NR, + NB_IOT_NTN, } diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnologyFamily.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnologyFamily.aidl index 85e9850cad4ff83a246c508839805918d778ba1f..9b05c97b55a148d9333e5d3d3d40f47c65543e53 100644 --- a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnologyFamily.aidl +++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnologyFamily.aidl @@ -36,5 +36,8 @@ package android.hardware.radio; @Backing(type="int") @JavaDerive(toString=true) @VintfStability enum RadioTechnologyFamily { THREE_GPP, + /** + * @deprecated Legacy CDMA is unsupported. + */ THREE_GPP2, } diff --git a/radio/aidl/android/hardware/radio/AccessNetwork.aidl b/radio/aidl/android/hardware/radio/AccessNetwork.aidl index 4099f83f044260aa6093df92455430a708bceca1..0d10009892e202e996a31980f1a3e03f76343d87 100644 --- a/radio/aidl/android/hardware/radio/AccessNetwork.aidl +++ b/radio/aidl/android/hardware/radio/AccessNetwork.aidl @@ -39,6 +39,7 @@ enum AccessNetwork { EUTRAN, /** * CDMA 2000 network + * @deprecated Legacy CDMA is unsupported. */ CDMA2000, /** diff --git a/radio/aidl/android/hardware/radio/RadioAccessFamily.aidl b/radio/aidl/android/hardware/radio/RadioAccessFamily.aidl index 9ab4583c08bcf8019f0477b894b617d0cf2000e0..8c10bb9cbfe5dd572f9edcd06e9196f25bbc6a65 100644 --- a/radio/aidl/android/hardware/radio/RadioAccessFamily.aidl +++ b/radio/aidl/android/hardware/radio/RadioAccessFamily.aidl @@ -27,15 +27,22 @@ enum RadioAccessFamily { GPRS = 1 << RadioTechnology.GPRS, EDGE = 1 << RadioTechnology.EDGE, UMTS = 1 << RadioTechnology.UMTS, + /** @deprecated Legacy CDMA is unsupported. */ IS95A = 1 << RadioTechnology.IS95A, + /** @deprecated Legacy CDMA is unsupported. */ IS95B = 1 << RadioTechnology.IS95B, + /** @deprecated Legacy CDMA is unsupported. */ ONE_X_RTT = 1 << RadioTechnology.ONE_X_RTT, + /** @deprecated Legacy CDMA is unsupported. */ EVDO_0 = 1 << RadioTechnology.EVDO_0, + /** @deprecated Legacy CDMA is unsupported. */ EVDO_A = 1 << RadioTechnology.EVDO_A, HSDPA = 1 << RadioTechnology.HSDPA, HSUPA = 1 << RadioTechnology.HSUPA, HSPA = 1 << RadioTechnology.HSPA, + /** @deprecated Legacy CDMA is unsupported. */ EVDO_B = 1 << RadioTechnology.EVDO_B, + /** @deprecated Legacy CDMA is unsupported. */ EHRPD = 1 << RadioTechnology.EHRPD, LTE = 1 << RadioTechnology.LTE, HSPAP = 1 << RadioTechnology.HSPAP, @@ -48,4 +55,8 @@ enum RadioAccessFamily { * 5G NR. This is only use in 5G Standalone mode. */ NR = 1 << RadioTechnology.NR, + /** + * 3GPP NB-IOT (Narrowband Internet of Things) over Non-Terrestrial-Networks technology. + */ + NB_IOT_NTN = 1 << RadioTechnology.NB_IOT_NTN, } diff --git a/radio/aidl/android/hardware/radio/RadioError.aidl b/radio/aidl/android/hardware/radio/RadioError.aidl index 6ce8f67e51d31bb8dea7e5d9422f0d7a325bf91a..6a28893aa2ec4cb842b53611fcc6c04761768593 100644 --- a/radio/aidl/android/hardware/radio/RadioError.aidl +++ b/radio/aidl/android/hardware/radio/RadioError.aidl @@ -61,12 +61,11 @@ enum RadioError { */ SMS_SEND_FAIL_RETRY = 10, /** - * Fail to set the location where CDMA subscription shall be retrieved because of SIM or - * RUIM card absent + * SIM or RUIM card absent */ SIM_ABSENT = 11, /** - * Fail to find CDMA subscription from specified location + * Failed to find subscription from specified location */ SUBSCRIPTION_NOT_AVAILABLE = 12, /** diff --git a/radio/aidl/android/hardware/radio/RadioTechnology.aidl b/radio/aidl/android/hardware/radio/RadioTechnology.aidl index 7ae428bac6a52bd7d48c5d1495558318b3492ccc..843bfd0e7d12604e471e2b4d123cf6a01b377d7f 100644 --- a/radio/aidl/android/hardware/radio/RadioTechnology.aidl +++ b/radio/aidl/android/hardware/radio/RadioTechnology.aidl @@ -25,15 +25,22 @@ enum RadioTechnology { GPRS, EDGE, UMTS, + /** @deprecated Legacy CDMA is unsupported. */ IS95A, + /** @deprecated Legacy CDMA is unsupported. */ IS95B, + /** @deprecated Legacy CDMA is unsupported. */ ONE_X_RTT, + /** @deprecated Legacy CDMA is unsupported. */ EVDO_0, + /** @deprecated Legacy CDMA is unsupported. */ EVDO_A, HSDPA, HSUPA, HSPA, + /** @deprecated Legacy CDMA is unsupported. */ EVDO_B, + /** @deprecated Legacy CDMA is unsupported. */ EHRPD, LTE, /** @@ -55,4 +62,8 @@ enum RadioTechnology { * 5G NR. This is only used in 5G Standalone mode. */ NR, + /** + * 3GPP NB-IOT (Narrowband Internet of Things) over Non-Terrestrial-Networks technology. + */ + NB_IOT_NTN, } diff --git a/radio/aidl/android/hardware/radio/RadioTechnologyFamily.aidl b/radio/aidl/android/hardware/radio/RadioTechnologyFamily.aidl index 4b5498cc07e79f0e8a661b3f80fbcf72a9cac9c4..a13c358b9de258a65065c5b261c5542b65579b81 100644 --- a/radio/aidl/android/hardware/radio/RadioTechnologyFamily.aidl +++ b/radio/aidl/android/hardware/radio/RadioTechnologyFamily.aidl @@ -27,6 +27,7 @@ enum RadioTechnologyFamily { THREE_GPP, /** * 3GPP2 Technologies - CDMA + * @deprecated Legacy CDMA is unsupported. */ THREE_GPP2, } diff --git a/radio/aidl/android/hardware/radio/config/IRadioConfig.aidl b/radio/aidl/android/hardware/radio/config/IRadioConfig.aidl index 936315c6a3fad0df9d17c0bea4e6c885fc630cba..e819fe04b784f49552040c030ad52f5438586f7d 100644 --- a/radio/aidl/android/hardware/radio/config/IRadioConfig.aidl +++ b/radio/aidl/android/hardware/radio/config/IRadioConfig.aidl @@ -27,6 +27,7 @@ package android.hardware.radio.config; import android.hardware.radio.config.IRadioConfigIndication; import android.hardware.radio.config.IRadioConfigResponse; +import android.hardware.radio.config.SimType; import android.hardware.radio.config.SlotPortMapping; /** @hide */ @@ -208,4 +209,39 @@ oneway interface IRadioConfig { * This is available when android.hardware.telephony is defined. */ void getSimultaneousCallingSupport(in int serial); + + /** + * Get the sim type information. + * + * Response provides the current active sim type and supported sim types associated with each + * active physical slot ids. + * + * @param serial Serial number of request. + * + * Response callback is IRadioConfigResponse.getSimTypeInfoResponse() + * + * This is available when android.hardware.telephony.subscription is defined. + */ + void getSimTypeInfo(in int serial); + + /** + * Set the sim type associated with the physical slot id and activate if the sim type is + * currently inactive. + * + * Example: There are 2 active physical slot ids and 3 physical sims(2 pSIM and 1 eSIM). First + * physical slot id is always linked pSIM and 2nd physical slot id supports either pSIM/eSIM one + * at a time. In order to activate eSIM on 2nd physical slot id, caller should pass + * corresponding sim type. + * + * simTypes[0] = pSIM + * simTypes[1] = eSIM + * + * @param serial Serial number of request. + * @param simTypes SimType to be activated on each logical slot + * + * Response callback is IRadioConfigResponse.setSimTypeResponse() + * + * This is available when android.hardware.telephony.subscription is defined. + */ + void setSimType(in int serial, in SimType[] simTypes); } diff --git a/radio/aidl/android/hardware/radio/config/IRadioConfigResponse.aidl b/radio/aidl/android/hardware/radio/config/IRadioConfigResponse.aidl index 8182cd158b98683f690d07ac62974a8c9a4fdd78..d526c513aa173a7fa56b5455613d11852f857b02 100644 --- a/radio/aidl/android/hardware/radio/config/IRadioConfigResponse.aidl +++ b/radio/aidl/android/hardware/radio/config/IRadioConfigResponse.aidl @@ -18,6 +18,7 @@ package android.hardware.radio.config; import android.hardware.radio.config.PhoneCapability; import android.hardware.radio.config.SimSlotStatus; +import android.hardware.radio.config.SimTypeInfo; /** * Interface declaring response functions to solicited radio config requests. @@ -152,4 +153,40 @@ oneway interface IRadioConfigResponse { */ void getSimultaneousCallingSupportResponse( in android.hardware.radio.RadioResponseInfo info, in int[] enabledLogicalSlots); + + /** + * Response to the asynchronous {@link IRadioConfig#getSimTypeInfo} request. + * + * @param info Response info struct containing response type, serial number and error + * @param simTypeInfos Currently active and supported sim types associated with active + * physical slot ids. + * + * Valid errors returned: + * RadioError:REQUEST_NOT_SUPPORTED when android.hardware.telephony.subscription is not + * defined + * RadioError:NONE + * RadioError:RADIO_NOT_AVAILABLE + * RadioError:NO_MEMORY + * RadioError:INTERNAL_ERR + * RadioError:MODEM_ERR + */ + void getSimTypeInfoResponse( + in android.hardware.radio.RadioResponseInfo info, in SimTypeInfo[] simTypeInfo); + + /** + * Response to the asynchronous {@link IRadioConfig#setSimType} request. + * + * @param info Response info struct containing response type, serial number and error + * + * Valid errors returned: + * RadioError:REQUEST_NOT_SUPPORTED when android.hardware.telephony.subscription is not + * defined + * RadioError:NONE + * RadioError:RADIO_NOT_AVAILABLE + * RadioError:NO_MEMORY + * RadioError:INTERNAL_ERR + * RadioError:INVALID_ARGUMENTS + * RadioError:MODEM_ERR + */ + void setSimTypeResponse(in android.hardware.radio.RadioResponseInfo info); } diff --git a/radio/aidl/android/hardware/radio/config/SimType.aidl b/radio/aidl/android/hardware/radio/config/SimType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..fc9915e90ba4a6207d68bb7f53c71db9a237bd5b --- /dev/null +++ b/radio/aidl/android/hardware/radio/config/SimType.aidl @@ -0,0 +1,36 @@ +/* + * 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. + */ + +package android.hardware.radio.config; + +/** @hide */ +@VintfStability +@Backing(type="int") +@JavaDerive(toString=true) +enum SimType { + /** + * Unknown + **/ + UNKNOWN = 0, + /** + * Physical SIM (can be eUICC capable) + **/ + PHYSICAL = 1 << 0, + /** + * Embedded SIM + **/ + ESIM = 1 << 1, +} diff --git a/radio/aidl/android/hardware/radio/config/SimTypeInfo.aidl b/radio/aidl/android/hardware/radio/config/SimTypeInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..053462628274664a0e136185b206a0555f972b23 --- /dev/null +++ b/radio/aidl/android/hardware/radio/config/SimTypeInfo.aidl @@ -0,0 +1,38 @@ +/* + * 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. + */ + +package android.hardware.radio.config; + +import android.hardware.radio.config.SimType; + +/** @hide */ +@VintfStability +@JavaDerive(toString=true) +parcelable SimTypeInfo { + /** + * Current SimType on the physical slot id. + **/ + SimType currentSimType = SimType.UNKNOWN; + /** + * Bitmask of the sim types supported by the physical slot id. Physical slot can support more + * than one SimType. + * Example: + * if the physical slot id supports either pSIM/eSIM and currently pSIM is active, + * currentSimType will be SimType::PHYSICAL and supportedSimTypes will be + * SimType::PHYSICAL | SimType::ESIM. + **/ + int supportedSimTypes; +} diff --git a/radio/aidl/android/hardware/radio/data/DataCallFailCause.aidl b/radio/aidl/android/hardware/radio/data/DataCallFailCause.aidl index 6f043d9ad3ed11e92ed70df1066356403c3fe2c7..592fde69fa18e80c5d83b8abde94ab4f8f56e01f 100644 --- a/radio/aidl/android/hardware/radio/data/DataCallFailCause.aidl +++ b/radio/aidl/android/hardware/radio/data/DataCallFailCause.aidl @@ -421,6 +421,7 @@ enum DataCallFailCause { TRAT_SWAP_FAILED = 0x800, /** * Device falls back from eHRPD to HRPD. + * @deprecated Legacy CDMA is unsupported. */ EHRPD_TO_HRPD_FALLBACK = 0x801, /** @@ -521,26 +522,32 @@ enum DataCallFailCause { PDN_NON_IP_CALL_DISALLOWED = 0x817, /** * Device in CDMA locked state. + * @deprecated Legacy CDMA is unsupported. */ CDMA_LOCK = 0x818, /** * Received an intercept order from the base station. + * @deprecated Legacy CDMA is unsupported. */ CDMA_INTERCEPT = 0x819, /** * Receiving a reorder from the base station. + * @deprecated Legacy CDMA is unsupported. */ CDMA_REORDER = 0x81A, /** * Receiving a release from the base station with a SO (Service Option) Reject reason. + * @deprecated Legacy CDMA is unsupported. */ CDMA_RELEASE_DUE_TO_SO_REJECTION = 0x81B, /** * Receiving an incoming call from the base station. + * @deprecated Legacy CDMA is unsupported. */ CDMA_INCOMING_CALL = 0x81C, /** * Received an alert stop from the base station due to incoming only. + * @deprecated Legacy CDMA is unsupported. */ CDMA_ALERT_STOP = 0x81D, /** @@ -570,6 +577,7 @@ enum DataCallFailCause { CONCURRENT_SERVICES_INCOMPATIBLE = 0x823, /** * Device does not have CDMA service. + * @deprecated Legacy CDMA is unsupported. */ NO_CDMA_SERVICE = 0x824, /** @@ -578,6 +586,7 @@ enum DataCallFailCause { RUIM_NOT_PRESENT = 0x825, /** * Receiving a retry order from the base station. + * @deprecated Legacy CDMA is unsupported. */ CDMA_RETRY_ORDER = 0x826, /** @@ -1062,30 +1071,37 @@ enum DataCallFailCause { UMTS_HANDOVER_TO_IWLAN = 0x897, /** * Received a connection deny due to general or network busy on EVDO network. + * @deprecated Legacy CDMA is unsupported. */ EVDO_CONNECTION_DENY_BY_GENERAL_OR_NETWORK_BUSY = 0x898, /** * Received a connection deny due to billing or authentication failure on EVDO network. + * @deprecated Legacy CDMA is unsupported. */ EVDO_CONNECTION_DENY_BY_BILLING_OR_AUTHENTICATION_FAILURE = 0x899, /** * HDR system has been changed due to redirection or the PRL was not preferred. + * @deprecated Legacy CDMA is unsupported. */ EVDO_HDR_CHANGED = 0x89A, /** * Device exited HDR due to redirection or the PRL was not preferred. + * @deprecated Legacy CDMA is unsupported. */ EVDO_HDR_EXITED = 0x89B, /** * Device does not have an HDR session. + * @deprecated Legacy CDMA is unsupported. */ EVDO_HDR_NO_SESSION = 0x89C, /** * It is ending an HDR call origination in favor of a GPS fix. + * @deprecated Legacy CDMA is unsupported. */ EVDO_USING_GPS_FIX_INSTEAD_OF_HDR_CALL = 0x89D, /** * Connection setup on the HDR system was time out. + * @deprecated Legacy CDMA is unsupported. */ EVDO_HDR_CONNECTION_SETUP_TIMEOUT = 0x89E, /** diff --git a/radio/aidl/android/hardware/radio/messaging/CdmaBroadcastSmsConfigInfo.aidl b/radio/aidl/android/hardware/radio/messaging/CdmaBroadcastSmsConfigInfo.aidl index 35a6a8d9b477d25566d86a4819bba79c2d50e38f..cef8f5d9694fc36bc3efc57159bf67f80368f600 100644 --- a/radio/aidl/android/hardware/radio/messaging/CdmaBroadcastSmsConfigInfo.aidl +++ b/radio/aidl/android/hardware/radio/messaging/CdmaBroadcastSmsConfigInfo.aidl @@ -23,15 +23,18 @@ parcelable CdmaBroadcastSmsConfigInfo { /** * Defines a broadcast message identifier whose value is 0x0000 - 0xFFFF as defined in * C.R1001G 9.3.1 and 9.3.2. + * @deprecated Legacy CDMA is unsupported. */ int serviceCategory; /** * Language code of broadcast message whose value is 0x00 - 0x07 as defined in C.R1001G 9.2. + * @deprecated Legacy CDMA is unsupported. */ int language; /** * Selected false means message types specified in serviceCategory are not accepted, * while true means accepted. + * @deprecated Legacy CDMA is unsupported. */ boolean selected; } diff --git a/radio/aidl/android/hardware/radio/messaging/CdmaSmsAck.aidl b/radio/aidl/android/hardware/radio/messaging/CdmaSmsAck.aidl index 2544ab5cf01378381c7a9a4b69f5e26599b35b86..ea5d8b2b5cf026feac5fb8632f1c98d14b34e266 100644 --- a/radio/aidl/android/hardware/radio/messaging/CdmaSmsAck.aidl +++ b/radio/aidl/android/hardware/radio/messaging/CdmaSmsAck.aidl @@ -20,10 +20,12 @@ package android.hardware.radio.messaging; @VintfStability @JavaDerive(toString=true) parcelable CdmaSmsAck { + /** @deprecated Legacy CDMA is unsupported. */ boolean errorClass; /** * SMS cause code as defined in N.S00005, 6.5.2.125. * Currently, only 35 (resource shortage) and 39 (other terminal problem) are reported. + * @deprecated Legacy CDMA is unsupported. */ int smsCauseCode; } diff --git a/radio/aidl/android/hardware/radio/messaging/CdmaSmsAddress.aidl b/radio/aidl/android/hardware/radio/messaging/CdmaSmsAddress.aidl index a7ad23356580e1b17aa4d70637b1a80b1db1bedc..11d953b390359c69dba99caca6acb2d6e59eb26a 100644 --- a/radio/aidl/android/hardware/radio/messaging/CdmaSmsAddress.aidl +++ b/radio/aidl/android/hardware/radio/messaging/CdmaSmsAddress.aidl @@ -22,40 +22,60 @@ package android.hardware.radio.messaging; parcelable CdmaSmsAddress { /** * DTMF digits + * @deprecated Legacy CDMA is unsupported. */ const int DIGIT_MODE_FOUR_BIT = 0; + /** @deprecated Legacy CDMA is unsupported. */ const int DIGIT_MODE_EIGHT_BIT = 1; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_PLAN_UNKNOWN = 0; /** * CCITT E.164 and E.163, including ISDN plan + * @deprecated Legacy CDMA is unsupported. */ const int NUMBER_PLAN_TELEPHONY = 1; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_PLAN_RESERVED_2 = 2; /** * CCITT X.121 + * @deprecated Legacy CDMA is unsupported. */ const int NUMBER_PLAN_DATA = 3; /** * CCITT F.69 + * @deprecated Legacy CDMA is unsupported. */ const int NUMBER_PLAN_TELEX = 4; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_PLAN_RESERVED_5 = 5; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_PLAN_RESERVED_6 = 6; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_PLAN_RESERVED_7 = 7; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_PLAN_RESERVED_8 = 8; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_PLAN_PRIVATE = 9; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_PLAN_RESERVED_10 = 10; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_PLAN_RESERVED_11 = 11; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_PLAN_RESERVED_12 = 12; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_PLAN_RESERVED_13 = 13; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_PLAN_RESERVED_14 = 14; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_PLAN_RESERVED_15 = 15; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_TYPE_UNKNOWN = 0; /** * INTERNATIONAL is used when number mode is not data network address. DATA_IP is used when the * number mode is data network address. + * @deprecated Legacy CDMA is unsupported. */ const int NUMBER_TYPE_INTERNATIONAL_OR_DATA_IP = 1; /** @@ -63,25 +83,33 @@ parcelable CdmaSmsAddress { * when the number mode is data network address. For INTERNET_MAIL, in the address data * "digits", each byte contains an ASCII character. Examples are: "x@y.com,a@b.com" * Ref TIA/EIA-637A 3.4.3.3 + * @deprecated Legacy CDMA is unsupported. */ const int NUMBER_TYPE_NATIONAL_OR_INTERNET_MAIL = 2; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_TYPE_NETWORK = 3; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_TYPE_SUBSCRIBER = 4; /** * GSM SMS: address value is GSM 7-bit chars + * @deprecated Legacy CDMA is unsupported. */ const int NUMBER_TYPE_ALPHANUMERIC = 5; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_TYPE_ABBREVIATED = 6; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_TYPE_RESERVED_7 = 7; /** * CdmaSmsDigitMode is of two types : 4 bit and 8 bit. * For 4-bit type, only "digits" field defined below in this struct is used. * Values are DIGIT_MODE_ + * @deprecated Legacy CDMA is unsupported. */ int digitMode; /** * Used only when digitMode is 8-bit. + * @deprecated Legacy CDMA is unsupported. */ boolean isNumberModeDataNetwork; /** @@ -92,15 +120,18 @@ parcelable CdmaSmsAddress { * numberPlan = TELEPHONY * digits = ASCII digits, e.g. '1', '2', '3', '4', and '5' * Values are NUMBER_TYPE_ + * @deprecated Legacy CDMA is unsupported. */ int numberType; /** * Used only when digitMode is 8-bit. * Values are NUMBER_PLAN_ + * @deprecated Legacy CDMA is unsupported. */ int numberPlan; /** * Each byte in this array represents a 4 bit or 8-bit digit of address data. + * @deprecated Legacy CDMA is unsupported. */ byte[] digits; } diff --git a/radio/aidl/android/hardware/radio/messaging/CdmaSmsMessage.aidl b/radio/aidl/android/hardware/radio/messaging/CdmaSmsMessage.aidl index 51388b6f6fb90510b28b92f97564a069eb27f362..5332d824d929e3ec0f4ffb6bfea46500abdb391f 100644 --- a/radio/aidl/android/hardware/radio/messaging/CdmaSmsMessage.aidl +++ b/radio/aidl/android/hardware/radio/messaging/CdmaSmsMessage.aidl @@ -23,13 +23,19 @@ import android.hardware.radio.messaging.CdmaSmsSubaddress; @VintfStability @JavaDerive(toString=true) parcelable CdmaSmsMessage { + /** @deprecated Legacy CDMA is unsupported. */ int teleserviceId; + /** @deprecated Legacy CDMA is unsupported. */ boolean isServicePresent; + /** @deprecated Legacy CDMA is unsupported. */ int serviceCategory; + /** @deprecated Legacy CDMA is unsupported. */ CdmaSmsAddress address; + /** @deprecated Legacy CDMA is unsupported. */ CdmaSmsSubaddress subAddress; /** * 3GPP2 C.S0015-B, v2.0 + * @deprecated Legacy CDMA is unsupported. */ byte[] bearerData; } diff --git a/radio/aidl/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl b/radio/aidl/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl index 8c494bb24e2b7316eb3cfde92a52bee2d94942c6..132bbbb6108e86386667af4ff79f83ed9fe68a2f 100644 --- a/radio/aidl/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl +++ b/radio/aidl/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl @@ -23,23 +23,28 @@ package android.hardware.radio.messaging; parcelable CdmaSmsSubaddress { /** * CCITT X.213 or ISO 8348 AD2 + * @deprecated Legacy CDMA is unsupported. */ const int SUBADDRESS_TYPE_NSAP = 0; /** * e.g. X.25 + * @deprecated Legacy CDMA is unsupported. */ const int SUBADDRESS_TYPE_USER_SPECIFIED = 1; /** * Values are SUBADDRESS_TYPE_ + * @deprecated Legacy CDMA is unsupported. */ int subaddressType; /** * True means the last byte's lower 4 bits must be ignored + * @deprecated Legacy CDMA is unsupported. */ boolean odd; /** * Each byte represents an 8-bit digit of subaddress data + * @deprecated Legacy CDMA is unsupported. */ byte[] digits; } diff --git a/radio/aidl/android/hardware/radio/messaging/CdmaSmsWriteArgs.aidl b/radio/aidl/android/hardware/radio/messaging/CdmaSmsWriteArgs.aidl index 897ec80ce9f0ec4ddb610dae9782fba750c38825..3047859cffbf4ee2c7ec2d0d451ea68f126690f8 100644 --- a/radio/aidl/android/hardware/radio/messaging/CdmaSmsWriteArgs.aidl +++ b/radio/aidl/android/hardware/radio/messaging/CdmaSmsWriteArgs.aidl @@ -22,15 +22,21 @@ import android.hardware.radio.messaging.CdmaSmsMessage; @VintfStability @JavaDerive(toString=true) parcelable CdmaSmsWriteArgs { + /** @deprecated Legacy CDMA is unsupported. */ const int STATUS_REC_UNREAD = 0; + /** @deprecated Legacy CDMA is unsupported. */ const int STATUS_REC_READ = 1; + /** @deprecated Legacy CDMA is unsupported. */ const int STATUS_STO_UNSENT = 2; + /** @deprecated Legacy CDMA is unsupported. */ const int STATUS_STO_SENT = 3; /** * Status of message. See TS 27.005 3.1 * Values are STATUS_ + * @deprecated Legacy CDMA is unsupported. */ int status; + /** @deprecated Legacy CDMA is unsupported. */ CdmaSmsMessage message; } diff --git a/radio/aidl/android/hardware/radio/messaging/IRadioMessaging.aidl b/radio/aidl/android/hardware/radio/messaging/IRadioMessaging.aidl index 945453c771814e1afb05b652423b4e2fcf492815..b60a2258bff69382965e5c1a83ebd85aa9e7dc9e 100644 --- a/radio/aidl/android/hardware/radio/messaging/IRadioMessaging.aidl +++ b/radio/aidl/android/hardware/radio/messaging/IRadioMessaging.aidl @@ -65,6 +65,8 @@ oneway interface IRadioMessaging { * Response function is IRadioMessagingResponse.acknowledgeLastIncomingCdmaSmsResponse() * * This is available when android.hardware.telephony.cdma is defined. + * + * @deprecated Legacy CDMA is unsupported. */ void acknowledgeLastIncomingCdmaSms(in int serial, in CdmaSmsAck smsAck); @@ -94,6 +96,8 @@ oneway interface IRadioMessaging { * Response function is IRadioMessagingResponse.deleteSmsOnRuimResponse() * * This is available when android.hardware.telephony.cdma is defined. + * + * @deprecated Legacy CDMA is unsupported. */ void deleteSmsOnRuim(in int serial, in int index); @@ -117,6 +121,8 @@ oneway interface IRadioMessaging { * Response function is IRadioMessagingResponse.getCdmaBroadcastConfigResponse() * * This is available when android.hardware.telephony.cdma is defined. + * + * @deprecated Legacy CDMA is unsupported. */ void getCdmaBroadcastConfig(in int serial); @@ -173,6 +179,8 @@ oneway interface IRadioMessaging { * Response function is IRadioMessagingResponse.sendCdmaSmsResponse() * * This is available when android.hardware.telephony.cdma is defined. + * + * @deprecated Legacy CDMA is unsupported. */ void sendCdmaSms(in int serial, in CdmaSmsMessage sms); @@ -186,6 +194,8 @@ oneway interface IRadioMessaging { * Response function is IRadioMessagingResponse.sendCdmaSmsExpectMoreResponse() * * This is available when android.hardware.telephony.cdma is defined. + * + * @deprecated Legacy CDMA is unsupported. */ void sendCdmaSmsExpectMore(in int serial, in CdmaSmsMessage sms); @@ -243,6 +253,8 @@ oneway interface IRadioMessaging { * Response function is IRadioMessagingResponse.setCdmaBroadcastActivationResponse() * * This is available when android.hardware.telephony.cdma is defined. + * + * @deprecated Legacy CDMA is unsupported. */ void setCdmaBroadcastActivation(in int serial, in boolean activate); @@ -255,6 +267,8 @@ oneway interface IRadioMessaging { * Response function is IRadioMessagingResponse.setCdmaBroadcastConfigResponse() * * This is available when android.hardware.telephony.cdma is defined. + * + * @deprecated Legacy CDMA is unsupported. */ void setCdmaBroadcastConfig(in int serial, in CdmaBroadcastSmsConfigInfo[] configInfo); @@ -315,6 +329,8 @@ oneway interface IRadioMessaging { * Response function is IRadioMessagingResponse.writeSmsToRuimResponse() * * This is available when android.hardware.telephony.cdma is defined. + * + * @deprecated Legacy CDMA is unsupported. */ void writeSmsToRuim(in int serial, in CdmaSmsWriteArgs cdmaSms); diff --git a/radio/aidl/android/hardware/radio/messaging/IRadioMessagingIndication.aidl b/radio/aidl/android/hardware/radio/messaging/IRadioMessagingIndication.aidl index a177c2cbddcda29f3d63670b7c432bf0619a54a6..4c6529b20b7ff77a92f13c1d99e7a387dd0030dd 100644 --- a/radio/aidl/android/hardware/radio/messaging/IRadioMessagingIndication.aidl +++ b/radio/aidl/android/hardware/radio/messaging/IRadioMessagingIndication.aidl @@ -32,6 +32,7 @@ oneway interface IRadioMessagingIndication { * * @param type Type of radio indication * @param msg Cdma Sms Message + * @deprecated Legacy CDMA is unsupported. */ void cdmaNewSms(in RadioIndicationType type, in CdmaSmsMessage msg); @@ -40,6 +41,7 @@ oneway interface IRadioMessagingIndication { * space is freed. * * @param type Type of radio indication + * @deprecated Legacy CDMA is unsupported. */ void cdmaRuimSmsStorageFull(in RadioIndicationType type); diff --git a/radio/aidl/android/hardware/radio/messaging/IRadioMessagingResponse.aidl b/radio/aidl/android/hardware/radio/messaging/IRadioMessagingResponse.aidl index f0d799909b27f2ff836f1107d984ccda93a0bb6b..9b6e461f173ada42580c4129bf4223752ffdab7f 100644 --- a/radio/aidl/android/hardware/radio/messaging/IRadioMessagingResponse.aidl +++ b/radio/aidl/android/hardware/radio/messaging/IRadioMessagingResponse.aidl @@ -62,6 +62,7 @@ oneway interface IRadioMessagingResponse { * RadioError:OPERATION_NOT_ALLOWED * RadioError:NO_RESOURCES * RadioError:CANCELLED + * @deprecated Legacy CDMA is unsupported. */ void acknowledgeLastIncomingCdmaSmsResponse(in RadioResponseInfo info); @@ -108,6 +109,7 @@ oneway interface IRadioMessagingResponse { * RadioError:INVALID_MODEM_STATE * RadioError:OPERATION_NOT_ALLOWED * RadioError:SIM_ABSENT + * @deprecated Legacy CDMA is unsupported. */ void deleteSmsOnRuimResponse(in RadioResponseInfo info); @@ -153,6 +155,7 @@ oneway interface IRadioMessagingResponse { * RadioError:NO_RESOURCES * RadioError:CANCELLED * RadioError:INVALID_MODEM_STATE + * @deprecated Legacy CDMA is unsupported. */ void getCdmaBroadcastConfigResponse( in RadioResponseInfo info, in CdmaBroadcastSmsConfigInfo[] configs); @@ -257,6 +260,7 @@ oneway interface IRadioMessagingResponse { * RadioError:SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED * RadioError:ACCESS_BARRED * RadioError:BLOCKED_DUE_TO_CALL + * @deprecated Legacy CDMA is unsupported. */ void sendCdmaSmsExpectMoreResponse(in RadioResponseInfo info, in SendSmsResult sms); @@ -291,6 +295,7 @@ oneway interface IRadioMessagingResponse { * RadioError:SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED * RadioError:ACCESS_BARRED * RadioError:BLOCKED_DUE_TO_CALL + * @deprecated Legacy CDMA is unsupported. */ void sendCdmaSmsResponse(in RadioResponseInfo info, in SendSmsResult sms); @@ -407,6 +412,7 @@ oneway interface IRadioMessagingResponse { * RadioError:NO_RESOURCES * RadioError:CANCELLED * RadioError:INVALID_MODEM_STATE + * @deprecated Legacy CDMA is unsupported. */ void setCdmaBroadcastActivationResponse(in RadioResponseInfo info); @@ -427,6 +433,7 @@ oneway interface IRadioMessagingResponse { * RadioError:NO_RESOURCES * RadioError:CANCELLED * RadioError:INVALID_MODEM_STATE + * @deprecated Legacy CDMA is unsupported. */ void setCdmaBroadcastConfigResponse(in RadioResponseInfo info); @@ -520,6 +527,7 @@ oneway interface IRadioMessagingResponse { * RadioError:CANCELLED * RadioError:INVALID_MODEM_STATE * RadioError:SIM_ABSENT + * @deprecated Legacy CDMA is unsupported. */ void writeSmsToRuimResponse(in RadioResponseInfo info, in int index); diff --git a/radio/aidl/android/hardware/radio/messaging/ImsSmsMessage.aidl b/radio/aidl/android/hardware/radio/messaging/ImsSmsMessage.aidl index bbcd1cb6e8e716a89a316b076568be254c8231bf..c2053233d1caa763c7d1a3cae80d23e39753f1c4 100644 --- a/radio/aidl/android/hardware/radio/messaging/ImsSmsMessage.aidl +++ b/radio/aidl/android/hardware/radio/messaging/ImsSmsMessage.aidl @@ -37,6 +37,7 @@ parcelable ImsSmsMessage { /** * Valid field if tech is 3GPP2 and size = 1 else must be empty. Only one of cdmaMessage and * gsmMessage must be of size 1 based on the RadioTechnologyFamily and the other must be size 0. + * @deprecated Legacy CDMA is unsupported. */ CdmaSmsMessage[] cdmaMessage; /** diff --git a/radio/aidl/android/hardware/radio/messaging/SendSmsResult.aidl b/radio/aidl/android/hardware/radio/messaging/SendSmsResult.aidl index ea9372703494902e4a21844ff7d4b210030c3c84..da41d84e2f08ebf5f9227beda33db701287130b5 100644 --- a/radio/aidl/android/hardware/radio/messaging/SendSmsResult.aidl +++ b/radio/aidl/android/hardware/radio/messaging/SendSmsResult.aidl @@ -23,15 +23,18 @@ parcelable SendSmsResult { /** * TP-Message-Reference for GSM, and BearerData MessageId for CDMA. * See 3GPP2 C.S0015-B, v2.0, table 4.5-1 + * @deprecated Legacy CDMA is unsupported. */ int messageRef; /** * Ack PDU or empty string if n/a + * @deprecated Legacy CDMA is unsupported. */ String ackPDU; /** * See 3GPP 27.005, 3.2.5 for GSM/UMTS, 3GPP2 N.S0005 (IS-41C) Table 171 for CDMA. * -1 if unknown or not applicable. + * @deprecated Legacy CDMA is unsupported. */ int errorCode; } diff --git a/radio/aidl/android/hardware/radio/modem/IRadioModem.aidl b/radio/aidl/android/hardware/radio/modem/IRadioModem.aidl index bfca5a9ef4ddfb9e5051d3970889b07a72ee9d98..15a833ee648135db3f8de5b8eb1a66f6f9aceb22 100644 --- a/radio/aidl/android/hardware/radio/modem/IRadioModem.aidl +++ b/radio/aidl/android/hardware/radio/modem/IRadioModem.aidl @@ -139,15 +139,15 @@ oneway interface IRadioModem { void nvReadItem(in int serial, in NvItem itemId); /** - * Reset the radio NV configuration to the factory state. - * This is used for device configuration by some CDMA operators. + * Reboots modem. + * + * This was historically used to reset NV configuration, but starting from Android U, NV APIs + * are deprecated. * * @param serial Serial number of request. - * @param resetType ResetNvType + * @param resetType Always ResetNvType.RELOAD. * * Response function is IRadioModemResponse.nvResetConfigResponse() - * - * Note: This will be deprecated in favor of a rebootModem API in Android U. */ void nvResetConfig(in int serial, in ResetNvType resetType); diff --git a/radio/aidl/android/hardware/radio/modem/IRadioModemResponse.aidl b/radio/aidl/android/hardware/radio/modem/IRadioModemResponse.aidl index 6d2504c24f8667b1d126cfe9d85288860fc3f956..498f22847fa1954a6b81b35680943122b380f405 100644 --- a/radio/aidl/android/hardware/radio/modem/IRadioModemResponse.aidl +++ b/radio/aidl/android/hardware/radio/modem/IRadioModemResponse.aidl @@ -175,8 +175,6 @@ oneway interface IRadioModemResponse { * Valid errors returned: * RadioError:NONE * RadioError:RADIO_NOT_AVAILABLE - * - * Note: This will be deprecated in favor of a rebootModemResponse API in Android U. */ void nvResetConfigResponse(in RadioResponseInfo info); diff --git a/radio/aidl/android/hardware/radio/modem/ResetNvType.aidl b/radio/aidl/android/hardware/radio/modem/ResetNvType.aidl index b6be54dee0da4c3bc20dd7fcb43895dfd572cf1f..95fa0d75dcd130c00f5276cf2d51d01bcc78580a 100644 --- a/radio/aidl/android/hardware/radio/modem/ResetNvType.aidl +++ b/radio/aidl/android/hardware/radio/modem/ResetNvType.aidl @@ -17,7 +17,6 @@ package android.hardware.radio.modem; /** - * Note: This will be deprecated along with nvResetConfig in Android U. * @hide */ @VintfStability @@ -26,15 +25,21 @@ package android.hardware.radio.modem; @SuppressWarnings(value={"redundant-name"}) enum ResetNvType { /** - * Reload all NV items + * Reboot modem. + * + * Historically, this has been also reloading all NV items. */ RELOAD, /** * Erase NV reset (SCRTN) + * + * @deprecated NV APIs are deprecated starting from Android U. */ ERASE, /** * Factory reset (RTN) + * + * @deprecated NV APIs are deprecated starting from Android U. */ FACTORY_RESET, } diff --git a/radio/aidl/android/hardware/radio/network/AccessTechnologySpecificInfo.aidl b/radio/aidl/android/hardware/radio/network/AccessTechnologySpecificInfo.aidl index 9c48a8d83815c69ce68211c5d2ff4666f20d2c74..10421d67f46ef18d26b696a17c58c9787840d5e2 100644 --- a/radio/aidl/android/hardware/radio/network/AccessTechnologySpecificInfo.aidl +++ b/radio/aidl/android/hardware/radio/network/AccessTechnologySpecificInfo.aidl @@ -25,6 +25,7 @@ import android.hardware.radio.network.NrVopsInfo; @JavaDerive(toString=true) union AccessTechnologySpecificInfo { boolean noinit; + /** @deprecated Legacy CDMA is unsupported. */ Cdma2000RegistrationInfo cdmaInfo; EutranRegistrationInfo eutranInfo; /** diff --git a/radio/aidl/android/hardware/radio/network/Cdma2000RegistrationInfo.aidl b/radio/aidl/android/hardware/radio/network/Cdma2000RegistrationInfo.aidl index 91b85004c7884a4b646c96038489d7da4629872e..333a6c4390348e28da7076a7b59b776c842ed764 100644 --- a/radio/aidl/android/hardware/radio/network/Cdma2000RegistrationInfo.aidl +++ b/radio/aidl/android/hardware/radio/network/Cdma2000RegistrationInfo.aidl @@ -20,29 +20,36 @@ package android.hardware.radio.network; @VintfStability @JavaDerive(toString=true) parcelable Cdma2000RegistrationInfo { + /** @deprecated Legacy CDMA is unsupported. */ const int PRL_INDICATOR_NOT_REGISTERED = -1; + /** @deprecated Legacy CDMA is unsupported. */ const int PRL_INDICATOR_NOT_IN_PRL = 0; + /** @deprecated Legacy CDMA is unsupported. */ const int PRL_INDICATOR_IN_PRL = 1; /** * Concurrent services support indicator. if registered on a CDMA system. * false - Concurrent services not supported, * true - Concurrent services supported + * @deprecated Legacy CDMA is unsupported. */ boolean cssSupported; /** * TSB-58 Roaming Indicator if registered on a CDMA or EVDO system or -1 if not. * Valid values are 0-255. + * @deprecated Legacy CDMA is unsupported. */ int roamingIndicator; /** * Indicates whether the current system is in the PRL if registered on a CDMA or EVDO system * or -1 if not. 0=not in the PRL, 1=in the PRL. * Values are PRL_INDICATOR_ + * @deprecated Legacy CDMA is unsupported. */ int systemIsInPrl; /** * Default Roaming Indicator from the PRL if registered on a CDMA or EVDO system or -1 if not. * Valid values are 0-255. + * @deprecated Legacy CDMA is unsupported. */ int defaultRoamingIndicator; } diff --git a/radio/aidl/android/hardware/radio/network/CdmaRoamingType.aidl b/radio/aidl/android/hardware/radio/network/CdmaRoamingType.aidl index 0bb7c0410a0a4c11efae200a1a0262511b7369a2..4cad136b3feea7cfa7bd014766abe0cf9f1fec3b 100644 --- a/radio/aidl/android/hardware/radio/network/CdmaRoamingType.aidl +++ b/radio/aidl/android/hardware/radio/network/CdmaRoamingType.aidl @@ -21,7 +21,10 @@ package android.hardware.radio.network; @Backing(type="int") @JavaDerive(toString=true) enum CdmaRoamingType { + /** @deprecated Legacy CDMA is unsupported. */ HOME_NETWORK, + /** @deprecated Legacy CDMA is unsupported. */ AFFILIATED_ROAM, + /** @deprecated Legacy CDMA is unsupported. */ ANY_ROAM, } diff --git a/radio/aidl/android/hardware/radio/network/CdmaSignalStrength.aidl b/radio/aidl/android/hardware/radio/network/CdmaSignalStrength.aidl index 0e241d359ed44e932a704b6196c6c8920cf299c6..214a512a2bd6ea52878a86d9252feff8ac49be0c 100644 --- a/radio/aidl/android/hardware/radio/network/CdmaSignalStrength.aidl +++ b/radio/aidl/android/hardware/radio/network/CdmaSignalStrength.aidl @@ -23,11 +23,13 @@ parcelable CdmaSignalStrength { /** * This value is the actual RSSI value multiplied by -1. Example: If the actual RSSI is -75, * then this response value will be 75. RadioConst:VALUE_UNAVAILABLE means invalid/unreported. + * @deprecated Legacy CDMA is unsupported. */ int dbm; /** * This value is the actual Ec/Io multiplied by -10. Example: If the actual Ec/Io is -12.5 dB, * then this response value will be 125. RadioConst:VALUE_UNAVAILABLE means invalid/unreported. + * @deprecated Legacy CDMA is unsupported. */ int ecio; } diff --git a/radio/aidl/android/hardware/radio/network/CellIdentity.aidl b/radio/aidl/android/hardware/radio/network/CellIdentity.aidl index 61420876804dc8cc7e7c47e0bd444f932c2c463d..76a667584f83e8d6d2ff2156939db8662c4555a0 100644 --- a/radio/aidl/android/hardware/radio/network/CellIdentity.aidl +++ b/radio/aidl/android/hardware/radio/network/CellIdentity.aidl @@ -34,6 +34,7 @@ union CellIdentity { CellIdentityGsm gsm; CellIdentityWcdma wcdma; CellIdentityTdscdma tdscdma; + /** @deprecated Legacy CDMA is unsupported. */ CellIdentityCdma cdma; CellIdentityLte lte; CellIdentityNr nr; diff --git a/radio/aidl/android/hardware/radio/network/CellIdentityCdma.aidl b/radio/aidl/android/hardware/radio/network/CellIdentityCdma.aidl index acf3db19bdbd2955833f12401d565bf7b5c6ad26..7f33d2d905c1de50deca62246e50deccb0ddefbc 100644 --- a/radio/aidl/android/hardware/radio/network/CellIdentityCdma.aidl +++ b/radio/aidl/android/hardware/radio/network/CellIdentityCdma.aidl @@ -24,30 +24,36 @@ import android.hardware.radio.network.OperatorInfo; parcelable CellIdentityCdma { /** * Network Id 0..65535, RadioConst:VALUE_UNAVAILABLE if unknown + * @deprecated Legacy CDMA is unsupported. */ int networkId; /** * CDMA System Id 0..32767, RadioConst:VALUE_UNAVAILABLE if unknown + * @deprecated Legacy CDMA is unsupported. */ int systemId; /** * Base Station Id 0..65535, RadioConst:VALUE_UNAVAILABLE if unknown + * @deprecated Legacy CDMA is unsupported. */ int baseStationId; /** * Longitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0. It is represented in * units of 0.25 seconds and ranges from -2592000 to 2592000, both values inclusive * (corresponding to a range of -180 to +180 degrees). RadioConst:VALUE_UNAVAILABLE if unknown + * @deprecated Legacy CDMA is unsupported. */ int longitude; /** * Latitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0. It is represented in * units of 0.25 seconds and ranges from -1296000 to 1296000, both values inclusive * (corresponding to a range of -90 to +90 degrees). RadioConst:VALUE_UNAVAILABLE if unknown + * @deprecated Legacy CDMA is unsupported. */ int latitude; /** * OperatorInfo containing alphaLong and alphaShort + * @deprecated Legacy CDMA is unsupported. */ OperatorInfo operatorNames; } diff --git a/radio/aidl/android/hardware/radio/network/CellInfoCdma.aidl b/radio/aidl/android/hardware/radio/network/CellInfoCdma.aidl index 0a2bc542137ebea9d77ad40eb10602a5388ae874..0a0c0c075df4fa47567133e7a6f728c4cef4d0c0 100644 --- a/radio/aidl/android/hardware/radio/network/CellInfoCdma.aidl +++ b/radio/aidl/android/hardware/radio/network/CellInfoCdma.aidl @@ -24,7 +24,10 @@ import android.hardware.radio.network.EvdoSignalStrength; @VintfStability @JavaDerive(toString=true) parcelable CellInfoCdma { + /** @deprecated Legacy CDMA is unsupported. */ CellIdentityCdma cellIdentityCdma; + /** @deprecated Legacy CDMA is unsupported. */ CdmaSignalStrength signalStrengthCdma; + /** @deprecated Legacy CDMA is unsupported. */ EvdoSignalStrength signalStrengthEvdo; } diff --git a/radio/aidl/android/hardware/radio/network/CellInfoRatSpecificInfo.aidl b/radio/aidl/android/hardware/radio/network/CellInfoRatSpecificInfo.aidl index 10a4a5f993a8d35fb733b50e9f3832ac982f8dd8..eebed9e187afaeb84380749581e4ea5558138357 100644 --- a/radio/aidl/android/hardware/radio/network/CellInfoRatSpecificInfo.aidl +++ b/radio/aidl/android/hardware/radio/network/CellInfoRatSpecificInfo.aidl @@ -37,6 +37,7 @@ union CellInfoRatSpecificInfo { CellInfoNr nr; /** * 3gpp2 CellInfo types; + * @deprecated Legacy CDMA is unsupported. */ CellInfoCdma cdma; } diff --git a/radio/aidl/android/hardware/radio/network/EvdoSignalStrength.aidl b/radio/aidl/android/hardware/radio/network/EvdoSignalStrength.aidl index ac6928e4636ba9d0914ac4ec62e4b1fc656c7f25..e89eb8867e702332049a3f4693a2f3149b067cda 100644 --- a/radio/aidl/android/hardware/radio/network/EvdoSignalStrength.aidl +++ b/radio/aidl/android/hardware/radio/network/EvdoSignalStrength.aidl @@ -23,16 +23,19 @@ parcelable EvdoSignalStrength { /** * This value is the actual RSSI value multiplied by -1. Example: If the actual RSSI is -75, * then this response value will be 75; RadioConst:VALUE_UNAVAILABLE means invalid/unreported. + * @deprecated Legacy CDMA is unsupported. */ int dbm; /** * This value is the actual Ec/Io multiplied by -10. Example: If the actual Ec/Io is -12.5 dB, * then this response value will be 125; RadioConst:VALUE_UNAVAILABLE means invalid/unreported. + * @deprecated Legacy CDMA is unsupported. */ int ecio; /** * Valid values are 0-8. 8 is the highest signal to noise ratio; RadioConst:VALUE_UNAVAILABLE * means invalid/unreported. + * @deprecated Legacy CDMA is unsupported. */ int signalNoiseRatio; } diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl index 81d21e16843b439a1eb34a480c314afe9bef075c..68e4829a45eb46a25d58ece51e9a9551ec5ddcb2 100644 --- a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl +++ b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl @@ -94,6 +94,8 @@ oneway interface IRadioNetwork { * Response function is IRadioNetworkResponse.getCdmaRoamingPreferenceResponse() * * This is available when android.hardware.telephony.cdma is defined. + * + * @deprecated Legacy CDMA is unsupported. */ void getCdmaRoamingPreference(in int serial); @@ -272,6 +274,8 @@ oneway interface IRadioNetwork { * Response function is IRadioNetworkResponse.setCdmaRoamingPreferenceResponse() * * This is available when android.hardware.telephony.cdma is defined. + * + * @deprecated Legacy CDMA is unsupported. */ void setCdmaRoamingPreference(in int serial, in CdmaRoamingType type); @@ -334,7 +338,7 @@ oneway interface IRadioNetwork { /** * Enables/disables network state change notifications due to changes in LAC and/or CID (for - * GSM) or BID/SID/NID/latitude/longitude (for CDMA). Basically +CREG=2 vs. +CREG=1 (TS 27.007). + * GSM). Basically +CREG=2 vs. +CREG=1 (TS 27.007). * The Radio implementation must default to "updates enabled" when the screen is on and * "updates disabled" when the screen is off. * @@ -713,4 +717,60 @@ oneway interface IRadioNetwork { * This is available when android.hardware.telephony.access is defined. */ void isSecurityAlgorithmsUpdatedEnabled(in int serial); + + /** + * Set the non-terrestrial PLMN with lower priority than terrestrial networks. + * MCC/MNC broadcast by the non-terrestrial networks may not be included in OPLMNwACT file on + * SIM profile. Acquisition of satellite based system is lower priority to terrestrial + * networks. UE shall make all attempts to acquire terrestrial service prior to camping on + * satellite LTE service. + * + * @param serial Serial number of request + * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use + * this information to determine the relevant carrier. + * @param carrierPlmnArray Array of roaming PLMN used for connecting to satellite networks + * supported by user subscription. + * @param allSatellitePlmnArray allSatellitePlmnArray contains all the PLMNs present in + * carrierPlmnArray and also list of satellite PLMNs that are not + * supported by the carrier. + * Modem should use the allSatellitePlmnArray to identify satellite + * PLMNs that are not supported by the carrier and make sure not to + * attach to them. + * + * Response function is IRadioNetworkResponse.setSatellitePlmnResponse() + * + * This is available when android.hardware.telephony.radio.access is defined. + */ + void setSatellitePlmn(in int serial, in int simSlot, in String[] carrierPlmnArray, + in String[] allSatellitePlmnArray); + + /** + * Enable or disable satellite in the cellular modem associated with a carrier. + * + * Refer setSatellitePlmn for the details of satellite PLMN scanning process. Once modem is + * disabled, modem should not attach to any of the PLMNs present in allSatellitePlmnArray. + * If modem is enabled, modem should attach to only PLMNs present in carrierPlmnArray. + * + * @param serial Serial number of request + * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use + * this information to determine the relevant carrier. + * @param satelliteEnabled {@code true} to enable satellite, {@code false} to disable satellite. + * + * Response function is IRadioNetworkResponse.setSatelliteEnabledForCarrier() + * + * This is available when android.hardware.telephony.radio.access is defined. + */ + void setSatelliteEnabledForCarrier(in int serial, in int simSlot, boolean satelliteEnabled); + + /** + * Check whether satellite is enabled in the cellular modem associated with a carrier. + * + * @param serial Serial number of request + * @param simSlot Indicates the SIM slot to which this API will be applied. + * + * Response function is IRadioNetworkResponse.isSatelliteEnabledForCarrier() + * + * This is available when android.hardware.telephony.radio.access is defined. + */ + void isSatelliteEnabledForCarrier(in int serial, in int simSlot); } diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl index 7b6fc6e403f5dae9622372d7d9b834c52402eb48..295061b23976655384dc2aefffac07f23da4d26d 100644 --- a/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl +++ b/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl @@ -63,6 +63,7 @@ oneway interface IRadioNetworkIndication { * * @param type Type of radio indication * @param version PRL version after PRL changes + * @deprecated Legacy CDMA is unsupported. */ void cdmaPrlChanged(in RadioIndicationType type, in int version); diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl index 5dcdb69bc29e2f397cce2caee457ea98f238c35c..4c1a394aec2dd25f9a43a5113dc6609dbdb245cc 100644 --- a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl +++ b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl @@ -136,6 +136,7 @@ oneway interface IRadioNetworkResponse { * RadioError:NO_RESOURCES * RadioError:CANCELLED * RadioError:SIM_ABSENT + * @deprecated Legacy CDMA is unsupported. */ void getCdmaRoamingPreferenceResponse(in RadioResponseInfo info, in CdmaRoamingType type); @@ -372,6 +373,7 @@ oneway interface IRadioNetworkResponse { * RadioError:NO_RESOURCES * RadioError:CANCELLED * RadioError:SIM_ABSENT + * @deprecated Legacy CDMA is unsupported. */ void setCdmaRoamingPreferenceResponse(in RadioResponseInfo info); @@ -814,4 +816,53 @@ oneway interface IRadioNetworkResponse { */ void isSecurityAlgorithmsUpdatedEnabledResponse( in RadioResponseInfo info, in boolean isEnabled); + + /** + * Response of setSatellitePlmn. + * This is an optional API. + * + * @param info Response info struct containing response type, serial no. and error. + * + * Valid errors returned: + * RadioError:REQUEST_NOT_SUPPORTED + * RadioError:NONE + * RadioError:RADIO_NOT_AVAILABLE + * RadioError:INTERNAL_ERR + * RadioError:REQUEST_NOT_SUPPORTED + * RadioError:INVALID_STATE + */ + void setSatellitePlmnResponse(in RadioResponseInfo info); + + /** + * Response of setSatelliteEnabledForCarrier. + * This is an optional API. + * + * @param info Response info struct containing response type, serial no. and error. + * + * Valid errors returned: + * RadioError:REQUEST_NOT_SUPPORTED + * RadioError:NONE + * RadioError:RADIO_NOT_AVAILABLE + * RadioError:INTERNAL_ERR + * RadioError:REQUEST_NOT_SUPPORTED + * RadioError:INVALID_STATE + */ + void setSatelliteEnabledForCarrierResponse(in RadioResponseInfo info); + + /** + * Response of isSatelliteEnabledForCarrier. + * This is an optional API. + * + * @param info Response info struct containing response type, serial no. and error. + * @param isEnabled Indicates whether satellite is enabled for carrier or not. + * + * Valid errors returned: + * RadioError:REQUEST_NOT_SUPPORTED + * RadioError:NONE + * RadioError:RADIO_NOT_AVAILABLE + * RadioError:INTERNAL_ERR + * RadioError:REQUEST_NOT_SUPPORTED + * RadioError:INVALID_STATE + */ + void isSatelliteEnabledForCarrierResponse(in RadioResponseInfo info, boolean isEnabled); } diff --git a/radio/aidl/android/hardware/radio/network/RegStateResult.aidl b/radio/aidl/android/hardware/radio/network/RegStateResult.aidl index a7857ef2ea9d0688fdf0063fae43f8fad7d1afb9..a4cb6476da244e56f6d475ba8d02924d6e053001 100644 --- a/radio/aidl/android/hardware/radio/network/RegStateResult.aidl +++ b/radio/aidl/android/hardware/radio/network/RegStateResult.aidl @@ -27,7 +27,7 @@ import android.hardware.radio.network.RegistrationFailCause; @JavaDerive(toString=true) parcelable RegStateResult { /** - * Registration state. If the RAT is indicated as a GERAN, UTRAN, or CDMA2000 technology, this + * Registration state. If the RAT is indicated as a GERAN or UTRAN technology, this * value reports registration in the Circuit-switched domain. If the RAT is indicated as an * EUTRAN, NGRAN, or another technology that does not support circuit-switched services, this * value reports registration in the Packet-switched domain. @@ -57,7 +57,7 @@ parcelable RegStateResult { */ String registeredPlmn; /** - * Access-technology-specific registration information, such as for CDMA2000. + * Access-technology-specific registration information. */ AccessTechnologySpecificInfo accessTechnologySpecificInfo; } diff --git a/radio/aidl/android/hardware/radio/network/SignalStrength.aidl b/radio/aidl/android/hardware/radio/network/SignalStrength.aidl index fbe3be21fb6c85949ee92a6a2fcaf66eb410eda2..4e3bcf074d3a6058e561d26186fe5a8217a0f7de 100644 --- a/radio/aidl/android/hardware/radio/network/SignalStrength.aidl +++ b/radio/aidl/android/hardware/radio/network/SignalStrength.aidl @@ -36,11 +36,13 @@ parcelable SignalStrength { /** * If CDMA measurements are provided, this structure must contain valid measurements; otherwise * all fields should be set to RadioConst:VALUE_UNAVAILABLE to mark them as invalid. + * @deprecated Legacy CDMA is unsupported. */ CdmaSignalStrength cdma; /** * If EvDO measurements are provided, this structure must contain valid measurements; otherwise * all fields should be set to RadioConst:VALUE_UNAVAILABLE to mark them as invalid. + * @deprecated Legacy CDMA is unsupported. */ EvdoSignalStrength evdo; /** diff --git a/radio/aidl/android/hardware/radio/network/SignalThresholdInfo.aidl b/radio/aidl/android/hardware/radio/network/SignalThresholdInfo.aidl index 393388936ac2babee39ec8c8dce245543a15a244..1305a2c484e04d1878557513c34aeb6aced74559 100644 --- a/radio/aidl/android/hardware/radio/network/SignalThresholdInfo.aidl +++ b/radio/aidl/android/hardware/radio/network/SignalThresholdInfo.aidl @@ -29,7 +29,7 @@ parcelable SignalThresholdInfo { /** * Received Signal Strength Indication. * Range: -113 dBm and -51 dBm - * Used RAN: GERAN, CDMA2000 + * Used RAN: GERAN * Reference: 3GPP TS 27.007 section 8.5. */ const int SIGNAL_MEASUREMENT_TYPE_RSSI = 1; diff --git a/radio/aidl/android/hardware/radio/sim/CardStatus.aidl b/radio/aidl/android/hardware/radio/sim/CardStatus.aidl index 90aa8e06816362faa30b0a48f7dd32eee0c46cf7..7321b368d87d2c78bcda4043dbc995392bd8160f 100644 --- a/radio/aidl/android/hardware/radio/sim/CardStatus.aidl +++ b/radio/aidl/android/hardware/radio/sim/CardStatus.aidl @@ -54,7 +54,8 @@ parcelable CardStatus { */ int gsmUmtsSubscriptionAppIndex; /** - * Value < RadioConst:CARD_MAX_APPS, -1 if none + * Value ignored. + * @deprecated Legacy CDMA is unsupported. */ int cdmaSubscriptionAppIndex; /** diff --git a/radio/aidl/android/hardware/radio/sim/CdmaSubscriptionSource.aidl b/radio/aidl/android/hardware/radio/sim/CdmaSubscriptionSource.aidl index 4c6c1efbbe65d9cdd9adee131b5b9dde2c2eb87e..2dbd6a800fa54e4019d81c26a35c236508e8d768 100644 --- a/radio/aidl/android/hardware/radio/sim/CdmaSubscriptionSource.aidl +++ b/radio/aidl/android/hardware/radio/sim/CdmaSubscriptionSource.aidl @@ -21,6 +21,8 @@ package android.hardware.radio.sim; @Backing(type="int") @JavaDerive(toString=true) enum CdmaSubscriptionSource { + /** @deprecated Legacy CDMA is unsupported. */ RUIM_SIM, + /** @deprecated Legacy CDMA is unsupported. */ NV, } diff --git a/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl b/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl index 1e010b90be19e4a6d462a523bda334d021556f23..24c732069f15ee70dbd98bedc2e3fe352b8b8134 100644 --- a/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl +++ b/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl @@ -123,6 +123,8 @@ oneway interface IRadioSim { * Response function is IRadioSimResponse.getCdmaSubscriptionResponse() * * This is available when android.hardware.telephony.cdma is defined. + * + * @deprecated Legacy CDMA is unsupported. */ void getCdmaSubscription(in int serial); @@ -134,6 +136,8 @@ oneway interface IRadioSim { * Response function is IRadioSimResponse.getCdmaSubscriptionSourceResponse() * * This is available when android.hardware.telephony.cdma is defined. + * + * @deprecated Legacy CDMA is unsupported. */ void getCdmaSubscriptionSource(in int serial); @@ -255,7 +259,7 @@ oneway interface IRadioSim { /** * Request APDU exchange on the basic channel. This command reflects TS 27.007 - * "generic SIM access" operation (+CSIM). The modem must ensure proper function of GSM/CDMA, + * "generic SIM access" operation (+CSIM). The modem must ensure proper function of GSM, * and filter commands appropriately. It must filter channel management and SELECT by DF * name commands. "sessionId" field is always 0 (for aid="") and may be ignored. * @@ -406,6 +410,8 @@ oneway interface IRadioSim { * Response function is IRadioSimResponse.setCdmaSubscriptionSourceResponse() * * This is available when android.hardware.telephony.cdma is defined. + * + * @deprecated Legacy CDMA is unsupported. */ void setCdmaSubscriptionSource(in int serial, in CdmaSubscriptionSource cdmaSub); diff --git a/radio/aidl/android/hardware/radio/sim/IRadioSimIndication.aidl b/radio/aidl/android/hardware/radio/sim/IRadioSimIndication.aidl index fc6355d42559f98be515a78363a73d4208a9c7f5..d9735d3fb21a29016323eecf1af9244892660af2 100644 --- a/radio/aidl/android/hardware/radio/sim/IRadioSimIndication.aidl +++ b/radio/aidl/android/hardware/radio/sim/IRadioSimIndication.aidl @@ -41,6 +41,7 @@ oneway interface IRadioSimIndication { * * @param type Type of radio indication * @param cdmaSource New CdmaSubscriptionSource + * @deprecated Legacy CDMA is unsupported. */ void cdmaSubscriptionSourceChanged( in RadioIndicationType type, in CdmaSubscriptionSource cdmaSource); diff --git a/radio/aidl/android/hardware/radio/sim/IRadioSimResponse.aidl b/radio/aidl/android/hardware/radio/sim/IRadioSimResponse.aidl index cf08bada7f35eede1487eeefdf1a6f9eafdbbe25..92815d2ac17cf303033a2d5f67d611c126226754 100644 --- a/radio/aidl/android/hardware/radio/sim/IRadioSimResponse.aidl +++ b/radio/aidl/android/hardware/radio/sim/IRadioSimResponse.aidl @@ -145,6 +145,7 @@ oneway interface IRadioSimResponse { * RadioError:NO_RESOURCES * RadioError:CANCELLED * RadioError:SIM_ABSENT + * @deprecated Legacy CDMA is unsupported. */ void getCdmaSubscriptionResponse(in RadioResponseInfo info, in String mdn, in String hSid, in String hNid, in String min, in String prl); @@ -163,6 +164,7 @@ oneway interface IRadioSimResponse { * RadioError:NO_RESOURCES * RadioError:CANCELLED * RadioError:SIM_ABSENT + * @deprecated Legacy CDMA is unsupported. */ void getCdmaSubscriptionSourceResponse( in RadioResponseInfo info, in CdmaSubscriptionSource source); @@ -381,6 +383,7 @@ oneway interface IRadioSimResponse { * RadioError:INVALID_MODEM_STATE * RadioError:SIM_ERR * RadioError:INVALID_ARGUMENTS + * RadioError:REQUEST_NOT_SUPPORTED */ void requestIccSimAuthenticationResponse(in RadioResponseInfo info, in IccIoResult result); @@ -483,6 +486,7 @@ oneway interface IRadioSimResponse { * RadioError:NO_MEMORY * RadioError:NO_RESOURCES * RadioError:CANCELLED + * @deprecated Legacy CDMA is unsupported. */ void setCdmaSubscriptionSourceResponse(in RadioResponseInfo info); diff --git a/radio/aidl/android/hardware/radio/voice/Call.aidl b/radio/aidl/android/hardware/radio/voice/Call.aidl index 9990f2810f07930302da248d7ece75a59eda0154..5f62faad1ceadae966238bd4f6b65a20793f3cc0 100644 --- a/radio/aidl/android/hardware/radio/voice/Call.aidl +++ b/radio/aidl/android/hardware/radio/voice/Call.aidl @@ -77,6 +77,7 @@ parcelable Call { boolean isVoice; /** * true if CDMA voice privacy mode is active + * @deprecated Legacy CDMA is unsupported. */ boolean isVoicePrivacy; /** diff --git a/radio/aidl/android/hardware/radio/voice/CdmaCallWaiting.aidl b/radio/aidl/android/hardware/radio/voice/CdmaCallWaiting.aidl index d97b3193d344237cf75ad5ce606e5c04e8248187..c77f3ec857da4a0ccfa6461d373aef21a47a7147 100644 --- a/radio/aidl/android/hardware/radio/voice/CdmaCallWaiting.aidl +++ b/radio/aidl/android/hardware/radio/voice/CdmaCallWaiting.aidl @@ -22,44 +22,64 @@ import android.hardware.radio.voice.CdmaSignalInfoRecord; @VintfStability @JavaDerive(toString=true) parcelable CdmaCallWaiting { + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_PLAN_UNKNOWN = 0; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_PLAN_ISDN = 1; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_PLAN_DATA = 3; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_PLAN_TELEX = 4; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_PLAN_NATIONAL = 8; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_PLAN_PRIVATE = 9; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_PRESENTATION_ALLOWED = 0; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_PRESENTATION_RESTRICTED = 1; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_PRESENTATION_UNKNOWN = 2; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_TYPE_UNKNOWN = 0; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_TYPE_INTERNATIONAL = 1; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_TYPE_NATIONAL = 2; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_TYPE_NETWORK_SPECIFIC = 3; + /** @deprecated Legacy CDMA is unsupported. */ const int NUMBER_TYPE_SUBSCRIBER = 4; /** * Remote party number + * @deprecated Legacy CDMA is unsupported. */ String number; /** * Values are NUMBER_PRESENTATION_ + * @deprecated Legacy CDMA is unsupported. */ int numberPresentation; /** * Remote party name + * @deprecated Legacy CDMA is unsupported. */ String name; + /** @deprecated Legacy CDMA is unsupported. */ CdmaSignalInfoRecord signalInfoRecord; /** * Required to support International Call Waiting * Values are NUMBER_TYPE_ + * @deprecated Legacy CDMA is unsupported. */ int numberType; /** * Required to support International Call Waiting * Values are NUMBER_PLAN_ + * @deprecated Legacy CDMA is unsupported. */ int numberPlan; } diff --git a/radio/aidl/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl b/radio/aidl/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl index 90b2715c80e7d544d94ae514949203e0748ecab4..bba6e4d6e813531eb046cd0e7d5325fe9519bf48 100644 --- a/radio/aidl/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl +++ b/radio/aidl/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl @@ -28,9 +28,11 @@ package android.hardware.radio.voice; @JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) parcelable CdmaDisplayInfoRecord { + /** @deprecated Legacy CDMA is unsupported. */ const int CDMA_ALPHA_INFO_BUFFER_LENGTH = 64; /** * Max length = CDMA_ALPHA_INFO_BUFFER_LENGTH + * @deprecated Legacy CDMA is unsupported. */ String alphaBuf; } diff --git a/radio/aidl/android/hardware/radio/voice/CdmaInformationRecord.aidl b/radio/aidl/android/hardware/radio/voice/CdmaInformationRecord.aidl index 19903c6431f244435fcccc573bcd90f3282ab78d..7232eba0b5d579022d20f7d78b4929e740b402d8 100644 --- a/radio/aidl/android/hardware/radio/voice/CdmaInformationRecord.aidl +++ b/radio/aidl/android/hardware/radio/voice/CdmaInformationRecord.aidl @@ -32,54 +32,74 @@ import android.hardware.radio.voice.CdmaT53ClirInfoRecord; @JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) parcelable CdmaInformationRecord { + /** @deprecated Legacy CDMA is unsupported. */ const int CDMA_MAX_NUMBER_OF_INFO_RECS = 10; /** * Names of the CDMA info records (C.S0005 section 3.7.5) + * @deprecated Legacy CDMA is unsupported. */ const int NAME_DISPLAY = 0; + /** @deprecated Legacy CDMA is unsupported. */ const int NAME_CALLED_PARTY_NUMBER = 1; + /** @deprecated Legacy CDMA is unsupported. */ const int NAME_CALLING_PARTY_NUMBER = 2; + /** @deprecated Legacy CDMA is unsupported. */ const int NAME_CONNECTED_NUMBER = 3; + /** @deprecated Legacy CDMA is unsupported. */ const int NAME_SIGNAL = 4; + /** @deprecated Legacy CDMA is unsupported. */ const int NAME_REDIRECTING_NUMBER = 5; + /** @deprecated Legacy CDMA is unsupported. */ const int NAME_LINE_CONTROL = 6; + /** @deprecated Legacy CDMA is unsupported. */ const int NAME_EXTENDED_DISPLAY = 7; + /** @deprecated Legacy CDMA is unsupported. */ const int NAME_T53_CLIR = 8; + /** @deprecated Legacy CDMA is unsupported. */ const int NAME_T53_RELEASE = 9; + /** @deprecated Legacy CDMA is unsupported. */ const int NAME_T53_AUDIO_CONTROL = 10; /** * Based on CdmaInfoRecName, only one of the below vectors must have size = 1. * All other vectors must have size 0. * Values are NAME_ + * @deprecated Legacy CDMA is unsupported. */ int name; /** * Display and extended display info rec + * @deprecated Legacy CDMA is unsupported. */ CdmaDisplayInfoRecord[] display; /** * Called party number, calling party number, connected number info rec + * @deprecated Legacy CDMA is unsupported. */ CdmaNumberInfoRecord[] number; /** * Signal info rec + * @deprecated Legacy CDMA is unsupported. */ CdmaSignalInfoRecord[] signal; /** * Redirecting number info rec + * @deprecated Legacy CDMA is unsupported. */ CdmaRedirectingNumberInfoRecord[] redir; /** * Line control info rec + * @deprecated Legacy CDMA is unsupported. */ CdmaLineControlInfoRecord[] lineCtrl; /** * T53 CLIR info rec + * @deprecated Legacy CDMA is unsupported. */ CdmaT53ClirInfoRecord[] clir; /** * T53 Audio Control info rec + * @deprecated Legacy CDMA is unsupported. */ CdmaT53AudioControlInfoRecord[] audioCtrl; } diff --git a/radio/aidl/android/hardware/radio/voice/CdmaLineControlInfoRecord.aidl b/radio/aidl/android/hardware/radio/voice/CdmaLineControlInfoRecord.aidl index 15c22a08b24e1a3adcc20fb1948a59c925e50431..9cf0103d9ec8d6cb7b5b49bea8a8764a48acecab 100644 --- a/radio/aidl/android/hardware/radio/voice/CdmaLineControlInfoRecord.aidl +++ b/radio/aidl/android/hardware/radio/voice/CdmaLineControlInfoRecord.aidl @@ -23,8 +23,12 @@ package android.hardware.radio.voice; @VintfStability @JavaDerive(toString=true) parcelable CdmaLineControlInfoRecord { + /** @deprecated Legacy CDMA is unsupported. */ byte lineCtrlPolarityIncluded; + /** @deprecated Legacy CDMA is unsupported. */ byte lineCtrlToggle; + /** @deprecated Legacy CDMA is unsupported. */ byte lineCtrlReverse; + /** @deprecated Legacy CDMA is unsupported. */ byte lineCtrlPowerDenial; } diff --git a/radio/aidl/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl b/radio/aidl/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl index 3a00cae8634693f0ff10b1bc2793137649a3e788..bc00acbd77a15f49a1688a15002fae07f37cbb18 100644 --- a/radio/aidl/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl +++ b/radio/aidl/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl @@ -26,13 +26,19 @@ package android.hardware.radio.voice; @JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) parcelable CdmaNumberInfoRecord { + /** @deprecated Legacy CDMA is unsupported. */ const int CDMA_NUMBER_INFO_BUFFER_LENGTH = 81; /** * Max length = CDMA_NUMBER_INFO_BUFFER_LENGTH + * @deprecated Legacy CDMA is unsupported. */ String number; + /** @deprecated Legacy CDMA is unsupported. */ byte numberType; + /** @deprecated Legacy CDMA is unsupported. */ byte numberPlan; + /** @deprecated Legacy CDMA is unsupported. */ byte pi; + /** @deprecated Legacy CDMA is unsupported. */ byte si; } diff --git a/radio/aidl/android/hardware/radio/voice/CdmaOtaProvisionStatus.aidl b/radio/aidl/android/hardware/radio/voice/CdmaOtaProvisionStatus.aidl index b6444abab29e7034184b92a41da35dbbcde21168..1f003a8111b79b4f4b69bb099fb2c7f82cf3c813 100644 --- a/radio/aidl/android/hardware/radio/voice/CdmaOtaProvisionStatus.aidl +++ b/radio/aidl/android/hardware/radio/voice/CdmaOtaProvisionStatus.aidl @@ -21,16 +21,28 @@ package android.hardware.radio.voice; @Backing(type="int") @JavaDerive(toString=true) enum CdmaOtaProvisionStatus { + /** @deprecated Legacy CDMA is unsupported. */ SPL_UNLOCKED, + /** @deprecated Legacy CDMA is unsupported. */ SPC_RETRIES_EXCEEDED, + /** @deprecated Legacy CDMA is unsupported. */ A_KEY_EXCHANGED, + /** @deprecated Legacy CDMA is unsupported. */ SSD_UPDATED, + /** @deprecated Legacy CDMA is unsupported. */ NAM_DOWNLOADED, + /** @deprecated Legacy CDMA is unsupported. */ MDN_DOWNLOADED, + /** @deprecated Legacy CDMA is unsupported. */ IMSI_DOWNLOADED, + /** @deprecated Legacy CDMA is unsupported. */ PRL_DOWNLOADED, + /** @deprecated Legacy CDMA is unsupported. */ COMMITTED, + /** @deprecated Legacy CDMA is unsupported. */ OTAPA_STARTED, + /** @deprecated Legacy CDMA is unsupported. */ OTAPA_STOPPED, + /** @deprecated Legacy CDMA is unsupported. */ OTAPA_ABORTED, } diff --git a/radio/aidl/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl b/radio/aidl/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl index cb30da84a13bb68c7de125a902f9c2e776c1702a..514b8e12c27598355e374e3f5128b2f833904399 100644 --- a/radio/aidl/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl +++ b/radio/aidl/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl @@ -25,19 +25,28 @@ import android.hardware.radio.voice.CdmaNumberInfoRecord; parcelable CdmaRedirectingNumberInfoRecord { /** * Redirecting Number Information Record as defined in C.S0005 section 3.7.5.11 + * @deprecated Legacy CDMA is unsupported. */ const int REDIRECTING_REASON_UNKNOWN = 0; + /** @deprecated Legacy CDMA is unsupported. */ const int REDIRECTING_REASON_CALL_FORWARDING_BUSY = 1; + /** @deprecated Legacy CDMA is unsupported. */ const int REDIRECTING_REASON_CALL_FORWARDING_NO_REPLY = 2; + /** @deprecated Legacy CDMA is unsupported. */ const int REDIRECTING_REASON_CALLED_DTE_OUT_OF_ORDER = 9; + /** @deprecated Legacy CDMA is unsupported. */ const int REDIRECTING_REASON_CALL_FORWARDING_BY_THE_CALLED_DTE = 10; + /** @deprecated Legacy CDMA is unsupported. */ const int REDIRECTING_REASON_CALL_FORWARDING_UNCONDITIONAL = 15; + /** @deprecated Legacy CDMA is unsupported. */ const int REDIRECTING_REASON_RESERVED = 16; + /** @deprecated Legacy CDMA is unsupported. */ CdmaNumberInfoRecord redirectingNumber; /** * Set to UNKNOWN if not included. * Values are REDIRECTING_REASON_ + * @deprecated Legacy CDMA is unsupported. */ int redirectingReason; } diff --git a/radio/aidl/android/hardware/radio/voice/CdmaSignalInfoRecord.aidl b/radio/aidl/android/hardware/radio/voice/CdmaSignalInfoRecord.aidl index 4302ba48a268d59efdbadd7214e949c003799ca8..2ada10b3f875235fce2e82e569ace8be4caea446 100644 --- a/radio/aidl/android/hardware/radio/voice/CdmaSignalInfoRecord.aidl +++ b/radio/aidl/android/hardware/radio/voice/CdmaSignalInfoRecord.aidl @@ -25,18 +25,22 @@ package android.hardware.radio.voice; parcelable CdmaSignalInfoRecord { /** * True if signal information record is present + * @deprecated Legacy CDMA is unsupported. */ boolean isPresent; /** * Defined in 3.7.5.5-1 + * @deprecated Legacy CDMA is unsupported. */ byte signalType; /** * Defined in 3.7.5.5-2 + * @deprecated Legacy CDMA is unsupported. */ byte alertPitch; /** * Defined in 3.7.5.5-3, 3.7.5.5-4 or 3.7.5.5-5 + * @deprecated Legacy CDMA is unsupported. */ byte signal; } diff --git a/radio/aidl/android/hardware/radio/voice/CdmaT53AudioControlInfoRecord.aidl b/radio/aidl/android/hardware/radio/voice/CdmaT53AudioControlInfoRecord.aidl index 44ac2b4320e8fc92f71b94e12a9a9e93962c1bdf..68b19b85cd19da35eab5cad1f1709f75549fbbcc 100644 --- a/radio/aidl/android/hardware/radio/voice/CdmaT53AudioControlInfoRecord.aidl +++ b/radio/aidl/android/hardware/radio/voice/CdmaT53AudioControlInfoRecord.aidl @@ -23,6 +23,8 @@ package android.hardware.radio.voice; @VintfStability @JavaDerive(toString=true) parcelable CdmaT53AudioControlInfoRecord { + /** @deprecated Legacy CDMA is unsupported. */ byte upLink; + /** @deprecated Legacy CDMA is unsupported. */ byte downLink; } diff --git a/radio/aidl/android/hardware/radio/voice/CdmaT53ClirInfoRecord.aidl b/radio/aidl/android/hardware/radio/voice/CdmaT53ClirInfoRecord.aidl index 564d7614b4c81b1ae633e2eb5f568f60c9ae96eb..6a1b99249e712eca5ae5a7d0fafe6d989c69d31f 100644 --- a/radio/aidl/android/hardware/radio/voice/CdmaT53ClirInfoRecord.aidl +++ b/radio/aidl/android/hardware/radio/voice/CdmaT53ClirInfoRecord.aidl @@ -23,5 +23,6 @@ package android.hardware.radio.voice; @VintfStability @JavaDerive(toString=true) parcelable CdmaT53ClirInfoRecord { + /** @deprecated Legacy CDMA is unsupported. */ byte cause; } diff --git a/radio/aidl/android/hardware/radio/voice/IRadioVoice.aidl b/radio/aidl/android/hardware/radio/voice/IRadioVoice.aidl index 0c2b51d2aa48d8f85d712409691328ae395ff965..74b1d5f9dccb395ace72660afc34bc6bf05553ff 100644 --- a/radio/aidl/android/hardware/radio/voice/IRadioVoice.aidl +++ b/radio/aidl/android/hardware/radio/voice/IRadioVoice.aidl @@ -369,6 +369,8 @@ oneway interface IRadioVoice { * Response function is IRadioVoiceResponse.sendCdmaFeatureCodeResponse() * * This is available when android.hardware.telephony.cdma is defined. + * + * @deprecated Legacy CDMA is unsupported. */ void sendCdmaFeatureCode(in int serial, in String featureCode); diff --git a/radio/aidl/android/hardware/radio/voice/IRadioVoiceIndication.aidl b/radio/aidl/android/hardware/radio/voice/IRadioVoiceIndication.aidl index 9de6364546270961f570292940ea28f64daa6d74..f8bd999a7ca5a885db7b91431a67b51d79a30da0 100644 --- a/radio/aidl/android/hardware/radio/voice/IRadioVoiceIndication.aidl +++ b/radio/aidl/android/hardware/radio/voice/IRadioVoiceIndication.aidl @@ -42,8 +42,8 @@ oneway interface IRadioVoiceIndication { * value of 3000 (3 seconds) if absent. * * @param type Type of radio indication - * @param isGsm true for GSM & false for CDMA - * @param record Cdma Signal Information + * @param isGsm Always true (Legacy CDMA is unsupported) + * @param record Always empty (Legacy CDMA is unsupported) */ void callRing(in RadioIndicationType type, in boolean isGsm, in CdmaSignalInfoRecord record); @@ -62,6 +62,7 @@ oneway interface IRadioVoiceIndication { * * @param type Type of radio indication * @param callWaitingRecord Cdma CallWaiting information + * @deprecated Legacy CDMA is unsupported. */ void cdmaCallWaiting(in RadioIndicationType type, in CdmaCallWaiting callWaitingRecord); @@ -71,6 +72,7 @@ oneway interface IRadioVoiceIndication { * @param type Type of radio indication * @param records New CDMA information records. * Max length is RadioConst:CDMA_MAX_NUMBER_OF_INFO_RECS + * @deprecated Legacy CDMA is unsupported. */ void cdmaInfoRec(in RadioIndicationType type, in CdmaInformationRecord[] records); @@ -79,6 +81,7 @@ oneway interface IRadioVoiceIndication { * * @param type Type of radio indication * @param status Cdma OTA provision status + * @deprecated Legacy CDMA is unsupported. */ void cdmaOtaProvisionStatus(in RadioIndicationType type, in CdmaOtaProvisionStatus status); diff --git a/radio/aidl/android/hardware/radio/voice/IRadioVoiceResponse.aidl b/radio/aidl/android/hardware/radio/voice/IRadioVoiceResponse.aidl index a904eaab439aaba25de122e29c91effe6495f9ae..cf36ef9d6b0b99641b4fb8ae16a173209781b4e3 100644 --- a/radio/aidl/android/hardware/radio/voice/IRadioVoiceResponse.aidl +++ b/radio/aidl/android/hardware/radio/voice/IRadioVoiceResponse.aidl @@ -564,6 +564,7 @@ oneway interface IRadioVoiceResponse { * RadioError:NO_RESOURCES * RadioError:CANCELLED * RadioError:OPERATION_NOT_ALLOWED + * @deprecated Legacy CDMA is unsupported. */ void sendCdmaFeatureCodeResponse(in RadioResponseInfo info); diff --git a/radio/aidl/android/hardware/radio/voice/LastCallFailCause.aidl b/radio/aidl/android/hardware/radio/voice/LastCallFailCause.aidl index 7737e94dd1de5b11376a737207a741e923d52fed..f6f4585722fdf74260afe918c9dafa969c656f2d 100644 --- a/radio/aidl/android/hardware/radio/voice/LastCallFailCause.aidl +++ b/radio/aidl/android/hardware/radio/voice/LastCallFailCause.aidl @@ -142,18 +142,28 @@ enum LastCallFailCause { * Explicit network detach */ NETWORK_DETACH = 261, + /** @deprecated Legacy CDMA is unsupported. */ CDMA_LOCKED_UNTIL_POWER_CYCLE = 1000, + /** @deprecated Legacy CDMA is unsupported. */ CDMA_DROP = 1001, + /** @deprecated Legacy CDMA is unsupported. */ CDMA_INTERCEPT = 1002, + /** @deprecated Legacy CDMA is unsupported. */ CDMA_REORDER = 1003, + /** @deprecated Legacy CDMA is unsupported. */ CDMA_SO_REJECT = 1004, + /** @deprecated Legacy CDMA is unsupported. */ CDMA_RETRY_ORDER = 1005, + /** @deprecated Legacy CDMA is unsupported. */ CDMA_ACCESS_FAILURE = 1006, + /** @deprecated Legacy CDMA is unsupported. */ CDMA_PREEMPTED = 1007, /** * For non-emergency number dialed during emergency callback mode + * @deprecated Legacy CDMA is unsupported. */ CDMA_NOT_EMERGENCY = 1008, + /** @deprecated Legacy CDMA is unsupported. */ CDMA_ACCESS_BLOCKED = 1009, /** * OEM specific error codes. Used to distinguish error from diff --git a/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp b/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp index 837c62656a95db54338f09039acbb71f65e2e7fc..3834eccbfb9399f7b625f018a76a196b9c8bfdbb 100644 --- a/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp +++ b/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp @@ -109,4 +109,19 @@ ScopedAStatus RadioConfig::setSimSlotsMapping( // return ok(); } +ScopedAStatus RadioConfig::getSimTypeInfo(int32_t serial) { + LOG_CALL << serial; + LOG(ERROR) << " getSimTypeInfo is unsupported by HIDL HALs"; + respond()->getSimTypeInfoResponse(notSupported(serial), {}); + return ok(); +} + +ScopedAStatus RadioConfig::setSimType( + int32_t serial, const std::vector& /*simTypes*/) { + LOG_CALL << serial; + LOG(ERROR) << " setSimType is unsupported by HIDL HALs"; + respond()->setSimTypeResponse(notSupported(serial)); + return ok(); +} + } // namespace android::hardware::radio::compat diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfig.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfig.h index 17d59858a4a0d8470e2807a7953a7f82c7abb2bd..a1e48dcaff2f1d0ab3aae751b9a4d05648b4c064 100644 --- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfig.h +++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfig.h @@ -55,7 +55,11 @@ class RadioConfig : public aidl::android::hardware::radio::config::BnRadioConfig int32_t serial, const std::vector& slotMap) override; - + ::ndk::ScopedAStatus getSimTypeInfo(int32_t serial) override; + ::ndk::ScopedAStatus setSimType( + int32_t serial, + const std::vector& simTypes) + override; protected: std::shared_ptr<::aidl::android::hardware::radio::config::IRadioConfigResponse> respond(); diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h index 56724ae7335c6ecd771476a17bd26e0221f693e6..c9a32706dafa442c7fed06036395020de1df2bf7 100644 --- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h +++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h @@ -114,6 +114,13 @@ class RadioNetwork : public RadioCompatBase, ::ndk::ScopedAStatus setSecurityAlgorithmsUpdatedEnabled(int32_t serial, bool enabled) override; ::ndk::ScopedAStatus isSecurityAlgorithmsUpdatedEnabled(int32_t serial) override; + ::ndk::ScopedAStatus setSatellitePlmn( + int32_t serial, int32_t simSlot, const std::vector& carrierPlmnArray, + const std::vector& allSatellitePlmnArray) override; + ::ndk::ScopedAStatus setSatelliteEnabledForCarrier(int32_t serial, int32_t simSlot, + bool satelliteEnabled) override; + ::ndk::ScopedAStatus isSatelliteEnabledForCarrier(int32_t serial, int32_t simSlot) override; + protected: std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkResponse> respond(); diff --git a/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp b/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp index 1e4378961635e633826eb008853f23a8b90db069..b5aee5c0854b9b50a37120d38e0ed362f5a405da 100644 --- a/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp +++ b/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp @@ -402,4 +402,28 @@ ScopedAStatus RadioNetwork::setSecurityAlgorithmsUpdatedEnabled(int32_t serial, return ok(); } +ScopedAStatus RadioNetwork::setSatellitePlmn( + int32_t serial, int32_t /*simSlot*/, const std::vector& /*carrierPlmnArray*/, + const std::vector& /*allSatellitePlmnArray*/) { + LOG_CALL << serial; + LOG(ERROR) << " setSatellitePlmn is unsupported by HIDL HALs"; + respond()->setSatellitePlmnResponse(notSupported(serial)); + return ok(); +} + +ScopedAStatus RadioNetwork::setSatelliteEnabledForCarrier(int32_t serial, int32_t /*simSlot*/, + bool /*enable*/) { + LOG_CALL << serial; + LOG(ERROR) << " setSatelliteEnabledForCarrier is unsupported by HIDL HALs"; + respond()->setSatelliteEnabledForCarrierResponse(notSupported(serial)); + return ok(); +} + +ScopedAStatus RadioNetwork::isSatelliteEnabledForCarrier(int32_t serial, int32_t /*simSlot*/) { + LOG_CALL << serial; + LOG(ERROR) << " isSatelliteEnabledForCarrier is unsupported by HIDL HALs"; + respond()->isSatelliteEnabledForCarrierResponse(notSupported(serial), false); + return ok(); +} + } // namespace android::hardware::radio::compat diff --git a/radio/aidl/vts/radio_config_response.cpp b/radio/aidl/vts/radio_config_response.cpp index c532440dcc3ceece8002b6408fb20a2cc1437ec8..49439fa3a2a5715237976bbd88c90329132bddf8 100644 --- a/radio/aidl/vts/radio_config_response.cpp +++ b/radio/aidl/vts/radio_config_response.cpp @@ -75,3 +75,17 @@ ndk::ScopedAStatus RadioConfigResponse::getHalDeviceCapabilitiesResponse( parent_config.notify(info.serial); return ndk::ScopedAStatus::ok(); } + +ndk::ScopedAStatus RadioConfigResponse::getSimTypeInfoResponse(const RadioResponseInfo& info, + const std::vector& /* simTypeInfo */) { + rspInfo = info; + parent_config.notify(info.serial); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus RadioConfigResponse::setSimTypeResponse(const RadioResponseInfo& info) { + rspInfo = info; + parent_config.notify(info.serial); + return ndk::ScopedAStatus::ok(); +} + diff --git a/radio/aidl/vts/radio_config_utils.h b/radio/aidl/vts/radio_config_utils.h index 84c74fcec7a25f5ae9d125db5ac5724b6cda64ca..cdcc1bcdb3594a5d7e881737863b235a22647ec1 100644 --- a/radio/aidl/vts/radio_config_utils.h +++ b/radio/aidl/vts/radio_config_utils.h @@ -62,6 +62,11 @@ class RadioConfigResponse : public BnRadioConfigResponse { virtual ndk::ScopedAStatus getHalDeviceCapabilitiesResponse( const RadioResponseInfo& info, bool modemReducedFeatureSet1) override; + + virtual ndk::ScopedAStatus getSimTypeInfoResponse( + const RadioResponseInfo& info, const std::vector& simTypeInfo) override; + + virtual ndk::ScopedAStatus setSimTypeResponse(const RadioResponseInfo& info) override; }; /* Callback class for radio config indication */ diff --git a/radio/aidl/vts/radio_network_response.cpp b/radio/aidl/vts/radio_network_response.cpp index 4d452d0c786eefcc593e3a2c9c618687c54e4b29..df59687ad2e0a21dcf2dcbbe6d42f745c00f6b2e 100644 --- a/radio/aidl/vts/radio_network_response.cpp +++ b/radio/aidl/vts/radio_network_response.cpp @@ -350,3 +350,24 @@ ndk::ScopedAStatus RadioNetworkResponse::isSecurityAlgorithmsUpdatedEnabledRespo parent_network.notify(info.serial); return ndk::ScopedAStatus::ok(); } + +ndk::ScopedAStatus RadioNetworkResponse::setSatellitePlmnResponse(const RadioResponseInfo& info) { + rspInfo = info; + parent_network.notify(info.serial); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus RadioNetworkResponse::setSatelliteEnabledForCarrierResponse( + const RadioResponseInfo& info) { + rspInfo = info; + parent_network.notify(info.serial); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus RadioNetworkResponse::isSatelliteEnabledForCarrierResponse( + const RadioResponseInfo& info, bool enabled) { + rspInfo = info; + this->isSatelliteEnabledForCarrier = enabled; + parent_network.notify(info.serial); + return ndk::ScopedAStatus::ok(); +} diff --git a/radio/aidl/vts/radio_network_test.cpp b/radio/aidl/vts/radio_network_test.cpp index 914cad0cd2402fac1b85fa9731dc7d04a881962f..1778c3fb144b4c063c823963fc6801d9b87f7b44 100644 --- a/radio/aidl/vts/radio_network_test.cpp +++ b/radio/aidl/vts/radio_network_test.cpp @@ -609,6 +609,11 @@ TEST_P(RadioNetworkTest, setSignalStrengthReportingCriteria_Cdma2000) { } } + if (!deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) { + GTEST_SKIP() << "Skipping setSignalStrengthReportingCriteria_Cdma2000 " + "due to undefined FEATURE_TELEPHONY_CDMA"; + } + serial = GetRandomSerialNumber(); SignalThresholdInfo signalThresholdInfo; @@ -824,9 +829,12 @@ TEST_P(RadioNetworkTest, setSignalStrengthReportingCriteria_multiRansPerRequest) signalThresholdInfoNgran.isEnabled = true; signalThresholdInfoNgran.ran = AccessNetwork::NGRAN; - const static std::vector candidateSignalThresholdInfos = { + std::vector candidateSignalThresholdInfos = { signalThresholdInfoGeran, signalThresholdInfoUtran, signalThresholdInfoEutran, - signalThresholdInfoCdma2000, signalThresholdInfoNgran}; + signalThresholdInfoNgran}; + if (deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) { + candidateSignalThresholdInfos.push_back(signalThresholdInfoCdma2000); + } std::vector supportedSignalThresholdInfos; for (size_t i = 0; i < candidateSignalThresholdInfos.size(); i++) { @@ -2606,3 +2614,82 @@ TEST_P(RadioNetworkTest, isSecurityAlgorithmsUpdatedEnabled) { {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR, RadioError::REQUEST_NOT_SUPPORTED})); } + +/* + * Test IRadioNetwork.setSatellitePlmn for the response returned. + */ +TEST_P(RadioNetworkTest, setSatellitePlmn) { + int32_t aidl_version; + ndk::ScopedAStatus aidl_status = radio_network->getInterfaceVersion(&aidl_version); + ASSERT_OK(aidl_status); + if (aidl_version < 4) { + ALOGI("Skipped the test since" + " setSatellitePlmn is not supported on version < 4"); + GTEST_SKIP(); + } + + serial = GetRandomSerialNumber(); + radio_network->setSatellitePlmn(serial, 0, {"123456"}, {"123456, 3456789"}); + 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::RADIO_NOT_AVAILABLE, + RadioError::MODEM_ERR, RadioError::REQUEST_NOT_SUPPORTED})); +} + +/* + * Test IRadioNetwork.setSatelliteEnabledForCarrier for the response returned. + */ +TEST_P(RadioNetworkTest, setSatelliteEnabledForCarrier) { + int32_t aidl_version; + ndk::ScopedAStatus aidl_status = radio_network->getInterfaceVersion(&aidl_version); + ASSERT_OK(aidl_status); + if (aidl_version < 4) { + ALOGI("Skipped the test since" + " setSatelliteEnabledForCarrier is not supported on version < 4"); + GTEST_SKIP(); + } + + // Get current value + serial = GetRandomSerialNumber(); + radio_network->isSatelliteEnabledForCarrier(serial, 0); + EXPECT_EQ(std::cv_status::no_timeout, wait()); + bool originalSatelliteEnabledSetting = radioRsp_network->isSatelliteEnabledForCarrier; + + // We want to test flipping the value, so we are going to set it to the opposite of what + // the existing setting is. The test for isSatelliteEnabledForCarrier should check + // for the right default value. + bool valueToSet = !originalSatelliteEnabledSetting; + serial = GetRandomSerialNumber(); + radio_network->setSatelliteEnabledForCarrier(serial, 0, valueToSet); + 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::RADIO_NOT_AVAILABLE, + RadioError::MODEM_ERR, RadioError::REQUEST_NOT_SUPPORTED})); + + if (radioRsp_network->rspInfo.error == RadioError::NONE) { + // Assert the value has changed + serial = GetRandomSerialNumber(); + ndk::ScopedAStatus res = radio_network->isSatelliteEnabledForCarrier(serial, 0); + + ASSERT_OK(res); + 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::RADIO_NOT_AVAILABLE, + RadioError::MODEM_ERR, RadioError::REQUEST_NOT_SUPPORTED})); + EXPECT_EQ(valueToSet, radioRsp_network->isSatelliteEnabledForCarrier); + + // Reset original state + radio_network->setSatelliteEnabledForCarrier(serial, 0, originalSatelliteEnabledSetting); + EXPECT_EQ(std::cv_status::no_timeout, wait()); + EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type); + EXPECT_EQ(serial, radioRsp_network->rspInfo.serial); + } +} diff --git a/radio/aidl/vts/radio_network_utils.h b/radio/aidl/vts/radio_network_utils.h index ad530eb36bd98278eef332d300a6161785dda141..17c089673ba72c388c204fda96f375d6c15a32fe 100644 --- a/radio/aidl/vts/radio_network_utils.h +++ b/radio/aidl/vts/radio_network_utils.h @@ -48,6 +48,7 @@ class RadioNetworkResponse : public BnRadioNetworkResponse { std::vector specifiers; bool isCellularIdentifierTransparencyEnabled = false; bool isSecurityAlgorithmsUpdatedEnabled = false; + bool isSatelliteEnabledForCarrier = false; virtual ndk::ScopedAStatus acknowledgeRequest(int32_t serial) override; @@ -183,6 +184,14 @@ class RadioNetworkResponse : public BnRadioNetworkResponse { virtual ndk::ScopedAStatus setSecurityAlgorithmsUpdatedEnabledResponse( const RadioResponseInfo& info) override; + + virtual ndk::ScopedAStatus setSatellitePlmnResponse(const RadioResponseInfo& info) override; + + virtual ndk::ScopedAStatus setSatelliteEnabledForCarrierResponse( + const RadioResponseInfo& info) override; + + virtual ndk::ScopedAStatus isSatelliteEnabledForCarrierResponse(const RadioResponseInfo& info, + bool isEnabled) override; }; /* Callback class for radio network indication */ diff --git a/sensors/aidl/Android.bp b/sensors/aidl/Android.bp index 8877e6eaa3f4e1bd9353dcc9d03021d5001e4436..63ace909184e677021846010c7f30cf91b60f703 100644 --- a/sensors/aidl/Android.bp +++ b/sensors/aidl/Android.bp @@ -43,6 +43,6 @@ aidl_interface { }, ], - frozen: true, + frozen: false, } diff --git a/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/AdditionalInfo.aidl b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/AdditionalInfo.aidl index 518472305de74f121e7aae5c1b8809590b9ef6ff..a35b54ca385fac81a07d8650000e6e480ee354ba 100644 --- a/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/AdditionalInfo.aidl +++ b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/AdditionalInfo.aidl @@ -54,23 +54,23 @@ parcelable AdditionalInfo { enum AdditionalInfoType { AINFO_BEGIN = 0, AINFO_END = 1, - AINFO_UNTRACKED_DELAY = 65536, - AINFO_INTERNAL_TEMPERATURE = 65537, - AINFO_VEC3_CALIBRATION = 65538, - AINFO_SENSOR_PLACEMENT = 65539, - AINFO_SAMPLING = 65540, - AINFO_CHANNEL_NOISE = 131072, - AINFO_CHANNEL_SAMPLER = 131073, - AINFO_CHANNEL_FILTER = 131074, - AINFO_CHANNEL_LINEAR_TRANSFORM = 131075, - AINFO_CHANNEL_NONLINEAR_MAP = 131076, - AINFO_CHANNEL_RESAMPLER = 131077, - AINFO_LOCAL_GEOMAGNETIC_FIELD = 196608, - AINFO_LOCAL_GRAVITY = 196609, - AINFO_DOCK_STATE = 196610, - AINFO_HIGH_PERFORMANCE_MODE = 196611, - AINFO_MAGNETIC_FIELD_CALIBRATION = 196612, - AINFO_CUSTOM_START = 268435456, - AINFO_DEBUGGING_START = 1073741824, + AINFO_UNTRACKED_DELAY = 0x10000, + AINFO_INTERNAL_TEMPERATURE, + AINFO_VEC3_CALIBRATION, + AINFO_SENSOR_PLACEMENT, + AINFO_SAMPLING, + AINFO_CHANNEL_NOISE = 0x20000, + AINFO_CHANNEL_SAMPLER, + AINFO_CHANNEL_FILTER, + AINFO_CHANNEL_LINEAR_TRANSFORM, + AINFO_CHANNEL_NONLINEAR_MAP, + AINFO_CHANNEL_RESAMPLER, + AINFO_LOCAL_GEOMAGNETIC_FIELD = 0x30000, + AINFO_LOCAL_GRAVITY, + AINFO_DOCK_STATE, + AINFO_HIGH_PERFORMANCE_MODE, + AINFO_MAGNETIC_FIELD_CALIBRATION, + AINFO_CUSTOM_START = 0x10000000, + AINFO_DEBUGGING_START = 0x40000000, } } diff --git a/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/ISensors.aidl b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/ISensors.aidl index b26040b56d5290cf7c8e095899d5b8348921f338..0566a64c3cca537a71b9adfb9e91e5f42d00b4d9 100644 --- a/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/ISensors.aidl +++ b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/ISensors.aidl @@ -44,28 +44,28 @@ interface ISensors { int registerDirectChannel(in android.hardware.sensors.ISensors.SharedMemInfo mem); void setOperationMode(in android.hardware.sensors.ISensors.OperationMode mode); void unregisterDirectChannel(in int channelHandle); - const int ERROR_NO_MEMORY = -12; - const int ERROR_BAD_VALUE = -22; + const int ERROR_NO_MEMORY = (-12) /* -12 */; + const int ERROR_BAD_VALUE = (-22) /* -22 */; const int WAKE_LOCK_TIMEOUT_SECONDS = 1; - const int EVENT_QUEUE_FLAG_BITS_READ_AND_PROCESS = 1; - const int EVENT_QUEUE_FLAG_BITS_EVENTS_READ = 2; - const int WAKE_LOCK_QUEUE_FLAG_BITS_DATA_WRITTEN = 1; - const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_FIELD = 0; - const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_REPORT_TOKEN = 4; - const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_SENSOR_TYPE = 8; - const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_ATOMIC_COUNTER = 12; - const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_TIMESTAMP = 16; - const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_DATA = 24; - const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_RESERVED = 88; + const int EVENT_QUEUE_FLAG_BITS_READ_AND_PROCESS = (1 << 0) /* 1 */; + const int EVENT_QUEUE_FLAG_BITS_EVENTS_READ = (1 << 1) /* 2 */; + const int WAKE_LOCK_QUEUE_FLAG_BITS_DATA_WRITTEN = (1 << 0) /* 1 */; + const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_FIELD = 0x0; + const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_REPORT_TOKEN = 0x4; + const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_SENSOR_TYPE = 0x8; + const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_ATOMIC_COUNTER = 0xC; + const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_TIMESTAMP = 0x10; + const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_DATA = 0x18; + const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_RESERVED = 0x58; const int DIRECT_REPORT_SENSOR_EVENT_TOTAL_LENGTH = 104; - const int RUNTIME_SENSORS_HANDLE_BASE = 1593835520; - const int RUNTIME_SENSORS_HANDLE_END = 1610612735; + const int RUNTIME_SENSORS_HANDLE_BASE = 0x5F000000; + const int RUNTIME_SENSORS_HANDLE_END = 0x5FFFFFFF; @Backing(type="int") @VintfStability enum RateLevel { - STOP = 0, - NORMAL = 1, - FAST = 2, - VERY_FAST = 3, + STOP, + NORMAL, + FAST, + VERY_FAST, } @Backing(type="int") @VintfStability enum OperationMode { @@ -85,7 +85,7 @@ interface ISensors { @Backing(type="int") @VintfStability enum SharedMemType { ASHMEM = 1, - GRALLOC = 2, + GRALLOC, } } } diff --git a/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorInfo.aidl b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorInfo.aidl index 996be3d4dbd4a85beba35dd5dac6e3ab5c31e8c1..677e6c4e39832a56d232569abaead287bce929e6 100644 --- a/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorInfo.aidl +++ b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorInfo.aidl @@ -54,14 +54,14 @@ parcelable SensorInfo { const int SENSOR_FLAG_BITS_ON_CHANGE_MODE = 2; const int SENSOR_FLAG_BITS_ONE_SHOT_MODE = 4; const int SENSOR_FLAG_BITS_SPECIAL_REPORTING_MODE = 6; - const int SENSOR_FLAG_BITS_DATA_INJECTION = 16; - const int SENSOR_FLAG_BITS_DYNAMIC_SENSOR = 32; - const int SENSOR_FLAG_BITS_ADDITIONAL_INFO = 64; - const int SENSOR_FLAG_BITS_DIRECT_CHANNEL_ASHMEM = 1024; - const int SENSOR_FLAG_BITS_DIRECT_CHANNEL_GRALLOC = 2048; - const int SENSOR_FLAG_BITS_MASK_REPORTING_MODE = 14; - const int SENSOR_FLAG_BITS_MASK_DIRECT_REPORT = 896; - const int SENSOR_FLAG_BITS_MASK_DIRECT_CHANNEL = 3072; + const int SENSOR_FLAG_BITS_DATA_INJECTION = 0x10; + const int SENSOR_FLAG_BITS_DYNAMIC_SENSOR = 0x20; + const int SENSOR_FLAG_BITS_ADDITIONAL_INFO = 0x40; + const int SENSOR_FLAG_BITS_DIRECT_CHANNEL_ASHMEM = 0x400; + const int SENSOR_FLAG_BITS_DIRECT_CHANNEL_GRALLOC = 0x800; + const int SENSOR_FLAG_BITS_MASK_REPORTING_MODE = 0xE; + const int SENSOR_FLAG_BITS_MASK_DIRECT_REPORT = 0x380; + const int SENSOR_FLAG_BITS_MASK_DIRECT_CHANNEL = 0xC00; const int SENSOR_FLAG_SHIFT_REPORTING_MODE = 1; const int SENSOR_FLAG_SHIFT_DATA_INJECTION = 4; const int SENSOR_FLAG_SHIFT_DYNAMIC_SENSOR = 5; diff --git a/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorStatus.aidl b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorStatus.aidl index 45217107fc6d9f16007f313c94e6beaf007c8956..f401dac04cf1fa8380efc0a4de659323e2c27a8c 100644 --- a/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorStatus.aidl +++ b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorStatus.aidl @@ -34,7 +34,7 @@ package android.hardware.sensors; @Backing(type="byte") @VintfStability enum SensorStatus { - NO_CONTACT = -1, + NO_CONTACT = (-1) /* -1 */, UNRELIABLE = 0, ACCURACY_LOW = 1, ACCURACY_MEDIUM = 2, diff --git a/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorType.aidl b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorType.aidl index 8c864e90be18e1e9f328404ed7cb7a27306b62d3..9332c63af5f3320997fd349cfc707b108eaf12be 100644 --- a/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorType.aidl +++ b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorType.aidl @@ -76,5 +76,6 @@ enum SensorType { ACCELEROMETER_LIMITED_AXES_UNCALIBRATED = 40, GYROSCOPE_LIMITED_AXES_UNCALIBRATED = 41, HEADING = 42, - DEVICE_PRIVATE_BASE = 65536, + MOISTURE_INTRUSION = 43, + DEVICE_PRIVATE_BASE = 0x10000, } diff --git a/sensors/aidl/android/hardware/sensors/Event.aidl b/sensors/aidl/android/hardware/sensors/Event.aidl index b95299c50699651a58d5978c0f5b78c69ca2e837..7775cfc267c7e17a2b0bc3c66a5dc3fb472475d9 100644 --- a/sensors/aidl/android/hardware/sensors/Event.aidl +++ b/sensors/aidl/android/hardware/sensors/Event.aidl @@ -88,7 +88,7 @@ parcelable Event { * SensorType::GLANCE_GESTURE, SensorType::PICK_UP_GESTURE, * SensorType::WRIST_TILT_GESTURE, SensorType::STATIONARY_DETECT, * SensorType::MOTION_DETECT, SensorType::HEART_BEAT, - * SensorType::LOW_LATENCY_OFFBODY_DETECT + * SensorType::LOW_LATENCY_OFFBODY_DETECT, SensorType::MOISTURE_INTRUSION */ float scalar; diff --git a/sensors/aidl/android/hardware/sensors/SensorType.aidl b/sensors/aidl/android/hardware/sensors/SensorType.aidl index 4904c3f65d587eaf1acebddecd4244af509f6462..adaf8e65e8e919901dc7a683fd2206454c1240d8 100644 --- a/sensors/aidl/android/hardware/sensors/SensorType.aidl +++ b/sensors/aidl/android/hardware/sensors/SensorType.aidl @@ -717,6 +717,20 @@ enum SensorType { */ HEADING = 42, + /** + * MOISTURE_INTRUSION + * trigger mode: on-change + * + * Detects moisture intrusion in the chassis of device. This detection is + * one-way and persistent. Once a device is detected to have water damage, + * it will always report 1 (across factory reset /reboot) even if moisture + * is no longer present, until the device has been repaired. + * The only allowed values to return are: + * 0.0: no moisture intrusion detected in relevant history + * 1.0: moisture intrusion detected now or previously + */ + MOISTURE_INTRUSION = 43, + /** * Base of the range reserved for device manufacturers' private sensor * types. These sensor types aren't documented in the SDK. diff --git a/sensors/aidl/convert/Android.bp b/sensors/aidl/convert/Android.bp index 7217b2fb382028b1fd88469c4669d202138a8aa6..548308e491bdf66f6b6364cc1bfd65ecffa316a6 100644 --- a/sensors/aidl/convert/Android.bp +++ b/sensors/aidl/convert/Android.bp @@ -36,7 +36,7 @@ cc_library_static { "libhardware", "libbase", "libutils", - "android.hardware.sensors-V2-ndk", + "android.hardware.sensors-V3-ndk", ], whole_static_libs: [ "sensors_common_convert", diff --git a/sensors/aidl/default/Android.bp b/sensors/aidl/default/Android.bp index 6f011eefeb360947fc499f8a9cdf51ccd714e71d..4bdcfb029222e2742b23487c3513fd89c5c87cc5 100644 --- a/sensors/aidl/default/Android.bp +++ b/sensors/aidl/default/Android.bp @@ -32,7 +32,7 @@ cc_library_static { "libfmq", "libpower", "libbinder_ndk", - "android.hardware.sensors-V2-ndk", + "android.hardware.sensors-V3-ndk", ], export_include_dirs: ["include"], srcs: [ @@ -58,7 +58,7 @@ cc_binary { static_libs: [ "android.hardware.common-V2-ndk", "android.hardware.common.fmq-V1-ndk", - "android.hardware.sensors-V2-ndk", + "android.hardware.sensors-V3-ndk", "android.system.suspend-V1-ndk", "libbase", "libcutils", diff --git a/sensors/aidl/default/multihal/Android.bp b/sensors/aidl/default/multihal/Android.bp index 7482ffe7b52888c57142a7bf382b684cb0e2aecc..6ca81d93d1c322609de4dbccd7325acea4e67475 100644 --- a/sensors/aidl/default/multihal/Android.bp +++ b/sensors/aidl/default/multihal/Android.bp @@ -39,7 +39,7 @@ cc_library_static { "android.hardware.sensors@1.0", "android.hardware.sensors@2.0", "android.hardware.sensors@2.1", - "android.hardware.sensors-V2-ndk", + "android.hardware.sensors-V3-ndk", ], export_include_dirs: ["include"], srcs: [ diff --git a/sensors/aidl/default/sensors-default.xml b/sensors/aidl/default/sensors-default.xml index 36b28ed0a6fe0cf594782ccab9e78565c7ab3cec..bed2538b5fb68e5f084dded1ab51429e2adcfe6b 100644 --- a/sensors/aidl/default/sensors-default.xml +++ b/sensors/aidl/default/sensors-default.xml @@ -1,7 +1,7 @@ android.hardware.sensors - 2 + 3 ISensors/default diff --git a/sensors/aidl/multihal/Android.bp b/sensors/aidl/multihal/Android.bp index cac5fc27c83f284670516dee85292879fecf9ea9..cee3db608dcd7f0ed4b1b35079beeab6b08e954b 100644 --- a/sensors/aidl/multihal/Android.bp +++ b/sensors/aidl/multihal/Android.bp @@ -41,7 +41,7 @@ cc_binary { "android.hardware.sensors@2.0-ScopedWakelock", "android.hardware.sensors@2.0", "android.hardware.sensors@2.1", - "android.hardware.sensors-V2-ndk", + "android.hardware.sensors-V3-ndk", "libbase", "libcutils", "libfmq", diff --git a/sensors/aidl/multihal/android.hardware.sensors-multihal.xml b/sensors/aidl/multihal/android.hardware.sensors-multihal.xml index 5da4fbd9a1e094a960c96229ac98a7472af1e8a3..9186f648b99c1b481a8f658186bf5bb404df2711 100644 --- a/sensors/aidl/multihal/android.hardware.sensors-multihal.xml +++ b/sensors/aidl/multihal/android.hardware.sensors-multihal.xml @@ -17,7 +17,7 @@ android.hardware.sensors - 2 + 3 ISensors/default diff --git a/sensors/aidl/vts/Android.bp b/sensors/aidl/vts/Android.bp index 1f96bb438e9e9aadd92d42727a7346a1ecb9a704..63371cd2d7cd4b2bcd26a55d6baf1ab9fde9ea63 100644 --- a/sensors/aidl/vts/Android.bp +++ b/sensors/aidl/vts/Android.bp @@ -42,7 +42,7 @@ cc_test { "android.hardware.common.fmq-V1-ndk", ], static_libs: [ - "android.hardware.sensors-V2-ndk", + "android.hardware.sensors-V3-ndk", "VtsHalSensorsTargetTestUtils", "libaidlcommonsupport", ], diff --git a/thermal/aidl/Android.bp b/thermal/aidl/Android.bp index 597a166beb6f95305479057e977c7591d4c7106a..db777834ac11a727e2719e28020c4b4e6c11fff2 100644 --- a/thermal/aidl/Android.bp +++ b/thermal/aidl/Android.bp @@ -48,8 +48,7 @@ aidl_interface { version: "2", imports: [], }, - ], - frozen: true, + frozen: false, } diff --git a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermal.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermal.aidl index 904496cdf1e7c1ed1577460431b6f03d165f3588..3cff780092b6cc90e19fdc3d98f10e7d234b0cd4 100644 --- a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermal.aidl +++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermal.aidl @@ -46,4 +46,5 @@ interface IThermal { void unregisterThermalChangedCallback(in android.hardware.thermal.IThermalChangedCallback callback); void registerCoolingDeviceChangedCallbackWithType(in android.hardware.thermal.ICoolingDeviceChangedCallback callback, in android.hardware.thermal.CoolingType type); void unregisterCoolingDeviceChangedCallback(in android.hardware.thermal.ICoolingDeviceChangedCallback callback); + float forecastSkinTemperature(in int forecastSeconds); } diff --git a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermalChangedCallback.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermalChangedCallback.aidl index 5e1d753d181c7d897aeda66a88af60d235559805..779544b8cdcecc1482b1aef97625f537bad4ff9e 100644 --- a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermalChangedCallback.aidl +++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermalChangedCallback.aidl @@ -36,4 +36,5 @@ package android.hardware.thermal; @VintfStability interface IThermalChangedCallback { oneway void notifyThrottling(in android.hardware.thermal.Temperature temperature); + oneway void notifyThresholdChanged(in android.hardware.thermal.TemperatureThreshold threshold); } diff --git a/thermal/aidl/android/hardware/thermal/IThermal.aidl b/thermal/aidl/android/hardware/thermal/IThermal.aidl index 4aa4090752c7fd1bf7827377d2ed88a2c4e28c59..87f7637d696762bd26f1868d518cb1b7b770443b 100644 --- a/thermal/aidl/android/hardware/thermal/IThermal.aidl +++ b/thermal/aidl/android/hardware/thermal/IThermal.aidl @@ -225,4 +225,20 @@ interface IThermal { * getMessage() must be populated with human-readable error message. */ void unregisterCoolingDeviceChangedCallback(in ICoolingDeviceChangedCallback callback); + + /** + * Retrieves the forecasted skin temperature in Celsius. + * + * @param forecastSeconds the number of seconds to forecast the skin temperature, it should + * at least support superset of [0, 60] seconds range. + * + * @return forecasted skin temperature in Celsius. + * + * @throws EX_ILLEGAL_STATE If the Thermal HAL is not initialized successfully + * @throws EX_ILLEGAL_ARGUMENT If the provided forecastSeconds is negative + * @throws EX_UNSUPPORTED_OPERATION if API is not supported or the forecastSeconds exceeds the + * supported range. And the getMessage() must be populated with human-readable + * error message. + */ + float forecastSkinTemperature(in int forecastSeconds); } diff --git a/thermal/aidl/android/hardware/thermal/IThermalChangedCallback.aidl b/thermal/aidl/android/hardware/thermal/IThermalChangedCallback.aidl index 105f085864c77451858db50c0a1210305ef29298..1ff4b7af27dd878729af801be3162867373be02b 100644 --- a/thermal/aidl/android/hardware/thermal/IThermalChangedCallback.aidl +++ b/thermal/aidl/android/hardware/thermal/IThermalChangedCallback.aidl @@ -17,6 +17,7 @@ package android.hardware.thermal; import android.hardware.thermal.Temperature; +import android.hardware.thermal.TemperatureThreshold; /** * IThermalChangedCallback send throttling notification to clients. @@ -25,11 +26,19 @@ import android.hardware.thermal.Temperature; @VintfStability interface IThermalChangedCallback { /** - * Send a thermal throttling event to all ThermalHAL + * Send a thermal throttling event to all Thermal HAL * thermal event listeners. * * @param temperature The temperature associated with the * throttling event. */ oneway void notifyThrottling(in Temperature temperature); + + /** + * Send a thermal threshold change event to all Thermal HAL + * thermal event listeners. + * + * @param threshold The temperature threshold that changed. + */ + oneway void notifyThresholdChanged(in TemperatureThreshold threshold); } diff --git a/thermal/aidl/default/Android.bp b/thermal/aidl/default/Android.bp index 9fe62cebdb905ccba10762b19947f361ff5ca3f5..9d89903078215e725f05b9c40f1afd1a1f1af553 100644 --- a/thermal/aidl/default/Android.bp +++ b/thermal/aidl/default/Android.bp @@ -27,7 +27,7 @@ cc_binary { vendor: true, stl: "c++_static", static_libs: [ - "android.hardware.thermal-V2-ndk", + "android.hardware.thermal-V3-ndk", "libbase", ], shared_libs: [ diff --git a/thermal/aidl/default/Thermal.cpp b/thermal/aidl/default/Thermal.cpp index 41d0be8346937433aac92a98df887c8014e35a67..04efbd6ec2d0595f92a3c36560d11cbcdc2840ff 100644 --- a/thermal/aidl/default/Thermal.cpp +++ b/thermal/aidl/default/Thermal.cpp @@ -47,27 +47,85 @@ ScopedAStatus Thermal::getCoolingDevicesWithType(CoolingType in_type, return ScopedAStatus::ok(); } -ScopedAStatus Thermal::getTemperatures(std::vector* /* out_temperatures */) { +ScopedAStatus Thermal::getTemperatures(std::vector* out_temperatures) { LOG(VERBOSE) << __func__; + std::vector temperatures; + temperatures.push_back(Temperature{ + .name = "skin", + .type = TemperatureType::SKIN, + .value = 30.1f, + }); + temperatures.push_back(Temperature{ + .name = "battery", + .type = TemperatureType::BATTERY, + .value = 30.2f, + }); + *out_temperatures = temperatures; return ScopedAStatus::ok(); } ScopedAStatus Thermal::getTemperaturesWithType(TemperatureType in_type, - std::vector* /* out_temperatures */) { + std::vector* out_temperatures) { LOG(VERBOSE) << __func__ << " TemperatureType: " << static_cast(in_type); + if (in_type == TemperatureType::SKIN) { + std::vector temperatures; + temperatures.push_back(Temperature{ + .name = "skin", + .type = TemperatureType::SKIN, + .value = 30.1f, + }); + *out_temperatures = temperatures; + } else if (in_type == TemperatureType::BATTERY) { + std::vector temperatures; + temperatures.push_back(Temperature{ + .name = "battery", + .type = TemperatureType::BATTERY, + .value = 30.2f, + }); + *out_temperatures = temperatures; + } return ScopedAStatus::ok(); } ScopedAStatus Thermal::getTemperatureThresholds( - std::vector* /* out_temperatureThresholds */) { + std::vector* out_temperatureThresholds) { LOG(VERBOSE) << __func__; + std::vector temperatureThresholds; + temperatureThresholds.push_back(TemperatureThreshold{ + .name = "skin", + .type = TemperatureType::SKIN, + .hotThrottlingThresholds = {30.0f, 31.0f, 32.0f, 33.0f, 34.0f, 35.0f, 36.0f}, + }); + temperatureThresholds.push_back(TemperatureThreshold{ + .name = "battery", + .type = TemperatureType::BATTERY, + .hotThrottlingThresholds = {30.0f, 31.0f, 32.0f, 33.0f, 34.0f, 35.0f, 36.0f}, + }); + *out_temperatureThresholds = temperatureThresholds; return ScopedAStatus::ok(); } ScopedAStatus Thermal::getTemperatureThresholdsWithType( TemperatureType in_type, - std::vector* /* out_temperatureThresholds */) { + std::vector* out_temperatureThresholds) { LOG(VERBOSE) << __func__ << " TemperatureType: " << static_cast(in_type); + if (in_type == TemperatureType::SKIN) { + std::vector temperatureThresholds; + temperatureThresholds.push_back(TemperatureThreshold{ + .name = "skin", + .type = TemperatureType::SKIN, + .hotThrottlingThresholds = {30.0f, 31.0f, 32.0f, 33.0f, 34.0f, 35.0f, 36.0f}, + }); + *out_temperatureThresholds = temperatureThresholds; + } else if (in_type == TemperatureType::BATTERY) { + std::vector temperatureThresholds; + temperatureThresholds.push_back(TemperatureThreshold{ + .name = "battery", + .type = TemperatureType::BATTERY, + .hotThrottlingThresholds = {30.0f, 31.0f, 32.0f, 33.0f, 34.0f, 35.0f, 36.0f}, + }); + *out_temperatureThresholds = temperatureThresholds; + } return ScopedAStatus::ok(); } @@ -191,4 +249,9 @@ ScopedAStatus Thermal::unregisterCoolingDeviceChangedCallback( } return ScopedAStatus::ok(); } + +ndk::ScopedAStatus Thermal::forecastSkinTemperature(int32_t, float*) { + return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +} + } // namespace aidl::android::hardware::thermal::impl::example diff --git a/thermal/aidl/default/Thermal.h b/thermal/aidl/default/Thermal.h index d3d88748ee78e2654c7eccaf395a2e022f52d7d6..a4d8b0020434fcbbd1e826495f8cc29e1038c010 100644 --- a/thermal/aidl/default/Thermal.h +++ b/thermal/aidl/default/Thermal.h @@ -60,6 +60,8 @@ class Thermal : public BnThermal { ndk::ScopedAStatus unregisterCoolingDeviceChangedCallback( const std::shared_ptr& in_callback) override; + ndk::ScopedAStatus forecastSkinTemperature(int32_t forecastSeconds, + float* _aidl_return) override; private: std::mutex thermal_callback_mutex_; diff --git a/thermal/aidl/default/thermal-example.xml b/thermal/aidl/default/thermal-example.xml index 08dc68ca046e6af0992daa71e8bcdfa611803184..148ddbfcb112c421614d4295c3353900bc7200d3 100644 --- a/thermal/aidl/default/thermal-example.xml +++ b/thermal/aidl/default/thermal-example.xml @@ -1,7 +1,7 @@ android.hardware.thermal - 2 + 3 IThermal/default diff --git a/thermal/aidl/vts/Android.bp b/thermal/aidl/vts/Android.bp index 35f76492ebf02bbae7f502333943694447abe508..18cb0514bd599248662cef86d58e575ce826915d 100644 --- a/thermal/aidl/vts/Android.bp +++ b/thermal/aidl/vts/Android.bp @@ -33,7 +33,7 @@ cc_test { "libbinder_ndk", ], static_libs: [ - "android.hardware.thermal-V2-ndk", + "android.hardware.thermal-V3-ndk", ], test_suites: [ "vts", diff --git a/thermal/aidl/vts/VtsHalThermalTargetTest.cpp b/thermal/aidl/vts/VtsHalThermalTargetTest.cpp index 687b5edaed4ed4f3dd2dfbdca82154bbe4ffcf37..9dd5153177b9f01921d268175a8cc4baa2cb8071 100644 --- a/thermal/aidl/vts/VtsHalThermalTargetTest.cpp +++ b/thermal/aidl/vts/VtsHalThermalTargetTest.cpp @@ -94,6 +94,10 @@ class ThermalCallback : public BnThermalChangedCallback { return ndk::ScopedAStatus::ok(); } + ndk::ScopedAStatus notifyThresholdChanged(const TemperatureThreshold&) { + return ndk::ScopedAStatus::ok(); + } + template [[nodiscard]] bool waitForCallback(std::chrono::duration duration) { std::unique_lock lock(mMutex); @@ -454,6 +458,23 @@ TEST_P(ThermalAidlTest, CoolingDeviceTest) { } } +// Test Thermal->forecastSkinTemperature. +TEST_P(ThermalAidlTest, ForecastSkinTemperatureTest) { + auto apiLevel = ::android::base::GetIntProperty("ro.vendor.api_level", 0); + if (apiLevel < 202504) { + GTEST_SKIP() << "Skipping test as the vendor level is below 202504: " << apiLevel; + } + float temperature = 0.0f; + ::ndk::ScopedAStatus status = mThermal->forecastSkinTemperature(1, &temperature); + if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) { + GTEST_SKIP() << "Skipping test as temperature forecast is not supported"; + } + for (int i = 0; i <= 60; i++) { + status = mThermal->forecastSkinTemperature(i, &temperature); + ASSERT_NE(NAN, temperature); + } +} + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ThermalAidlTest); INSTANTIATE_TEST_SUITE_P( Thermal, ThermalAidlTest, diff --git a/tv/input/aidl/Android.bp b/tv/input/aidl/Android.bp index afc811a165dc3f10ef8ab04d5ef69a44e6e90809..8d36ab1589ad43061c278ab93fad5332809d9df8 100644 --- a/tv/input/aidl/Android.bp +++ b/tv/input/aidl/Android.bp @@ -45,5 +45,5 @@ aidl_interface { }, ], - frozen: true, + frozen: false, } diff --git a/tv/input/aidl/aidl_api/android.hardware.tv.input/current/android/hardware/tv/input/ITvInput.aidl b/tv/input/aidl/aidl_api/android.hardware.tv.input/current/android/hardware/tv/input/ITvInput.aidl index 84fe2fb7d7925459c2b750351355961aff853132..2ff2719783b7e899b92872ef238122ddb0525820 100644 --- a/tv/input/aidl/aidl_api/android.hardware.tv.input/current/android/hardware/tv/input/ITvInput.aidl +++ b/tv/input/aidl/aidl_api/android.hardware.tv.input/current/android/hardware/tv/input/ITvInput.aidl @@ -40,6 +40,8 @@ interface ITvInput { void setCallback(in android.hardware.tv.input.ITvInputCallback callback); void setTvMessageEnabled(int deviceId, int streamId, in android.hardware.tv.input.TvMessageEventType type, boolean enabled); void getTvMessageQueueDesc(out android.hardware.common.fmq.MQDescriptor queue, int deviceId, int streamId); + void setPictureProfileId(in int deviceId, in int streamId, in long profileId); + void setSoundProfileId(in int deviceId, in int streamId, in long profileId); const int STATUS_UNKNOWN = 1; const int STATUS_NO_RESOURCE = 2; const int STATUS_INVALID_ARGUMENTS = 3; diff --git a/tv/input/aidl/android/hardware/tv/input/ITvInput.aidl b/tv/input/aidl/android/hardware/tv/input/ITvInput.aidl index c63e0aca0f8d37f9d9d7896a4236f9349fe1b29c..e57edf9ea40a44f0393bb492132d44760ed56b08 100644 --- a/tv/input/aidl/android/hardware/tv/input/ITvInput.aidl +++ b/tv/input/aidl/android/hardware/tv/input/ITvInput.aidl @@ -109,4 +109,28 @@ interface ITvInput { */ void getTvMessageQueueDesc( out MQDescriptor queue, int deviceId, int streamId); + + /** + * Set the picture profile ID for a specific stream in a device. + * + * @param deviceId Device ID for the stream to use the profile. + * @param streamId Stream ID for the stream to use the profile. Must be one of the + * stream IDs returned from getStreamConfigurations(). + * @param profileId Picture profile ID for the stream. The ID is assigned by the framework, + * and can be set by applications or TV input framework. See + * android.media.quality.PictureQuality for more details. + */ + void setPictureProfileId(in int deviceId, in int streamId, in long profileId); + + /** + * Set the sound profile ID for a specific stream in a device. + * + * @param deviceId Device ID for the stream to use the profile. + * @param streamId Stream ID for the stream to use the profile. Must be one of the + * stream IDs returned from getStreamConfigurations(). + * @param profileId Sound profile ID for the stream. The ID is assigned by the framework, + * and can be set by applications or TV input framework. See + * android.media.quality.SoundQuality for more details. + */ + void setSoundProfileId(in int deviceId, in int streamId, in long profileId); } diff --git a/tv/mediaquality/OWNERS b/tv/mediaquality/OWNERS new file mode 100644 index 0000000000000000000000000000000000000000..35ca732bb8f6218ce1c3a26d33485a08648e9de5 --- /dev/null +++ b/tv/mediaquality/OWNERS @@ -0,0 +1,3 @@ +quxiangfang@google.com +shubang@google.com +haofanw@google.com \ No newline at end of file diff --git a/tv/mediaquality/aidl/Android.bp b/tv/mediaquality/aidl/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..49cfd80b034c32c2ea9d668e3e05c420eff0e8e0 --- /dev/null +++ b/tv/mediaquality/aidl/Android.bp @@ -0,0 +1,39 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +aidl_interface { + name: "android.hardware.tv.mediaquality", + vendor_available: true, + owner: "haofanw", + srcs: [ + "android/hardware/tv/mediaquality/*.aidl", + ], + imports: [ + "android.hardware.graphics.common-V5", + ], + stability: "vintf", + backend: { + java: { + enabled: true, + platform_apis: true, + }, + ndk: { + enabled: true, + min_sdk_version: "31", + }, + rust: { + enabled: true, + min_sdk_version: "31", + }, + cpp: { + enabled: false, + }, + }, + frozen: false, +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/AmbientBacklightCompressAlgorithm.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/AmbientBacklightCompressAlgorithm.aidl new file mode 100644 index 0000000000000000000000000000000000000000..d441370c7b7fe1914fc7fb6074658747cdf1fd64 --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/AmbientBacklightCompressAlgorithm.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +enum AmbientBacklightCompressAlgorithm { + NONE = 0, + RLE = 1, +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/AmbientBacklightEvent.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/AmbientBacklightEvent.aidl new file mode 100644 index 0000000000000000000000000000000000000000..2fc2cc690644462987a645b93d5802a21a2923fc --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/AmbientBacklightEvent.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +union AmbientBacklightEvent { + boolean enabled; + android.hardware.tv.mediaquality.AmbientBacklightMetadata metadata; +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/AmbientBacklightMetadata.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/AmbientBacklightMetadata.aidl new file mode 100644 index 0000000000000000000000000000000000000000..bbdfd62fea1f1dbe8a62d5e693cd2ef7936fb35a --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/AmbientBacklightMetadata.aidl @@ -0,0 +1,40 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +parcelable AmbientBacklightMetadata { + android.hardware.tv.mediaquality.AmbientBacklightSettings settings; + android.hardware.tv.mediaquality.AmbientBacklightCompressAlgorithm compressAlgorithm; + int[] zonesColors; +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/AmbientBacklightSettings.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/AmbientBacklightSettings.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ffbae2613653730614ad6395ae84c7b2af8a01af --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/AmbientBacklightSettings.aidl @@ -0,0 +1,45 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +parcelable AmbientBacklightSettings { + String packageName; + android.hardware.tv.mediaquality.AmbientBacklightSource source; + int maxFramerate; + android.hardware.graphics.common.PixelFormat colorFormat; + int hZonesNumber; + int vZonesNumber; + boolean hasLetterbox; + int threshold; +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/AmbientBacklightSource.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/AmbientBacklightSource.aidl new file mode 100644 index 0000000000000000000000000000000000000000..22912f4e429939d5101a345cd866548ea4a15a22 --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/AmbientBacklightSource.aidl @@ -0,0 +1,40 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +enum AmbientBacklightSource { + NONE = 0, + AUDIO = 1, + VIDEO = 2, +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/ColorRange.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/ColorRange.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c08c6cc6a5bc4a877766a2d57b597487a520fae8 --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/ColorRange.aidl @@ -0,0 +1,40 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +enum ColorRange { + AUTO, + LIMITED, + FULL, +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/ColorSpace.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/ColorSpace.aidl new file mode 100644 index 0000000000000000000000000000000000000000..9bcddcb97f310ec361b2a3926275fdd0d8cedc2e --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/ColorSpace.aidl @@ -0,0 +1,44 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +enum ColorSpace { + AUTO, + S_RGB_BT_709, + DCI, + ADOBE_RGB, + BT2020, + ON, + OFF, +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/ColorTemperature.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/ColorTemperature.aidl new file mode 100644 index 0000000000000000000000000000000000000000..2d26aca050162f4b9093e8062ab319b1e2c08e23 --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/ColorTemperature.aidl @@ -0,0 +1,47 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +enum ColorTemperature { + USER, + COOL, + STANDARD, + WARM, + USER_HDR10PLUS, + COOL_HDR10PLUS, + STANDARD_HDR10PLUS, + WARM_HDR10PLUS, + FMMSDR, + FMMHDR, +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/DigitalOutput.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/DigitalOutput.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a6e8b913b3c0c9e098c1889288898fd6bce477bc --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/DigitalOutput.aidl @@ -0,0 +1,40 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +enum DigitalOutput { + AUTO, + BYPASS, + PCM, +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/DolbyAudioProcessing.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/DolbyAudioProcessing.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c29ae18707b49abf4ef38aa02a816586301d23e4 --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/DolbyAudioProcessing.aidl @@ -0,0 +1,47 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +parcelable DolbyAudioProcessing { + android.hardware.tv.mediaquality.DolbyAudioProcessing.SoundMode soundMode; + boolean volumeLeveler; + boolean surroundVirtualizer; + boolean doblyAtmos; + enum SoundMode { + GAME, + MOVIE, + MUSIC, + NEWS, + } +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/DownmixMode.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/DownmixMode.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ecb7db2e9f0a87b352152c7a62324296e07840d4 --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/DownmixMode.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +enum DownmixMode { + STEREO, + SURROUND, +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/DtsVirtualX.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/DtsVirtualX.aidl new file mode 100644 index 0000000000000000000000000000000000000000..d136dd91390eb52f95c401c732cc176efb224c05 --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/DtsVirtualX.aidl @@ -0,0 +1,44 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +parcelable DtsVirtualX { + boolean tbHdx; + boolean limiter; + boolean truSurroundX; + boolean truVolumeHd; + boolean dialogClarity; + boolean definition; + boolean height; +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/EqualizerDetail.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/EqualizerDetail.aidl new file mode 100644 index 0000000000000000000000000000000000000000..99543e99a3225802838826361143add69950eddd --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/EqualizerDetail.aidl @@ -0,0 +1,42 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +parcelable EqualizerDetail { + int band120Hz; + int band500Hz; + int band1_5kHz; + int band5kHz; + int band10kHz; +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/Gamma.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/Gamma.aidl new file mode 100644 index 0000000000000000000000000000000000000000..89bb80807782ba9cb8c7d2b6a645fcc98f7e3a09 --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/Gamma.aidl @@ -0,0 +1,40 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +enum Gamma { + DARK, + MIDDLE, + BRIGHT, +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/IMediaQuality.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/IMediaQuality.aidl new file mode 100644 index 0000000000000000000000000000000000000000..b569baa74ab026d9ebdcba3e987a69cabc3b3b14 --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/IMediaQuality.aidl @@ -0,0 +1,60 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +interface IMediaQuality { + void setCallback(in android.hardware.tv.mediaquality.IMediaQualityCallback callback); + void setAmbientBacklightDetector(in android.hardware.tv.mediaquality.AmbientBacklightSettings settings); + void setAmbientBacklightDetectionEnabled(in boolean enabled); + boolean getAmbientBacklightDetectionEnabled(); + boolean isAutoPqSupported(); + boolean getAutoPqEnabled(); + void setAutoPqEnabled(boolean enable); + boolean isAutoSrSupported(); + boolean getAutoSrEnabled(); + void setAutoSrEnabled(boolean enable); + boolean isAutoAqSupported(); + boolean getAutoAqEnabled(); + void setAutoAqEnabled(boolean enable); + android.hardware.tv.mediaquality.IPictureProfileChangedListener getPictureProfileListener(); + void setPictureProfileAdjustmentListener(android.hardware.tv.mediaquality.IPictureProfileAdjustmentListener listener); + void sendDefaultPictureParameters(in android.hardware.tv.mediaquality.PictureParameters pictureParameters); + android.hardware.tv.mediaquality.ISoundProfileChangedListener getSoundProfileListener(); + void setSoundProfileAdjustmentListener(android.hardware.tv.mediaquality.ISoundProfileAdjustmentListener listener); + void sendDefaultSoundParameters(in android.hardware.tv.mediaquality.SoundParameters soundParameters); + void getParamCaps(in android.hardware.tv.mediaquality.ParameterName[] paramNames, out android.hardware.tv.mediaquality.ParamCapability[] caps); + void getVendorParamCaps(in android.hardware.tv.mediaquality.VendorParameterIdentifier[] names, out android.hardware.tv.mediaquality.VendorParamCapability[] caps); + void sendPictureParameters(in android.hardware.tv.mediaquality.PictureParameters pictureParameters); + void sendSoundParameters(in android.hardware.tv.mediaquality.SoundParameters soundParameters); +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/IMediaQualityCallback.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/IMediaQualityCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..014bf5830d6c63a11185396c1abe1e5b0ea868fd --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/IMediaQualityCallback.aidl @@ -0,0 +1,38 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +interface IMediaQualityCallback { + oneway void notifyAmbientBacklightEvent(in android.hardware.tv.mediaquality.AmbientBacklightEvent event); +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/IPictureProfileAdjustmentListener.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/IPictureProfileAdjustmentListener.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e1a882ea4d9fb5a5951fcef3894d5977ef459351 --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/IPictureProfileAdjustmentListener.aidl @@ -0,0 +1,41 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +interface IPictureProfileAdjustmentListener { + oneway void onPictureProfileAdjusted(in android.hardware.tv.mediaquality.PictureProfile pictureProfile); + oneway void onParamCapabilityChanged(long pictureProfileId, in android.hardware.tv.mediaquality.ParamCapability[] caps); + oneway void onVendorParamCapabilityChanged(long pictureProfileId, in android.hardware.tv.mediaquality.VendorParamCapability[] caps); + oneway void onRequestPictureParameters(long pictureProfileId); +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/IPictureProfileChangedListener.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/IPictureProfileChangedListener.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c1bfc36b8c5f28b6c95ee1084192f3129cb20062 --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/IPictureProfileChangedListener.aidl @@ -0,0 +1,38 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +interface IPictureProfileChangedListener { + oneway void onPictureProfileChanged(in android.hardware.tv.mediaquality.PictureProfile pictureProfile); +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/ISoundProfileAdjustmentListener.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/ISoundProfileAdjustmentListener.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e162601eb6c28cc6eaea05cf87a63b6ae2e0cbc4 --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/ISoundProfileAdjustmentListener.aidl @@ -0,0 +1,41 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +interface ISoundProfileAdjustmentListener { + oneway void onSoundProfileAdjusted(in android.hardware.tv.mediaquality.SoundProfile soundProfile); + oneway void onParamCapabilityChanged(long soundProfileId, in android.hardware.tv.mediaquality.ParamCapability[] caps); + oneway void onVendorParamCapabilityChanged(long soundProfileId, in android.hardware.tv.mediaquality.VendorParamCapability[] caps); + oneway void onRequestSoundParameters(long SoundProfileId); +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/ISoundProfileChangedListener.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/ISoundProfileChangedListener.aidl new file mode 100644 index 0000000000000000000000000000000000000000..d07abe75ace29529b166e0f1c1010daa0b778339 --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/ISoundProfileChangedListener.aidl @@ -0,0 +1,38 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +interface ISoundProfileChangedListener { + oneway void onSoundProfileChanged(in android.hardware.tv.mediaquality.SoundProfile soundProfile); +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/NumberRange.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/NumberRange.aidl new file mode 100644 index 0000000000000000000000000000000000000000..9fc9d0d95bb8c2577d65a7182676522a3f2082ae --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/NumberRange.aidl @@ -0,0 +1,43 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +union NumberRange { + @nullable int[2] intMinMax; + @nullable long[2] longMinMax; + @nullable double[2] doubleMinMax; + @nullable int[] intValuesSupported; + @nullable long[] longValuesSupported; + @nullable double[] doubleValuesSupported; +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/ParamCapability.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/ParamCapability.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c60f1d10f8cccda080337a06730927a9256c057b --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/ParamCapability.aidl @@ -0,0 +1,41 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +parcelable ParamCapability { + android.hardware.tv.mediaquality.ParameterName name; + boolean isSupported; + @nullable android.hardware.tv.mediaquality.ParameterDefaultValue defaultValue; + @nullable android.hardware.tv.mediaquality.ParameterRange range; +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/ParameterDefaultValue.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/ParameterDefaultValue.aidl new file mode 100644 index 0000000000000000000000000000000000000000..14e5ff4b89d2c298f4520af2378ed53e87747127 --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/ParameterDefaultValue.aidl @@ -0,0 +1,41 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +union ParameterDefaultValue { + int intDefault; + long longDefault; + double doubleDefault; + String stringDefault; +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/ParameterName.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/ParameterName.aidl new file mode 100644 index 0000000000000000000000000000000000000000..711e2708a9fd5521330f4ddae37c0de437971b1f --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/ParameterName.aidl @@ -0,0 +1,80 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +enum ParameterName { + BRIGHTNESS, + CONTRAST, + SHARPNESS, + SATURATION, + HUE, + COLOR_TUNER_BRIGHTNESS, + COLOR_TUNER_SATURATION, + COLOR_TUNER_HUE, + COLOR_TUNER_RED_OFFSET, + COLOR_TUNER_GREEN_OFFSET, + COLOR_TUNER_BLUE_OFFSET, + COLOR_TUNER_RED_GAIN, + COLOR_TUNER_GREEN_GAIN, + COLOR_TUNER_BLUE_GAIN, + NOISE_REDUCTION, + MPEG_NOISE_REDUCTION, + FLASH_TONE, + DE_CONTOUR, + DYNAMIC_LUMA_CONTROL, + FILM_MODE, + BLACK_STRETCH, + BLUE_STRETCH, + COLOR_TUNE, + COLOR_TEMPERATURE, + GLOBE_DIMMING, + AUTO_PICTUREQUALITY_ENABLED, + AUTO_SUPER_RESOLUTION_ENABLED, + BALANCE, + BASS, + TREBLE, + SURROUND_SOUND_ENABLED, + EQUALIZER_DETAIL, + SPEAKERS_ENABLED, + SPEAKERS_DELAY_MS, + ENHANCED_AUDIO_RETURN_CHANNEL_ENABLED, + AUTO_VOLUME_CONTROL, + DOWNMIX_MODE, + DTS_DRC, + DOLBY_AUDIO_PROCESSING, + DOLBY_DIALOGUE_ENHANCER, + DTS_VIRTUAL_X, + DIGITAL_OUTPUT, + DIGITAL_OUTPUT_DELAY_MS, +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/ParameterRange.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/ParameterRange.aidl new file mode 100644 index 0000000000000000000000000000000000000000..66bc405997962ca66d27103ed762ff21b29fca59 --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/ParameterRange.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +parcelable ParameterRange { + android.hardware.tv.mediaquality.NumberRange numRange; + ParcelableHolder vendorDefinedValues; +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/PictureParameter.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/PictureParameter.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c38e96f883d30ac7361d6b1a4d588a342498a0f4 --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/PictureParameter.aidl @@ -0,0 +1,74 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +union PictureParameter { + float brightness; + int contrast; + int sharpness; + int saturation; + int hue; + int colorTunerBrightness; + int colorTunerSaturation; + int colorTunerHue; + int colorTunerRedOffset; + int colorTunerGreenOffset; + int colorTunerBlueOffset; + int colorTunerRedGain; + int colorTunerGreenGain; + int colorTunerBlueGain; + android.hardware.tv.mediaquality.QualityLevel noiseReduction; + android.hardware.tv.mediaquality.QualityLevel mpegNoiseReduction; + android.hardware.tv.mediaquality.QualityLevel fleshTone; + android.hardware.tv.mediaquality.QualityLevel deContour; + android.hardware.tv.mediaquality.QualityLevel dynamicLumaControl; + boolean filmMode; + boolean blueStretch; + boolean colorTune; + android.hardware.tv.mediaquality.ColorTemperature colorTemperature; + boolean globeDimming; + boolean autoPictureQualityEnabled; + boolean autoSuperResolutionEnabled; + android.hardware.tv.mediaquality.ColorRange levelRange; + boolean gamutMapping; + boolean pcMode; + boolean lowLatency; + boolean vrr; + boolean cvrr; + android.hardware.tv.mediaquality.ColorRange hdmiRgbRange; + android.hardware.tv.mediaquality.ColorSpace colorSpace; + int panelInitMaxLuminceNits; + boolean panelInitMaxLuminceValid; + android.hardware.tv.mediaquality.Gamma gamma; +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/PictureParameters.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/PictureParameters.aidl new file mode 100644 index 0000000000000000000000000000000000000000..627369dff66f42242f4a66695b95018a98d32cc2 --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/PictureParameters.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +parcelable PictureParameters { + android.hardware.tv.mediaquality.PictureParameter[] pictureParameters; + ParcelableHolder vendorPictureParameters; +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/PictureProfile.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/PictureProfile.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ec2f9ff69f1d2cbb347566a38d9ddeb08c2be947 --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/PictureProfile.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +parcelable PictureProfile { + long pictureProfileId; + android.hardware.tv.mediaquality.PictureParameters parameters; +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/QualityLevel.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/QualityLevel.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a7f130f6d3645407c9bc0bfbf18b5fef7592901c --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/QualityLevel.aidl @@ -0,0 +1,41 @@ +/* + * Copyright 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +enum QualityLevel { + OFF, + LOW, + MEDIUM, + HIGH, +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/SoundParameter.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/SoundParameter.aidl new file mode 100644 index 0000000000000000000000000000000000000000..63eb55f3496c0c78d89480898e0610bac64c7753 --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/SoundParameter.aidl @@ -0,0 +1,53 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +union SoundParameter { + int balance; + int bass; + int treble; + boolean surroundSoundEnabled; + android.hardware.tv.mediaquality.EqualizerDetail equalizerDetail; + boolean speakersEnabled; + int speakersDelayMs; + boolean enhancedAudioReturnChannelEnabled; + boolean autoVolumeControl; + android.hardware.tv.mediaquality.DownmixMode downmixMode; + boolean dtsDrc; + @nullable android.hardware.tv.mediaquality.DolbyAudioProcessing dolbyAudioProcessing; + android.hardware.tv.mediaquality.QualityLevel dolbyDialogueEnhancer; + @nullable android.hardware.tv.mediaquality.DtsVirtualX dtsVirtualX; + android.hardware.tv.mediaquality.DigitalOutput digitalOutput; + int digitalOutputDelayMs; +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/SoundParameters.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/SoundParameters.aidl new file mode 100644 index 0000000000000000000000000000000000000000..64921631ead1a8523db01bb968df8a0086abc73b --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/SoundParameters.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +parcelable SoundParameters { + android.hardware.tv.mediaquality.SoundParameter[] soundParameters; + ParcelableHolder vendorSoundParameters; +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/SoundProfile.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/SoundProfile.aidl new file mode 100644 index 0000000000000000000000000000000000000000..05f936f433025d5750cf89b2d21487090801881b --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/SoundProfile.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +parcelable SoundProfile { + long soundProfileId; + android.hardware.tv.mediaquality.SoundParameters parameters; +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/VendorParamCapability.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/VendorParamCapability.aidl new file mode 100644 index 0000000000000000000000000000000000000000..5f16de97f755f91d5e99dde39587f8a703f567b9 --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/VendorParamCapability.aidl @@ -0,0 +1,41 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +parcelable VendorParamCapability { + android.hardware.tv.mediaquality.VendorParameterIdentifier identifier; + boolean isSupported; + @nullable android.hardware.tv.mediaquality.ParameterDefaultValue defaultValue; + @nullable android.hardware.tv.mediaquality.ParameterRange range; +} diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/VendorParameterIdentifier.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/VendorParameterIdentifier.aidl new file mode 100644 index 0000000000000000000000000000000000000000..016c22d24e3cffd304316792afe4fed8e0ff8077 --- /dev/null +++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/VendorParameterIdentifier.aidl @@ -0,0 +1,38 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.mediaquality; +@VintfStability +parcelable VendorParameterIdentifier { + ParcelableHolder identifier; +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/AmbientBacklightCompressAlgorithm.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/AmbientBacklightCompressAlgorithm.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e1c68b35934b3a6da9f6888c1e698534c40f68eb --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/AmbientBacklightCompressAlgorithm.aidl @@ -0,0 +1,29 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +@VintfStability +enum AmbientBacklightCompressAlgorithm { + /** + * The compress algorithm is disabled. + */ + NONE = 0, + /** + * The compress algorithm is enabled for RLE (Run-Length Encoding). + */ + RLE = 1, +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/AmbientBacklightEvent.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/AmbientBacklightEvent.aidl new file mode 100644 index 0000000000000000000000000000000000000000..237e5319c51ec9f09976606bef3483d3661b7304 --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/AmbientBacklightEvent.aidl @@ -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. + */ + +package android.hardware.tv.mediaquality; + +import android.hardware.tv.mediaquality.AmbientBacklightMetadata; + +@VintfStability +union AmbientBacklightEvent { + /** + * This field is relevant when the event signifies that ambient backlight is enabled. + */ + boolean enabled; + + /** + * This field is relevant when the event includes ambient backlight metadata. + */ + AmbientBacklightMetadata metadata; +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/AmbientBacklightMetadata.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/AmbientBacklightMetadata.aidl new file mode 100644 index 0000000000000000000000000000000000000000..49b3a28115182268006fdfc0820376a24105b4c2 --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/AmbientBacklightMetadata.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +import android.hardware.tv.mediaquality.AmbientBacklightCompressAlgorithm; +import android.hardware.tv.mediaquality.AmbientBacklightSettings; + +@VintfStability +parcelable AmbientBacklightMetadata { + /** + * The settings which are used to generate the colors. + */ + AmbientBacklightSettings settings; + + /** + * The compress algorithm of the ambient backlight colors. + */ + AmbientBacklightCompressAlgorithm compressAlgorithm; + + /** + * The colors for the zones. Format of the color will be indicated in the + * AmbientBacklightSettings::colorFormat. + */ + int[] zonesColors; +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/AmbientBacklightSettings.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/AmbientBacklightSettings.aidl new file mode 100644 index 0000000000000000000000000000000000000000..b6a26eef4f900ca855279cc81e3ae93b7f3a35c2 --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/AmbientBacklightSettings.aidl @@ -0,0 +1,70 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +import android.hardware.graphics.common.PixelFormat; +import android.hardware.tv.mediaquality.AmbientBacklightSource; + +@VintfStability +parcelable AmbientBacklightSettings { + /** + * The package name of the ambient backlight control application. + */ + String packageName; + + /** + * The source of the ambient backlight. + */ + AmbientBacklightSource source; + + /** + * The maximum framerate for the ambient backlight. + */ + int maxFramerate; + + /** + * The color format for the ambient backlight. + */ + PixelFormat colorFormat; + + /** + * The number of zones in horizontal direction. + */ + int hZonesNumber; + + /** + * The number of zones in vertical direction. + */ + int vZonesNumber; + + /** + * When a video has a different aspect ratio than the display people + * watching it on, they often get black bars at the top and bottom + * (or sometimes the sides). These black bars are called "letterboxing". + * It's a way to show the entire video without distortion, but it means + * some of the screen space is unused. This configuration determines + * whether to ignore the black bar used for padding. + */ + boolean hasLetterbox; + + /** + * The color threshold for the ambient backlight. The units of the color deopends on + * the colorFormat. For example, RGB888, where the values of R/G/B range from 0 to 255, + * and the threshold is a positive number within the same range. + */ + int threshold; +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/AmbientBacklightSource.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/AmbientBacklightSource.aidl new file mode 100644 index 0000000000000000000000000000000000000000..8051fb671a7e0bfd5a2cfcc367a23a9c2bd08844 --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/AmbientBacklightSource.aidl @@ -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. + */ + +package android.hardware.tv.mediaquality; + +@VintfStability +enum AmbientBacklightSource { + /** + * The detection is disabled. + */ + NONE = 0, + /** + * The detection is enabled for audio. + */ + AUDIO = 1, + /** + * The detection is enabled for video. + */ + VIDEO = 2, +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/ColorRange.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/ColorRange.aidl new file mode 100644 index 0000000000000000000000000000000000000000..29f12efd920958e30cb37cbb8f3269f4cf04c1c6 --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/ColorRange.aidl @@ -0,0 +1,27 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +/** + * The range of color the TV can display. + */ +@VintfStability +enum ColorRange { + AUTO, + LIMITED, + FULL, +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/ColorSpace.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/ColorSpace.aidl new file mode 100644 index 0000000000000000000000000000000000000000..bd4511dcc5ea7c0322af5ee4694ccdec1eb77850 --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/ColorSpace.aidl @@ -0,0 +1,31 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +/** + * Specific model used to define and represent colors numerically. + */ +@VintfStability +enum ColorSpace { + AUTO, + S_RGB_BT_709, + DCI, + ADOBE_RGB, + BT2020, + ON, + OFF, +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/ColorTemperature.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/ColorTemperature.aidl new file mode 100644 index 0000000000000000000000000000000000000000..4d4b01c7d082d770931c88d42cb84aa0a19f9154 --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/ColorTemperature.aidl @@ -0,0 +1,31 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +@VintfStability +enum ColorTemperature { + USER, + COOL, + STANDARD, + WARM, + USER_HDR10PLUS, + COOL_HDR10PLUS, + STANDARD_HDR10PLUS, + WARM_HDR10PLUS, + FMMSDR, + FMMHDR, +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/DigitalOutput.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/DigitalOutput.aidl new file mode 100644 index 0000000000000000000000000000000000000000..1a46ae6fd1799728be8db90484d98488648a4704 --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/DigitalOutput.aidl @@ -0,0 +1,41 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +@VintfStability +enum DigitalOutput { + /** + * Automatically selects the best audio format to send to the connected audio device + * based on the incoming audio stream. This mode prioritizes high-quality formats + * like Dolby Digital or DTS if supported by the device, otherwise falls back to PCM. + */ + AUTO, + + /** + * Sends the raw, unprocessed audio stream directly to the connected audio device. + * This mode requires the audio device to handle decoding and processing of various + * audio formats like Dolby Digital or DTS. + */ + BYPASS, + + /** + * Converts all incoming audio to 2-channel PCM (Pulse Code Modulation) stereo + * before sending it to the audio device. This ensures compatibility with a wide + * range of devices but sacrifices surround sound capabilities. + */ + PCM, +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/DolbyAudioProcessing.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/DolbyAudioProcessing.aidl new file mode 100644 index 0000000000000000000000000000000000000000..d56848caffba4753215692576bc434ae47dfadab --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/DolbyAudioProcessing.aidl @@ -0,0 +1,64 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +@VintfStability +parcelable DolbyAudioProcessing { + enum SoundMode { + GAME, + MOVIE, + MUSIC, + NEWS, + } + + /** + * sound mode for dolby audio processing. + */ + SoundMode soundMode; + + /** + * Indicates whether Volume Leveler is enabled. + * + *

Volume Leveler helps to maintain a consistent volume level across different + * types of content and even within the same program. It minimizes the jarring jumps + * between loud commercials and quiet dialogue or action sequences. + */ + boolean volumeLeveler; + + /** + * Indicates whether Surround Virtualizer is enabled. + * + *

Surround Virtualizer creates a virtual surround sound experience from stereo + * content, making it seem like the sound is coming from multiple speakers, even if + * you only have your TV's built-in speakers. It expands the soundstage and adds + * depth to the audio. + */ + boolean surroundVirtualizer; + + /** + * Indicates whether Dolby Atmos is enabled. + * + *

Dolby Atmos creates a more immersive and realistic sound experience by adding + * a height dimension to surround sound. It allows sound to be placed and moved + * precisely around you, including overhead. + * + *

Note: To experience Dolby Atmos, you need content that has been specifically + * mixed in Dolby Atmos and a compatible sound system with upward-firing speakers + * or a Dolby Atmos soundbar. + */ + boolean doblyAtmos; +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/DownmixMode.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/DownmixMode.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c30a0ba772bd1819346c2f73760117180ba9fa0e --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/DownmixMode.aidl @@ -0,0 +1,23 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +@VintfStability +enum DownmixMode { + STEREO, + SURROUND, +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/DtsVirtualX.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/DtsVirtualX.aidl new file mode 100644 index 0000000000000000000000000000000000000000..b26a41df7848a6b4f04cfffd8dfee67b61f5fdf9 --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/DtsVirtualX.aidl @@ -0,0 +1,57 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +@VintfStability +parcelable DtsVirtualX { + /* + * Total Bass Harmonic Distortion (X). + * Enables/disables TBHDX bass enhancement. Provides a richer low-frequency experience, + * simulating deeper bass. + */ + boolean tbHdx; + + /* + * Activates an audio limiter. Prevents excessive volume peaks that could cause distortion + * or speaker damage + */ + boolean limiter; + + /* + * Enables/disables the core DTS Virtual:X surround sound processing. Creates an immersive, + * multi-channel audio experience from the speaker configuration. + */ + boolean truSurroundX; + + /* + * Activates DTS TruVolume HD. Reduces the dynamic range of audio, minimizing loudness + * variations between content and channels. + */ + boolean truVolumeHd; + + /* Enhances the clarity and intelligibility of speech in audio content. */ + boolean dialogClarity; + + /* Applies audio processing to improve overall sound definition and clarity. */ + boolean definition; + + /* + * Enables/disables the processing of virtual height channels. Creates a more immersive + * audio experience by simulating sounds from above. + */ + boolean height; +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/EqualizerDetail.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/EqualizerDetail.aidl new file mode 100644 index 0000000000000000000000000000000000000000..6eebdc0f0c17d8c9c1c6112445f7ba7220e497b1 --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/EqualizerDetail.aidl @@ -0,0 +1,26 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +@VintfStability +parcelable EqualizerDetail { + int band120Hz; // Range: -50 to 50 + int band500Hz; // Range: -50 to 50 + int band1_5kHz; // Range: -50 to 50 + int band5kHz; // Range: -50 to 50 + int band10kHz; // Range: -50 to 50 +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/Gamma.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/Gamma.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c633557c845d89b84bb6f7b3c9b512fb2ebe6399 --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/Gamma.aidl @@ -0,0 +1,24 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +@VintfStability +enum Gamma { + DARK, + MIDDLE, + BRIGHT, +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/IMediaQuality.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/IMediaQuality.aidl new file mode 100644 index 0000000000000000000000000000000000000000..373a977754ebbb5879437803bdc0ea2a79c2f8e4 --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/IMediaQuality.aidl @@ -0,0 +1,226 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +import android.hardware.tv.mediaquality.AmbientBacklightSettings; +import android.hardware.tv.mediaquality.IMediaQualityCallback; +import android.hardware.tv.mediaquality.IPictureProfileAdjustmentListener; +import android.hardware.tv.mediaquality.IPictureProfileChangedListener; +import android.hardware.tv.mediaquality.ISoundProfileAdjustmentListener; +import android.hardware.tv.mediaquality.ISoundProfileChangedListener; +import android.hardware.tv.mediaquality.ParamCapability; +import android.hardware.tv.mediaquality.ParameterName; +import android.hardware.tv.mediaquality.PictureParameters; +import android.hardware.tv.mediaquality.SoundParameters; +import android.hardware.tv.mediaquality.VendorParamCapability; +import android.hardware.tv.mediaquality.VendorParameterIdentifier; + +/** + * Interface for the media quality service + */ +@VintfStability +interface IMediaQuality { + /** + * Sets a callback for events. + * + * @param callback Callback object to pass events. + */ + void setCallback(in IMediaQualityCallback callback); + + /** + * Sets the ambient backlight detector settings. + * + * @param settings Ambient backlight detector settings. + */ + void setAmbientBacklightDetector(in AmbientBacklightSettings settings); + + /** + * Sets the ambient backlight detection enabled or disabled. The ambient backlight is the + * projection of light against the wall driven by the current content playing. Enable will + * detects the Ambient backlight metadata and ambient control app can control the related + * device as configured before. + * + * @param enabled True to enable the ambient backlight detection, false to disable. + */ + void setAmbientBacklightDetectionEnabled(in boolean enabled); + + /** + * Gets the ambient backlight detection enabled status. The ambient backlight is enabled by + * calling setAmbientBacklightDetectionEnabled(in boolean enabled). True to enable the + * ambient light detection and False to disable the ambient backlight detection. + * + * @return True if the ambient backlight detection is enabled, false otherwise. + */ + boolean getAmbientBacklightDetectionEnabled(); + + /** + * Check if auto picture quality feature is supported on the current TV device. + * + * @return true when the device supports the auto picture quality, false when the device does + * not supports the auto picture quality. + */ + boolean isAutoPqSupported(); + + /** + * Get the current state of auto picture quality. + * + * @return true when auto picture quality is enabled, false when auto picture quality is + * disabled. + */ + boolean getAutoPqEnabled(); + + /** + * Set the auto picture quality enable/disable. Auto picture quality is to adjust the Picture + * parameters depends on the current content playing. + * + * @param enable True to enable, false to disable. + */ + void setAutoPqEnabled(boolean enable); + + /** + * Check if auto super resolution feature is supported on the current TV device. + * + * @return true when the device supports the super resolution feature, false when the device + * does not support super resolution. + */ + boolean isAutoSrSupported(); + + /** + * Get the current state of auto super resolution. + * + * @return true when auto super resolution is enabled, false when auto super resolution is + * disabled. + */ + boolean getAutoSrEnabled(); + + /** + * Set the auto super resolution enable/disable. Auto super resolution is to analyze the + * lower resolution image and invent the missing pixel to make the image looks sharper. + * + * @param enable True to enable, false to disable. + */ + void setAutoSrEnabled(boolean enable); + + /** + * Check if auto sound/audio quality feature is supported on the current TV device. + * + * @return true when the device supports the auto sound/audio quality, false when + * the device does not supports the auto sound/audio quality. + */ + boolean isAutoAqSupported(); + + /** + * Get the current state of auto sound/audio quality. + * + * @return true when auto sound/audio quality is enabled, false when auto sound/audio + * quality is disabled. + */ + boolean getAutoAqEnabled(); + + /** + * Set the auto sound/audio quality enable/disable. Auto sound/audio quality is to + * adjust the sound parameters depends on the current content playing. + * + * @param enable True to enable, false to disable. + */ + void setAutoAqEnabled(boolean enable); + + /** + * Get picture profile changed listener. + * + * @return the IPictureProfileChangedListener. + */ + IPictureProfileChangedListener getPictureProfileListener(); + + /** + * Sets the listener for picture adjustment from the HAL. + * + * When the same client registers this listener multiple times, only the most recent + * registration will be active. The previous listener will be overwritten. + * + * When different client registers this listener, it will overwrite the previous registered + * client. Only one listener can be active. + * + * @param IPictureProfileAdjustmentListener listener object to pass picture profile, profile + * id and hardware capability. + */ + void setPictureProfileAdjustmentListener(IPictureProfileAdjustmentListener listener); + + /** + * Send the default picture parameters to the vendor code or HAL to apply the picture + * parameters. + * + * @param pictureParameters PictureParameters with pre-defined parameters and vendor defined + * parameters. + */ + void sendDefaultPictureParameters(in PictureParameters pictureParameters); + + /** + * Get sound profile changed listener. + * + * @return the ISoundProfileChangedListener. + */ + ISoundProfileChangedListener getSoundProfileListener(); + + /** + * Sets the listener for sound adjustment from the HAL. + * + * When the same client registers this listener multiple times, only the most recent + * registration will be active. The previous listener will be overwritten. + * + * When different client registers this listener, it will overwrite the previous registered + * client. Only one listener can be active. + * + * @param ISoundProfileAdjustmentListener listener object to pass sound profile, profile id + * and hardware capability. + */ + void setSoundProfileAdjustmentListener(ISoundProfileAdjustmentListener listener); + + /** + * Send the default sound parameters to the vendor code or HAL to apply the sound parameters. + * + * @param soundParameters SoundParameters with pre-defined parameters and vendor defined + * parameters. + */ + void sendDefaultSoundParameters(in SoundParameters soundParameters); + + /** + * Gets capability information of the given parameters. + */ + void getParamCaps(in ParameterName[] paramNames, out ParamCapability[] caps); + + /** + * Gets vendor capability information of the given parameters. + */ + void getVendorParamCaps(in VendorParameterIdentifier[] names, out VendorParamCapability[] caps); + + /** + * When HAL request picture parameters by picture profile id, the framework will use this to + * send the picture parameters associate with the profile id. + * + * @param pictureParameters pictureParameters that associate with the profile id HAL provided. + */ + void sendPictureParameters(in PictureParameters pictureParameters); + + /** + * When HAL request sound parameters by sound profile id, the framework will use this to + * send the sound parameters associate with the profile id. + * + * @param soundParameters soundParameters that associate with the profile id HAL provided. + */ + void sendSoundParameters(in SoundParameters soundParameters); +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/IMediaQualityCallback.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/IMediaQualityCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..31ab2555654e6f7cc1cecbfdaf27f6a2be476b34 --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/IMediaQualityCallback.aidl @@ -0,0 +1,30 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +import android.hardware.tv.mediaquality.AmbientBacklightEvent; + +@VintfStability +oneway interface IMediaQualityCallback { + /** + * Notifies the client that an ambient backlight event has occurred. For possible + * event types, check AmbientBacklightEventType. + * + * @param event Event passed to the client. + */ + void notifyAmbientBacklightEvent(in AmbientBacklightEvent event); +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/IPictureProfileAdjustmentListener.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/IPictureProfileAdjustmentListener.aidl new file mode 100644 index 0000000000000000000000000000000000000000..06651e4461839a452d5a9578b192f786760a8984 --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/IPictureProfileAdjustmentListener.aidl @@ -0,0 +1,63 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +import android.hardware.tv.mediaquality.ParamCapability; +import android.hardware.tv.mediaquality.PictureProfile; +import android.hardware.tv.mediaquality.VendorParamCapability; + +@VintfStability +oneway interface IPictureProfileAdjustmentListener { + /** + * Notifies Media Quality Manager when the picture profile changed. + * + * @param pictureProfile Picture profile. + */ + void onPictureProfileAdjusted(in PictureProfile pictureProfile); + + /** + * Notifies Media Quality Manager when parameter capabilities changed. + * + * @param pictureProfileId the ID of the profile used by the media content. -1 if there + * is no associated profile. + * @param caps the updated capabilities. + */ + void onParamCapabilityChanged(long pictureProfileId, in ParamCapability[] caps); + + /** + * Notifies Media Quality Manager when vendor parameter capabilities changed. + * + *

This should be also called when the listener is registered to let the client know + * what vendor parameters are supported. + * + * @param pictureProfileId the ID of the profile used by the media content. -1 if there + * is no associated profile. + * @param caps the updated vendor capabilities. + */ + void onVendorParamCapabilityChanged(long pictureProfileId, in VendorParamCapability[] caps); + + /** + * Request the picture parameters by picture profile id. Check PictureParameters for its detail. + * This is called from the HAL to media quality framework. + * + * The requested picture parameters will get from IMediaQuality::sendPictureParameters called + * by the framework. + * + * @param pictureProfileId The PictureProfile id that associate with the PictureProfile. + */ + void onRequestPictureParameters(long pictureProfileId); +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/IPictureProfileChangedListener.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/IPictureProfileChangedListener.aidl new file mode 100644 index 0000000000000000000000000000000000000000..35112e117fd808c654b476d6fdc1e8c7b5ad97e5 --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/IPictureProfileChangedListener.aidl @@ -0,0 +1,30 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +import android.hardware.tv.mediaquality.PictureProfile; + +@VintfStability +oneway interface IPictureProfileChangedListener { + /** + * Notifies the composer HAL that the picture profile has changed. For picture profile details, + * check PictureProfile. + * + * @param pictureProfile Picture profile passed to the composer HAL. + */ + void onPictureProfileChanged(in PictureProfile pictureProfile); +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/ISoundProfileAdjustmentListener.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/ISoundProfileAdjustmentListener.aidl new file mode 100644 index 0000000000000000000000000000000000000000..2ab9c6c0d2e2b9762eaf01897a4be29699cb586a --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/ISoundProfileAdjustmentListener.aidl @@ -0,0 +1,63 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +import android.hardware.tv.mediaquality.ParamCapability; +import android.hardware.tv.mediaquality.SoundProfile; +import android.hardware.tv.mediaquality.VendorParamCapability; + +@VintfStability +oneway interface ISoundProfileAdjustmentListener { + /** + * Notifies Media Quality Manager when the sound profile changed. + * + * @param soundProfile Sound profile. + */ + void onSoundProfileAdjusted(in SoundProfile soundProfile); + + /** + * Notifies Media Quality Manager when parameter capabilities changed. + * + * @param soundProfileId the ID of the profile used by the media content. -1 if there + * is no associated profile. + * @param caps the updated capabilities. + */ + void onParamCapabilityChanged(long soundProfileId, in ParamCapability[] caps); + + /** + * Notifies Media Quality Manager when vendor parameter capabilities changed. + * + *

This should be also called when the listener is registered to let the client know + * what vendor parameters are supported. + * + * @param soundProfileId the ID of the profile used by the media content. -1 if there + * is no associated profile. + * @param caps the updated vendor capabilities. + */ + void onVendorParamCapabilityChanged(long soundProfileId, in VendorParamCapability[] caps); + + /** + * Request the sound parameters by sound profile id. Check SoundParameters for its detail. + * This is called from the HAL to media quality framework. + * + * The requested sound parameters will get from IMediaQuality::sendSoundParameters called + * by the framework. + * + * @param SoundProfileId The SoundProfile id that associate with the SoundProfile. + */ + void onRequestSoundParameters(long SoundProfileId); +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/ISoundProfileChangedListener.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/ISoundProfileChangedListener.aidl new file mode 100644 index 0000000000000000000000000000000000000000..cb2d75e9af9605f2c84bdb7e3a37c9f237da698f --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/ISoundProfileChangedListener.aidl @@ -0,0 +1,30 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +import android.hardware.tv.mediaquality.SoundProfile; + +@VintfStability +oneway interface ISoundProfileChangedListener { + /** + * Notifies the audio HAL that the sound profile has changed. For sound profile details, + * check SoundProfile. + * + * @param soundProfile Sound profile passed to the audio HAL. + */ + void onSoundProfileChanged(in SoundProfile soundProfile); +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/NumberRange.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/NumberRange.aidl new file mode 100644 index 0000000000000000000000000000000000000000..94a041c36e42f3f76385449332c36df1b7a66365 --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/NumberRange.aidl @@ -0,0 +1,35 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +/** Parameter supported number range **/ +@VintfStability +union NumberRange { + /** Min value and max value of an int parameter. Inclusive. */ + @nullable int[2] intMinMax; + /** Min value and max value of a long parameter. Inclusive. */ + @nullable long[2] longMinMax; + /** Min value and max value of a double parameter. Inclusive. */ + @nullable double[2] doubleMinMax; + + /** An array of supported int values. */ + @nullable int[] intValuesSupported; + /** An array of supported long values. */ + @nullable long[] longValuesSupported; + /** An array of supported double values. */ + @nullable double[] doubleValuesSupported; +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/ParamCapability.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/ParamCapability.aidl new file mode 100644 index 0000000000000000000000000000000000000000..933a1a3e87c15d8a698475fb0707fdacae0b22d9 --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/ParamCapability.aidl @@ -0,0 +1,42 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +import android.hardware.tv.mediaquality.ParameterDefaultValue; +import android.hardware.tv.mediaquality.ParameterName; +import android.hardware.tv.mediaquality.ParameterRange; +/** + * Capability of parameters. + */ +@VintfStability +parcelable ParamCapability { + /** Name of the parameter **/ + ParameterName name; + + /** true if this parameter is supported **/ + boolean isSupported; + + /** + * Default value of this parameter. null if there is no default value. + */ + @nullable ParameterDefaultValue defaultValue; + + /** + * The supported range of this parameter. null if there is no specific range. + */ + @nullable ParameterRange range; +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/ParameterDefaultValue.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/ParameterDefaultValue.aidl new file mode 100644 index 0000000000000000000000000000000000000000..3827134c8d53c0ef6191fa50d2b5530a1d66672a --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/ParameterDefaultValue.aidl @@ -0,0 +1,26 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +/** Parameter default value **/ +@VintfStability +union ParameterDefaultValue { + int intDefault; + long longDefault; + double doubleDefault; + String stringDefault; +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/ParameterName.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/ParameterName.aidl new file mode 100644 index 0000000000000000000000000000000000000000..0a3c97bfc5347e4ccb728000cf135266e4d60b66 --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/ParameterName.aidl @@ -0,0 +1,71 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +/** + * Parameter names. + *

Details of the parameters can be found at + * android.hardware.tv.mediaquality.PictureParameter and + * android.hardware.tv.mediaquality.SoundParameter. + */ +@VintfStability +enum ParameterName { + BRIGHTNESS, + CONTRAST, + SHARPNESS, + SATURATION, + HUE, + COLOR_TUNER_BRIGHTNESS, + COLOR_TUNER_SATURATION, + COLOR_TUNER_HUE, + COLOR_TUNER_RED_OFFSET, + COLOR_TUNER_GREEN_OFFSET, + COLOR_TUNER_BLUE_OFFSET, + COLOR_TUNER_RED_GAIN, + COLOR_TUNER_GREEN_GAIN, + COLOR_TUNER_BLUE_GAIN, + NOISE_REDUCTION, + MPEG_NOISE_REDUCTION, + FLASH_TONE, + DE_CONTOUR, + DYNAMIC_LUMA_CONTROL, + FILM_MODE, + BLACK_STRETCH, + BLUE_STRETCH, + COLOR_TUNE, + COLOR_TEMPERATURE, + GLOBE_DIMMING, + AUTO_PICTUREQUALITY_ENABLED, + AUTO_SUPER_RESOLUTION_ENABLED, + + BALANCE, + BASS, + TREBLE, + SURROUND_SOUND_ENABLED, + EQUALIZER_DETAIL, + SPEAKERS_ENABLED, + SPEAKERS_DELAY_MS, + ENHANCED_AUDIO_RETURN_CHANNEL_ENABLED, + AUTO_VOLUME_CONTROL, + DOWNMIX_MODE, + DTS_DRC, + DOLBY_AUDIO_PROCESSING, + DOLBY_DIALOGUE_ENHANCER, + DTS_VIRTUAL_X, + DIGITAL_OUTPUT, + DIGITAL_OUTPUT_DELAY_MS, +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/ParameterRange.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/ParameterRange.aidl new file mode 100644 index 0000000000000000000000000000000000000000..836b5b8f690b9568ff722b6e378acdc181636662 --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/ParameterRange.aidl @@ -0,0 +1,29 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +import android.hardware.tv.mediaquality.NumberRange; + +/** Parameter supported range **/ +@VintfStability +parcelable ParameterRange { + /** Supported number range */ + NumberRange numRange; + + /** Supported vendor-defined values **/ + ParcelableHolder vendorDefinedValues; +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/PictureParameter.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/PictureParameter.aidl new file mode 100644 index 0000000000000000000000000000000000000000..b7f2a119d9ed5c717fe96bb07bcdd877e4f6a55d --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/PictureParameter.aidl @@ -0,0 +1,256 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +import android.hardware.tv.mediaquality.ColorRange; +import android.hardware.tv.mediaquality.ColorSpace; +import android.hardware.tv.mediaquality.ColorTemperature; +import android.hardware.tv.mediaquality.Gamma; +import android.hardware.tv.mediaquality.QualityLevel; + +/** + * The parameters for Picture Profile. + */ +@VintfStability +union PictureParameter { + /* + * Brightness field represents the brightness level of the TV. + * Brightness value range are from 0.0 to 1.0, where 0.0 represents the minimum brightness and + * 1.0 represents the maximum brightness. The content-unmodified value is 0.5. + * + * note: when a picture profile is applied to the entire display, the media quality framework + * will synchronize the brightness field. + */ + float brightness; + + /* + * This value represents the image contrast on an arbitrary scale from 0 to 100, + * where 0 represents the darkest black (black screen) and 100 represents the brightest + * white (brighter). + * The default/unmodified value for contrast is 50. + */ + int contrast; + + /* + * Control that increases edge contrast so that objects become more distinct. + * Sharpness value range are from 0 to 100, where 0 represents the minimum sharpness that + * makes the image appear softer with less defined edges, 100 represents the maximum + * sharpness that makes the image appear halos around objects due to excessive edges. + * The default/unmodified value for sharpness is 50. + */ + int sharpness; + + /* + * Saturation value controls the intensity or purity of colors. + * Saturation values are from 0 to 100, where 0 represents grayscale (no color) and 100 + * represents the most vivid colors. + * The default/unmodified value for saturation is 50. + */ + int saturation; + + /* + * Hue affects the balance between red, green and blue primary colors on the screen. + * Hue values are from -50 to 50, where -50 represents cooler and 50 represents warmer. + * The default/unmodified value for hue is 0. + */ + int hue; + + /* + * Adjust brightness in advance color engine. Similar to a "brightness" control on a TV + * but acts at a lower level. + * + * The range is from 0 to 100, where 0 represents the minimum brightness and 100 represents + * the maximum brightness. The default/unmodified value is 50. + */ + int colorTunerBrightness; + + /* + * Adjust saturation in advance color engine. Similar to a "saturation" control on a TV + * but acts at a lower level. + * + * The range is from 0 to 100, where 0 being completely desaturated/grayscale and 100 being + * the most saturated. The default/unmodified value is 50. + */ + int colorTunerSaturation; + + /* + * Adjust hue in advance color engine. Similar to a "hue" control on a TV but acts at a lower + * level. + * + * The range is from -50 to 50, where -50 represents cooler setting for a specific color and 50 + * represents warmer setting for a specific color. The default/unmodified value is 0. + */ + int colorTunerHue; + + /* + * Advance setting for red offset. Adjust the black level of red color channels, it control + * the minimum intensity of each color, affecting the shadows and dark areas of the image. + * + * The range is from 0 to 100, where 0 makes shadows darker and 100 makes shadows brighter. + * The default/unmodified value is 50. + */ + int colorTunerRedOffset; + + /* + * Advance setting for green offset. Adjust the black level of green color channels, it control + * the minimum intensity of each color, affecting the shadows and dark areas of the image. + * + * The range is from 0 to 100, where 0 makes shadows darker and 100 makes shadows brighter. + * The default/unmodified value is 50. + */ + int colorTunerGreenOffset; + + /* + * Advance setting for blue offset. Adjust the black level of blue color channels, it control + * the minimum intensity of each color, affecting the shadows and dark areas of the image. + * + * The range is from 0 to 100, where 0 makes shadows darker and 100 makes shadows brighter. + * The default/unmodified value is 50. + */ + int colorTunerBlueOffset; + + /* + * Advance setting for red gain. Adjust the gain or amplification of the red color channels. + * They control the overall intensity and white balance of red. + * + * The range is from 0 to 100, where 0 makes the red dimmer and 100 makes the red brighter. + * The default/unmodified value is 50. + */ + int colorTunerRedGain; + + /* + * Advance setting for green gain. Adjust the gain or amplification of the green color channels. + * They control the overall intensity and white balance of green. + * + * The range is from 0 to 100, where 0 makes the green dimmer and 100 makes the green brighter. + * The default/unmodified value is 50. + */ + int colorTunerGreenGain; + + /* + * Advance setting for blue gain. Adjust the gain or amplification of the blue color channels. + * They control the overall intensity and white balance of blue. + * + * The range is from 0 to 100, where 0 makes the blue dimmer and 100 makes the blue brighter. + * The default/unmodified value is 50. + */ + int colorTunerBlueGain; + + /* Noise reduction. (Off, Low, Medium, High) */ + QualityLevel noiseReduction; + + /* MPEG (moving picture experts group) noise reduction (Off, Low, Medium, High) */ + QualityLevel mpegNoiseReduction; + + /* + * Refine the flesh colors in the pictures without affecting the other colors on the screen. + * (Off, Low, Medium, High) + */ + QualityLevel fleshTone; + + /* Contour noise reduction. (Off, Low, Medium, High) */ + QualityLevel deContour; + + /* Dynamically change picture luma to enhance contrast. (Off, Low, Medium, High) */ + QualityLevel dynamicLumaControl; + + /* Enable/disable film mode */ + boolean filmMode; + + /* Enable/disable blue color auto stretch */ + boolean blueStretch; + + /* Enable/disable the overall color tuning feature. */ + boolean colorTune; + + /* Adjust color temperature type */ + ColorTemperature colorTemperature; + + /* Enable/disable globe dimming. */ + boolean globeDimming; + + /* Enable/disable auto adjust picture parameter based on the TV content. */ + boolean autoPictureQualityEnabled; + + /* + * Enable/disable auto upscaling the picture quality. It analyzes the lower-resolution + * image and uses its knowledge to invent the missing pixel, make the image look sharper. + */ + boolean autoSuperResolutionEnabled; + + /** + * The color range of the content. This indicates the range of luminance values + * used in the video signal. + */ + ColorRange levelRange; + + /** + * Enable/disable gamut mapping. Gamut mapping is a process that adjusts + * the colors in the video signal to match the color gamut of the display. + */ + boolean gamutMapping; + + /** + * Enable/disable PC mode. PC mode is a display mode that is optimized for + * use with computers. + */ + boolean pcMode; + + /** + * Enable/disable low latency mode. Low latency mode reduces the delay + * between the video source and the display. + */ + boolean lowLatency; + + /** + * Enable/disable variable refresh rate (VRR) mode. VRR allows the display to + * dynamically adjust its refresh rate to match the frame rate of the video + * source, reducing screen tearing. + */ + boolean vrr; + + /** + * Enable/disable continuous variable refresh rate (CVRR) mode. CVRR is a type + * of VRR that allows for a wider range of refresh rates. + */ + boolean cvrr; + + /** + * The color range of the HDMI input. This indicates the range of luminance + * values used in the HDMI signal. + */ + ColorRange hdmiRgbRange; + + /** + * The color space of the content. This indicates the color gamut and + * transfer function used in the video signal. + */ + ColorSpace colorSpace; + + /** + * The initial maximum luminance of the panel, in nits. + */ + int panelInitMaxLuminceNits; + + /** + * Whether the initial maximum luminance value is valid. + */ + boolean panelInitMaxLuminceValid; + + /* The gamma curve used for the display. */ + Gamma gamma; +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/PictureParameters.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/PictureParameters.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e5f6b83ea8ad7769869979c855e6fdc94bbd91bf --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/PictureParameters.aidl @@ -0,0 +1,31 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +import android.hardware.tv.mediaquality.PictureParameter; + +/** + * The pre-defined parameters and vendor parameters for Picture Profile. + */ +@VintfStability +parcelable PictureParameters { + /* Pre-defined picture parameters. */ + PictureParameter[] pictureParameters; + + /* Vendor defined picture parameters. */ + ParcelableHolder vendorPictureParameters; +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/PictureProfile.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/PictureProfile.aidl new file mode 100644 index 0000000000000000000000000000000000000000..7e02350acc49e229fe05039f2add041f45f0b9d2 --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/PictureProfile.aidl @@ -0,0 +1,30 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +import android.hardware.tv.mediaquality.PictureParameters; + +/** + * Picture profile that includes all the parameters. + */ +@VintfStability +parcelable PictureProfile { + long pictureProfileId; + + /* Picture parameters that associate with the id. */ + PictureParameters parameters; +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/QualityLevel.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/QualityLevel.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e0171ca8264cbd435c8858f3aa07751582f416a7 --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/QualityLevel.aidl @@ -0,0 +1,25 @@ +/* + * Copyright 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. + */ + +package android.hardware.tv.mediaquality; + +@VintfStability +enum QualityLevel { + OFF, + LOW, + MEDIUM, + HIGH, +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/SoundParameter.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/SoundParameter.aidl new file mode 100644 index 0000000000000000000000000000000000000000..4714ad2812eefe4854af32151c435a6654c899e9 --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/SoundParameter.aidl @@ -0,0 +1,95 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +import android.hardware.tv.mediaquality.DigitalOutput; +import android.hardware.tv.mediaquality.DolbyAudioProcessing; +import android.hardware.tv.mediaquality.DownmixMode; +import android.hardware.tv.mediaquality.DtsVirtualX; +import android.hardware.tv.mediaquality.EqualizerDetail; +import android.hardware.tv.mediaquality.QualityLevel; + +/** + * The parameters for Sound Profile. + */ +@VintfStability +union SoundParameter { + /* + * This parameter controls the balance between the left and tight speakers. + * The valid range is -50 to 50, where: + * - Negative values shift the balance towards the left speaker. + * - Positive values shift the balance towards the right speaker. + * - 0 represents a balanced output. + */ + int balance; + + /* + * Bass controls the intensity of low-frequency sounds. + * The valid range is 0 - 100. + */ + int bass; + + /* + * Treble controls the intensity of high-frequency sounds. + * The valid range is 0 - 100. + */ + int treble; + + /* Enable surround sound. */ + boolean surroundSoundEnabled; + + /* + * Equalizer can fine-tune the audio output by adjusting the loudness of different + * frequency bands; + * The frequency bands are 120Hz, 500Hz, 1.5kHz, 5kHz, 10kHz. + * Each band have a value of -50 to 50. + */ + EqualizerDetail equalizerDetail; + + /* Enable speaker output. */ + boolean speakersEnabled; + + /* Speaker delay in ms. */ + int speakersDelayMs; + + /* eARC allows for higher bandwidth audio transmission over HDMI */ + boolean enhancedAudioReturnChannelEnabled; + + /* Enable auto volume control sound effect. */ + boolean autoVolumeControl; + + /* Enable downmix mode. */ + DownmixMode downmixMode; + + /* Enable dynamic range compression */ + boolean dtsDrc; + + /* Sound effects from Dobly */ + @nullable DolbyAudioProcessing dolbyAudioProcessing; + + /* Sound effect from Dolby. */ + QualityLevel dolbyDialogueEnhancer; + + /* Sound effect from DTS. */ + @nullable DtsVirtualX dtsVirtualX; + + /* Digital output mode. */ + DigitalOutput digitalOutput; + + /* Digital output delay in ms. */ + int digitalOutputDelayMs; +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/SoundParameters.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/SoundParameters.aidl new file mode 100644 index 0000000000000000000000000000000000000000..2fe0ce71546081e7b393849e1e35c4bfd6f33156 --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/SoundParameters.aidl @@ -0,0 +1,31 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +import android.hardware.tv.mediaquality.SoundParameter; + +/** + * The pre-defined parameters and vendor parameters for Sound Profile. + */ +@VintfStability +parcelable SoundParameters { + /* Pre-defined sound parameters. */ + SoundParameter[] soundParameters; + + /* Vendor defined sound parameters. */ + ParcelableHolder vendorSoundParameters; +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/SoundProfile.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/SoundProfile.aidl new file mode 100644 index 0000000000000000000000000000000000000000..27628ebeef3896284f7f8d687c565a7730f3ad84 --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/SoundProfile.aidl @@ -0,0 +1,30 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +import android.hardware.tv.mediaquality.SoundParameters; + +/** + * Sound profile that includes all the parameters. + */ +@VintfStability +parcelable SoundProfile { + long soundProfileId; + + /* Sound parameters that associate with the id. */ + SoundParameters parameters; +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/VendorParamCapability.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/VendorParamCapability.aidl new file mode 100644 index 0000000000000000000000000000000000000000..bdc0188393b856dc14b011c4c34ee51fe9bccced --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/VendorParamCapability.aidl @@ -0,0 +1,43 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +import android.hardware.tv.mediaquality.ParameterDefaultValue; +import android.hardware.tv.mediaquality.ParameterRange; +import android.hardware.tv.mediaquality.VendorParameterIdentifier; + +/** + * Capability of vendor parameters. + */ +@VintfStability +parcelable VendorParamCapability { + /** Identifier of the parameter **/ + VendorParameterIdentifier identifier; + + /** true if this parameter is supported **/ + boolean isSupported; + + /** + * Default value of this parameter. null if there is no default value. + */ + @nullable ParameterDefaultValue defaultValue; + + /** + * The supported range of this parameter. null if there is no specific range. + */ + @nullable ParameterRange range; +} diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/VendorParameterIdentifier.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/VendorParameterIdentifier.aidl new file mode 100644 index 0000000000000000000000000000000000000000..f974b163bec028f4180fd418d06c662a523dc5bd --- /dev/null +++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/VendorParameterIdentifier.aidl @@ -0,0 +1,26 @@ +/* + * 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. + */ + +package android.hardware.tv.mediaquality; + +/** + * Identifier of vendor parameters. + */ +@VintfStability +parcelable VendorParameterIdentifier { + /** Identifier of the parameter **/ + ParcelableHolder identifier; +} diff --git a/tv/mediaquality/aidl/default/Android.bp b/tv/mediaquality/aidl/default/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..e25b01fdc50767615d3ab33da0c4984d606b71a0 --- /dev/null +++ b/tv/mediaquality/aidl/default/Android.bp @@ -0,0 +1,24 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +rust_binary { + name: "android.hardware.tv.mediaquality-service.example", + relative_install_path: "hw", + init_rc: ["mediaquality-default.rc"], + vintf_fragments: ["mediaquality-default.xml"], + vendor: true, + rustlibs: [ + "libandroid_logger", + "liblogger", + "liblog_rust", + "libbinder_rs", + "android.hardware.tv.mediaquality-V1-rust", + ], + srcs: ["main.rs"], +} diff --git a/tv/mediaquality/aidl/default/hal/media_quality_hal_impl.rs b/tv/mediaquality/aidl/default/hal/media_quality_hal_impl.rs new file mode 100644 index 0000000000000000000000000000000000000000..1946cec8d0b8a9b76eeb1ca1c3999e8bb2c5ba18 --- /dev/null +++ b/tv/mediaquality/aidl/default/hal/media_quality_hal_impl.rs @@ -0,0 +1,278 @@ +/* + * 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. + */ +//! This module implements the IMediaQuality AIDL interface. + +use android_hardware_tv_mediaquality::aidl::android::hardware::tv::mediaquality::{ + IMediaQuality::IMediaQuality, + IMediaQualityCallback::IMediaQualityCallback, + AmbientBacklightEvent::AmbientBacklightEvent, + AmbientBacklightSettings::AmbientBacklightSettings, + IPictureProfileAdjustmentListener::IPictureProfileAdjustmentListener, + IPictureProfileChangedListener::IPictureProfileChangedListener, + ParamCapability::ParamCapability, + ParameterName::ParameterName, + PictureParameters::PictureParameters, + ISoundProfileAdjustmentListener::ISoundProfileAdjustmentListener, + ISoundProfileChangedListener::ISoundProfileChangedListener, + SoundParameters::SoundParameters, + VendorParamCapability::VendorParamCapability, + VendorParameterIdentifier::VendorParameterIdentifier, +}; +use binder::{Interface, Strong}; +use std::sync::{Arc, Mutex}; +use std::thread; + +/// Defined so we can implement the IMediaQuality AIDL interface. +pub struct MediaQualityService { + callback: Arc>>>, + ambient_backlight_enabled: Arc>, + ambient_backlight_detector_settings: Arc>, + auto_pq_supported: Arc>, + auto_pq_enabled: Arc>, + auto_sr_supported: Arc>, + auto_sr_enabled: Arc>, + auto_aq_supported: Arc>, + auto_aq_enabled: Arc>, + picture_profile_adjustment_listener: + Arc>>>, + sound_profile_adjustment_listener: + Arc>>>, + picture_profile_changed_listener: Arc>>>, + sound_profile_changed_listener: Arc>>>, +} + +impl MediaQualityService { + + /// Create a new instance of the MediaQualityService. + pub fn new() -> Self { + Self { + callback: Arc::new(Mutex::new(None)), + ambient_backlight_enabled: Arc::new(Mutex::new(true)), + ambient_backlight_detector_settings: + Arc::new(Mutex::new(AmbientBacklightSettings::default())), + auto_pq_supported: Arc::new(Mutex::new(false)), + auto_pq_enabled: Arc::new(Mutex::new(false)), + auto_sr_supported: Arc::new(Mutex::new(false)), + auto_sr_enabled: Arc::new(Mutex::new(false)), + auto_aq_supported: Arc::new(Mutex::new(false)), + auto_aq_enabled: Arc::new(Mutex::new(false)), + picture_profile_adjustment_listener: Arc::new(Mutex::new(None)), + sound_profile_adjustment_listener: Arc::new(Mutex::new(None)), + picture_profile_changed_listener: Arc::new(Mutex::new(None)), + sound_profile_changed_listener: Arc::new(Mutex::new(None)), + } + } +} + +impl Interface for MediaQualityService {} + +impl IMediaQuality for MediaQualityService { + + fn setCallback( + &self, + callback: &Strong + ) -> binder::Result<()> { + println!("Received callback: {:?}", callback); + let mut cb = self.callback.lock().unwrap(); + *cb = Some(callback.clone()); + Ok(()) + } + + fn setAmbientBacklightDetector( + &self, + settings: &AmbientBacklightSettings + ) -> binder::Result<()> { + println!("Received settings: {:?}", settings); + let mut ambient_backlight_detector_settings = self.ambient_backlight_detector_settings.lock().unwrap(); + ambient_backlight_detector_settings.packageName = settings.packageName.clone(); + ambient_backlight_detector_settings.source = settings.source; + ambient_backlight_detector_settings.maxFramerate = settings.maxFramerate; + ambient_backlight_detector_settings.colorFormat = settings.colorFormat; + ambient_backlight_detector_settings.hZonesNumber = settings.hZonesNumber; + ambient_backlight_detector_settings.vZonesNumber = settings.vZonesNumber; + ambient_backlight_detector_settings.hasLetterbox = settings.hasLetterbox; + ambient_backlight_detector_settings.threshold = settings.threshold; + Ok(()) + } + + fn setAmbientBacklightDetectionEnabled(&self, enabled: bool) -> binder::Result<()> { + println!("Received enabled: {}", enabled); + let mut ambient_backlight_enabled = self.ambient_backlight_enabled.lock().unwrap(); + *ambient_backlight_enabled = enabled; + if enabled { + println!("Enable Ambient Backlight detection"); + thread::scope(|s| { + s.spawn(|| { + let cb = self.callback.lock().unwrap(); + if let Some(cb) = &*cb { + let enabled_event = AmbientBacklightEvent::Enabled(true); + cb.notifyAmbientBacklightEvent(&enabled_event).unwrap(); + } + }); + }); + } else { + println!("Disable Ambient Backlight detection"); + thread::scope(|s| { + s.spawn(|| { + let cb = self.callback.lock().unwrap(); + if let Some(cb) = &*cb { + let disabled_event = AmbientBacklightEvent::Enabled(false); + cb.notifyAmbientBacklightEvent(&disabled_event).unwrap(); + } + }); + }); + } + Ok(()) + } + + fn getAmbientBacklightDetectionEnabled(&self) -> binder::Result { + let ambient_backlight_enabled = self.ambient_backlight_enabled.lock().unwrap(); + Ok(*ambient_backlight_enabled) + } + + fn isAutoPqSupported(&self) -> binder::Result { + let auto_pq_supported = self.auto_pq_supported.lock().unwrap(); + Ok(*auto_pq_supported) + } + + fn getAutoPqEnabled(&self) -> binder::Result { + let auto_pq_enabled = self.auto_pq_enabled.lock().unwrap(); + Ok(*auto_pq_enabled) + } + + fn setAutoPqEnabled(&self, enabled: bool) -> binder::Result<()> { + let mut auto_pq_enabled = self.auto_pq_enabled.lock().unwrap(); + *auto_pq_enabled = enabled; + if enabled { + println!("Enable auto picture quality"); + } else { + println!("Disable auto picture quality"); + } + Ok(()) + } + + fn isAutoSrSupported(&self) -> binder::Result { + let auto_sr_supported = self.auto_sr_supported.lock().unwrap(); + Ok(*auto_sr_supported) + } + + fn getAutoSrEnabled(&self) -> binder::Result { + let auto_sr_enabled = self.auto_sr_enabled.lock().unwrap(); + Ok(*auto_sr_enabled) + } + + fn setAutoSrEnabled(&self, enabled: bool) -> binder::Result<()> { + let mut auto_sr_enabled = self.auto_sr_enabled.lock().unwrap(); + *auto_sr_enabled = enabled; + if enabled { + println!("Enable auto super resolution"); + } else { + println!("Disable auto super resolution"); + } + Ok(()) + } + + fn isAutoAqSupported(&self) -> binder::Result { + let auto_aq_supported = self.auto_aq_supported.lock().unwrap(); + Ok(*auto_aq_supported) + } + + fn getAutoAqEnabled(&self) -> binder::Result { + let auto_aq_enabled = self.auto_aq_enabled.lock().unwrap(); + Ok(*auto_aq_enabled) + } + + fn setAutoAqEnabled(&self, enabled: bool) -> binder::Result<()> { + let mut auto_aq_enabled = self.auto_aq_enabled.lock().unwrap(); + *auto_aq_enabled = enabled; + if enabled { + println!("Enable auto audio quality"); + } else { + println!("Disable auto audio quality"); + } + Ok(()) + } + + fn getPictureProfileListener(&self) -> binder::Result> { + println!("getPictureProfileListener"); + let listener = self.picture_profile_changed_listener.lock().unwrap(); + listener.clone().ok_or(binder::StatusCode::UNKNOWN_ERROR.into()) + } + + fn setPictureProfileAdjustmentListener( + &self, + picture_profile_adjustment_listener: &Strong + ) -> binder::Result<()> { + println!("Received picture profile adjustment"); + let mut listener = self.picture_profile_adjustment_listener.lock().unwrap(); + *listener = Some(picture_profile_adjustment_listener.clone()); + Ok(()) + } + + fn sendDefaultPictureParameters(&self, _picture_parameters: &PictureParameters) -> binder::Result<()>{ + println!("Received picture parameters"); + Ok(()) + } + + fn getSoundProfileListener(&self) -> binder::Result> { + println!("getSoundProfileListener"); + let listener = self.sound_profile_changed_listener.lock().unwrap(); + listener.clone().ok_or(binder::StatusCode::UNKNOWN_ERROR.into()) + } + + fn setSoundProfileAdjustmentListener( + &self, + sound_profile_adjustment_listener: &Strong + ) -> binder::Result<()> { + println!("Received sound profile adjustment"); + let mut listener = self.sound_profile_adjustment_listener.lock().unwrap(); + *listener = Some(sound_profile_adjustment_listener.clone()); + Ok(()) + } + + fn sendDefaultSoundParameters(&self, _sound_parameters: &SoundParameters) -> binder::Result<()>{ + println!("Received sound parameters"); + Ok(()) + } + + fn getParamCaps( + &self, + param_names: &[ParameterName], + _caps: &mut Vec + ) -> binder::Result<()> { + println!("getParamCaps. len= {}", param_names.len()); + Ok(()) + } + + fn getVendorParamCaps( + &self, + param_names: &[VendorParameterIdentifier], + _caps: &mut Vec + ) -> binder::Result<()> { + println!("getVendorParamCaps. len= {}", param_names.len()); + Ok(()) + } + + fn sendPictureParameters(&self, _picture_parameters: &PictureParameters) -> binder::Result<()>{ + println!("Received picture parameters"); + Ok(()) + } + + fn sendSoundParameters(&self, _sound_parameters: &SoundParameters) -> binder::Result<()>{ + println!("Received sound parameters"); + Ok(()) + } +} diff --git a/tv/mediaquality/aidl/default/hal/mod.rs b/tv/mediaquality/aidl/default/hal/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..5b5d4ac18f3a59aa9f9ed140ac23e60b6484da0a --- /dev/null +++ b/tv/mediaquality/aidl/default/hal/mod.rs @@ -0,0 +1,17 @@ +/* + * 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. + */ + +pub mod media_quality_hal_impl; \ No newline at end of file diff --git a/tv/mediaquality/aidl/default/main.rs b/tv/mediaquality/aidl/default/main.rs new file mode 100644 index 0000000000000000000000000000000000000000..f0cccb439ca4167075145c06a98839484b1cbbe7 --- /dev/null +++ b/tv/mediaquality/aidl/default/main.rs @@ -0,0 +1,45 @@ +/* + * 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. + */ +//! This implements the MediaQuality Example Service. +use android_hardware_tv_mediaquality::aidl::android::hardware::tv::mediaquality::IMediaQuality::{BnMediaQuality, IMediaQuality}; +use binder::BinderFeatures; + +mod hal; +use hal::media_quality_hal_impl::MediaQualityService; + +const LOG_TAG: &str = "mediaquality_service_example_rust"; + +use log::LevelFilter; + +fn main() { + + android_logger::init_once( + android_logger::Config::default() + .with_tag(LOG_TAG) + .with_max_level(LevelFilter::Info), + ); + + let media_quality_service = MediaQualityService::new(); + let media_quality_service_binder = BnMediaQuality::new_binder(media_quality_service, BinderFeatures::default()); + + let service_name = format!("{}/default", MediaQualityService::get_descriptor()); + binder::add_service(&service_name, media_quality_service_binder.as_binder()) + .expect("Failed to register service"); + + log::info!("MediaQualityHal service is running..."); + + binder::ProcessState::join_thread_pool(); +} diff --git a/tv/mediaquality/aidl/default/mediaquality-default.rc b/tv/mediaquality/aidl/default/mediaquality-default.rc new file mode 100644 index 0000000000000000000000000000000000000000..5a103a9909b1bb51d85fa3afbe80cc3f127eb41d --- /dev/null +++ b/tv/mediaquality/aidl/default/mediaquality-default.rc @@ -0,0 +1,4 @@ +service vendor.mediaquality-default /vendor/bin/hw/android.hardware.tv.mediaquality-service.example + class hal + user nobody + group nobody diff --git a/tv/mediaquality/aidl/default/mediaquality-default.xml b/tv/mediaquality/aidl/default/mediaquality-default.xml new file mode 100644 index 0000000000000000000000000000000000000000..865f663f27a14b36fc7eb69b9fa871134f7a3293 --- /dev/null +++ b/tv/mediaquality/aidl/default/mediaquality-default.xml @@ -0,0 +1,6 @@ + + + android.hardware.tv.mediaquality + IMediaQuality/default + + \ No newline at end of file diff --git a/tv/mediaquality/aidl/vts/functional/Android.bp b/tv/mediaquality/aidl/vts/functional/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..226569e26b885d1b68c1831321672d9c57ee603b --- /dev/null +++ b/tv/mediaquality/aidl/vts/functional/Android.bp @@ -0,0 +1,42 @@ +// 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. + +package { + default_team: "trendy_team_tv_os", + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_test { + name: "VtsHalMediaQualityTargetTest", + defaults: [ + "VtsHalTargetTestDefaults", + "use_libaidlvintf_gtest_helper_static", + ], + srcs: ["VtsHalMediaQualityTest.cpp"], + shared_libs: [ + "libbinder", + "libbinder_ndk", + ], + static_libs: [ + "android.hardware.tv.mediaquality-V1-ndk", + ], + test_suites: [ + "vts", + ], +} diff --git a/tv/mediaquality/aidl/vts/functional/VtsHalMediaQualityTest.cpp b/tv/mediaquality/aidl/vts/functional/VtsHalMediaQualityTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..84f798bd4cd006de0e787f26743dee5e97131324 --- /dev/null +++ b/tv/mediaquality/aidl/vts/functional/VtsHalMediaQualityTest.cpp @@ -0,0 +1,280 @@ +/* + * 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. + */ +#define LOG_TAG "ambient_backlight_aidl_hal_test" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +using aidl::android::hardware::graphics::common::PixelFormat; +using aidl::android::hardware::tv::mediaquality::AmbientBacklightEvent; +using aidl::android::hardware::tv::mediaquality::AmbientBacklightSettings; +using aidl::android::hardware::tv::mediaquality::AmbientBacklightSource; +using aidl::android::hardware::tv::mediaquality::BnMediaQualityCallback; +using aidl::android::hardware::tv::mediaquality::BnPictureProfileAdjustmentListener; +using aidl::android::hardware::tv::mediaquality::BnSoundProfileAdjustmentListener; +using aidl::android::hardware::tv::mediaquality::IMediaQuality; +using aidl::android::hardware::tv::mediaquality::ParamCapability; +using aidl::android::hardware::tv::mediaquality::PictureParameter; +using aidl::android::hardware::tv::mediaquality::PictureParameters; +using aidl::android::hardware::tv::mediaquality::PictureProfile; +using aidl::android::hardware::tv::mediaquality::SoundParameter; +using aidl::android::hardware::tv::mediaquality::SoundParameters; +using aidl::android::hardware::tv::mediaquality::SoundProfile; +using aidl::android::hardware::tv::mediaquality::VendorParamCapability; +using aidl::android::hardware::tv::mediaquality::VendorParameterIdentifier; +using android::ProcessState; +using android::String16; +using ndk::ScopedAStatus; +using ndk::SpAIBinder; + +#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk()) +#define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk()) + +class MediaQualityCallback : public BnMediaQualityCallback { + public: + explicit MediaQualityCallback( + const std::function& on_hal_event_cb) + : on_hal_event_cb_(on_hal_event_cb) {} + ScopedAStatus notifyAmbientBacklightEvent(const AmbientBacklightEvent& event) override { + on_hal_event_cb_(event); + return ScopedAStatus::ok(); + } + + private: + std::function on_hal_event_cb_; +}; + +class PictureProfileAdjustmentListener : public BnPictureProfileAdjustmentListener { + public: + explicit PictureProfileAdjustmentListener( + const std::function& + on_hal_picture_profile_adjust) + : on_hal_picture_profile_adjust_(on_hal_picture_profile_adjust) {} + ScopedAStatus onPictureProfileAdjusted(const PictureProfile& pictureProfile) override { + on_hal_picture_profile_adjust_(pictureProfile); + return ScopedAStatus::ok(); + } + + ScopedAStatus onParamCapabilityChanged(int64_t, const std::vector&) override { + return ScopedAStatus::ok(); + } + + ScopedAStatus onVendorParamCapabilityChanged(int64_t, + const std::vector&) { + return ScopedAStatus::ok(); + } + + ScopedAStatus onRequestPictureParameters(int64_t) { return ScopedAStatus::ok(); } + + private: + std::function on_hal_picture_profile_adjust_; +}; + +class SoundProfileAdjustmentListener : public BnSoundProfileAdjustmentListener { + public: + explicit SoundProfileAdjustmentListener( + const std::function& + on_hal_sound_profile_adjust) + : on_hal_sound_profile_adjust_(on_hal_sound_profile_adjust) {} + ScopedAStatus onSoundProfileAdjusted(const SoundProfile& soundProfile) override { + on_hal_sound_profile_adjust_(soundProfile); + return ScopedAStatus::ok(); + } + + ScopedAStatus onParamCapabilityChanged(int64_t, const std::vector&) override { + return ScopedAStatus::ok(); + } + + ScopedAStatus onVendorParamCapabilityChanged(int64_t, + const std::vector&) { + return ScopedAStatus::ok(); + } + + ScopedAStatus onRequestSoundParameters(int64_t) { return ScopedAStatus::ok(); } + + private: + std::function on_hal_sound_profile_adjust_; +}; + +class MediaQualityAidl : public testing::TestWithParam { + public: + virtual void SetUp() override { + mediaquality = IMediaQuality::fromBinder( + SpAIBinder(AServiceManager_waitForService(GetParam().c_str()))); + ASSERT_NE(mediaquality, nullptr); + } + std::shared_ptr mediaquality; +}; + +TEST_P(MediaQualityAidl, TestSetAmbientBacklightDetectionEnabled) { + std::promise open_cb_promise; + std::future open_cb_future{open_cb_promise.get_future()}; + std::shared_ptr callback = + ndk::SharedRefBase::make([&open_cb_promise](auto event) { + EXPECT_EQ(event.getTag(), AmbientBacklightEvent::Tag::enabled); + EXPECT_EQ(event.template get(), true); + open_cb_promise.set_value(); + return ScopedAStatus::ok(); + }); + ASSERT_OK(mediaquality->setCallback(callback)); + ASSERT_OK(mediaquality->setAmbientBacklightDetectionEnabled(true)); + std::chrono::milliseconds timeout{10000}; + EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready); +} + +TEST_P(MediaQualityAidl, TestGetAmbientBacklightDetectionEnabled) { + bool enabled; + ASSERT_OK(mediaquality->getAmbientBacklightDetectionEnabled(&enabled)); +} + +TEST_P(MediaQualityAidl, TestSetMediaQualityCallback) { + std::shared_ptr callback = ndk::SharedRefBase::make( + [](auto /* event */) { return ScopedAStatus::ok(); }); + ASSERT_OK(mediaquality->setCallback(callback)); +} + +TEST_P(MediaQualityAidl, TestSetPictureProfileAdjustmentListener) { + std::shared_ptr listener = + ndk::SharedRefBase::make( + [](auto /*picture profile*/) { return ScopedAStatus::ok(); }); + ASSERT_OK(mediaquality->setPictureProfileAdjustmentListener(listener)); +} + +TEST_P(MediaQualityAidl, TestSendDefaultPictureParameters) { + PictureParameters pictureParameters; + std::vector picParams; + + PictureParameter brightnessParam; + brightnessParam.set(0.5f); + picParams.push_back(brightnessParam); + + PictureParameter contrastParam; + contrastParam.set(50); + picParams.push_back(contrastParam); + + pictureParameters.pictureParameters = picParams; + ASSERT_OK(mediaquality->sendDefaultPictureParameters(pictureParameters)); +} + +TEST_P(MediaQualityAidl, TestSetSoundProfileAdjustmentListener) { + std::shared_ptr listener = + ndk::SharedRefBase::make( + [](auto /*sound profile*/) { return ScopedAStatus::ok(); }); + ASSERT_OK(mediaquality->setSoundProfileAdjustmentListener(listener)); +} + +TEST_P(MediaQualityAidl, TestSendDefaultSoundParameters) { + SoundParameters soundParameters; + std::vector soundParams; + + SoundParameter balanceParam; + balanceParam.set(50); + soundParams.push_back(balanceParam); + + SoundParameter bassParam; + bassParam.set(50); + soundParams.push_back(bassParam); + + soundParameters.soundParameters = soundParams; + ASSERT_OK(mediaquality->sendDefaultSoundParameters(soundParameters)); +} + +TEST_P(MediaQualityAidl, TestSetAmbientBacklightDetector) { + AmbientBacklightSettings in_settings = { + .packageName = "com.android.mediaquality", + .source = AmbientBacklightSource::VIDEO, + .colorFormat = PixelFormat::RGB_888, + .hZonesNumber = 32, + .vZonesNumber = 20, + .hasLetterbox = true, + .threshold = 0, + }; + ASSERT_OK(mediaquality->setAmbientBacklightDetector(in_settings)); +} + +TEST_P(MediaQualityAidl, TestIsAutoPqSupported) { + bool supported; + ASSERT_OK(mediaquality->isAutoPqSupported(&supported)); +} + +TEST_P(MediaQualityAidl, TestGetAutoPqEnabled) { + bool enabled; + ASSERT_OK(mediaquality->getAutoPqEnabled(&enabled)); +} + +TEST_P(MediaQualityAidl, TestSetAutoPqEnabled) { + ASSERT_OK(mediaquality->setAutoPqEnabled(true)); +} + +TEST_P(MediaQualityAidl, TestIsAutoSrSupported) { + bool supported; + ASSERT_OK(mediaquality->isAutoSrSupported(&supported)); +} + +TEST_P(MediaQualityAidl, TestGetAutoSrEnabled) { + bool enabled; + ASSERT_OK(mediaquality->getAutoSrEnabled(&enabled)); +} + +TEST_P(MediaQualityAidl, TestSetAutoSrEnabled) { + ASSERT_OK(mediaquality->setAutoSrEnabled(true)); +} + +TEST_P(MediaQualityAidl, TestIsAutoAqSupported) { + bool supported; + ASSERT_OK(mediaquality->isAutoAqSupported(&supported)); +} + +TEST_P(MediaQualityAidl, TestGetAutoAqEnabled) { + bool enabled; + ASSERT_OK(mediaquality->getAutoAqEnabled(&enabled)); +} + +TEST_P(MediaQualityAidl, TestSetAutoAqEnabled) { + ASSERT_OK(mediaquality->setAutoAqEnabled(true)); +} + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MediaQualityAidl); + +INSTANTIATE_TEST_SUITE_P( + PerInstance, MediaQualityAidl, + testing::ValuesIn(android::getAidlHalInstanceNames(IMediaQuality::descriptor)), + android::PrintInstanceNameToString); + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + ProcessState::self()->setThreadPoolMaxThreadCount(1); + ProcessState::self()->startThreadPool(); + return RUN_ALL_TESTS(); +} diff --git a/tv/tuner/aidl/Android.bp b/tv/tuner/aidl/Android.bp index efcc32773444333e3df19f2b3f9c62379969a4af..e53e84d19c695d37102d0af3ed963f0bdb864fc8 100644 --- a/tv/tuner/aidl/Android.bp +++ b/tv/tuner/aidl/Android.bp @@ -39,7 +39,7 @@ aidl_interface { "android.hardware.common.fmq-V1", ], }, - ], + frozen: false, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/AudioPreselectionRenderingIndicationType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/AudioPreselectionRenderingIndicationType.aidl index 783511fea81701486ed7ad818fae83e48ad47064..2977ff6ebcd13ab188dec2bc236be29ab47fdfb7 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/AudioPreselectionRenderingIndicationType.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/AudioPreselectionRenderingIndicationType.aidl @@ -35,9 +35,9 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum AudioPreselectionRenderingIndicationType { - NOT_INDICATED = 0, - STEREO = 1, - TWO_DIMENSIONAL = 2, - THREE_DIMENSIONAL = 3, - HEADPHONE = 4, + NOT_INDICATED, + STEREO, + TWO_DIMENSIONAL, + THREE_DIMENSIONAL, + HEADPHONE, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/AudioPresentation.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/AudioPresentation.aidl index 96a6d987c9a107bfa723b68e87d633d8df15ff98..eba820c6b57da4befe0e8b47eeaa8e2ee701ed00 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/AudioPresentation.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/AudioPresentation.aidl @@ -36,5 +36,5 @@ package android.hardware.tv.tuner; @VintfStability parcelable AudioPresentation { android.hardware.tv.tuner.AudioPreselection preselection; - int ac4ShortProgramId = -1; + int ac4ShortProgramId = (-1) /* -1 */; } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/AudioStreamType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/AudioStreamType.aidl index 6c538ea951e420d3a124a708eab788f98676d3d0..4754bb121f4b648a5177acc10deb94c599cbd5ec 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/AudioStreamType.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/AudioStreamType.aidl @@ -35,24 +35,24 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum AudioStreamType { - UNDEFINED = 0, - PCM = 1, - MP3 = 2, - MPEG1 = 3, - MPEG2 = 4, - MPEGH = 5, - AAC = 6, - AC3 = 7, - EAC3 = 8, - AC4 = 9, - DTS = 10, - DTS_HD = 11, - WMA = 12, - OPUS = 13, - VORBIS = 14, - DRA = 15, - AAC_ADTS = 16, - AAC_LATM = 17, - AAC_HE_ADTS = 18, - AAC_HE_LATM = 19, + UNDEFINED, + PCM, + MP3, + MPEG1, + MPEG2, + MPEGH, + AAC, + AC3, + EAC3, + AC4, + DTS, + DTS_HD, + WMA, + OPUS, + VORBIS, + DRA, + AAC_ADTS, + AAC_LATM, + AAC_HE_ADTS, + AAC_HE_LATM, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/Constant.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/Constant.aidl index 95ecc51e6c7592efc2671be49e932ef314ee65ce..1f7153b9c93ea9d1906c468923ec398dd64631f1 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/Constant.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/Constant.aidl @@ -35,17 +35,17 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum Constant { - INVALID_TS_PID = 65535, - INVALID_STREAM_ID = 65535, - INVALID_FILTER_ID = -1, - INVALID_AV_SYNC_ID = -1, - INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM = -1, - INVALID_FIRST_MACROBLOCK_IN_SLICE = -1, - INVALID_FRONTEND_SETTING_FREQUENCY = -1, - INVALID_IP_FILTER_CONTEXT_ID = -1, - INVALID_LTS_ID = -1, - INVALID_FRONTEND_ID = -1, - INVALID_LNB_ID = -1, - INVALID_KEYTOKEN = 0, - INVALID_TABINFO_VERSION = -1, + INVALID_TS_PID = 0xFFFF, + INVALID_STREAM_ID = 0xFFFF, + INVALID_FILTER_ID = 0xFFFFFFFF, + INVALID_AV_SYNC_ID = 0xFFFFFFFF, + INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM = 0xFFFFFFFF, + INVALID_FIRST_MACROBLOCK_IN_SLICE = 0xFFFFFFFF, + INVALID_FRONTEND_SETTING_FREQUENCY = 0xFFFFFFFF, + INVALID_IP_FILTER_CONTEXT_ID = 0xFFFFFFFF, + INVALID_LTS_ID = 0xFFFFFFFF, + INVALID_FRONTEND_ID = 0xFFFFFFFF, + INVALID_LNB_ID = 0xFFFFFFFF, + INVALID_KEYTOKEN = 0x00, + INVALID_TABINFO_VERSION = 0xFFFFFFFF, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/Constant64Bit.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/Constant64Bit.aidl index a56a0cf2f905bab256ace88b3e2104dab0edc6c1..ccbfd1a5c412a03a91c453428e05854a83ac0754 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/Constant64Bit.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/Constant64Bit.aidl @@ -35,7 +35,7 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="long") @VintfStability enum Constant64Bit { - INVALID_FILTER_ID_64BIT = -1, - INVALID_AV_SYNC_ID_64BIT = -1, - INVALID_PRESENTATION_TIME_STAMP = -1, + INVALID_FILTER_ID_64BIT = 0xFFFFFFFFFFFFFFFF, + INVALID_AV_SYNC_ID_64BIT = 0xFFFFFFFFFFFFFFFF, + INVALID_PRESENTATION_TIME_STAMP = 0xFFFFFFFFFFFFFFFF, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DataFormat.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DataFormat.aidl index 3b8fee403d7efe26ba12ff4e133411a0da2737cf..5fb34baab53c790c52d7803de933a987acd156c2 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DataFormat.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DataFormat.aidl @@ -35,9 +35,9 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum DataFormat { - TS = 0, - PES = 1, - ES = 2, - SHV_TLV = 3, - UNDEFINED = 4, + TS, + PES, + ES, + SHV_TLV, + UNDEFINED, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxAlpFilterType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxAlpFilterType.aidl index f0df497ed2b9e948b4a0666ff6afdb6fbd441df2..c164f192829f27d4aa831dd3af5d0e2e7b8544fe 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxAlpFilterType.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxAlpFilterType.aidl @@ -35,8 +35,8 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum DemuxAlpFilterType { - UNDEFINED = 0, - SECTION = 1, - PTP = 2, - PAYLOAD_THROUGH = 3, + UNDEFINED, + SECTION, + PTP, + PAYLOAD_THROUGH, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxAlpLengthType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxAlpLengthType.aidl index ccca6de8c6f62efce188c4811f02172734483fd7..59edc34007fcddf6dd1e7a60abca67017e49e1e9 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxAlpLengthType.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxAlpLengthType.aidl @@ -36,6 +36,6 @@ package android.hardware.tv.tuner; @Backing(type="byte") @VintfStability enum DemuxAlpLengthType { UNDEFINED = 0, - WITHOUT_ADDITIONAL_HEADER = 1, - WITH_ADDITIONAL_HEADER = 2, + WITHOUT_ADDITIONAL_HEADER, + WITH_ADDITIONAL_HEADER, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMainType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMainType.aidl index 6abd87b0f305ed6619d9310088adf99271d3eb3a..b78965dfd3203fa4357bfb35d6d1fef204adcf2c 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMainType.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMainType.aidl @@ -36,9 +36,9 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum DemuxFilterMainType { UNDEFINED = 0, - TS = 1, - MMTP = 2, - IP = 4, - TLV = 8, - ALP = 16, + TS = (1 << 0) /* 1 */, + MMTP = (1 << 1) /* 2 */, + IP = (1 << 2) /* 4 */, + TLV = (1 << 3) /* 8 */, + ALP = (1 << 4) /* 16 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl index 61a955590e1a32139b755fa6b2fa6ad620624621..126c740f6bd698a4fc645542a1f828269bccb85a 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl @@ -49,4 +49,7 @@ parcelable DemuxFilterMediaEvent { boolean isPesPrivateData; android.hardware.tv.tuner.DemuxFilterMediaEventExtraMetaData extraMetaData; android.hardware.tv.tuner.DemuxFilterScIndexMask scIndexMask; + int numDataPieces; + int indexInDataGroup; + int dataGroupId; } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMonitorEventType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMonitorEventType.aidl index 5d27f7602509c2da26ad9060bd73f2c01d01b6ee..062650b2e3d3551290fd898a15e90280f38d4989 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMonitorEventType.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMonitorEventType.aidl @@ -35,6 +35,6 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum DemuxFilterMonitorEventType { - SCRAMBLING_STATUS = 1, - IP_CID_CHANGE = 2, + SCRAMBLING_STATUS = (1 << 0) /* 1 */, + IP_CID_CHANGE = (1 << 1) /* 2 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterStatus.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterStatus.aidl index 1dc593ac18e39a53cbfca8e4995bde1786bc5708..cfc5838946a7388ddedbfbaa873a32cb3efe0fbe 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterStatus.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterStatus.aidl @@ -35,9 +35,9 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="byte") @VintfStability enum DemuxFilterStatus { - DATA_READY = 1, - LOW_WATER = 2, - HIGH_WATER = 4, - OVERFLOW = 8, - NO_DATA = 16, + DATA_READY = (1 << 0) /* 1 */, + LOW_WATER = (1 << 1) /* 2 */, + HIGH_WATER = (1 << 2) /* 4 */, + OVERFLOW = (1 << 3) /* 8 */, + NO_DATA = (1 << 4) /* 16 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxInfo.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxInfo.aidl index 872d9634d103ada3791d31a33373bc08d9af20af..12f9dc8a054815499cc814cf9e3d1d3fb9dc04d6 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxInfo.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxInfo.aidl @@ -35,5 +35,5 @@ package android.hardware.tv.tuner; /* @hide */ @VintfStability parcelable DemuxInfo { - int filterTypes = 0; + int filterTypes = android.hardware.tv.tuner.DemuxFilterMainType.UNDEFINED /* 0 */; } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxIpFilterType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxIpFilterType.aidl index b78ac9a69e143abdeca72eac80e7c525639cd380..7320aec497ff6018c4dd96ca8e60f535345f946a 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxIpFilterType.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxIpFilterType.aidl @@ -35,10 +35,10 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum DemuxIpFilterType { - UNDEFINED = 0, - SECTION = 1, - NTP = 2, - IP_PAYLOAD = 3, - IP = 4, - PAYLOAD_THROUGH = 5, + UNDEFINED, + SECTION, + NTP, + IP_PAYLOAD, + IP, + PAYLOAD_THROUGH, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxMmtpFilterType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxMmtpFilterType.aidl index 7e9e3a64a75df9d728227cb7a33823b83f0d64dd..a89c5b1650a240e8d9d8ef39bba39b4c6a3a4fdf 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxMmtpFilterType.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxMmtpFilterType.aidl @@ -35,12 +35,12 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum DemuxMmtpFilterType { - UNDEFINED = 0, - SECTION = 1, - PES = 2, - MMTP = 3, - AUDIO = 4, - VIDEO = 5, - RECORD = 6, - DOWNLOAD = 7, + UNDEFINED, + SECTION, + PES, + MMTP, + AUDIO, + VIDEO, + RECORD, + DOWNLOAD, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxQueueNotifyBits.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxQueueNotifyBits.aidl index bcd0aebbdeb96657e07355569a535db2303fc625..ecb4e8b28e33b0509d31874b1aaa266ee42b2290 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxQueueNotifyBits.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxQueueNotifyBits.aidl @@ -35,6 +35,6 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum DemuxQueueNotifyBits { - DATA_READY = 1, - DATA_CONSUMED = 2, + DATA_READY = (1 << 0) /* 1 */, + DATA_CONSUMED = (1 << 1) /* 2 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxRecordScIndexType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxRecordScIndexType.aidl index fb4430bbee00febc3ff61ebc0bff10f34933c0c0..5556bb2533219c70a0641d152acf88802e03c330 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxRecordScIndexType.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxRecordScIndexType.aidl @@ -35,9 +35,9 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum DemuxRecordScIndexType { - NONE = 0, - SC = 1, - SC_HEVC = 2, - SC_AVC = 3, - SC_VVC = 4, + NONE, + SC, + SC_HEVC, + SC_AVC, + SC_VVC, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxScAvcIndex.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxScAvcIndex.aidl index 651b66c3450906be52919abdab8f7d0d79ce9b9c..5c5179304e19c3cf7a70e05e34f1da542c16b113 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxScAvcIndex.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxScAvcIndex.aidl @@ -36,9 +36,9 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum DemuxScAvcIndex { UNDEFINED = 0, - I_SLICE = 1, - P_SLICE = 2, - B_SLICE = 4, - SI_SLICE = 8, - SP_SLICE = 16, + I_SLICE = (1 << 0) /* 1 */, + P_SLICE = (1 << 1) /* 2 */, + B_SLICE = (1 << 2) /* 4 */, + SI_SLICE = (1 << 3) /* 8 */, + SP_SLICE = (1 << 4) /* 16 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxScHevcIndex.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxScHevcIndex.aidl index 670b34e62a28ad506f13356059ec2275e680aba4..d07bcb7ba31110ad85a6faad7a15e26ad1e464b5 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxScHevcIndex.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxScHevcIndex.aidl @@ -36,12 +36,12 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum DemuxScHevcIndex { UNDEFINED = 0, - SPS = 1, - AUD = 2, - SLICE_CE_BLA_W_LP = 4, - SLICE_BLA_W_RADL = 8, - SLICE_BLA_N_LP = 16, - SLICE_IDR_W_RADL = 32, - SLICE_IDR_N_LP = 64, - SLICE_TRAIL_CRA = 128, + SPS = (1 << 0) /* 1 */, + AUD = (1 << 1) /* 2 */, + SLICE_CE_BLA_W_LP = (1 << 2) /* 4 */, + SLICE_BLA_W_RADL = (1 << 3) /* 8 */, + SLICE_BLA_N_LP = (1 << 4) /* 16 */, + SLICE_IDR_W_RADL = (1 << 5) /* 32 */, + SLICE_IDR_N_LP = (1 << 6) /* 64 */, + SLICE_TRAIL_CRA = (1 << 7) /* 128 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxScIndex.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxScIndex.aidl index 25f058571580f9b86c016c304f41d0e05a5ee338..509c1abbc8f06324be46a3bce884e1c077d47fa8 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxScIndex.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxScIndex.aidl @@ -36,8 +36,8 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum DemuxScIndex { UNDEFINED = 0, - I_FRAME = 1, - P_FRAME = 2, - B_FRAME = 4, - SEQUENCE = 8, + I_FRAME = (1 << 0) /* 1 */, + P_FRAME = (1 << 1) /* 2 */, + B_FRAME = (1 << 2) /* 4 */, + SEQUENCE = (1 << 3) /* 8 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxScVvcIndex.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxScVvcIndex.aidl index 3e08d26b59b8f289123ce70d5a15fd5d11216839..ac3a5e668f42492ff1e1c2a910af36cae5432b9e 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxScVvcIndex.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxScVvcIndex.aidl @@ -36,11 +36,11 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum DemuxScVvcIndex { UNDEFINED = 0, - SLICE_IDR_W_RADL = 1, - SLICE_IDR_N_LP = 2, - SLICE_CRA = 4, - SLICE_GDR = 8, - VPS = 16, - SPS = 32, - AUD = 64, + SLICE_IDR_W_RADL = (1 << 0) /* 1 */, + SLICE_IDR_N_LP = (1 << 1) /* 2 */, + SLICE_CRA = (1 << 2) /* 4 */, + SLICE_GDR = (1 << 3) /* 8 */, + VPS = (1 << 4) /* 16 */, + SPS = (1 << 5) /* 32 */, + AUD = (1 << 6) /* 64 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTlvFilterType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTlvFilterType.aidl index a4e1ff176e8adc9886d420d15ca9a669692aa194..bd9e58315090315af9ca5038535e8c1e1e97076e 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTlvFilterType.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTlvFilterType.aidl @@ -35,8 +35,8 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum DemuxTlvFilterType { - UNDEFINED = 0, - SECTION = 1, - TLV = 2, - PAYLOAD_THROUGH = 3, + UNDEFINED, + SECTION, + TLV, + PAYLOAD_THROUGH, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTsFilterType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTsFilterType.aidl index 8b806bf6ec478e1be9ab659a20954b446aafac89..8be0e9550836d2363f455e1f02c193fff0490ead 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTsFilterType.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTsFilterType.aidl @@ -35,13 +35,13 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum DemuxTsFilterType { - UNDEFINED = 0, - SECTION = 1, - PES = 2, - TS = 3, - AUDIO = 4, - VIDEO = 5, - PCR = 6, - RECORD = 7, - TEMI = 8, + UNDEFINED, + SECTION, + PES, + TS, + AUDIO, + VIDEO, + PCR, + RECORD, + TEMI, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTsIndex.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTsIndex.aidl index ed034779f9d85dd4ec85b6b56aa1a31ce407ff2c..9ca684f4b22c5d047680eef4cf12430c6bf6831c 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTsIndex.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTsIndex.aidl @@ -35,22 +35,22 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum DemuxTsIndex { - FIRST_PACKET = 1, - PAYLOAD_UNIT_START_INDICATOR = 2, - CHANGE_TO_NOT_SCRAMBLED = 4, - CHANGE_TO_EVEN_SCRAMBLED = 8, - CHANGE_TO_ODD_SCRAMBLED = 16, - DISCONTINUITY_INDICATOR = 32, - RANDOM_ACCESS_INDICATOR = 64, - PRIORITY_INDICATOR = 128, - PCR_FLAG = 256, - OPCR_FLAG = 512, - SPLICING_POINT_FLAG = 1024, - PRIVATE_DATA = 2048, - ADAPTATION_EXTENSION_FLAG = 4096, - MPT_INDEX_MPT = 65536, - MPT_INDEX_VIDEO = 131072, - MPT_INDEX_AUDIO = 262144, - MPT_INDEX_TIMESTAMP_TARGET_VIDEO = 524288, - MPT_INDEX_TIMESTAMP_TARGET_AUDIO = 1048576, + FIRST_PACKET = (1 << 0) /* 1 */, + PAYLOAD_UNIT_START_INDICATOR = (1 << 1) /* 2 */, + CHANGE_TO_NOT_SCRAMBLED = (1 << 2) /* 4 */, + CHANGE_TO_EVEN_SCRAMBLED = (1 << 3) /* 8 */, + CHANGE_TO_ODD_SCRAMBLED = (1 << 4) /* 16 */, + DISCONTINUITY_INDICATOR = (1 << 5) /* 32 */, + RANDOM_ACCESS_INDICATOR = (1 << 6) /* 64 */, + PRIORITY_INDICATOR = (1 << 7) /* 128 */, + PCR_FLAG = (1 << 8) /* 256 */, + OPCR_FLAG = (1 << 9) /* 512 */, + SPLICING_POINT_FLAG = (1 << 10) /* 1024 */, + PRIVATE_DATA = (1 << 11) /* 2048 */, + ADAPTATION_EXTENSION_FLAG = (1 << 12) /* 4096 */, + MPT_INDEX_MPT = (1 << 16) /* 65536 */, + MPT_INDEX_VIDEO = (1 << 17) /* 131072 */, + MPT_INDEX_AUDIO = (1 << 18) /* 262144 */, + MPT_INDEX_TIMESTAMP_TARGET_VIDEO = (1 << 19) /* 524288 */, + MPT_INDEX_TIMESTAMP_TARGET_AUDIO = (1 << 20) /* 1048576 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DvrType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DvrType.aidl index 3a0c1e421e3844007654f1c882b9d2b4914e764b..6dab74b301b353baddd8b6bb6f7280e76ee666c3 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DvrType.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DvrType.aidl @@ -35,6 +35,6 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="byte") @VintfStability enum DvrType { - RECORD = 0, - PLAYBACK = 1, + RECORD, + PLAYBACK, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FilterDelayHintType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FilterDelayHintType.aidl index 8c5a3f5cf1f06780d22bb744740766e3acc036df..af35c70e5dc3833ed8593306cfeeb5738330ad22 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FilterDelayHintType.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FilterDelayHintType.aidl @@ -35,7 +35,7 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum FilterDelayHintType { - INVALID = 0, - TIME_DELAY_IN_MS = 1, - DATA_SIZE_DELAY_IN_BYTES = 2, + INVALID, + TIME_DELAY_IN_MS, + DATA_SIZE_DELAY_IN_BYTES, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAnalogAftFlag.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAnalogAftFlag.aidl index 6b32110389b8f9e86d7a81ecc36c75405c16ee67..45aa2af49854ef03b77a30b21e07816d92182ff2 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAnalogAftFlag.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAnalogAftFlag.aidl @@ -35,7 +35,7 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum FrontendAnalogAftFlag { - UNDEFINED = 0, - AFT_TRUE = 1, - AFT_FALSE = 2, + UNDEFINED, + AFT_TRUE, + AFT_FALSE, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAnalogSifStandard.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAnalogSifStandard.aidl index 35025220ac582c9160b40cb046897fccf5bfd4af..8d19461d06106c5a0d01ce1b5a76092ae1e4409a 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAnalogSifStandard.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAnalogSifStandard.aidl @@ -36,22 +36,22 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendAnalogSifStandard { UNDEFINED = 0, - AUTO = 1, - BG = 2, - BG_A2 = 4, - BG_NICAM = 8, - I = 16, - DK = 32, - DK1_A2 = 64, - DK2_A2 = 128, - DK3_A2 = 256, - DK_NICAM = 512, - L = 1024, - M = 2048, - M_BTSC = 4096, - M_A2 = 8192, - M_EIAJ = 16384, - I_NICAM = 32768, - L_NICAM = 65536, - L_PRIME = 131072, + AUTO = (1 << 0) /* 1 */, + BG = (1 << 1) /* 2 */, + BG_A2 = (1 << 2) /* 4 */, + BG_NICAM = (1 << 3) /* 8 */, + I = (1 << 4) /* 16 */, + DK = (1 << 5) /* 32 */, + DK1_A2 = (1 << 6) /* 64 */, + DK2_A2 = (1 << 7) /* 128 */, + DK3_A2 = (1 << 8) /* 256 */, + DK_NICAM = (1 << 9) /* 512 */, + L = (1 << 10) /* 1024 */, + M = (1 << 11) /* 2048 */, + M_BTSC = (1 << 12) /* 4096 */, + M_A2 = (1 << 13) /* 8192 */, + M_EIAJ = (1 << 14) /* 16384 */, + I_NICAM = (1 << 15) /* 32768 */, + L_NICAM = (1 << 16) /* 65536 */, + L_PRIME = (1 << 17) /* 131072 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAnalogType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAnalogType.aidl index 33fd93dc63e979340dec361ab28823f08db5ef62..bf8b00094c64425b810f1420dcd041fe6729e6e3 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAnalogType.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAnalogType.aidl @@ -36,12 +36,12 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendAnalogType { UNDEFINED = 0, - AUTO = 1, - PAL = 2, - PAL_M = 4, - PAL_N = 8, - PAL_60 = 16, - NTSC = 32, - NTSC_443 = 64, - SECAM = 128, + AUTO = (1 << 0) /* 1 */, + PAL = (1 << 1) /* 2 */, + PAL_M = (1 << 2) /* 4 */, + PAL_N = (1 << 3) /* 8 */, + PAL_60 = (1 << 4) /* 16 */, + NTSC = (1 << 5) /* 32 */, + NTSC_443 = (1 << 6) /* 64 */, + SECAM = (1 << 7) /* 128 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3Bandwidth.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3Bandwidth.aidl index 51a3fc5c503c7acbf28dd24e993a90fd4aa7e1d6..9704f40a1ee27fd0820f5b1614c8e212c30d6e5d 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3Bandwidth.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3Bandwidth.aidl @@ -36,8 +36,8 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendAtsc3Bandwidth { UNDEFINED = 0, - AUTO = 1, - BANDWIDTH_6MHZ = 2, - BANDWIDTH_7MHZ = 4, - BANDWIDTH_8MHZ = 8, + AUTO = (1 << 0) /* 1 */, + BANDWIDTH_6MHZ = (1 << 1) /* 2 */, + BANDWIDTH_7MHZ = (1 << 2) /* 4 */, + BANDWIDTH_8MHZ = (1 << 3) /* 8 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3CodeRate.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3CodeRate.aidl index aec07186a33f26756beed9d29ccac2877b8f9be0..2d09271942e018d6d3b9d9e6710b83662d5502aa 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3CodeRate.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3CodeRate.aidl @@ -36,17 +36,17 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendAtsc3CodeRate { UNDEFINED = 0, - AUTO = 1, - CODERATE_2_15 = 2, - CODERATE_3_15 = 4, - CODERATE_4_15 = 8, - CODERATE_5_15 = 16, - CODERATE_6_15 = 32, - CODERATE_7_15 = 64, - CODERATE_8_15 = 128, - CODERATE_9_15 = 256, - CODERATE_10_15 = 512, - CODERATE_11_15 = 1024, - CODERATE_12_15 = 2048, - CODERATE_13_15 = 4096, + AUTO = (1 << 0) /* 1 */, + CODERATE_2_15 = (1 << 1) /* 2 */, + CODERATE_3_15 = (1 << 2) /* 4 */, + CODERATE_4_15 = (1 << 3) /* 8 */, + CODERATE_5_15 = (1 << 4) /* 16 */, + CODERATE_6_15 = (1 << 5) /* 32 */, + CODERATE_7_15 = (1 << 6) /* 64 */, + CODERATE_8_15 = (1 << 7) /* 128 */, + CODERATE_9_15 = (1 << 8) /* 256 */, + CODERATE_10_15 = (1 << 9) /* 512 */, + CODERATE_11_15 = (1 << 10) /* 1024 */, + CODERATE_12_15 = (1 << 11) /* 2048 */, + CODERATE_13_15 = (1 << 12) /* 4096 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3DemodOutputFormat.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3DemodOutputFormat.aidl index 8702a496c5fb14054933b554ad2e5d70416cfd7e..22267e7d30e7b0e21121f7091259af6f7598ed8c 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3DemodOutputFormat.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3DemodOutputFormat.aidl @@ -36,6 +36,6 @@ package android.hardware.tv.tuner; @Backing(type="byte") @VintfStability enum FrontendAtsc3DemodOutputFormat { UNDEFINED = 0, - ATSC3_LINKLAYER_PACKET = 1, - BASEBAND_PACKET = 2, + ATSC3_LINKLAYER_PACKET = (1 << 0) /* 1 */, + BASEBAND_PACKET = (1 << 1) /* 2 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3Fec.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3Fec.aidl index a2c140aa9faad89b29ace4dbeb8d91a8df304fc4..2e229c0a465533e2b29b9f20897c8102d3b7e436 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3Fec.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3Fec.aidl @@ -36,11 +36,11 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendAtsc3Fec { UNDEFINED = 0, - AUTO = 1, - BCH_LDPC_16K = 2, - BCH_LDPC_64K = 4, - CRC_LDPC_16K = 8, - CRC_LDPC_64K = 16, - LDPC_16K = 32, - LDPC_64K = 64, + AUTO = (1 << 0) /* 1 */, + BCH_LDPC_16K = (1 << 1) /* 2 */, + BCH_LDPC_64K = (1 << 2) /* 4 */, + CRC_LDPC_16K = (1 << 3) /* 8 */, + CRC_LDPC_64K = (1 << 4) /* 16 */, + LDPC_16K = (1 << 5) /* 32 */, + LDPC_64K = (1 << 6) /* 64 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3Modulation.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3Modulation.aidl index 09e513d8aac6d2486e4575a151e9b62a8ebfdd6e..cbe8c1f0ccd6a1ab595d455028a63e811f165436 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3Modulation.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3Modulation.aidl @@ -36,11 +36,11 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendAtsc3Modulation { UNDEFINED = 0, - AUTO = 1, - MOD_QPSK = 2, - MOD_16QAM = 4, - MOD_64QAM = 8, - MOD_256QAM = 16, - MOD_1024QAM = 32, - MOD_4096QAM = 64, + AUTO = (1 << 0) /* 1 */, + MOD_QPSK = (1 << 1) /* 2 */, + MOD_16QAM = (1 << 2) /* 4 */, + MOD_64QAM = (1 << 3) /* 8 */, + MOD_256QAM = (1 << 4) /* 16 */, + MOD_1024QAM = (1 << 5) /* 32 */, + MOD_4096QAM = (1 << 6) /* 64 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3TimeInterleaveMode.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3TimeInterleaveMode.aidl index a9747f0eb7dcdd5821602373b7441e2ad25d2272..4e706414f46c3aaed5f11ddc91572b82b26d1dde 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3TimeInterleaveMode.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3TimeInterleaveMode.aidl @@ -36,7 +36,7 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendAtsc3TimeInterleaveMode { UNDEFINED = 0, - AUTO = 1, - CTI = 2, - HTI = 4, + AUTO = (1 << 0) /* 1 */, + CTI = (1 << 1) /* 2 */, + HTI = (1 << 2) /* 4 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtscModulation.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtscModulation.aidl index 426fe2073908aff03ff68f9f4d51e3d356e2e79d..7da48f1f837c6303568106c746fd1fb2e2c30702 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtscModulation.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtscModulation.aidl @@ -36,7 +36,7 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendAtscModulation { UNDEFINED = 0, - AUTO = 1, - MOD_8VSB = 4, - MOD_16VSB = 8, + AUTO = (1 << 0) /* 1 */, + MOD_8VSB = (1 << 2) /* 4 */, + MOD_16VSB = (1 << 3) /* 8 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendCableTimeInterleaveMode.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendCableTimeInterleaveMode.aidl index ff71df39cfa2d4043bca6177f82c289072050726..61cbf12dd0554851ea9f5a4ea0f77da144bd40a9 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendCableTimeInterleaveMode.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendCableTimeInterleaveMode.aidl @@ -36,14 +36,14 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendCableTimeInterleaveMode { UNDEFINED = 0, - AUTO = 1, - INTERLEAVING_128_1_0 = 2, - INTERLEAVING_128_1_1 = 4, - INTERLEAVING_64_2 = 8, - INTERLEAVING_32_4 = 16, - INTERLEAVING_16_8 = 32, - INTERLEAVING_8_16 = 64, - INTERLEAVING_128_2 = 128, - INTERLEAVING_128_3 = 256, - INTERLEAVING_128_4 = 512, + AUTO = (1 << 0) /* 1 */, + INTERLEAVING_128_1_0 = (1 << 1) /* 2 */, + INTERLEAVING_128_1_1 = (1 << 2) /* 4 */, + INTERLEAVING_64_2 = (1 << 3) /* 8 */, + INTERLEAVING_32_4 = (1 << 4) /* 16 */, + INTERLEAVING_16_8 = (1 << 5) /* 32 */, + INTERLEAVING_8_16 = (1 << 6) /* 64 */, + INTERLEAVING_128_2 = (1 << 7) /* 128 */, + INTERLEAVING_128_3 = (1 << 8) /* 256 */, + INTERLEAVING_128_4 = (1 << 9) /* 512 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbBandwidth.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbBandwidth.aidl index 18d71d2a7f2aaf612ebb809b776b36b6954e166e..6f62d91c65e9bfa387dd87e73cccf92865c0fa14 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbBandwidth.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbBandwidth.aidl @@ -36,7 +36,7 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendDtmbBandwidth { UNDEFINED = 0, - AUTO = 1, - BANDWIDTH_8MHZ = 2, - BANDWIDTH_6MHZ = 4, + AUTO = (1 << 0) /* 1 */, + BANDWIDTH_8MHZ = (1 << 1) /* 2 */, + BANDWIDTH_6MHZ = (1 << 2) /* 4 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbCodeRate.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbCodeRate.aidl index c9454e7506a7f0fdb4f61e5eaa8b9409522ba12f..d6be63973940f4b3f567027f295d2d21072458da 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbCodeRate.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbCodeRate.aidl @@ -36,8 +36,8 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendDtmbCodeRate { UNDEFINED = 0, - AUTO = 1, - CODERATE_2_5 = 2, - CODERATE_3_5 = 4, - CODERATE_4_5 = 8, + AUTO = (1 << 0) /* 1 */, + CODERATE_2_5 = (1 << 1) /* 2 */, + CODERATE_3_5 = (1 << 2) /* 4 */, + CODERATE_4_5 = (1 << 3) /* 8 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbGuardInterval.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbGuardInterval.aidl index 872eb6ae1c332cc9f8ec3cb636e133e490053597..5626064634c649df82bec0ee2d1aa1fb42933661 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbGuardInterval.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbGuardInterval.aidl @@ -36,11 +36,11 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendDtmbGuardInterval { UNDEFINED = 0, - AUTO = 1, - PN_420_VARIOUS = 2, - PN_595_CONST = 4, - PN_945_VARIOUS = 8, - PN_420_CONST = 16, - PN_945_CONST = 32, - PN_RESERVED = 64, + AUTO = (1 << 0) /* 1 */, + PN_420_VARIOUS = (1 << 1) /* 2 */, + PN_595_CONST = (1 << 2) /* 4 */, + PN_945_VARIOUS = (1 << 3) /* 8 */, + PN_420_CONST = (1 << 4) /* 16 */, + PN_945_CONST = (1 << 5) /* 32 */, + PN_RESERVED = (1 << 6) /* 64 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbModulation.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbModulation.aidl index 088aac5e50d29f627e5bfcb6c5981014499bde05..036e64b7bf93c53db861029a69327e9c3bce4ea3 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbModulation.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbModulation.aidl @@ -36,10 +36,10 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendDtmbModulation { UNDEFINED = 0, - AUTO = 1, - CONSTELLATION_4QAM = 2, - CONSTELLATION_4QAM_NR = 4, - CONSTELLATION_16QAM = 8, - CONSTELLATION_32QAM = 16, - CONSTELLATION_64QAM = 32, + AUTO = (1 << 0) /* 1 */, + CONSTELLATION_4QAM = (1 << 1) /* 2 */, + CONSTELLATION_4QAM_NR = (1 << 2) /* 4 */, + CONSTELLATION_16QAM = (1 << 3) /* 8 */, + CONSTELLATION_32QAM = (1 << 4) /* 16 */, + CONSTELLATION_64QAM = (1 << 5) /* 32 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbTimeInterleaveMode.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbTimeInterleaveMode.aidl index 8321ad0ebc340458fc3f94a7e79a6a34ae45a23a..12238871ed148a3aead71987f6598445346b423e 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbTimeInterleaveMode.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbTimeInterleaveMode.aidl @@ -36,7 +36,7 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendDtmbTimeInterleaveMode { UNDEFINED = 0, - AUTO = 1, - TIMER_INT_240 = 2, - TIMER_INT_720 = 4, + AUTO = (1 << 0) /* 1 */, + TIMER_INT_240 = (1 << 1) /* 2 */, + TIMER_INT_720 = (1 << 2) /* 4 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbTransmissionMode.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbTransmissionMode.aidl index 5298291cd23d95c1319c898d0d0b42ec043a7779..0498825d300acd6c46ed4a65208d867dd5039b96 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbTransmissionMode.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbTransmissionMode.aidl @@ -36,7 +36,7 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendDtmbTransmissionMode { UNDEFINED = 0, - AUTO = 1, - C1 = 2, - C3780 = 4, + AUTO = (1 << 0) /* 1 */, + C1 = (1 << 1) /* 2 */, + C3780 = (1 << 2) /* 4 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcAnnex.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcAnnex.aidl index cdfedb67026d63ef00423c7697f7e3bb7ec29f9f..985add15343a616f627d25ea9554375e0f0f3aab 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcAnnex.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcAnnex.aidl @@ -36,7 +36,7 @@ package android.hardware.tv.tuner; @Backing(type="byte") @VintfStability enum FrontendDvbcAnnex { UNDEFINED = 0, - A = 1, - B = 2, - C = 4, + A = (1 << 0) /* 1 */, + B = (1 << 1) /* 2 */, + C = (1 << 2) /* 4 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcBandwidth.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcBandwidth.aidl index f0fe460d6801de7cde44756129678edfa3d1f4c9..c253cfe452cdb1666ce374a2fdf194aec1247cab 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcBandwidth.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcBandwidth.aidl @@ -36,8 +36,8 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendDvbcBandwidth { UNDEFINED = 0, - BANDWIDTH_5MHZ = 1, - BANDWIDTH_6MHZ = 2, - BANDWIDTH_7MHZ = 4, - BANDWIDTH_8MHZ = 8, + BANDWIDTH_5MHZ = (1 << 0) /* 1 */, + BANDWIDTH_6MHZ = (1 << 1) /* 2 */, + BANDWIDTH_7MHZ = (1 << 2) /* 4 */, + BANDWIDTH_8MHZ = (1 << 3) /* 8 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcModulation.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcModulation.aidl index 0871777509aee8f7a9dab7fab58ba290e173589a..c18e83e82b28de532c7b94fa6a84de30963d47c3 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcModulation.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcModulation.aidl @@ -36,10 +36,10 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendDvbcModulation { UNDEFINED = 0, - AUTO = 1, - MOD_16QAM = 2, - MOD_32QAM = 4, - MOD_64QAM = 8, - MOD_128QAM = 16, - MOD_256QAM = 32, + AUTO = (1 << 0) /* 1 */, + MOD_16QAM = (1 << 1) /* 2 */, + MOD_32QAM = (1 << 2) /* 4 */, + MOD_64QAM = (1 << 3) /* 8 */, + MOD_128QAM = (1 << 4) /* 16 */, + MOD_256QAM = (1 << 5) /* 32 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcOuterFec.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcOuterFec.aidl index f1e92c9d5adab5dc4aafa3868d1da0f3a679e276..a6fbc6de4e71dc8febded91305151df40a4769c1 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcOuterFec.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcOuterFec.aidl @@ -36,6 +36,6 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendDvbcOuterFec { UNDEFINED = 0, - OUTER_FEC_NONE = 1, - OUTER_FEC_RS = 2, + OUTER_FEC_NONE, + OUTER_FEC_RS, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsModulation.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsModulation.aidl index 25951ccecbf7166168d15264b1bfb7a0d33da47d..71957d5b727c97da8b8f949742ab1f31970b9555 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsModulation.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsModulation.aidl @@ -36,18 +36,18 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendDvbsModulation { UNDEFINED = 0, - AUTO = 1, - MOD_QPSK = 2, - MOD_8PSK = 4, - MOD_16QAM = 8, - MOD_16PSK = 16, - MOD_32PSK = 32, - MOD_ACM = 64, - MOD_8APSK = 128, - MOD_16APSK = 256, - MOD_32APSK = 512, - MOD_64APSK = 1024, - MOD_128APSK = 2048, - MOD_256APSK = 4096, - MOD_RESERVED = 8192, + AUTO = (1 << 0) /* 1 */, + MOD_QPSK = (1 << 1) /* 2 */, + MOD_8PSK = (1 << 2) /* 4 */, + MOD_16QAM = (1 << 3) /* 8 */, + MOD_16PSK = (1 << 4) /* 16 */, + MOD_32PSK = (1 << 5) /* 32 */, + MOD_ACM = (1 << 6) /* 64 */, + MOD_8APSK = (1 << 7) /* 128 */, + MOD_16APSK = (1 << 8) /* 256 */, + MOD_32APSK = (1 << 9) /* 512 */, + MOD_64APSK = (1 << 10) /* 1024 */, + MOD_128APSK = (1 << 11) /* 2048 */, + MOD_256APSK = (1 << 12) /* 4096 */, + MOD_RESERVED = (1 << 13) /* 8192 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsPilot.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsPilot.aidl index 4f2c6eb8d742bf832fc50b49b4f4749787293522..e3543b3c2fc3f8f60af1932c3a3a17d7b91b06cd 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsPilot.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsPilot.aidl @@ -35,8 +35,8 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum FrontendDvbsPilot { - UNDEFINED = 0, - ON = 1, - OFF = 2, - AUTO = 3, + UNDEFINED, + ON, + OFF, + AUTO, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsRolloff.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsRolloff.aidl index 56ee37b613369508dabaaa2b52a8c4b200b45a50..2181abf9efbf13ba8b63aeeca36dccc7aee605eb 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsRolloff.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsRolloff.aidl @@ -35,11 +35,11 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum FrontendDvbsRolloff { - UNDEFINED = 0, - ROLLOFF_0_35 = 1, - ROLLOFF_0_25 = 2, - ROLLOFF_0_20 = 3, - ROLLOFF_0_15 = 4, - ROLLOFF_0_10 = 5, - ROLLOFF_0_5 = 6, + UNDEFINED, + ROLLOFF_0_35, + ROLLOFF_0_25, + ROLLOFF_0_20, + ROLLOFF_0_15, + ROLLOFF_0_10, + ROLLOFF_0_5, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsScanType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsScanType.aidl index 110b1d8b1fe96b45c1e9b917e0cefde0636d9bf3..46edb56be23dddf24164fe3d79a0e1a5a9355529 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsScanType.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsScanType.aidl @@ -36,8 +36,8 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendDvbsScanType { UNDEFINED = 0, - DIRECT = 1, - DISEQC = 2, - UNICABLE = 3, - JESS = 4, + DIRECT, + DISEQC, + UNICABLE, + JESS, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsStandard.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsStandard.aidl index b9cb657fb50ba64868cd979ec5cf35c2ce8fbe53..bcb1c6da1195a3e5713afa10de8d2d07108a0771 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsStandard.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsStandard.aidl @@ -36,8 +36,8 @@ package android.hardware.tv.tuner; @Backing(type="byte") @VintfStability enum FrontendDvbsStandard { UNDEFINED = 0, - AUTO = 1, - S = 2, - S2 = 4, - S2X = 8, + AUTO = (1 << 0) /* 1 */, + S = (1 << 1) /* 2 */, + S2 = (1 << 2) /* 4 */, + S2X = (1 << 3) /* 8 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsVcmMode.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsVcmMode.aidl index 2cbff7cc1bde481cff76c94806b5109dce57261f..af874230a9b14622c4cc1e7d45c75b713be1e5f3 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsVcmMode.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsVcmMode.aidl @@ -35,7 +35,7 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum FrontendDvbsVcmMode { - UNDEFINED = 0, - AUTO = 1, - MANUAL = 2, + UNDEFINED, + AUTO, + MANUAL, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtBandwidth.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtBandwidth.aidl index f5d14e898ba2b88224a1d3255f168842b57c6c7b..ff2d9e4762fb52d445d41a06c28b2a972645160c 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtBandwidth.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtBandwidth.aidl @@ -36,11 +36,11 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendDvbtBandwidth { UNDEFINED = 0, - AUTO = 1, - BANDWIDTH_8MHZ = 2, - BANDWIDTH_7MHZ = 4, - BANDWIDTH_6MHZ = 8, - BANDWIDTH_5MHZ = 16, - BANDWIDTH_1_7MHZ = 32, - BANDWIDTH_10MHZ = 64, + AUTO = (1 << 0) /* 1 */, + BANDWIDTH_8MHZ = (1 << 1) /* 2 */, + BANDWIDTH_7MHZ = (1 << 2) /* 4 */, + BANDWIDTH_6MHZ = (1 << 3) /* 8 */, + BANDWIDTH_5MHZ = (1 << 4) /* 16 */, + BANDWIDTH_1_7MHZ = (1 << 5) /* 32 */, + BANDWIDTH_10MHZ = (1 << 6) /* 64 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtCoderate.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtCoderate.aidl index 8bd0489a6ec61ef7d58a6c79e7d723d19c41ea3f..8d2df06f30a41b8c1795c90f34b58d453b9cfde6 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtCoderate.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtCoderate.aidl @@ -36,14 +36,14 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendDvbtCoderate { UNDEFINED = 0, - AUTO = 1, - CODERATE_1_2 = 2, - CODERATE_2_3 = 4, - CODERATE_3_4 = 8, - CODERATE_5_6 = 16, - CODERATE_7_8 = 32, - CODERATE_3_5 = 64, - CODERATE_4_5 = 128, - CODERATE_6_7 = 256, - CODERATE_8_9 = 512, + AUTO = (1 << 0) /* 1 */, + CODERATE_1_2 = (1 << 1) /* 2 */, + CODERATE_2_3 = (1 << 2) /* 4 */, + CODERATE_3_4 = (1 << 3) /* 8 */, + CODERATE_5_6 = (1 << 4) /* 16 */, + CODERATE_7_8 = (1 << 5) /* 32 */, + CODERATE_3_5 = (1 << 6) /* 64 */, + CODERATE_4_5 = (1 << 7) /* 128 */, + CODERATE_6_7 = (1 << 8) /* 256 */, + CODERATE_8_9 = (1 << 9) /* 512 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtConstellation.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtConstellation.aidl index bc40901de496df9bd8f34a42c97f51cadc32beb8..4bd5691b9e4f5dec3d013e32a7e36da15a099be6 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtConstellation.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtConstellation.aidl @@ -36,13 +36,13 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendDvbtConstellation { UNDEFINED = 0, - AUTO = 1, - CONSTELLATION_QPSK = 2, - CONSTELLATION_16QAM = 4, - CONSTELLATION_64QAM = 8, - CONSTELLATION_256QAM = 16, - CONSTELLATION_QPSK_R = 32, - CONSTELLATION_16QAM_R = 64, - CONSTELLATION_64QAM_R = 128, - CONSTELLATION_256QAM_R = 256, + AUTO = (1 << 0) /* 1 */, + CONSTELLATION_QPSK = (1 << 1) /* 2 */, + CONSTELLATION_16QAM = (1 << 2) /* 4 */, + CONSTELLATION_64QAM = (1 << 3) /* 8 */, + CONSTELLATION_256QAM = (1 << 4) /* 16 */, + CONSTELLATION_QPSK_R = (1 << 5) /* 32 */, + CONSTELLATION_16QAM_R = (1 << 6) /* 64 */, + CONSTELLATION_64QAM_R = (1 << 7) /* 128 */, + CONSTELLATION_256QAM_R = (1 << 8) /* 256 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtGuardInterval.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtGuardInterval.aidl index 073a77e2b8a4726bff2d3036aa6988321bc8fccf..01c2b66b50b28b39c6c2d58e20dda7cf95464ca0 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtGuardInterval.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtGuardInterval.aidl @@ -36,12 +36,12 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendDvbtGuardInterval { UNDEFINED = 0, - AUTO = 1, - INTERVAL_1_32 = 2, - INTERVAL_1_16 = 4, - INTERVAL_1_8 = 8, - INTERVAL_1_4 = 16, - INTERVAL_1_128 = 32, - INTERVAL_19_128 = 64, - INTERVAL_19_256 = 128, + AUTO = (1 << 0) /* 1 */, + INTERVAL_1_32 = (1 << 1) /* 2 */, + INTERVAL_1_16 = (1 << 2) /* 4 */, + INTERVAL_1_8 = (1 << 3) /* 8 */, + INTERVAL_1_4 = (1 << 4) /* 16 */, + INTERVAL_1_128 = (1 << 5) /* 32 */, + INTERVAL_19_128 = (1 << 6) /* 64 */, + INTERVAL_19_256 = (1 << 7) /* 128 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtHierarchy.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtHierarchy.aidl index 9ed5c8ceaebe59cd8ddeadf9b5ffd1c7ac223893..bd86479794e01a30d5de0fd8d6f945e2822e3309 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtHierarchy.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtHierarchy.aidl @@ -36,13 +36,13 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendDvbtHierarchy { UNDEFINED = 0, - AUTO = 1, - HIERARCHY_NON_NATIVE = 2, - HIERARCHY_1_NATIVE = 4, - HIERARCHY_2_NATIVE = 8, - HIERARCHY_4_NATIVE = 16, - HIERARCHY_NON_INDEPTH = 32, - HIERARCHY_1_INDEPTH = 64, - HIERARCHY_2_INDEPTH = 128, - HIERARCHY_4_INDEPTH = 256, + AUTO = (1 << 0) /* 1 */, + HIERARCHY_NON_NATIVE = (1 << 1) /* 2 */, + HIERARCHY_1_NATIVE = (1 << 2) /* 4 */, + HIERARCHY_2_NATIVE = (1 << 3) /* 8 */, + HIERARCHY_4_NATIVE = (1 << 4) /* 16 */, + HIERARCHY_NON_INDEPTH = (1 << 5) /* 32 */, + HIERARCHY_1_INDEPTH = (1 << 6) /* 64 */, + HIERARCHY_2_INDEPTH = (1 << 7) /* 128 */, + HIERARCHY_4_INDEPTH = (1 << 8) /* 256 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtPlpMode.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtPlpMode.aidl index c80bc2aa5a792ff459171990191ebc0f9c2ac38f..dc8e12c6eddd0e9e6966c436c3e82ef1948de125 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtPlpMode.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtPlpMode.aidl @@ -35,7 +35,7 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum FrontendDvbtPlpMode { - UNDEFINED = 0, - AUTO = 1, - MANUAL = 2, + UNDEFINED, + AUTO, + MANUAL, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtStandard.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtStandard.aidl index c7ba68abc6b700d60ca06902d5a8094c445cbc43..080cc5cc846e643cdcdab3b8cac9b0eee2a54a8d 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtStandard.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtStandard.aidl @@ -36,7 +36,7 @@ package android.hardware.tv.tuner; @Backing(type="byte") @VintfStability enum FrontendDvbtStandard { UNDEFINED = 0, - AUTO = 1, - T = 2, - T2 = 4, + AUTO = (1 << 0) /* 1 */, + T = (1 << 1) /* 2 */, + T2 = (1 << 2) /* 4 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtTransmissionMode.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtTransmissionMode.aidl index e3ca2e3901658b5a2bef0f8cc3b3df1120862b6a..3731f8691d1b6a8b6dddb64cd6a245357862c49c 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtTransmissionMode.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtTransmissionMode.aidl @@ -36,14 +36,14 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendDvbtTransmissionMode { UNDEFINED = 0, - AUTO = 1, - MODE_2K = 2, - MODE_8K = 4, - MODE_4K = 8, - MODE_1K = 16, - MODE_16K = 32, - MODE_32K = 64, - MODE_8K_E = 128, - MODE_16K_E = 256, - MODE_32K_E = 512, + AUTO = (1 << 0) /* 1 */, + MODE_2K = (1 << 1) /* 2 */, + MODE_8K = (1 << 2) /* 4 */, + MODE_4K = (1 << 3) /* 8 */, + MODE_1K = (1 << 4) /* 16 */, + MODE_16K = (1 << 5) /* 32 */, + MODE_32K = (1 << 6) /* 64 */, + MODE_8K_E = (1 << 7) /* 128 */, + MODE_16K_E = (1 << 8) /* 256 */, + MODE_32K_E = (1 << 9) /* 512 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendEventType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendEventType.aidl index 443313feade4c05c76db80e896e7ef3d95691e01..101e347153f2aeb058cc7165430d9b422c1aa66e 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendEventType.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendEventType.aidl @@ -35,7 +35,7 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum FrontendEventType { - LOCKED = 0, - NO_SIGNAL = 1, - LOST_LOCK = 2, + LOCKED, + NO_SIGNAL, + LOST_LOCK, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendInnerFec.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendInnerFec.aidl index 19599a3f820c70f41bd0fe52429eb59e02614daf..da91888d73d9500d6f03fe6120299db36abebf40 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendInnerFec.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendInnerFec.aidl @@ -36,57 +36,57 @@ package android.hardware.tv.tuner; @Backing(type="long") @VintfStability enum FrontendInnerFec { FEC_UNDEFINED = 0, - AUTO = 1, - FEC_1_2 = 2, - FEC_1_3 = 4, - FEC_1_4 = 8, - FEC_1_5 = 16, - FEC_2_3 = 32, - FEC_2_5 = 64, - FEC_2_9 = 128, - FEC_3_4 = 256, - FEC_3_5 = 512, - FEC_4_5 = 1024, - FEC_4_15 = 2048, - FEC_5_6 = 4096, - FEC_5_9 = 8192, - FEC_6_7 = 16384, - FEC_7_8 = 32768, - FEC_7_9 = 65536, - FEC_7_15 = 131072, - FEC_8_9 = 262144, - FEC_8_15 = 524288, - FEC_9_10 = 1048576, - FEC_9_20 = 2097152, - FEC_11_15 = 4194304, - FEC_11_20 = 8388608, - FEC_11_45 = 16777216, - FEC_13_18 = 33554432, - FEC_13_45 = 67108864, - FEC_14_45 = 134217728, - FEC_23_36 = 268435456, - FEC_25_36 = 536870912, - FEC_26_45 = 1073741824, - FEC_28_45 = 2147483648, - FEC_29_45 = 4294967296, - FEC_31_45 = 8589934592, - FEC_32_45 = 17179869184, - FEC_77_90 = 34359738368, - FEC_2_15 = 68719476736, - FEC_3_15 = 137438953472, - FEC_5_15 = 274877906944, - FEC_6_15 = 549755813888, - FEC_9_15 = 1099511627776, - FEC_10_15 = 2199023255552, - FEC_12_15 = 4398046511104, - FEC_13_15 = 8796093022208, - FEC_18_30 = 17592186044416, - FEC_20_30 = 35184372088832, - FEC_90_180 = 70368744177664, - FEC_96_180 = 140737488355328, - FEC_104_180 = 281474976710656, - FEC_128_180 = 562949953421312, - FEC_132_180 = 1125899906842624, - FEC_135_180 = 2251799813685248, - FEC_140_180 = 4503599627370496, + AUTO = (1L << 0) /* 1 */, + FEC_1_2 = (1L << 1) /* 2 */, + FEC_1_3 = (1L << 2) /* 4 */, + FEC_1_4 = (1L << 3) /* 8 */, + FEC_1_5 = (1L << 4) /* 16 */, + FEC_2_3 = (1L << 5) /* 32 */, + FEC_2_5 = (1L << 6) /* 64 */, + FEC_2_9 = (1L << 7) /* 128 */, + FEC_3_4 = (1L << 8) /* 256 */, + FEC_3_5 = (1L << 9) /* 512 */, + FEC_4_5 = (1L << 10) /* 1024 */, + FEC_4_15 = (1L << 11) /* 2048 */, + FEC_5_6 = (1L << 12) /* 4096 */, + FEC_5_9 = (1L << 13) /* 8192 */, + FEC_6_7 = (1L << 14) /* 16384 */, + FEC_7_8 = (1L << 15) /* 32768 */, + FEC_7_9 = (1L << 16) /* 65536 */, + FEC_7_15 = (1L << 17) /* 131072 */, + FEC_8_9 = (1L << 18) /* 262144 */, + FEC_8_15 = (1L << 19) /* 524288 */, + FEC_9_10 = (1L << 20) /* 1048576 */, + FEC_9_20 = (1L << 21) /* 2097152 */, + FEC_11_15 = (1L << 22) /* 4194304 */, + FEC_11_20 = (1L << 23) /* 8388608 */, + FEC_11_45 = (1L << 24) /* 16777216 */, + FEC_13_18 = (1L << 25) /* 33554432 */, + FEC_13_45 = (1L << 26) /* 67108864 */, + FEC_14_45 = (1L << 27) /* 134217728 */, + FEC_23_36 = (1L << 28) /* 268435456 */, + FEC_25_36 = (1L << 29) /* 536870912 */, + FEC_26_45 = (1L << 30) /* 1073741824 */, + FEC_28_45 = (1L << 31) /* 2147483648 */, + FEC_29_45 = (1L << 32) /* 4294967296 */, + FEC_31_45 = (1L << 33) /* 8589934592 */, + FEC_32_45 = (1L << 34) /* 17179869184 */, + FEC_77_90 = (1L << 35) /* 34359738368 */, + FEC_2_15 = (1L << 36) /* 68719476736 */, + FEC_3_15 = (1L << 37) /* 137438953472 */, + FEC_5_15 = (1L << 38) /* 274877906944 */, + FEC_6_15 = (1L << 39) /* 549755813888 */, + FEC_9_15 = (1L << 40) /* 1099511627776 */, + FEC_10_15 = (1L << 41) /* 2199023255552 */, + FEC_12_15 = (1L << 42) /* 4398046511104 */, + FEC_13_15 = (1L << 43) /* 8796093022208 */, + FEC_18_30 = (1L << 44) /* 17592186044416 */, + FEC_20_30 = (1L << 45) /* 35184372088832 */, + FEC_90_180 = (1L << 46) /* 70368744177664 */, + FEC_96_180 = (1L << 47) /* 140737488355328 */, + FEC_104_180 = (1L << 48) /* 281474976710656 */, + FEC_128_180 = (1L << 49) /* 562949953421312 */, + FEC_132_180 = (1L << 50) /* 1125899906842624 */, + FEC_135_180 = (1L << 51) /* 2251799813685248 */, + FEC_140_180 = (1L << 52) /* 4503599627370496 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIptvSettingsFecType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIptvSettingsFecType.aidl index 50a12089ec10afc9e385aa0ce1a8245db524d905..5806cc501870af61ec5aeb63c78df6a31e513633 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIptvSettingsFecType.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIptvSettingsFecType.aidl @@ -36,7 +36,7 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendIptvSettingsFecType { UNDEFINED = 0, - COLUMN = 1, - ROW = 2, - COLUMN_ROW = 4, + COLUMN = (1 << 0) /* 1 */, + ROW = (1 << 1) /* 2 */, + COLUMN_ROW = (1 << 2) /* 4 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIptvSettingsIgmp.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIptvSettingsIgmp.aidl index aa0849658f2b3f3e12d52e3ef9534aae9d57ae93..43ae523f19aaac932580c5ed700ededbfa6ed7b6 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIptvSettingsIgmp.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIptvSettingsIgmp.aidl @@ -36,7 +36,7 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendIptvSettingsIgmp { UNDEFINED = 0, - V1 = 1, - V2 = 2, - V3 = 4, + V1 = (1 << 0) /* 1 */, + V2 = (1 << 1) /* 2 */, + V3 = (1 << 2) /* 4 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIptvSettingsProtocol.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIptvSettingsProtocol.aidl index 08a01f1a36d16349f1f844d118b515913027fdb1..2e4c47851b2c01dfdb7b5c0cdf57fb7eaea19adf 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIptvSettingsProtocol.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIptvSettingsProtocol.aidl @@ -36,6 +36,6 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendIptvSettingsProtocol { UNDEFINED = 0, - UDP = 1, - RTP = 2, + UDP = (1 << 0) /* 1 */, + RTP = (1 << 1) /* 2 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbs3Coderate.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbs3Coderate.aidl index 1ee7f07e71c866be7630c320200d9f768e9dd2f8..de865cae0171c7b7fad6abef3121a1024025751e 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbs3Coderate.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbs3Coderate.aidl @@ -36,16 +36,16 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendIsdbs3Coderate { UNDEFINED = 0, - AUTO = 1, - CODERATE_1_3 = 2, - CODERATE_2_5 = 4, - CODERATE_1_2 = 8, - CODERATE_3_5 = 16, - CODERATE_2_3 = 32, - CODERATE_3_4 = 64, - CODERATE_7_9 = 128, - CODERATE_4_5 = 256, - CODERATE_5_6 = 512, - CODERATE_7_8 = 1024, - CODERATE_9_10 = 2048, + AUTO = (1 << 0) /* 1 */, + CODERATE_1_3 = (1 << 1) /* 2 */, + CODERATE_2_5 = (1 << 2) /* 4 */, + CODERATE_1_2 = (1 << 3) /* 8 */, + CODERATE_3_5 = (1 << 4) /* 16 */, + CODERATE_2_3 = (1 << 5) /* 32 */, + CODERATE_3_4 = (1 << 6) /* 64 */, + CODERATE_7_9 = (1 << 7) /* 128 */, + CODERATE_4_5 = (1 << 8) /* 256 */, + CODERATE_5_6 = (1 << 9) /* 512 */, + CODERATE_7_8 = (1 << 10) /* 1024 */, + CODERATE_9_10 = (1 << 11) /* 2048 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbs3Modulation.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbs3Modulation.aidl index 3603292ecaba3c5b22fa4643a969515e19490c9f..adc902d591e86d1bcb17a1890d24cf0d1cb3ad53 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbs3Modulation.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbs3Modulation.aidl @@ -36,10 +36,10 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendIsdbs3Modulation { UNDEFINED = 0, - AUTO = 1, - MOD_BPSK = 2, - MOD_QPSK = 4, - MOD_8PSK = 8, - MOD_16APSK = 16, - MOD_32APSK = 32, + AUTO = (1 << 0) /* 1 */, + MOD_BPSK = (1 << 1) /* 2 */, + MOD_QPSK = (1 << 2) /* 4 */, + MOD_8PSK = (1 << 3) /* 8 */, + MOD_16APSK = (1 << 4) /* 16 */, + MOD_32APSK = (1 << 5) /* 32 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbs3Rolloff.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbs3Rolloff.aidl index 733760c4713340da9bc566796f50e39296d460a4..c93cf2004a2fa1bdab074be4317804eea3199fe5 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbs3Rolloff.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbs3Rolloff.aidl @@ -35,6 +35,6 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum FrontendIsdbs3Rolloff { - UNDEFINED = 0, - ROLLOFF_0_03 = 1, + UNDEFINED, + ROLLOFF_0_03, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsCoderate.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsCoderate.aidl index 09e9c5902d60687387f2151d132b5b23af6b6d30..a0e436f540ebb6ac3eef9001bb01f6396034eeaf 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsCoderate.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsCoderate.aidl @@ -36,10 +36,10 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendIsdbsCoderate { UNDEFINED = 0, - AUTO = 1, - CODERATE_1_2 = 2, - CODERATE_2_3 = 4, - CODERATE_3_4 = 8, - CODERATE_5_6 = 16, - CODERATE_7_8 = 32, + AUTO = (1 << 0) /* 1 */, + CODERATE_1_2 = (1 << 1) /* 2 */, + CODERATE_2_3 = (1 << 2) /* 4 */, + CODERATE_3_4 = (1 << 3) /* 8 */, + CODERATE_5_6 = (1 << 4) /* 16 */, + CODERATE_7_8 = (1 << 5) /* 32 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsModulation.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsModulation.aidl index 7b9bde66dd14f1904c298030a4d5be10e1d0ca7e..61a21c397f458a4834b140bda6275c335929d35d 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsModulation.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsModulation.aidl @@ -36,8 +36,8 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendIsdbsModulation { UNDEFINED = 0, - AUTO = 1, - MOD_BPSK = 2, - MOD_QPSK = 4, - MOD_TC8PSK = 8, + AUTO = (1 << 0) /* 1 */, + MOD_BPSK = (1 << 1) /* 2 */, + MOD_QPSK = (1 << 2) /* 4 */, + MOD_TC8PSK = (1 << 3) /* 8 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsRolloff.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsRolloff.aidl index a2ab1546618f68998aa61f63a9095f1c67609b1f..b76923104340a7001b117937f1b5a7707621474d 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsRolloff.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsRolloff.aidl @@ -35,6 +35,6 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum FrontendIsdbsRolloff { - UNDEFINED = 0, - ROLLOFF_0_35 = 1, + UNDEFINED, + ROLLOFF_0_35, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsStreamIdType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsStreamIdType.aidl index 089f611e9c868afe30792efd149041b3ca3d820f..77956b627880e86acd97c1dda12e0dcc885d8002 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsStreamIdType.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsStreamIdType.aidl @@ -35,7 +35,7 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum FrontendIsdbsStreamIdType { - STREAM_ID = 0, - RELATIVE_STREAM_NUMBER = 1, - UNDEFINED = 2, + STREAM_ID, + RELATIVE_STREAM_NUMBER, + UNDEFINED, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtBandwidth.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtBandwidth.aidl index cd492142a94abe5e41ae2f45eb18063f970edf12..209620fddf0e7925d1e34399a4178c52f5da0390 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtBandwidth.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtBandwidth.aidl @@ -36,8 +36,8 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendIsdbtBandwidth { UNDEFINED = 0, - AUTO = 1, - BANDWIDTH_8MHZ = 2, - BANDWIDTH_7MHZ = 4, - BANDWIDTH_6MHZ = 8, + AUTO = (1 << 0) /* 1 */, + BANDWIDTH_8MHZ = (1 << 1) /* 2 */, + BANDWIDTH_7MHZ = (1 << 2) /* 4 */, + BANDWIDTH_6MHZ = (1 << 3) /* 8 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtCoderate.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtCoderate.aidl index 2b747edbbd1135d3bede81cf5db8315cb93cbc20..4236b7cf585e02cb04cae8f6c7c3469c020d77df 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtCoderate.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtCoderate.aidl @@ -36,14 +36,14 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendIsdbtCoderate { UNDEFINED = 0, - AUTO = 1, - CODERATE_1_2 = 2, - CODERATE_2_3 = 4, - CODERATE_3_4 = 8, - CODERATE_5_6 = 16, - CODERATE_7_8 = 32, - CODERATE_3_5 = 64, - CODERATE_4_5 = 128, - CODERATE_6_7 = 256, - CODERATE_8_9 = 512, + AUTO = (1 << 0) /* 1 */, + CODERATE_1_2 = (1 << 1) /* 2 */, + CODERATE_2_3 = (1 << 2) /* 4 */, + CODERATE_3_4 = (1 << 3) /* 8 */, + CODERATE_5_6 = (1 << 4) /* 16 */, + CODERATE_7_8 = (1 << 5) /* 32 */, + CODERATE_3_5 = (1 << 6) /* 64 */, + CODERATE_4_5 = (1 << 7) /* 128 */, + CODERATE_6_7 = (1 << 8) /* 256 */, + CODERATE_8_9 = (1 << 9) /* 512 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtGuardInterval.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtGuardInterval.aidl index 42a023adc9370589cf84199af438d0612d98e662..86225e2ab1afd9196ce78ae727c3d5d5af1416ab 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtGuardInterval.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtGuardInterval.aidl @@ -36,12 +36,12 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendIsdbtGuardInterval { UNDEFINED = 0, - AUTO = 1, - INTERVAL_1_32 = 2, - INTERVAL_1_16 = 4, - INTERVAL_1_8 = 8, - INTERVAL_1_4 = 16, - INTERVAL_1_128 = 32, - INTERVAL_19_128 = 64, - INTERVAL_19_256 = 128, + AUTO = (1 << 0) /* 1 */, + INTERVAL_1_32 = (1 << 1) /* 2 */, + INTERVAL_1_16 = (1 << 2) /* 4 */, + INTERVAL_1_8 = (1 << 3) /* 8 */, + INTERVAL_1_4 = (1 << 4) /* 16 */, + INTERVAL_1_128 = (1 << 5) /* 32 */, + INTERVAL_19_128 = (1 << 6) /* 64 */, + INTERVAL_19_256 = (1 << 7) /* 128 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtMode.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtMode.aidl index 54698abb5325a0cfaeca4236a56c6ef31b596b34..0e38c263708e40b1b24895fe3e452552488fd301 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtMode.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtMode.aidl @@ -36,8 +36,8 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendIsdbtMode { UNDEFINED = 0, - AUTO = 1, - MODE_1 = 2, - MODE_2 = 4, - MODE_3 = 8, + AUTO = (1 << 0) /* 1 */, + MODE_1 = (1 << 1) /* 2 */, + MODE_2 = (1 << 2) /* 4 */, + MODE_3 = (1 << 3) /* 8 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtModulation.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtModulation.aidl index a31e0cf7b080f32fab60f99fbd47b49a17df9cb5..4474c839171355ae23b70c51104c8ac6640c1663 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtModulation.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtModulation.aidl @@ -36,9 +36,9 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendIsdbtModulation { UNDEFINED = 0, - AUTO = 1, - MOD_DQPSK = 2, - MOD_QPSK = 4, - MOD_16QAM = 8, - MOD_64QAM = 16, + AUTO = (1 << 0) /* 1 */, + MOD_DQPSK = (1 << 1) /* 2 */, + MOD_QPSK = (1 << 2) /* 4 */, + MOD_16QAM = (1 << 3) /* 8 */, + MOD_64QAM = (1 << 4) /* 16 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtPartialReceptionFlag.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtPartialReceptionFlag.aidl index 133887f6590fe44a70b1b3ec2edf29864224d628..1387e662de9e4be53bcaf5a49b956659a9440cfe 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtPartialReceptionFlag.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtPartialReceptionFlag.aidl @@ -36,7 +36,7 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendIsdbtPartialReceptionFlag { UNDEFINED = 0, - AUTO = 1, - FALSE = 2, - TRUE = 4, + AUTO = (1 << 0) /* 1 */, + FALSE = (1 << 1) /* 2 */, + TRUE = (1 << 2) /* 4 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtTimeInterleaveMode.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtTimeInterleaveMode.aidl index 50adde92b369dd5e3845a79a138d5a0d345f76fe..b9d76ee5b1412a82c5441fa6c84ca399ed7f3d02 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtTimeInterleaveMode.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtTimeInterleaveMode.aidl @@ -36,17 +36,17 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendIsdbtTimeInterleaveMode { UNDEFINED = 0, - AUTO = 1, - INTERLEAVE_1_0 = 2, - INTERLEAVE_1_4 = 4, - INTERLEAVE_1_8 = 8, - INTERLEAVE_1_16 = 16, - INTERLEAVE_2_0 = 32, - INTERLEAVE_2_2 = 64, - INTERLEAVE_2_4 = 128, - INTERLEAVE_2_8 = 256, - INTERLEAVE_3_0 = 512, - INTERLEAVE_3_1 = 1024, - INTERLEAVE_3_2 = 2048, - INTERLEAVE_3_4 = 4096, + AUTO = (1 << 0) /* 1 */, + INTERLEAVE_1_0 = (1 << 1) /* 2 */, + INTERLEAVE_1_4 = (1 << 2) /* 4 */, + INTERLEAVE_1_8 = (1 << 3) /* 8 */, + INTERLEAVE_1_16 = (1 << 4) /* 16 */, + INTERLEAVE_2_0 = (1 << 5) /* 32 */, + INTERLEAVE_2_2 = (1 << 6) /* 64 */, + INTERLEAVE_2_4 = (1 << 7) /* 128 */, + INTERLEAVE_2_8 = (1 << 8) /* 256 */, + INTERLEAVE_3_0 = (1 << 9) /* 512 */, + INTERLEAVE_3_1 = (1 << 10) /* 1024 */, + INTERLEAVE_3_2 = (1 << 11) /* 2048 */, + INTERLEAVE_3_4 = (1 << 12) /* 4096 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendScanMessageType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendScanMessageType.aidl index 6976ecd8d036e37b931b9bdd2690e61d56aadac9..186dbd7550c7691836f2e2921d22979828381612 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendScanMessageType.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendScanMessageType.aidl @@ -35,20 +35,20 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum FrontendScanMessageType { - LOCKED = 0, - END = 1, - PROGRESS_PERCENT = 2, - FREQUENCY = 3, - SYMBOL_RATE = 4, - HIERARCHY = 5, - ANALOG_TYPE = 6, - PLP_IDS = 7, - GROUP_IDS = 8, - INPUT_STREAM_IDS = 9, - STANDARD = 10, - ATSC3_PLP_INFO = 11, - MODULATION = 12, - DVBC_ANNEX = 13, - HIGH_PRIORITY = 14, - DVBT_CELL_IDS = 15, + LOCKED, + END, + PROGRESS_PERCENT, + FREQUENCY, + SYMBOL_RATE, + HIERARCHY, + ANALOG_TYPE, + PLP_IDS, + GROUP_IDS, + INPUT_STREAM_IDS, + STANDARD, + ATSC3_PLP_INFO, + MODULATION, + DVBC_ANNEX, + HIGH_PRIORITY, + DVBT_CELL_IDS, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendScanType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendScanType.aidl index ed42d0aac9529dc42df3633de87b2949fb514742..cef02ccd750b29d400246edb336e6dcfa55d4a84 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendScanType.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendScanType.aidl @@ -36,6 +36,6 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendScanType { SCAN_UNDEFINED = 0, - SCAN_AUTO = 1, - SCAN_BLIND = 2, + SCAN_AUTO = (1 << 0) /* 1 */, + SCAN_BLIND = (1 << 1) /* 2 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendSpectralInversion.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendSpectralInversion.aidl index ff11bb8dab39a18bfc7a2a4e0a56b149c52b91f8..14ec2fd4b9da2c094e3be716b95dab3df915e0da 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendSpectralInversion.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendSpectralInversion.aidl @@ -35,7 +35,7 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum FrontendSpectralInversion { - UNDEFINED = 0, - NORMAL = 1, - INVERTED = 2, + UNDEFINED, + NORMAL, + INVERTED, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStandardExt.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStandardExt.aidl new file mode 100644 index 0000000000000000000000000000000000000000..88637dbb243a107457ab64b1547d4f00b031aaec --- /dev/null +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStandardExt.aidl @@ -0,0 +1,40 @@ +/* + * Copyright 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.tuner; +/* @hide */ +@VintfStability +union FrontendStandardExt { + android.hardware.tv.tuner.FrontendDvbsStandard dvbsStandardExt = android.hardware.tv.tuner.FrontendDvbsStandard.UNDEFINED; + android.hardware.tv.tuner.FrontendDvbtStandard dvbtStandardExt = android.hardware.tv.tuner.FrontendDvbtStandard.UNDEFINED; +} diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatus.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatus.aidl index b991ab68367abe50ff6b49d1ed6a9f79c2677559..e79eba68abf222ccb0e2d62f8602687aaebfc2b9 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatus.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatus.aidl @@ -82,4 +82,5 @@ union FrontendStatus { long iptvPacketsLost; int iptvWorstJitterMs; int iptvAverageJitterMs; + android.hardware.tv.tuner.FrontendStandardExt standardExt; } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatusReadiness.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatusReadiness.aidl index 41944ce44099cd25b4199025bfec60466bcc49d9..13735fae8edbbe58d732a55a987d9a9c72a5a49a 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatusReadiness.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatusReadiness.aidl @@ -35,9 +35,9 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum FrontendStatusReadiness { - UNDEFINED = 0, - UNAVAILABLE = 1, - UNSTABLE = 2, - STABLE = 3, - UNSUPPORTED = 4, + UNDEFINED, + UNAVAILABLE, + UNSTABLE, + STABLE, + UNSUPPORTED, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatusType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatusType.aidl index 379129960a99024cae8062191f9cda270ed8db41..bfd2145e6256fc27a2a94015a714cf039fc3e9ea 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatusType.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatusType.aidl @@ -35,51 +35,52 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum FrontendStatusType { - DEMOD_LOCK = 0, - SNR = 1, - BER = 2, - PER = 3, - PRE_BER = 4, - SIGNAL_QUALITY = 5, - SIGNAL_STRENGTH = 6, - SYMBOL_RATE = 7, - FEC = 8, - MODULATION = 9, - SPECTRAL = 10, - LNB_VOLTAGE = 11, - PLP_ID = 12, - EWBS = 13, - AGC = 14, - LNA = 15, - LAYER_ERROR = 16, - MER = 17, - FREQ_OFFSET = 18, - HIERARCHY = 19, - RF_LOCK = 20, - ATSC3_PLP_INFO = 21, - MODULATIONS = 22, - BERS = 23, - CODERATES = 24, - BANDWIDTH = 25, - GUARD_INTERVAL = 26, - TRANSMISSION_MODE = 27, - UEC = 28, - T2_SYSTEM_ID = 29, - INTERLEAVINGS = 30, - ISDBT_SEGMENTS = 31, - TS_DATA_RATES = 32, - ROLL_OFF = 33, - IS_MISO = 34, - IS_LINEAR = 35, - IS_SHORT_FRAMES = 36, - ISDBT_MODE = 37, - ISDBT_PARTIAL_RECEPTION_FLAG = 38, - STREAM_ID_LIST = 39, - DVBT_CELL_IDS = 40, - ATSC3_ALL_PLP_INFO = 41, - IPTV_CONTENT_URL = 42, - IPTV_PACKETS_LOST = 43, - IPTV_PACKETS_RECEIVED = 44, - IPTV_WORST_JITTER_MS = 45, - IPTV_AVERAGE_JITTER_MS = 46, + DEMOD_LOCK, + SNR, + BER, + PER, + PRE_BER, + SIGNAL_QUALITY, + SIGNAL_STRENGTH, + SYMBOL_RATE, + FEC, + MODULATION, + SPECTRAL, + LNB_VOLTAGE, + PLP_ID, + EWBS, + AGC, + LNA, + LAYER_ERROR, + MER, + FREQ_OFFSET, + HIERARCHY, + RF_LOCK, + ATSC3_PLP_INFO, + MODULATIONS, + BERS, + CODERATES, + BANDWIDTH, + GUARD_INTERVAL, + TRANSMISSION_MODE, + UEC, + T2_SYSTEM_ID, + INTERLEAVINGS, + ISDBT_SEGMENTS, + TS_DATA_RATES, + ROLL_OFF, + IS_MISO, + IS_LINEAR, + IS_SHORT_FRAMES, + ISDBT_MODE, + ISDBT_PARTIAL_RECEPTION_FLAG, + STREAM_ID_LIST, + DVBT_CELL_IDS, + ATSC3_ALL_PLP_INFO, + IPTV_CONTENT_URL, + IPTV_PACKETS_LOST, + IPTV_PACKETS_RECEIVED, + IPTV_WORST_JITTER_MS, + IPTV_AVERAGE_JITTER_MS, + STANDARD_EXT, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendType.aidl index cbf5b4701c7f54e8576ad1ae8f4f1b3ba6fdcc79..455bbc0551ed75412d8915e76800771506446048 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendType.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendType.aidl @@ -36,15 +36,15 @@ package android.hardware.tv.tuner; @Backing(type="int") @VintfStability enum FrontendType { UNDEFINED = 0, - ANALOG = 1, - ATSC = 2, - ATSC3 = 3, - DVBC = 4, - DVBS = 5, - DVBT = 6, - ISDBS = 7, - ISDBS3 = 8, - ISDBT = 9, - DTMB = 10, - IPTV = 11, + ANALOG, + ATSC, + ATSC3, + DVBC, + DVBS, + DVBT, + ISDBS, + ISDBS3, + ISDBT, + DTMB, + IPTV, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/LnbEventType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/LnbEventType.aidl index e6e2b0548b553c59794a6201caa7f120db9c8e61..7bec809d7f808dc90231e9435917790fc8b20a28 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/LnbEventType.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/LnbEventType.aidl @@ -35,8 +35,8 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum LnbEventType { - DISEQC_RX_OVERFLOW = 0, - DISEQC_RX_TIMEOUT = 1, - DISEQC_RX_PARITY_ERROR = 2, - LNB_OVERLOAD = 3, + DISEQC_RX_OVERFLOW, + DISEQC_RX_TIMEOUT, + DISEQC_RX_PARITY_ERROR, + LNB_OVERLOAD, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/LnbPosition.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/LnbPosition.aidl index 5fc4d152d23f806967dc2cf0d4bff8af197bf947..a4a5740630779a8518b2bcfd00daccd8429080a1 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/LnbPosition.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/LnbPosition.aidl @@ -35,7 +35,7 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum LnbPosition { - UNDEFINED = 0, - POSITION_A = 1, - POSITION_B = 2, + UNDEFINED, + POSITION_A, + POSITION_B, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/LnbTone.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/LnbTone.aidl index 3217de99ff5599204b829777a0b57466bb16db09..06283540d98967b0f305d7f3ccedfba56a05e711 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/LnbTone.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/LnbTone.aidl @@ -35,6 +35,6 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum LnbTone { - NONE = 0, - CONTINUOUS = 1, + NONE, + CONTINUOUS, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/LnbVoltage.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/LnbVoltage.aidl index 034c7e6a6efd4ce97fa5065801307aa4c34b9a31..b18ff0e1200dd789c0ed8be69f08182d8582a6d1 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/LnbVoltage.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/LnbVoltage.aidl @@ -35,13 +35,13 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum LnbVoltage { - NONE = 0, - VOLTAGE_5V = 1, - VOLTAGE_11V = 2, - VOLTAGE_12V = 3, - VOLTAGE_13V = 4, - VOLTAGE_14V = 5, - VOLTAGE_15V = 6, - VOLTAGE_18V = 7, - VOLTAGE_19V = 8, + NONE, + VOLTAGE_5V, + VOLTAGE_11V, + VOLTAGE_12V, + VOLTAGE_13V, + VOLTAGE_14V, + VOLTAGE_15V, + VOLTAGE_18V, + VOLTAGE_19V, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/PlaybackStatus.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/PlaybackStatus.aidl index 850b73755916ffe964af0ee58d005c9aefded658..a8b63782f2d44dcf152adf94d7379b493ea5a6b7 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/PlaybackStatus.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/PlaybackStatus.aidl @@ -35,8 +35,8 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum PlaybackStatus { - SPACE_EMPTY = 1, - SPACE_ALMOST_EMPTY = 2, - SPACE_ALMOST_FULL = 4, - SPACE_FULL = 8, + SPACE_EMPTY = (1 << 0) /* 1 */, + SPACE_ALMOST_EMPTY = (1 << 1) /* 2 */, + SPACE_ALMOST_FULL = (1 << 2) /* 4 */, + SPACE_FULL = (1 << 3) /* 8 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/RecordStatus.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/RecordStatus.aidl index 48bf9ecacffb156ef35387f12ed66e97bd49b229..e06b6160db687372194d9d7fde876eb85daf3779 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/RecordStatus.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/RecordStatus.aidl @@ -35,8 +35,8 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="byte") @VintfStability enum RecordStatus { - DATA_READY = 1, - LOW_WATER = 2, - HIGH_WATER = 4, - OVERFLOW = 8, + DATA_READY = (1 << 0) /* 1 */, + LOW_WATER = (1 << 1) /* 2 */, + HIGH_WATER = (1 << 2) /* 4 */, + OVERFLOW = (1 << 3) /* 8 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/Result.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/Result.aidl index 4e22f678c8ee5e8cdd7bc0c35440fa4de101b474..ae43350549f094d8027f7a92a9ae67d3e94724a5 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/Result.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/Result.aidl @@ -35,11 +35,11 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum Result { - SUCCESS = 0, - UNAVAILABLE = 1, - NOT_INITIALIZED = 2, - INVALID_STATE = 3, - INVALID_ARGUMENT = 4, - OUT_OF_MEMORY = 5, - UNKNOWN_ERROR = 6, + SUCCESS, + UNAVAILABLE, + NOT_INITIALIZED, + INVALID_STATE, + INVALID_ARGUMENT, + OUT_OF_MEMORY, + UNKNOWN_ERROR, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ScramblingStatus.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ScramblingStatus.aidl index 656fe20f217014bb55d902c5ba8eb187ecf15f59..4d52de17c36f59f227b8a0f3a79b6456bc421d1b 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ScramblingStatus.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ScramblingStatus.aidl @@ -35,7 +35,7 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum ScramblingStatus { - UNKNOWN = 1, - NOT_SCRAMBLED = 2, - SCRAMBLED = 4, + UNKNOWN = (1 << 0) /* 1 */, + NOT_SCRAMBLED = (1 << 1) /* 2 */, + SCRAMBLED = (1 << 2) /* 4 */, } diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/VideoStreamType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/VideoStreamType.aidl index dbb6033addc5ce37445e203ab3d9d7d6d83afa52..530f4549d2788f915dac8301237709e18d8e4763 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/VideoStreamType.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/VideoStreamType.aidl @@ -35,18 +35,18 @@ package android.hardware.tv.tuner; /* @hide */ @Backing(type="int") @VintfStability enum VideoStreamType { - UNDEFINED = 0, - RESERVED = 1, - MPEG1 = 2, - MPEG2 = 3, - MPEG4P2 = 4, - AVC = 5, - HEVC = 6, - VC1 = 7, - VP8 = 8, - VP9 = 9, - AV1 = 10, - AVS = 11, - AVS2 = 12, - VVC = 13, + UNDEFINED, + RESERVED, + MPEG1, + MPEG2, + MPEG4P2, + AVC, + HEVC, + VC1, + VP8, + VP9, + AV1, + AVS, + AVS2, + VVC, } diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl index 32f0cb28bb9a54b920b3e0189612285927caa8c5..06f087b9af6d4759f535af218fa601f6a51965d8 100644 --- a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl +++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl @@ -17,7 +17,6 @@ package android.hardware.tv.tuner; import android.hardware.common.NativeHandle; - import android.hardware.tv.tuner.DemuxFilterMediaEventExtraMetaData; import android.hardware.tv.tuner.DemuxFilterScIndexMask; @@ -91,4 +90,32 @@ parcelable DemuxFilterMediaEvent { * access unit framing at decode stage. */ DemuxFilterScIndexMask scIndexMask; + + /** + * This attribute is used together with dataGroupId and indexInDataGroup to + * associate fragmented data. + * + * 1 if the media event contains the complete data. dataGroupId can be + * ignored. + * Greater than 1 if the media event contains incomplete data. Data can be + * reassembled by gathering all media events with the same dataGroupId. + */ + int numDataPieces; + + /** + * This attribute is used together with numDataPieces and dataGroupId to + * associate fragmented data. + * + * The value should be in the range of [0, numDataPieces - 1], indicating + * this piece is the Nth piece. + */ + int indexInDataGroup; + + /** + * This attribute is used together with numDataPieces and indexInDataGroup to + * associate fragmented data. + * + * The value is the id of the data group. + */ + int dataGroupId; } diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStandardExt.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStandardExt.aidl new file mode 100644 index 0000000000000000000000000000000000000000..0b68e89239da14a4b794e4a291811ccf7b5c110f --- /dev/null +++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStandardExt.aidl @@ -0,0 +1,36 @@ +/* + * Copyright 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. + */ + +package android.hardware.tv.tuner; + +import android.hardware.tv.tuner.FrontendDvbsStandard; +import android.hardware.tv.tuner.FrontendDvbtStandard; + +/** + * @hide + */ +@VintfStability +union FrontendStandardExt { + /** + * The DVB-S standard extension after standard transition. + */ + FrontendDvbsStandard dvbsStandardExt = FrontendDvbsStandard.UNDEFINED; + + /** + * The DVB-T standard extension after standard transition. + */ + FrontendDvbtStandard dvbtStandardExt = FrontendDvbtStandard.UNDEFINED; +} diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatus.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatus.aidl index 391f29be2a6d36c13f79d3e2c217afa80249f2b7..a3902df171ad7f0c720326876fd23af390885652 100644 --- a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatus.aidl +++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatus.aidl @@ -28,6 +28,7 @@ import android.hardware.tv.tuner.FrontendModulationStatus; import android.hardware.tv.tuner.FrontendRollOff; import android.hardware.tv.tuner.FrontendScanAtsc3PlpInfo; import android.hardware.tv.tuner.FrontendSpectralInversion; +import android.hardware.tv.tuner.FrontendStandardExt; import android.hardware.tv.tuner.FrontendStatusAtsc3PlpInfo; import android.hardware.tv.tuner.FrontendTransmissionMode; import android.hardware.tv.tuner.LnbVoltage; @@ -272,4 +273,13 @@ union FrontendStatus { * Average jitter (milliseconds). */ int iptvAverageJitterMs; + + /** + * Standard extension. + * + * DVB-T and DVB-S can transition to another standard within the same standard series. For + * example, DVB-T can transition to DVB-T2 and back. This attribute represents the standard + * extension. Valid values include FrontendDvbtStandard.T or FrontendDvbsStandard.S2 etc. + */ + FrontendStandardExt standardExt; } diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatusType.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatusType.aidl index 6804b2daf2a9392af019dfa38a6030e6d1bece24..3225c428bea5a08101463cabe382c123b696049c 100644 --- a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatusType.aidl +++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatusType.aidl @@ -259,4 +259,9 @@ enum FrontendStatusType { * Average jitter (milliseconds). */ IPTV_AVERAGE_JITTER_MS, + + /** + * Standard extension. + */ + STANDARD_EXT, } diff --git a/tv/tuner/aidl/default/Filter.cpp b/tv/tuner/aidl/default/Filter.cpp index 5f7a4cda8d8e19819b04b1aee4202dec54845170..946ec3a2a53c499fb35acde2c8f344ffb5726cdf 100644 --- a/tv/tuner/aidl/default/Filter.cpp +++ b/tv/tuner/aidl/default/Filter.cpp @@ -333,8 +333,8 @@ Filter::~Filter() { // All the filter event callbacks in start are for testing purpose. switch (mType.mainType) { case DemuxFilterMainType::TS: - createMediaEvent(events, false); - createMediaEvent(events, true); + createMediaEvent(events, false, 0); + createMediaEvent(events, true, 1); createTsRecordEvent(events); createTemiEvent(events); break; @@ -1235,7 +1235,8 @@ bool Filter::sameFile(int fd1, int fd2) { return (stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino); } -void Filter::createMediaEvent(vector& events, bool isAudioPresentation) { +void Filter::createMediaEvent(vector& events, bool isAudioPresentation, + int indexInDataGroup) { DemuxFilterMediaEvent mediaEvent; mediaEvent.streamId = 1; mediaEvent.isPtsPresent = true; @@ -1302,6 +1303,10 @@ void Filter::createMediaEvent(vector& events, bool isAudioPres mediaEvent.avDataId = static_cast(dataId); mediaEvent.avMemory = ::android::dupToAidl(nativeHandle); + mediaEvent.numDataPieces = 2; + mediaEvent.indexInDataGroup = indexInDataGroup; + mediaEvent.dataGroupId = 321; + events.push_back(DemuxFilterEvent::make(std::move(mediaEvent))); native_handle_close(nativeHandle); diff --git a/tv/tuner/aidl/default/Filter.h b/tv/tuner/aidl/default/Filter.h index e2a0c7abfac37b783e90925265decfc71ffa93cb..4be15e2cdbbc2231d2c675ee7d6a2196aafd2357 100644 --- a/tv/tuner/aidl/default/Filter.h +++ b/tv/tuner/aidl/default/Filter.h @@ -231,7 +231,8 @@ class Filter : public BnFilter { ::ndk::ScopedAStatus createShareMemMediaEvents(vector& output); bool sameFile(int fd1, int fd2); - void createMediaEvent(vector&, bool isAudioPresentation); + void createMediaEvent(vector&, bool isAudioPresentation, + int indexInDataGroup); void createTsRecordEvent(vector&); void createMmtpRecordEvent(vector&); void createSectionEvent(vector&); diff --git a/tv/tuner/aidl/default/Frontend.cpp b/tv/tuner/aidl/default/Frontend.cpp index 10316047ff4004b6a74814f112f884723fed3a6a..bba004a3f91450e1990ad825f676b9c44bb2a2a5 100644 --- a/tv/tuner/aidl/default/Frontend.cpp +++ b/tv/tuner/aidl/default/Frontend.cpp @@ -81,6 +81,7 @@ Frontend::Frontend(FrontendType type, int32_t id) { FrontendStatusType::SIGNAL_STRENGTH, FrontendStatusType::SYMBOL_RATE, FrontendStatusType::MODULATION, FrontendStatusType::MODULATIONS, FrontendStatusType::ROLL_OFF, FrontendStatusType::IS_MISO, + FrontendStatusType::STANDARD_EXT, }; break; } @@ -96,6 +97,7 @@ Frontend::Frontend(FrontendType type, int32_t id) { FrontendStatusType::TRANSMISSION_MODE, FrontendStatusType::T2_SYSTEM_ID, FrontendStatusType::DVBT_CELL_IDS, + FrontendStatusType::STANDARD_EXT, }; break; } @@ -985,6 +987,17 @@ void Frontend::scanThreadLoop() { status.set(5); break; } + case FrontendStatusType::STANDARD_EXT: { + FrontendStandardExt standardExt; + if (mType == FrontendType::DVBS) { + standardExt.set( + FrontendDvbsStandard::S2X); + } else if (mType == FrontendType::DVBT) { + standardExt.set(FrontendDvbtStandard::T2); + } + status.set(standardExt); + break; + } default: { continue; } diff --git a/tv/tuner/aidl/default/tuner-default.xml b/tv/tuner/aidl/default/tuner-default.xml index bff8ff01ed06b22351c8d439b1776781d03cbe49..261fcbf75a62e8e9f668bfcefbb40ef1f503ed99 100644 --- a/tv/tuner/aidl/default/tuner-default.xml +++ b/tv/tuner/aidl/default/tuner-default.xml @@ -2,6 +2,6 @@ android.hardware.tv.tuner ITuner/default - 2 + 3 diff --git a/tv/tuner/aidl/vts/functional/FilterTests.cpp b/tv/tuner/aidl/vts/functional/FilterTests.cpp index 533d0e678224810eb497792f73876b0b18f79066..788ebbd2576c487305f6c012edea61d23a3d07ec 100644 --- a/tv/tuner/aidl/vts/functional/FilterTests.cpp +++ b/tv/tuner/aidl/vts/functional/FilterTests.cpp @@ -105,17 +105,30 @@ void FilterCallback::readFilterEventsData(const vector& events // todo separate filter handlers for (int i = 0; i < events.size(); i++) { switch (events[i].getTag()) { - case DemuxFilterEvent::Tag::media: - ALOGD("[vts] Media filter event, avMemHandle numFds=%zu.", - events[i].get().avMemory.fds.size()); + case DemuxFilterEvent::Tag::media: { + int numDataPieces = events[i].get().numDataPieces; + int indexInDataGroup + = events[i].get().indexInDataGroup; + ALOGD("[vts] Media filter event, avMemHandle numFds=%zu, numDataPieces=%d," + " indexInDataGroup=%d, dataGroupId=%d.", + events[i].get().avMemory.fds.size(), + numDataPieces, + indexInDataGroup, + events[i].get().dataGroupId); + if (numDataPieces > 1) { + EXPECT_TRUE(indexInDataGroup >= 0); + EXPECT_TRUE(indexInDataGroup < numDataPieces); + } dumpAvData(events[i].get()); break; - case DemuxFilterEvent::Tag::tsRecord: + } + case DemuxFilterEvent::Tag::tsRecord: { ALOGD("[vts] TS record filter event, pts=%" PRIu64 ", firstMbInSlice=%d", events[i].get().pts, events[i].get().firstMbInSlice); break; - case DemuxFilterEvent::Tag::mmtpRecord: + } + case DemuxFilterEvent::Tag::mmtpRecord: { ALOGD("[vts] MMTP record filter event, pts=%" PRIu64 ", firstMbInSlice=%d, mpuSequenceNumber=%d, tsIndexMask=%d", events[i].get().pts, @@ -123,7 +136,8 @@ void FilterCallback::readFilterEventsData(const vector& events events[i].get().mpuSequenceNumber, events[i].get().tsIndexMask); break; - case DemuxFilterEvent::Tag::monitorEvent: + } + case DemuxFilterEvent::Tag::monitorEvent: { switch (events[i].get().getTag()) { case DemuxFilterMonitorEvent::Tag::scramblingStatus: mScramblingStatusEvent++; @@ -135,13 +149,16 @@ void FilterCallback::readFilterEventsData(const vector& events break; } break; - case DemuxFilterEvent::Tag::startId: + } + case DemuxFilterEvent::Tag::startId: { ALOGD("[vts] Restart filter event, startId=%d", events[i].get()); mStartIdReceived = true; break; - default: + } + default: { break; + } } } } diff --git a/tv/tuner/aidl/vts/functional/FrontendTests.cpp b/tv/tuner/aidl/vts/functional/FrontendTests.cpp index 85d0496a2c4f6454ba8014be981e65f4cc0c5c16..99c0283485aaf073fb716203d1333d9b3df15314 100644 --- a/tv/tuner/aidl/vts/functional/FrontendTests.cpp +++ b/tv/tuner/aidl/vts/functional/FrontendTests.cpp @@ -636,7 +636,7 @@ void FrontendTests::statusReadinessTest(FrontendConfig frontendConf) { ASSERT_TRUE(tuneFrontend(frontendConf, false /*testWithDemux*/)); // TODO: find a better way to push all frontend status types - for (int32_t i = 0; i <= static_cast(FrontendStatusType::ATSC3_ALL_PLP_INFO); i++) { + for (int32_t i = 0; i <= static_cast(FrontendStatusType::STANDARD_EXT); i++) { allTypes.push_back(static_cast(i)); } diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePwleV2.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePwleV2.aidl new file mode 100644 index 0000000000000000000000000000000000000000..de0bdb57ff96a2428e16e0cbf90bf897dd80bd3c --- /dev/null +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePwleV2.aidl @@ -0,0 +1,38 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.vibrator; +@VintfStability +parcelable CompositePwleV2 { + android.hardware.vibrator.PwleV2Primitive[] pwlePrimitives; +} diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/FrequencyAccelerationMapEntry.aidl similarity index 97% rename from vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl rename to vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/FrequencyAccelerationMapEntry.aidl index a5eda52bc7895d747a9e94bbe2eec72c96ccf0bc..e6743f9190c2019a8ddf30e07704fe002907e78c 100644 --- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/FrequencyAccelerationMapEntry.aidl @@ -33,7 +33,7 @@ package android.hardware.vibrator; @VintfStability -parcelable PwleV2OutputMapEntry { +parcelable FrequencyAccelerationMapEntry { float frequencyHz; float maxOutputAccelerationGs; } diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrationSession.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrationSession.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ec301b27c78d0f339298f9ec437063f4d2a4090e --- /dev/null +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrationSession.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.vibrator; +@VintfStability +interface IVibrationSession { + void close(); + void abort(); +} diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl index 0dcc6579554674bbcb42322669168c5ae3247c20..9fad9522e594b90d4cffcf55a2c7d4d1c1d8a080 100644 --- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl @@ -51,19 +51,40 @@ interface IVibrator { void alwaysOnDisable(in int id); float getResonantFrequency(); float getQFactor(); + /** + * @deprecated This method is deprecated from AIDL v3 and is no longer required to be implemented even if CAP_FREQUENCY_CONTROL capability is reported. + */ float getFrequencyResolution(); + /** + * @deprecated This method is deprecated from AIDL v3 and is no longer required to be implemented even if CAP_FREQUENCY_CONTROL capability is reported. + */ float getFrequencyMinimum(); + /** + * @deprecated This method is deprecated from AIDL v3 and is no longer required to be implemented even if CAP_FREQUENCY_CONTROL capability is reported. + */ float[] getBandwidthAmplitudeMap(); + /** + * @deprecated This method is deprecated from AIDL v3 and is no longer required to be implemented. Use `IVibrator.getPwleV2PrimitiveDurationMaxMillis` instead. + */ int getPwlePrimitiveDurationMax(); + /** + * @deprecated This method is deprecated from AIDL v3 and is no longer required to be implemented. Use `IVibrator.getPwleV2CompositionSizeMax` instead. + */ int getPwleCompositionSizeMax(); + /** + * @deprecated This method is deprecated from AIDL v3 and is no longer required to be implemented. + */ android.hardware.vibrator.Braking[] getSupportedBraking(); + /** + * @deprecated This method is deprecated from AIDL v3 and is no longer required to be implemented. Use `IVibrator.composePwleV2` instead. + */ void composePwle(in android.hardware.vibrator.PrimitivePwle[] composite, in android.hardware.vibrator.IVibratorCallback callback); void performVendorEffect(in android.hardware.vibrator.VendorEffect vendorEffect, in android.hardware.vibrator.IVibratorCallback callback); - List getPwleV2FrequencyToOutputAccelerationMap(); + List getFrequencyToOutputAccelerationMap(); int getPwleV2PrimitiveDurationMaxMillis(); int getPwleV2CompositionSizeMax(); int getPwleV2PrimitiveDurationMinMillis(); - void composePwleV2(in android.hardware.vibrator.PwleV2Primitive[] composite, in android.hardware.vibrator.IVibratorCallback callback); + void composePwleV2(in android.hardware.vibrator.CompositePwleV2 composite, in android.hardware.vibrator.IVibratorCallback callback); const int CAP_ON_CALLBACK = (1 << 0) /* 1 */; const int CAP_PERFORM_CALLBACK = (1 << 1) /* 2 */; const int CAP_AMPLITUDE_CONTROL = (1 << 2) /* 4 */; diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorManager.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorManager.aidl index ef5794c6446f88502decca0f47ac1b1bb019cdca..081d9dcf70bec1ade8b4b2ac6c97ad5521b633c5 100644 --- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorManager.aidl +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorManager.aidl @@ -40,6 +40,8 @@ interface IVibratorManager { void prepareSynced(in int[] vibratorIds); void triggerSynced(in android.hardware.vibrator.IVibratorCallback callback); void cancelSynced(); + android.hardware.vibrator.IVibrationSession startSession(in int[] vibratorIds, in android.hardware.vibrator.VibrationSessionConfig config, in android.hardware.vibrator.IVibratorCallback callback); + void clearSessions(); const int CAP_SYNC = (1 << 0) /* 1 */; const int CAP_PREPARE_ON = (1 << 1) /* 2 */; const int CAP_PREPARE_PERFORM = (1 << 2) /* 4 */; @@ -48,4 +50,5 @@ interface IVibratorManager { const int CAP_MIXED_TRIGGER_PERFORM = (1 << 5) /* 32 */; const int CAP_MIXED_TRIGGER_COMPOSE = (1 << 6) /* 64 */; const int CAP_TRIGGER_CALLBACK = (1 << 7) /* 128 */; + const int CAP_START_SESSIONS = (1 << 8) /* 256 */; } diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/VibrationSessionConfig.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/VibrationSessionConfig.aidl new file mode 100644 index 0000000000000000000000000000000000000000..01136aa4697ad21bab25ee66b49116f0be8b2fb7 --- /dev/null +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/VibrationSessionConfig.aidl @@ -0,0 +1,38 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.vibrator; +@VintfStability +parcelable VibrationSessionConfig { + ParcelableHolder vendorExtension; +} diff --git a/vibrator/aidl/android/hardware/vibrator/CompositePwleV2.aidl b/vibrator/aidl/android/hardware/vibrator/CompositePwleV2.aidl new file mode 100644 index 0000000000000000000000000000000000000000..f0d097084305195f146288ccedaa83d692c5dd17 --- /dev/null +++ b/vibrator/aidl/android/hardware/vibrator/CompositePwleV2.aidl @@ -0,0 +1,31 @@ +/* + * 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. + */ + +package android.hardware.vibrator; + +import android.hardware.vibrator.PwleV2Primitive; + +@VintfStability +parcelable CompositePwleV2 { + /** + * Represents a PWLE (Piecewise-Linear Envelope) effect as an array of primitives. + * + * A PWLE effect defines a vibration waveform using amplitude and frequency points. + * The envelope linearly interpolates both amplitude and frequency between consecutive points, + * creating smooth transitions in the vibration pattern. + */ + PwleV2Primitive[] pwlePrimitives; +} diff --git a/vibrator/aidl/android/hardware/vibrator/PwleV2OutputMapEntry.aidl b/vibrator/aidl/android/hardware/vibrator/FrequencyAccelerationMapEntry.aidl similarity index 89% rename from vibrator/aidl/android/hardware/vibrator/PwleV2OutputMapEntry.aidl rename to vibrator/aidl/android/hardware/vibrator/FrequencyAccelerationMapEntry.aidl index a8db87cd25031f658765f43903e65ab2d40f5603..013ae841c4b9b5dd94c27a4c681633e925004597 100644 --- a/vibrator/aidl/android/hardware/vibrator/PwleV2OutputMapEntry.aidl +++ b/vibrator/aidl/android/hardware/vibrator/FrequencyAccelerationMapEntry.aidl @@ -17,7 +17,7 @@ package android.hardware.vibrator; @VintfStability -parcelable PwleV2OutputMapEntry { +parcelable FrequencyAccelerationMapEntry { /** * Absolute frequency point in the units of hertz * @@ -29,7 +29,7 @@ parcelable PwleV2OutputMapEntry { * * This value represents the maximum safe output acceleration (in Gs) achievable at the * specified frequency, typically determined during calibration. The actual output acceleration - * is assumed to scale linearly with the input amplitude within the range of [0, 1]. + * should scale linearly based on the 'amplitude' input value. */ float maxOutputAccelerationGs; } diff --git a/vibrator/aidl/android/hardware/vibrator/IVibrationSession.aidl b/vibrator/aidl/android/hardware/vibrator/IVibrationSession.aidl new file mode 100644 index 0000000000000000000000000000000000000000..88382e5efe6d8c13cbf9ee2ef2cc12f3386d4374 --- /dev/null +++ b/vibrator/aidl/android/hardware/vibrator/IVibrationSession.aidl @@ -0,0 +1,42 @@ +/* + * 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. + */ + +package android.hardware.vibrator; + +@VintfStability +interface IVibrationSession { + /** + * Request the end of this session. + * + * This will cause this session to end once the ongoing vibration commands are completed in each + * individual vibrator. The immediate end of this session can stll be trigged via abort(). + * + * This should not block on the end of this session. The callback provided during the creation + * of this session should be used to indicate the vibrations are done and the session has + * ended. The session object can be safely destroyed after this is called, and the session + * should end as expected. + */ + void close(); + + /** + * Immediately end this session. + * + * This will cause this session to end immediately and stop any ongoing vibration. The vibrator + * manager and each individual vibrator in this session will be reset and available when this + * returns. + */ + void abort(); +} diff --git a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl index 11f36baf2c883a7fa6679736aca6335a602f64d0..81d79482a8724874f831ab4aa290be71001cf793 100644 --- a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl +++ b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl @@ -19,12 +19,12 @@ package android.hardware.vibrator; import android.hardware.vibrator.Braking; import android.hardware.vibrator.CompositeEffect; import android.hardware.vibrator.CompositePrimitive; +import android.hardware.vibrator.CompositePwleV2; import android.hardware.vibrator.Effect; import android.hardware.vibrator.EffectStrength; +import android.hardware.vibrator.FrequencyAccelerationMapEntry; import android.hardware.vibrator.IVibratorCallback; import android.hardware.vibrator.PrimitivePwle; -import android.hardware.vibrator.PwleV2OutputMapEntry; -import android.hardware.vibrator.PwleV2Primitive; import android.hardware.vibrator.VendorEffect; @VintfStability @@ -290,6 +290,8 @@ interface IVibrator { * * @return The frequency resolution of the bandwidth amplitude map. * Non-zero value if supported, or value should be ignored if not supported. + * @deprecated This method is deprecated from AIDL v3 and is no longer required to be + * implemented even if CAP_FREQUENCY_CONTROL capability is reported. */ float getFrequencyResolution(); @@ -301,6 +303,8 @@ interface IVibrator { * * @return The minimum frequency allowed. Non-zero value if supported, * or value should be ignored if not supported. + * @deprecated This method is deprecated from AIDL v3 and is no longer required to be + * implemented even if CAP_FREQUENCY_CONTROL capability is reported. */ float getFrequencyMinimum(); @@ -322,6 +326,8 @@ interface IVibrator { * * @return The maximum output acceleration amplitude for each supported frequency, * starting at getMinimumFrequency() + * @deprecated This method is deprecated from AIDL v3 and is no longer required to be + * implemented even if CAP_FREQUENCY_CONTROL capability is reported. */ float[] getBandwidthAmplitudeMap(); @@ -333,6 +339,8 @@ interface IVibrator { * * @return The maximum duration allowed for a single PrimitivePwle. * Non-zero value if supported, or value should be ignored if not supported. + * @deprecated This method is deprecated from AIDL v3 and is no longer required to be + * implemented. Use `IVibrator.getPwleV2PrimitiveDurationMaxMillis` instead. */ int getPwlePrimitiveDurationMax(); @@ -344,6 +352,8 @@ interface IVibrator { * * @return The maximum count allowed. Non-zero value if supported, * or value should be ignored if not supported. + * @deprecated This method is deprecated from AIDL v3 and is no longer required to be + * implemented. Use `IVibrator.getPwleV2CompositionSizeMax` instead. */ int getPwleCompositionSizeMax(); @@ -355,6 +365,8 @@ interface IVibrator { * Implementations are optional but encouraged if available. * * @return The braking mechanisms which are supported by the composePwle API. + * @deprecated This method is deprecated from AIDL v3 and is no longer required to be + * implemented. */ Braking[] getSupportedBraking(); @@ -368,6 +380,8 @@ interface IVibrator { * explicitly call off. IVibratorCallback.onComplete() support is required for this API. * * @param composite Array of PWLEs. + * @deprecated This method is deprecated from AIDL v3 and is no longer required to be + * implemented. Use `IVibrator.composePwleV2` instead. */ void composePwle(in PrimitivePwle[] composite, in IVibratorCallback callback); @@ -396,12 +410,12 @@ interface IVibrator { * Retrieves a mapping of vibration frequency (Hz) to the maximum achievable output * acceleration (Gs) the device can reach at that frequency. * - * The map, represented as a list of `PwleV2OutputMapEntry` (frequency, output acceleration) - * pairs, defines the device's frequency response. The platform uses the minimum and maximum - * frequency values to determine the supported input range for `IVibrator.composePwleV2`. - * Output acceleration values are used to identify a frequency range suitable to safely play - * perceivable vibrations with a simple API. The map is also exposed for developers using an - * advanced API. + * The map, represented as a list of `FrequencyAccelerationMapEntry` (frequency, output + * acceleration) pairs, defines the device's frequency response. The platform uses the minimum + * and maximum frequency values to determine the supported input range for + * `IVibrator.composePwleV2`. Output acceleration values are used to identify a frequency range + * suitable to safely play perceivable vibrations with a simple API. The map is also exposed for + * developers using an advanced API. * * The platform does not impose specific requirements on map resolution which can vary * depending on the shape of device output curve. The values will be linearly interpolated @@ -410,7 +424,7 @@ interface IVibrator { * * * This may not be supported and this support is reflected in getCapabilities - * (CAP_COMPOSE_PWLE_EFFECTS_V2). If this is supported, it's expected to be non-empty and + * (CAP_FREQUENCY_CONTROL). If this is supported, it's expected to be non-empty and * describe a valid non-empty frequency range where the simple API can be defined * (i.e. a range where the output acceleration is always above 10 db SL). * @@ -418,7 +432,7 @@ interface IVibrator { * mapping. * @throws EX_UNSUPPORTED_OPERATION if unsupported, as reflected by getCapabilities. */ - List getPwleV2FrequencyToOutputAccelerationMap(); + List getFrequencyToOutputAccelerationMap(); /** * Retrieve the maximum duration allowed for any primitive PWLE in units of @@ -436,8 +450,8 @@ interface IVibrator { * Retrieve the maximum number of PWLE primitives input supported by IVibrator.composePwleV2. * * This may not be supported and this support is reflected in - * getCapabilities (CAP_COMPOSE_PWLE_EFFECTS_V2). Devices supporting PWLE effects must - * support effects with at least 16 PwleV2Primitive. + * getCapabilities (CAP_COMPOSE_PWLE_EFFECTS_V2). Devices supporting + * PWLE effects must support effects with at least 16 PwleV2Primitive. * * @return The maximum count allowed. Non-zero value if supported. * @throws EX_UNSUPPORTED_OPERATION if unsupported, as reflected by getCapabilities. @@ -458,15 +472,23 @@ interface IVibrator { int getPwleV2PrimitiveDurationMinMillis(); /** - * Play composed sequence of chirps with optional callback upon completion. + * Play composed sequence of PWLEs with optional callback upon completion. + * + * A PWLE (Piecewise-Linear Envelope) effect defines a vibration waveform using amplitude and + * frequency points. The envelope linearly interpolates both amplitude and frequency between + * consecutive points, creating smooth transitions in the vibration pattern. * * This may not be supported and this support is reflected in * getCapabilities (CAP_COMPOSE_PWLE_EFFECTS_V2). * + * Note: Devices reporting CAP_COMPOSE_PWLE_EFFECTS_V2 support MUST also have the + * CAP_FREQUENCY_CONTROL capability and provide a valid frequency to output acceleration map. + * * Doing this operation while the vibrator is already on is undefined behavior. Clients should * explicitly call off. IVibratorCallback.onComplete() support is required for this API. * - * @param composite An array of primitives that represents a PWLE (Piecewise-Linear Envelope). + * @param composite A CompositePwleV2 representing a composite vibration effect, composed of an + * array of primitives that define the PWLE (Piecewise-Linear Envelope). */ - void composePwleV2(in PwleV2Primitive[] composite, in IVibratorCallback callback); + void composePwleV2(in CompositePwleV2 composite, in IVibratorCallback callback); } diff --git a/vibrator/aidl/android/hardware/vibrator/IVibratorManager.aidl b/vibrator/aidl/android/hardware/vibrator/IVibratorManager.aidl index eb5e9ccd3f20192f32b3ec1fca0e33ce003f92e6..e8b85c5b27b8baf4bfaf6ec954f972d94b50cb9b 100644 --- a/vibrator/aidl/android/hardware/vibrator/IVibratorManager.aidl +++ b/vibrator/aidl/android/hardware/vibrator/IVibratorManager.aidl @@ -16,8 +16,10 @@ package android.hardware.vibrator; +import android.hardware.vibrator.IVibrationSession; import android.hardware.vibrator.IVibrator; import android.hardware.vibrator.IVibratorCallback; +import android.hardware.vibrator.VibrationSessionConfig; @VintfStability interface IVibratorManager { @@ -42,17 +44,23 @@ interface IVibratorManager { */ const int CAP_MIXED_TRIGGER_ON = 1 << 4; /** - * Whether IVibrator 'perform' can be triggered with other functions in sync with 'triggerSynced'. + * Whether IVibrator 'perform' can be triggered with other functions in sync with + * 'triggerSynced'. */ const int CAP_MIXED_TRIGGER_PERFORM = 1 << 5; /** - * Whether IVibrator 'compose' can be triggered with other functions in sync with 'triggerSynced'. + * Whether IVibrator 'compose' can be triggered with other functions in sync with + * 'triggerSynced'. */ const int CAP_MIXED_TRIGGER_COMPOSE = 1 << 6; /** * Whether on w/ IVibratorCallback can be used w/ 'trigerSynced' function. */ const int CAP_TRIGGER_CALLBACK = 1 << 7; + /** + * Whether vibration sessions are supported. + */ + const int CAP_START_SESSIONS = 1 << 8; /** * Determine capabilities of the vibrator manager HAL (CAP_* mask) @@ -75,8 +83,8 @@ interface IVibratorManager { * This function must only be called after the previous synced vibration was triggered or * canceled (through cancelSynced()). * - * Doing this operation while any of the specified vibrators is already on is undefined behavior. - * Clients should explicitly call off in each vibrator. + * Doing this operation while any of the specified vibrators is already on is undefined + * behavior. Clients should explicitly call off in each vibrator. * * @param vibratorIds ids of the vibrators to play vibrations in sync. */ @@ -99,4 +107,41 @@ interface IVibratorManager { * Cancel a previously-started preparation for synced vibration, if any. */ void cancelSynced(); + + /** + * Start a vibration session. + * + * A vibration session can be used to send commands without resetting the vibrator state. Once a + * session starts, the individual vibrators can receive one or more commands like on(), + * performEffect(), setAmplitude(), etc. The vibrations performed in a session must have the + * same behavior they have outside them. Multiple commands can be synced in a session via + * prepareSynced as usual. + * + * Starting a session on a vibrator already in another session or in a prepareSynced state is + * not allowed and should throw illegal state. The end of a session should always notify the + * callback provided, even if it ends prematurely due to an error. + * + * This may not be supported and this support is reflected in + * getCapabilities (CAP_START_SESSIONS). IVibratorCallback.onComplete() support is required for + * this API. + * + * @param vibratorIds ids of the vibrators in the session. + * @param config The parameters for starting a vibration session. + * @param callback A callback used to inform Frameworks of state change. + * @throws : + * - EX_UNSUPPORTED_OPERATION if unsupported, as reflected by getCapabilities. + * - EX_ILLEGAL_ARGUMENT for invalid vibrator IDs. + * - EX_ILLEGAL_STATE for vibrator IDs already in a session or in a prepareSynced state. + * - EX_SERVICE_SPECIFIC for bad vendor data. + */ + IVibrationSession startSession( + in int[] vibratorIds, in VibrationSessionConfig config, in IVibratorCallback callback); + + /** + * Abort and clear all ongoing vibration sessions. + * + * This can be used to reset the vibrator manager and some individual vibrators to an idle + * state. + */ + void clearSessions(); } diff --git a/vibrator/aidl/android/hardware/vibrator/PwleV2Primitive.aidl b/vibrator/aidl/android/hardware/vibrator/PwleV2Primitive.aidl index bd7bec6036c0eb14ba7bbf9463f647cdf54495c9..1ad1a9f7b76725b5bdf92e561d2bcc7bd8709bb5 100644 --- a/vibrator/aidl/android/hardware/vibrator/PwleV2Primitive.aidl +++ b/vibrator/aidl/android/hardware/vibrator/PwleV2Primitive.aidl @@ -21,7 +21,7 @@ parcelable PwleV2Primitive { /** * Input amplitude ranges from 0.0 (inclusive) to 1.0 (inclusive), representing the relative * input value. Actual output acceleration depends on frequency and device response curve - * (see IVibrator.getPwleV2FrequencyToOutputAccelerationMap for max values). + * (see IVibrator.getFrequencyToOutputAccelerationMap for max values). * * Input amplitude linearly maps to output acceleration (e.g., 0.5 amplitude yields half the * max acceleration for that frequency). @@ -36,7 +36,7 @@ parcelable PwleV2Primitive { * Absolute frequency point in the units of hertz * * Values are within the continuous inclusive frequency range defined by - * IVibrator#getPwleV2FrequencyToOutputAccelerationMap. + * IVibrator#getFrequencyToOutputAccelerationMap. */ float frequencyHz; diff --git a/vibrator/aidl/android/hardware/vibrator/VibrationSessionConfig.aidl b/vibrator/aidl/android/hardware/vibrator/VibrationSessionConfig.aidl new file mode 100644 index 0000000000000000000000000000000000000000..56cdde3d09a4e4d4acfc171080020276c96d3ea9 --- /dev/null +++ b/vibrator/aidl/android/hardware/vibrator/VibrationSessionConfig.aidl @@ -0,0 +1,25 @@ +/* + * 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. + */ + +package android.hardware.vibrator; + +@VintfStability +parcelable VibrationSessionConfig { + /** + * Vendor extension point for starting a vibration session. + */ + ParcelableHolder vendorExtension; +} diff --git a/vibrator/aidl/default/Android.bp b/vibrator/aidl/default/Android.bp index b25a5ba75233d4c646fe130d9e8b3e14743e7353..de228cdfad83baa8e66258a94ebd14548e4b6296 100644 --- a/vibrator/aidl/default/Android.bp +++ b/vibrator/aidl/default/Android.bp @@ -19,6 +19,7 @@ cc_library_static { ], export_include_dirs: ["include"], srcs: [ + "VibrationSession.cpp", "Vibrator.cpp", "VibratorManager.cpp", ], diff --git a/vibrator/aidl/default/VibrationSession.cpp b/vibrator/aidl/default/VibrationSession.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4eac831d5f67d0eba6696457ef1cddac60b31ee7 --- /dev/null +++ b/vibrator/aidl/default/VibrationSession.cpp @@ -0,0 +1,44 @@ +/* + * 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 "vibrator-impl/VibrationSession.h" + +#include +#include + +namespace aidl { +namespace android { +namespace hardware { +namespace vibrator { + +static constexpr int32_t SESSION_END_DELAY_MS = 20; + +ndk::ScopedAStatus VibrationSession::close() { + LOG(VERBOSE) << "Vibration Session close"; + mManager->closeSession(SESSION_END_DELAY_MS); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus VibrationSession::abort() { + LOG(VERBOSE) << "Vibration Session abort"; + mManager->abortSession(); + return ndk::ScopedAStatus::ok(); +} + +} // namespace vibrator +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/vibrator/aidl/default/Vibrator.cpp b/vibrator/aidl/default/Vibrator.cpp index 4f8c2b84f0a983e847c729265d38a6a5c83a0bdc..165a3bf4718ac928ce08c2fa353554ee19a04473 100644 --- a/vibrator/aidl/default/Vibrator.cpp +++ b/vibrator/aidl/default/Vibrator.cpp @@ -45,11 +45,62 @@ static constexpr float PWLE_BW_MAP_SIZE = // Service specific error code used for vendor vibration effects. static constexpr int32_t ERROR_CODE_INVALID_DURATION = 1; +void Vibrator::dispatchVibrate(int32_t timeoutMs, + const std::shared_ptr& callback) { + std::lock_guard lock(mMutex); + if (mIsVibrating) { + // Already vibrating, ignore new request. + return; + } + mVibrationCallback = callback; + mIsVibrating = true; + // Note that thread lambdas aren't using implicit capture [=], to avoid capturing "this", + // which may be asynchronously destructed. + std::thread([timeoutMs, callback, sharedThis = this->ref()] { + LOG(VERBOSE) << "Starting delayed callback on another thread"; + usleep(timeoutMs * 1000); + + if (sharedThis) { + std::lock_guard lock(sharedThis->mMutex); + sharedThis->mIsVibrating = false; + if (sharedThis->mVibrationCallback && (callback == sharedThis->mVibrationCallback)) { + LOG(VERBOSE) << "Notifying callback onComplete"; + if (!sharedThis->mVibrationCallback->onComplete().isOk()) { + LOG(ERROR) << "Failed to call onComplete"; + } + sharedThis->mVibrationCallback = nullptr; + } + if (sharedThis->mGlobalVibrationCallback) { + LOG(VERBOSE) << "Notifying global callback onComplete"; + if (!sharedThis->mGlobalVibrationCallback->onComplete().isOk()) { + LOG(ERROR) << "Failed to call onComplete"; + } + sharedThis->mGlobalVibrationCallback = nullptr; + } + } + }).detach(); +} + +void Vibrator::setGlobalVibrationCallback(const std::shared_ptr& callback) { + std::lock_guard lock(mMutex); + if (mIsVibrating) { + mGlobalVibrationCallback = callback; + } else if (callback) { + std::thread([callback] { + LOG(VERBOSE) << "Notifying global callback onComplete"; + if (!callback->onComplete().isOk()) { + LOG(ERROR) << "Failed to call onComplete"; + } + }).detach(); + } +} + ndk::ScopedAStatus Vibrator::getCapabilities(int32_t* _aidl_return) { LOG(VERBOSE) << "Vibrator reporting capabilities"; std::lock_guard lock(mMutex); if (mCapabilities == 0) { - if (!getInterfaceVersion(&mVersion).isOk()) { + int32_t version; + if (!getInterfaceVersion(&version).isOk()) { return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_ILLEGAL_STATE)); } mCapabilities = IVibrator::CAP_ON_CALLBACK | IVibrator::CAP_PERFORM_CALLBACK | @@ -59,9 +110,9 @@ ndk::ScopedAStatus Vibrator::getCapabilities(int32_t* _aidl_return) { IVibrator::CAP_GET_Q_FACTOR | IVibrator::CAP_FREQUENCY_CONTROL | IVibrator::CAP_COMPOSE_PWLE_EFFECTS; - if (mVersion >= 3) { - mCapabilities |= (IVibrator::CAP_PERFORM_VENDOR_EFFECTS | - IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2); + if (version >= 3) { + mCapabilities |= + IVibrator::CAP_PERFORM_VENDOR_EFFECTS | IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2; } } @@ -71,25 +122,35 @@ ndk::ScopedAStatus Vibrator::getCapabilities(int32_t* _aidl_return) { ndk::ScopedAStatus Vibrator::off() { LOG(VERBOSE) << "Vibrator off"; + std::lock_guard lock(mMutex); + std::shared_ptr callback = mVibrationCallback; + std::shared_ptr globalCallback = mGlobalVibrationCallback; + mIsVibrating = false; + mVibrationCallback = nullptr; + mGlobalVibrationCallback = nullptr; + if (callback || globalCallback) { + std::thread([callback, globalCallback] { + if (callback) { + LOG(VERBOSE) << "Notifying callback onComplete"; + if (!callback->onComplete().isOk()) { + LOG(ERROR) << "Failed to call onComplete"; + } + } + if (globalCallback) { + LOG(VERBOSE) << "Notifying global callback onComplete"; + if (!globalCallback->onComplete().isOk()) { + LOG(ERROR) << "Failed to call onComplete"; + } + } + }).detach(); + } return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus Vibrator::on(int32_t timeoutMs, const std::shared_ptr& callback) { LOG(VERBOSE) << "Vibrator on for timeoutMs: " << timeoutMs; - if (callback != nullptr) { - // Note that thread lambdas aren't using implicit capture [=], to avoid capturing "this", - // which may be asynchronously destructed. - // If "this" is needed, use [sharedThis = this->ref()]. - std::thread([timeoutMs, callback] { - LOG(VERBOSE) << "Starting on on another thread"; - usleep(timeoutMs * 1000); - LOG(VERBOSE) << "Notifying on complete"; - if (!callback->onComplete().isOk()) { - LOG(ERROR) << "Failed to call onComplete"; - } - }).detach(); - } + dispatchVibrate(timeoutMs, callback); return ndk::ScopedAStatus::ok(); } @@ -107,16 +168,7 @@ ndk::ScopedAStatus Vibrator::perform(Effect effect, EffectStrength strength, } constexpr size_t kEffectMillis = 100; - - if (callback != nullptr) { - std::thread([callback] { - LOG(VERBOSE) << "Starting perform on another thread"; - usleep(kEffectMillis * 1000); - LOG(VERBOSE) << "Notifying perform complete"; - callback->onComplete(); - }).detach(); - } - + dispatchVibrate(kEffectMillis, callback); *_aidl_return = kEffectMillis; return ndk::ScopedAStatus::ok(); } @@ -150,15 +202,7 @@ ndk::ScopedAStatus Vibrator::performVendorEffect( return ndk::ScopedAStatus::fromServiceSpecificError(ERROR_CODE_INVALID_DURATION); } - if (callback != nullptr) { - std::thread([callback, durationMs] { - LOG(VERBOSE) << "Starting perform on another thread for durationMs:" << durationMs; - usleep(durationMs * 1000); - LOG(VERBOSE) << "Notifying perform vendor effect complete"; - callback->onComplete(); - }).detach(); - } - + dispatchVibrate(durationMs, callback); return ndk::ScopedAStatus::ok(); } @@ -237,28 +281,14 @@ ndk::ScopedAStatus Vibrator::compose(const std::vector& composi } } - // The thread may theoretically outlive the vibrator, so take a proper reference to it. - std::thread([sharedThis = this->ref(), composite, callback] { - LOG(VERBOSE) << "Starting compose on another thread"; - - for (auto& e : composite) { - if (e.delayMs) { - usleep(e.delayMs * 1000); - } - LOG(VERBOSE) << "triggering primitive " << static_cast(e.primitive) << " @ scale " - << e.scale; - - int32_t durationMs; - sharedThis->getPrimitiveDuration(e.primitive, &durationMs); - usleep(durationMs * 1000); - } - - if (callback != nullptr) { - LOG(VERBOSE) << "Notifying perform complete"; - callback->onComplete(); - } - }).detach(); + int32_t totalDuration = 0; + for (auto& e : composite) { + int32_t durationMs; + getPrimitiveDuration(e.primitive, &durationMs); + totalDuration += e.delayMs + durationMs; + } + dispatchVibrate(totalDuration, callback); return ndk::ScopedAStatus::ok(); } @@ -460,21 +490,21 @@ ndk::ScopedAStatus Vibrator::composePwle(const std::vector &compo } } - std::thread([totalDuration, callback] { - LOG(VERBOSE) << "Starting composePwle on another thread"; - usleep(totalDuration * 1000); - if (callback != nullptr) { - LOG(VERBOSE) << "Notifying compose PWLE complete"; - callback->onComplete(); - } - }).detach(); - + dispatchVibrate(totalDuration, callback); return ndk::ScopedAStatus::ok(); } -ndk::ScopedAStatus Vibrator::getPwleV2FrequencyToOutputAccelerationMap( - std::vector* _aidl_return) { - std::vector frequencyToOutputAccelerationMap; +ndk::ScopedAStatus Vibrator::getFrequencyToOutputAccelerationMap( + std::vector* _aidl_return) { + int32_t capabilities = 0; + if (!getCapabilities(&capabilities).isOk()) { + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); + } + if (!(capabilities & IVibrator::CAP_FREQUENCY_CONTROL)) { + return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION)); + } + + std::vector frequencyToOutputAccelerationMap; std::vector> frequencyToOutputAccelerationData = { {30.0f, 0.01f}, {46.0f, 0.09f}, {50.0f, 0.1f}, {55.0f, 0.12f}, {62.0f, 0.66f}, @@ -485,8 +515,8 @@ ndk::ScopedAStatus Vibrator::getPwleV2FrequencyToOutputAccelerationMap( {263.0f, 1.39f}, {65.0f, 1.38f}, {278.0f, 1.37f}, {294.0f, 1.35f}, {300.0f, 1.34f}}; for (const auto& entry : frequencyToOutputAccelerationData) { frequencyToOutputAccelerationMap.push_back( - PwleV2OutputMapEntry(/*frequency=*/entry.first, - /*maxOutputAcceleration=*/entry.second)); + FrequencyAccelerationMapEntry(/*frequency=*/entry.first, + /*maxOutputAcceleration=*/entry.second)); } *_aidl_return = frequencyToOutputAccelerationMap; @@ -509,7 +539,8 @@ ndk::ScopedAStatus Vibrator::getPwleV2PrimitiveDurationMinMillis(int32_t* minDur return ndk::ScopedAStatus::ok(); } -float getPwleV2FrequencyMinHz(std::vector frequencyToOutputAccelerationMap) { +float getPwleV2FrequencyMinHz( + std::vector frequencyToOutputAccelerationMap) { if (frequencyToOutputAccelerationMap.empty()) { return 0.0f; } @@ -525,7 +556,8 @@ float getPwleV2FrequencyMinHz(std::vector frequencyToOutpu return minFrequency; } -float getPwleV2FrequencyMaxHz(std::vector frequencyToOutputAccelerationMap) { +float getPwleV2FrequencyMaxHz( + std::vector frequencyToOutputAccelerationMap) { if (frequencyToOutputAccelerationMap.empty()) { return 0.0f; } @@ -541,29 +573,31 @@ float getPwleV2FrequencyMaxHz(std::vector frequencyToOutpu return maxFrequency; } -ndk::ScopedAStatus Vibrator::composePwleV2(const std::vector& composite, +ndk::ScopedAStatus Vibrator::composePwleV2(const CompositePwleV2& composite, const std::shared_ptr& callback) { + LOG(VERBOSE) << "Vibrator compose PWLE V2"; int32_t capabilities = 0; if (!getCapabilities(&capabilities).isOk()) { return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); } - if ((capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2) == 0) { + if (!(capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2) || + !(capabilities & IVibrator::CAP_FREQUENCY_CONTROL)) { return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION)); } int compositionSizeMax; getPwleV2CompositionSizeMax(&compositionSizeMax); - if (composite.size() <= 0 || composite.size() > compositionSizeMax) { + if (composite.pwlePrimitives.empty() || composite.pwlePrimitives.size() > compositionSizeMax) { return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } int32_t totalEffectDuration = 0; - std::vector frequencyToOutputAccelerationMap; - getPwleV2FrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap); + std::vector frequencyToOutputAccelerationMap; + getFrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap); float minFrequency = getPwleV2FrequencyMinHz(frequencyToOutputAccelerationMap); float maxFrequency = getPwleV2FrequencyMaxHz(frequencyToOutputAccelerationMap); - for (auto& e : composite) { + for (auto& e : composite.pwlePrimitives) { if (e.timeMillis < 0.0f || e.timeMillis > COMPOSE_PWLE_V2_PRIMITIVE_DURATION_MAX_MS) { return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } @@ -576,15 +610,7 @@ ndk::ScopedAStatus Vibrator::composePwleV2(const std::vector& c totalEffectDuration += e.timeMillis; } - std::thread([totalEffectDuration, callback] { - LOG(VERBOSE) << "Starting composePwleV2 on another thread"; - usleep(totalEffectDuration * 1000); - if (callback != nullptr) { - LOG(VERBOSE) << "Notifying compose PWLE V2 complete"; - callback->onComplete(); - } - }).detach(); - + dispatchVibrate(totalEffectDuration, callback); return ndk::ScopedAStatus::ok(); } diff --git a/vibrator/aidl/default/VibratorManager.cpp b/vibrator/aidl/default/VibratorManager.cpp index 26edf5a8051566e032d11d2aa4f82efe4a7a4089..c3be46814e6bf6d29f782cf907bc4364f30b09d6 100644 --- a/vibrator/aidl/default/VibratorManager.cpp +++ b/vibrator/aidl/default/VibratorManager.cpp @@ -15,6 +15,9 @@ */ #include "vibrator-impl/VibratorManager.h" +#include "vibrator-impl/VibrationSession.h" + +#include #include #include @@ -26,25 +29,52 @@ namespace vibrator { static constexpr int32_t kDefaultVibratorId = 1; +class VibratorCallback : public BnVibratorCallback { + public: + VibratorCallback(const std::function& callback) : mCallback(callback) {} + ndk::ScopedAStatus onComplete() override { + mCallback(); + return ndk::ScopedAStatus::ok(); + } + + private: + std::function mCallback; +}; + ndk::ScopedAStatus VibratorManager::getCapabilities(int32_t* _aidl_return) { - LOG(INFO) << "Vibrator manager reporting capabilities"; - *_aidl_return = - IVibratorManager::CAP_SYNC | IVibratorManager::CAP_PREPARE_ON | - IVibratorManager::CAP_PREPARE_PERFORM | IVibratorManager::CAP_PREPARE_COMPOSE | - IVibratorManager::CAP_MIXED_TRIGGER_ON | IVibratorManager::CAP_MIXED_TRIGGER_PERFORM | - IVibratorManager::CAP_MIXED_TRIGGER_COMPOSE | IVibratorManager::CAP_TRIGGER_CALLBACK; + LOG(VERBOSE) << "Vibrator manager reporting capabilities"; + std::lock_guard lock(mMutex); + if (mCapabilities == 0) { + int32_t version; + if (!getInterfaceVersion(&version).isOk()) { + return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_ILLEGAL_STATE)); + } + mCapabilities = IVibratorManager::CAP_SYNC | IVibratorManager::CAP_PREPARE_ON | + IVibratorManager::CAP_PREPARE_PERFORM | + IVibratorManager::CAP_PREPARE_COMPOSE | + IVibratorManager::CAP_MIXED_TRIGGER_ON | + IVibratorManager::CAP_MIXED_TRIGGER_PERFORM | + IVibratorManager::CAP_MIXED_TRIGGER_COMPOSE | + IVibratorManager::CAP_TRIGGER_CALLBACK; + + if (version >= 3) { + mCapabilities |= IVibratorManager::CAP_START_SESSIONS; + } + } + + *_aidl_return = mCapabilities; return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus VibratorManager::getVibratorIds(std::vector* _aidl_return) { - LOG(INFO) << "Vibrator manager getting vibrator ids"; + LOG(VERBOSE) << "Vibrator manager getting vibrator ids"; *_aidl_return = {kDefaultVibratorId}; return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus VibratorManager::getVibrator(int32_t vibratorId, std::shared_ptr* _aidl_return) { - LOG(INFO) << "Vibrator manager getting vibrator " << vibratorId; + LOG(VERBOSE) << "Vibrator manager getting vibrator " << vibratorId; if (vibratorId == kDefaultVibratorId) { *_aidl_return = mDefaultVibrator; return ndk::ScopedAStatus::ok(); @@ -55,32 +85,131 @@ ndk::ScopedAStatus VibratorManager::getVibrator(int32_t vibratorId, } ndk::ScopedAStatus VibratorManager::prepareSynced(const std::vector& vibratorIds) { - LOG(INFO) << "Vibrator Manager prepare synced"; - if (vibratorIds.size() == 1 && vibratorIds[0] == kDefaultVibratorId) { - return ndk::ScopedAStatus::ok(); - } else { + LOG(VERBOSE) << "Vibrator Manager prepare synced"; + if (vibratorIds.size() != 1 || vibratorIds[0] != kDefaultVibratorId) { return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } + std::lock_guard lock(mMutex); + if (mIsPreparing) { + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); + } + mIsPreparing = true; + return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus VibratorManager::triggerSynced( const std::shared_ptr& callback) { - LOG(INFO) << "Vibrator Manager trigger synced"; + LOG(VERBOSE) << "Vibrator Manager trigger synced"; + std::lock_guard lock(mMutex); + if (!mIsPreparing) { + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); + } std::thread([callback] { if (callback != nullptr) { - LOG(INFO) << "Notifying perform complete"; + LOG(VERBOSE) << "Notifying perform complete"; callback->onComplete(); } }).detach(); - + mIsPreparing = false; return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus VibratorManager::cancelSynced() { - LOG(INFO) << "Vibrator Manager cancel synced"; + LOG(VERBOSE) << "Vibrator Manager cancel synced"; + std::lock_guard lock(mMutex); + mIsPreparing = false; return ndk::ScopedAStatus::ok(); } +ndk::ScopedAStatus VibratorManager::startSession(const std::vector& vibratorIds, + const VibrationSessionConfig&, + const std::shared_ptr& callback, + std::shared_ptr* _aidl_return) { + LOG(VERBOSE) << "Vibrator Manager start session"; + *_aidl_return = nullptr; + int32_t capabilities = 0; + if (!getCapabilities(&capabilities).isOk()) { + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); + } + if ((capabilities & IVibratorManager::CAP_START_SESSIONS) == 0) { + return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION)); + } + if (vibratorIds.size() != 1 || vibratorIds[0] != kDefaultVibratorId) { + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + std::lock_guard lock(mMutex); + if (mIsPreparing || mSession) { + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); + } + mSessionCallback = callback; + mSession = ndk::SharedRefBase::make(this->ref()); + *_aidl_return = static_cast>(mSession); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus VibratorManager::clearSessions() { + LOG(VERBOSE) << "Vibrator Manager clear sessions"; + abortSession(); + return ndk::ScopedAStatus::ok(); +} + +void VibratorManager::abortSession() { + std::shared_ptr session; + { + std::lock_guard lock(mMutex); + session = mSession; + } + if (session) { + mDefaultVibrator->off(); + clearSession(session); + } +} + +void VibratorManager::closeSession(int32_t delayMs) { + std::shared_ptr session; + { + std::lock_guard lock(mMutex); + if (mIsClosingSession) { + // Already closing session, ignore this. + return; + } + session = mSession; + mIsClosingSession = true; + } + if (session) { + auto callback = ndk::SharedRefBase::make( + [session, delayMs, sharedThis = this->ref()] { + LOG(VERBOSE) << "Closing session after vibrator became idle"; + usleep(delayMs * 1000); + + if (sharedThis) { + sharedThis->clearSession(session); + } + }); + mDefaultVibrator->setGlobalVibrationCallback(callback); + } +} + +void VibratorManager::clearSession(const std::shared_ptr& session) { + std::lock_guard lock(mMutex); + if (mSession != session) { + // Probably a delayed call from an old session that was already cleared, ignore it. + return; + } + std::shared_ptr callback = mSessionCallback; + mSession = nullptr; + mSessionCallback = nullptr; // make sure any delayed call will not trigger this again. + mIsClosingSession = false; + if (callback) { + std::thread([callback] { + LOG(VERBOSE) << "Notifying session complete"; + if (!callback->onComplete().isOk()) { + LOG(ERROR) << "Failed to call onComplete"; + } + }).detach(); + } +} + } // namespace vibrator } // namespace hardware } // namespace android diff --git a/vibrator/aidl/default/include/vibrator-impl/VibrationSession.h b/vibrator/aidl/default/include/vibrator-impl/VibrationSession.h new file mode 100644 index 0000000000000000000000000000000000000000..98bdd1cf6d8372025032c667cb80bed713d16703 --- /dev/null +++ b/vibrator/aidl/default/include/vibrator-impl/VibrationSession.h @@ -0,0 +1,46 @@ +/* + * 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. + */ + +#pragma once + +#include +#include +#include +#include + +#include "vibrator-impl/VibratorManager.h" + +namespace aidl { +namespace android { +namespace hardware { +namespace vibrator { + +class VibrationSession : public BnVibrationSession { + public: + VibrationSession(std::shared_ptr manager) : mManager(std::move(manager)) {}; + + ndk::ScopedAStatus close() override; + ndk::ScopedAStatus abort() override; + + private: + mutable std::mutex mMutex; + std::shared_ptr mManager; +}; + +} // namespace vibrator +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/vibrator/aidl/default/include/vibrator-impl/Vibrator.h b/vibrator/aidl/default/include/vibrator-impl/Vibrator.h index 28bc763ffb91ff14e8c47647724bf0f2fd85ea8f..354ba46575511e7bd78df00acd05e230b0ef4bfd 100644 --- a/vibrator/aidl/default/include/vibrator-impl/Vibrator.h +++ b/vibrator/aidl/default/include/vibrator-impl/Vibrator.h @@ -25,6 +25,7 @@ namespace hardware { namespace vibrator { class Vibrator : public BnVibrator { + public: ndk::ScopedAStatus getCapabilities(int32_t* _aidl_return) override; ndk::ScopedAStatus off() override; ndk::ScopedAStatus on(int32_t timeoutMs, @@ -58,18 +59,24 @@ class Vibrator : public BnVibrator { ndk::ScopedAStatus getSupportedBraking(std::vector* supported) override; ndk::ScopedAStatus composePwle(const std::vector &composite, const std::shared_ptr &callback) override; - ndk::ScopedAStatus getPwleV2FrequencyToOutputAccelerationMap( - std::vector* _aidl_return) override; + ndk::ScopedAStatus getFrequencyToOutputAccelerationMap( + std::vector* _aidl_return) override; ndk::ScopedAStatus getPwleV2PrimitiveDurationMaxMillis(int32_t* maxDurationMs) override; ndk::ScopedAStatus getPwleV2PrimitiveDurationMinMillis(int32_t* minDurationMs) override; ndk::ScopedAStatus getPwleV2CompositionSizeMax(int32_t* maxSize) override; - ndk::ScopedAStatus composePwleV2(const std::vector& composite, + ndk::ScopedAStatus composePwleV2(const CompositePwleV2& composite, const std::shared_ptr& callback) override; + void setGlobalVibrationCallback(const std::shared_ptr& callback); + private: mutable std::mutex mMutex; - int32_t mVersion GUARDED_BY(mMutex) = 0; // current Hal version + bool mIsVibrating GUARDED_BY(mMutex) = false; int32_t mCapabilities GUARDED_BY(mMutex) = 0; + std::shared_ptr mVibrationCallback GUARDED_BY(mMutex) = nullptr; + std::shared_ptr mGlobalVibrationCallback GUARDED_BY(mMutex) = nullptr; + + void dispatchVibrate(int32_t timeoutMs, const std::shared_ptr& callback); }; } // namespace vibrator diff --git a/vibrator/aidl/default/include/vibrator-impl/VibratorManager.h b/vibrator/aidl/default/include/vibrator-impl/VibratorManager.h index 319eb05c1f9495eafcf881aa1ce388b9d4582ad8..fe303942f1ba8e963de7b86ea9da01d8706dcd35 100644 --- a/vibrator/aidl/default/include/vibrator-impl/VibratorManager.h +++ b/vibrator/aidl/default/include/vibrator-impl/VibratorManager.h @@ -17,6 +17,9 @@ #pragma once #include +#include + +#include "vibrator-impl/Vibrator.h" namespace aidl { namespace android { @@ -25,7 +28,8 @@ namespace vibrator { class VibratorManager : public BnVibratorManager { public: - VibratorManager(std::shared_ptr vibrator) : mDefaultVibrator(std::move(vibrator)){}; + VibratorManager(std::shared_ptr vibrator) : mDefaultVibrator(std::move(vibrator)) {}; + ndk::ScopedAStatus getCapabilities(int32_t* _aidl_return) override; ndk::ScopedAStatus getVibratorIds(std::vector* _aidl_return) override; ndk::ScopedAStatus getVibrator(int32_t vibratorId, @@ -33,9 +37,25 @@ class VibratorManager : public BnVibratorManager { ndk::ScopedAStatus prepareSynced(const std::vector& vibratorIds) override; ndk::ScopedAStatus triggerSynced(const std::shared_ptr& callback) override; ndk::ScopedAStatus cancelSynced() override; + ndk::ScopedAStatus startSession(const std::vector& vibratorIds, + const VibrationSessionConfig& config, + const std::shared_ptr& callback, + std::shared_ptr* _aidl_return) override; + ndk::ScopedAStatus clearSessions() override; + + void abortSession(); + void closeSession(int32_t delayMs); private: - std::shared_ptr mDefaultVibrator; + std::shared_ptr mDefaultVibrator; + mutable std::mutex mMutex; + int32_t mCapabilities GUARDED_BY(mMutex) = 0; + bool mIsPreparing GUARDED_BY(mMutex) = false; + bool mIsClosingSession GUARDED_BY(mMutex) = false; + std::shared_ptr mSession GUARDED_BY(mMutex) = nullptr; + std::shared_ptr mSessionCallback GUARDED_BY(mMutex) = nullptr; + + void clearSession(const std::shared_ptr& session); }; } // namespace vibrator diff --git a/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp index 3c2a3607b100ce94a0a869c7e83f75418470c304..101d4f585fed4b512ab492c2b7e0d7f18551fc72 100644 --- a/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp +++ b/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp @@ -16,12 +16,14 @@ #include #include #include +#include #include #include #include #include +#include #include #include @@ -32,10 +34,14 @@ using aidl::android::hardware::vibrator::CompositeEffect; using aidl::android::hardware::vibrator::CompositePrimitive; using aidl::android::hardware::vibrator::Effect; using aidl::android::hardware::vibrator::EffectStrength; +using aidl::android::hardware::vibrator::IVibrationSession; using aidl::android::hardware::vibrator::IVibrator; using aidl::android::hardware::vibrator::IVibratorManager; +using aidl::android::hardware::vibrator::VibrationSessionConfig; using std::chrono::high_resolution_clock; +using namespace ::std::chrono_literals; + const std::vector kEffects{ndk::enum_range().begin(), ndk::enum_range().end()}; const std::vector kEffectStrengths{ndk::enum_range().begin(), @@ -43,6 +49,11 @@ const std::vector kEffectStrengths{ndk::enum_range kPrimitives{ndk::enum_range().begin(), ndk::enum_range().end()}; +// Timeout to wait for vibration callback completion. +static constexpr std::chrono::milliseconds VIBRATION_CALLBACK_TIMEOUT = 100ms; + +static constexpr int32_t VIBRATION_SESSIONS_MIN_VERSION = 3; + class CompletionCallback : public BnVibratorCallback { public: CompletionCallback(const std::function& callback) : mCallback(callback) {} @@ -64,9 +75,29 @@ class VibratorAidl : public testing::TestWithParam { ASSERT_NE(manager, nullptr); EXPECT_OK(manager->getCapabilities(&capabilities)); EXPECT_OK(manager->getVibratorIds(&vibratorIds)); + EXPECT_OK(manager->getInterfaceVersion(&version)); + } + + virtual void TearDown() override { + // Reset manager state between tests. + if (capabilities & IVibratorManager::CAP_SYNC) { + manager->cancelSynced(); + } + if (capabilities & IVibratorManager::CAP_START_SESSIONS) { + manager->clearSessions(); + } + // Reset all managed vibrators. + for (int32_t id : vibratorIds) { + std::shared_ptr vibrator; + EXPECT_OK(manager->getVibrator(id, &vibrator)); + ASSERT_NE(vibrator, nullptr); + EXPECT_OK(vibrator->off()); + } } std::shared_ptr manager; + std::shared_ptr session; + int32_t version; int32_t capabilities; std::vector vibratorIds; }; @@ -109,7 +140,7 @@ TEST_P(VibratorAidl, PrepareOnNotSupported) { if (vibratorIds.empty()) return; if (!(capabilities & IVibratorManager::CAP_SYNC)) return; if (!(capabilities & IVibratorManager::CAP_PREPARE_ON)) { - uint32_t durationMs = 250; + int32_t durationMs = 250; EXPECT_OK(manager->prepareSynced(vibratorIds)); std::shared_ptr vibrator; for (int32_t id : vibratorIds) { @@ -170,7 +201,7 @@ TEST_P(VibratorAidl, TriggerWithCallback) { std::future completionFuture{completionPromise.get_future()}; auto callback = ndk::SharedRefBase::make( [&completionPromise] { completionPromise.set_value(); }); - uint32_t durationMs = 250; + int32_t durationMs = 250; std::chrono::milliseconds timeout{durationMs * 2}; EXPECT_OK(manager->prepareSynced(vibratorIds)); @@ -202,6 +233,435 @@ TEST_P(VibratorAidl, TriggerCallbackNotSupported) { } } +TEST_P(VibratorAidl, VibrationSessionsSupported) { + if (!(capabilities & IVibratorManager::CAP_START_SESSIONS)) return; + if (vibratorIds.empty()) return; + + std::promise sessionPromise; + std::future sessionFuture{sessionPromise.get_future()}; + auto sessionCallback = ndk::SharedRefBase::make( + [&sessionPromise] { sessionPromise.set_value(); }); + + VibrationSessionConfig sessionConfig; + EXPECT_OK(manager->startSession(vibratorIds, sessionConfig, sessionCallback, &session)); + ASSERT_NE(session, nullptr); + + int32_t durationMs = 250; + std::vector> vibrationPromises; + std::vector> vibrationFutures; + for (int32_t id : vibratorIds) { + std::shared_ptr vibrator; + EXPECT_OK(manager->getVibrator(id, &vibrator)); + ASSERT_NE(vibrator, nullptr); + + std::promise& vibrationPromise = vibrationPromises.emplace_back(); + vibrationFutures.push_back(vibrationPromise.get_future()); + auto vibrationCallback = ndk::SharedRefBase::make( + [&vibrationPromise] { vibrationPromise.set_value(); }); + EXPECT_OK(vibrator->on(durationMs, vibrationCallback)); + } + + auto timeout = std::chrono::milliseconds(durationMs) + VIBRATION_CALLBACK_TIMEOUT; + for (std::future& future : vibrationFutures) { + EXPECT_EQ(future.wait_for(timeout), std::future_status::ready); + } + + // Session callback not triggered. + EXPECT_EQ(sessionFuture.wait_for(VIBRATION_CALLBACK_TIMEOUT), std::future_status::timeout); + + // Ending a session should not take long since the vibration was already completed + EXPECT_OK(session->close()); + EXPECT_EQ(sessionFuture.wait_for(VIBRATION_CALLBACK_TIMEOUT), std::future_status::ready); +} + +TEST_P(VibratorAidl, VibrationSessionInterrupted) { + if (!(capabilities & IVibratorManager::CAP_START_SESSIONS)) return; + if (vibratorIds.empty()) return; + + std::promise sessionPromise; + std::future sessionFuture{sessionPromise.get_future()}; + auto sessionCallback = ndk::SharedRefBase::make( + [&sessionPromise] { sessionPromise.set_value(); }); + + VibrationSessionConfig sessionConfig; + EXPECT_OK(manager->startSession(vibratorIds, sessionConfig, sessionCallback, &session)); + ASSERT_NE(session, nullptr); + + std::vector> vibrationPromises; + std::vector> vibrationFutures; + for (int32_t id : vibratorIds) { + std::shared_ptr vibrator; + EXPECT_OK(manager->getVibrator(id, &vibrator)); + ASSERT_NE(vibrator, nullptr); + + std::promise& vibrationPromise = vibrationPromises.emplace_back(); + vibrationFutures.push_back(vibrationPromise.get_future()); + auto vibrationCallback = ndk::SharedRefBase::make( + [&vibrationPromise] { vibrationPromise.set_value(); }); + + // Vibration longer than test timeout. + EXPECT_OK(vibrator->on(2000, vibrationCallback)); + } + + // Session callback not triggered. + EXPECT_EQ(sessionFuture.wait_for(VIBRATION_CALLBACK_TIMEOUT), std::future_status::timeout); + + // Interrupt vibrations and session. + EXPECT_OK(session->abort()); + + // Both callbacks triggered. + EXPECT_EQ(sessionFuture.wait_for(VIBRATION_CALLBACK_TIMEOUT), std::future_status::ready); + for (std::future& future : vibrationFutures) { + EXPECT_EQ(future.wait_for(VIBRATION_CALLBACK_TIMEOUT), std::future_status::ready); + } +} + +TEST_P(VibratorAidl, VibrationSessionEndingInterrupted) { + if (!(capabilities & IVibratorManager::CAP_START_SESSIONS)) return; + if (vibratorIds.empty()) return; + + std::promise sessionPromise; + std::future sessionFuture{sessionPromise.get_future()}; + auto sessionCallback = ndk::SharedRefBase::make( + [&sessionPromise] { sessionPromise.set_value(); }); + + VibrationSessionConfig sessionConfig; + EXPECT_OK(manager->startSession(vibratorIds, sessionConfig, sessionCallback, &session)); + ASSERT_NE(session, nullptr); + + std::vector> vibrationPromises; + std::vector> vibrationFutures; + for (int32_t id : vibratorIds) { + std::shared_ptr vibrator; + EXPECT_OK(manager->getVibrator(id, &vibrator)); + ASSERT_NE(vibrator, nullptr); + + std::promise& vibrationPromise = vibrationPromises.emplace_back(); + vibrationFutures.push_back(vibrationPromise.get_future()); + auto vibrationCallback = ndk::SharedRefBase::make( + [&vibrationPromise] { vibrationPromise.set_value(); }); + + // Vibration longer than test timeout. + EXPECT_OK(vibrator->on(2000, vibrationCallback)); + } + + // Session callback not triggered. + EXPECT_EQ(sessionFuture.wait_for(VIBRATION_CALLBACK_TIMEOUT), std::future_status::timeout); + + // End session, this might take a while + EXPECT_OK(session->close()); + + // Interrupt ending session. + EXPECT_OK(session->abort()); + + // Both callbacks triggered. + EXPECT_EQ(sessionFuture.wait_for(VIBRATION_CALLBACK_TIMEOUT), std::future_status::ready); + for (std::future& future : vibrationFutures) { + EXPECT_EQ(future.wait_for(VIBRATION_CALLBACK_TIMEOUT), std::future_status::ready); + } +} + +TEST_P(VibratorAidl, VibrationSessionCleared) { + if (!(capabilities & IVibratorManager::CAP_START_SESSIONS)) return; + if (vibratorIds.empty()) return; + + std::promise sessionPromise; + std::future sessionFuture{sessionPromise.get_future()}; + auto sessionCallback = ndk::SharedRefBase::make( + [&sessionPromise] { sessionPromise.set_value(); }); + + VibrationSessionConfig sessionConfig; + EXPECT_OK(manager->startSession(vibratorIds, sessionConfig, sessionCallback, &session)); + ASSERT_NE(session, nullptr); + + int32_t durationMs = 250; + std::vector> vibrationPromises; + std::vector> vibrationFutures; + for (int32_t id : vibratorIds) { + std::shared_ptr vibrator; + EXPECT_OK(manager->getVibrator(id, &vibrator)); + ASSERT_NE(vibrator, nullptr); + + std::promise& vibrationPromise = vibrationPromises.emplace_back(); + vibrationFutures.push_back(vibrationPromise.get_future()); + auto vibrationCallback = ndk::SharedRefBase::make( + [&vibrationPromise] { vibrationPromise.set_value(); }); + EXPECT_OK(vibrator->on(durationMs, vibrationCallback)); + } + + // Session callback not triggered. + EXPECT_EQ(sessionFuture.wait_for(VIBRATION_CALLBACK_TIMEOUT), std::future_status::timeout); + + // Clearing sessions should abort ongoing session + EXPECT_OK(manager->clearSessions()); + + EXPECT_EQ(sessionFuture.wait_for(VIBRATION_CALLBACK_TIMEOUT), std::future_status::ready); + for (std::future& future : vibrationFutures) { + EXPECT_EQ(future.wait_for(VIBRATION_CALLBACK_TIMEOUT), std::future_status::ready); + } +} + +TEST_P(VibratorAidl, VibrationSessionsClearedWithoutSession) { + if (!(capabilities & IVibratorManager::CAP_START_SESSIONS)) return; + + EXPECT_OK(manager->clearSessions()); +} + +TEST_P(VibratorAidl, VibrationSessionsWithSyncedVibrations) { + if (!(capabilities & IVibratorManager::CAP_START_SESSIONS)) return; + if (!(capabilities & IVibratorManager::CAP_SYNC)) return; + if (!(capabilities & IVibratorManager::CAP_PREPARE_ON)) return; + if (!(capabilities & IVibratorManager::CAP_TRIGGER_CALLBACK)) return; + if (vibratorIds.empty()) return; + + std::promise sessionPromise; + std::future sessionFuture{sessionPromise.get_future()}; + auto sessionCallback = ndk::SharedRefBase::make( + [&sessionPromise] { sessionPromise.set_value(); }); + + VibrationSessionConfig sessionConfig; + EXPECT_OK(manager->startSession(vibratorIds, sessionConfig, sessionCallback, &session)); + ASSERT_NE(session, nullptr); + + EXPECT_OK(manager->prepareSynced(vibratorIds)); + + int32_t durationMs = 250; + std::vector> vibrationPromises; + std::vector> vibrationFutures; + for (int32_t id : vibratorIds) { + std::shared_ptr vibrator; + EXPECT_OK(manager->getVibrator(id, &vibrator)); + ASSERT_NE(vibrator, nullptr); + + std::promise& vibrationPromise = vibrationPromises.emplace_back(); + vibrationFutures.push_back(vibrationPromise.get_future()); + auto vibrationCallback = ndk::SharedRefBase::make( + [&vibrationPromise] { vibrationPromise.set_value(); }); + EXPECT_OK(vibrator->on(durationMs, vibrationCallback)); + } + + std::promise triggerPromise; + std::future triggerFuture{triggerPromise.get_future()}; + auto triggerCallback = ndk::SharedRefBase::make( + [&triggerPromise] { triggerPromise.set_value(); }); + + EXPECT_OK(manager->triggerSynced(triggerCallback)); + + auto timeout = std::chrono::milliseconds(durationMs) + VIBRATION_CALLBACK_TIMEOUT; + EXPECT_EQ(triggerFuture.wait_for(timeout), std::future_status::ready); + for (std::future& future : vibrationFutures) { + EXPECT_EQ(future.wait_for(timeout), std::future_status::ready); + } + + // Session callback not triggered. + EXPECT_EQ(sessionFuture.wait_for(VIBRATION_CALLBACK_TIMEOUT), std::future_status::timeout); + + // Ending a session should not take long since the vibration was already completed + EXPECT_OK(session->close()); + EXPECT_EQ(sessionFuture.wait_for(VIBRATION_CALLBACK_TIMEOUT), std::future_status::ready); +} + +TEST_P(VibratorAidl, VibrationSessionWithMultipleIndependentVibrations) { + if (!(capabilities & IVibratorManager::CAP_START_SESSIONS)) return; + if (vibratorIds.empty()) return; + + std::promise sessionPromise; + std::future sessionFuture{sessionPromise.get_future()}; + auto sessionCallback = ndk::SharedRefBase::make( + [&sessionPromise] { sessionPromise.set_value(); }); + + VibrationSessionConfig sessionConfig; + EXPECT_OK(manager->startSession(vibratorIds, sessionConfig, sessionCallback, &session)); + ASSERT_NE(session, nullptr); + + for (int32_t id : vibratorIds) { + std::shared_ptr vibrator; + EXPECT_OK(manager->getVibrator(id, &vibrator)); + ASSERT_NE(vibrator, nullptr); + + EXPECT_OK(vibrator->on(100, nullptr)); + EXPECT_OK(vibrator->on(200, nullptr)); + EXPECT_OK(vibrator->on(300, nullptr)); + } + + // Session callback not triggered. + EXPECT_EQ(sessionFuture.wait_for(VIBRATION_CALLBACK_TIMEOUT), std::future_status::timeout); + + EXPECT_OK(session->close()); + + int32_t maxDurationMs = 100 + 200 + 300; + auto timeout = std::chrono::milliseconds(maxDurationMs) + VIBRATION_CALLBACK_TIMEOUT; + EXPECT_EQ(sessionFuture.wait_for(timeout), std::future_status::ready); +} + +TEST_P(VibratorAidl, VibrationSessionsIgnoresSecondSessionWhenFirstIsOngoing) { + if (!(capabilities & IVibratorManager::CAP_START_SESSIONS)) return; + if (vibratorIds.empty()) return; + + std::promise sessionPromise; + std::future sessionFuture{sessionPromise.get_future()}; + auto sessionCallback = ndk::SharedRefBase::make( + [&sessionPromise] { sessionPromise.set_value(); }); + + VibrationSessionConfig sessionConfig; + EXPECT_OK(manager->startSession(vibratorIds, sessionConfig, sessionCallback, &session)); + ASSERT_NE(session, nullptr); + + std::shared_ptr secondSession; + EXPECT_ILLEGAL_STATE( + manager->startSession(vibratorIds, sessionConfig, nullptr, &secondSession)); + EXPECT_EQ(secondSession, nullptr); + + // First session was not cancelled. + EXPECT_EQ(sessionFuture.wait_for(VIBRATION_CALLBACK_TIMEOUT), std::future_status::timeout); + + // First session still ongoing, we can still vibrate. + int32_t durationMs = 100; + for (int32_t id : vibratorIds) { + std::shared_ptr vibrator; + EXPECT_OK(manager->getVibrator(id, &vibrator)); + ASSERT_NE(vibrator, nullptr); + EXPECT_OK(vibrator->on(durationMs, nullptr)); + } + + EXPECT_OK(session->close()); + + auto timeout = std::chrono::milliseconds(durationMs) + VIBRATION_CALLBACK_TIMEOUT; + EXPECT_EQ(sessionFuture.wait_for(timeout), std::future_status::ready); +} + +TEST_P(VibratorAidl, VibrationSessionEndMultipleTimes) { + if (!(capabilities & IVibratorManager::CAP_START_SESSIONS)) return; + if (vibratorIds.empty()) return; + + std::promise sessionPromise; + std::future sessionFuture{sessionPromise.get_future()}; + auto sessionCallback = ndk::SharedRefBase::make( + [&sessionPromise] { sessionPromise.set_value(); }); + + VibrationSessionConfig sessionConfig; + EXPECT_OK(manager->startSession(vibratorIds, sessionConfig, sessionCallback, &session)); + ASSERT_NE(session, nullptr); + + int32_t durationMs = 250; + std::vector> vibrationPromises; + std::vector> vibrationFutures; + for (int32_t id : vibratorIds) { + std::shared_ptr vibrator; + EXPECT_OK(manager->getVibrator(id, &vibrator)); + ASSERT_NE(vibrator, nullptr); + + std::promise& vibrationPromise = vibrationPromises.emplace_back(); + vibrationFutures.push_back(vibrationPromise.get_future()); + auto vibrationCallback = ndk::SharedRefBase::make( + [&vibrationPromise] { vibrationPromise.set_value(); }); + EXPECT_OK(vibrator->on(durationMs, vibrationCallback)); + } + + // Session callback not triggered. + EXPECT_EQ(sessionFuture.wait_for(VIBRATION_CALLBACK_TIMEOUT), std::future_status::timeout); + + // End session, this might take a while + EXPECT_OK(session->close()); + + // End session again + EXPECT_OK(session->close()); + + // Both callbacks triggered within timeout. + auto timeout = std::chrono::milliseconds(durationMs) + VIBRATION_CALLBACK_TIMEOUT; + EXPECT_EQ(sessionFuture.wait_for(timeout), std::future_status::ready); + for (std::future& future : vibrationFutures) { + EXPECT_EQ(future.wait_for(timeout), std::future_status::ready); + } +} + +TEST_P(VibratorAidl, VibrationSessionDeletedAfterEnded) { + if (!(capabilities & IVibratorManager::CAP_START_SESSIONS)) return; + if (vibratorIds.empty()) return; + + std::promise sessionPromise; + std::future sessionFuture{sessionPromise.get_future()}; + auto sessionCallback = ndk::SharedRefBase::make( + [&sessionPromise] { sessionPromise.set_value(); }); + + VibrationSessionConfig sessionConfig; + EXPECT_OK(manager->startSession(vibratorIds, sessionConfig, sessionCallback, &session)); + ASSERT_NE(session, nullptr); + + int32_t durationMs = 250; + std::vector> vibrationPromises; + std::vector> vibrationFutures; + for (int32_t id : vibratorIds) { + std::shared_ptr vibrator; + EXPECT_OK(manager->getVibrator(id, &vibrator)); + ASSERT_NE(vibrator, nullptr); + + std::promise& vibrationPromise = vibrationPromises.emplace_back(); + vibrationFutures.push_back(vibrationPromise.get_future()); + auto vibrationCallback = ndk::SharedRefBase::make( + [&vibrationPromise] { vibrationPromise.set_value(); }); + EXPECT_OK(vibrator->on(durationMs, vibrationCallback)); + } + + // Session callback not triggered. + EXPECT_EQ(sessionFuture.wait_for(VIBRATION_CALLBACK_TIMEOUT), std::future_status::timeout); + + // End session, this might take a while + EXPECT_OK(session->close()); + + session.reset(); + + // Both callbacks triggered within timeout, even after session was deleted. + auto timeout = std::chrono::milliseconds(durationMs) + VIBRATION_CALLBACK_TIMEOUT; + EXPECT_EQ(sessionFuture.wait_for(timeout), std::future_status::ready); + for (std::future& future : vibrationFutures) { + EXPECT_EQ(future.wait_for(timeout), std::future_status::ready); + } +} + +TEST_P(VibratorAidl, VibrationSessionWrongVibratorIdsFail) { + if (!(capabilities & IVibratorManager::CAP_START_SESSIONS)) return; + + auto maxIdIt = std::max_element(vibratorIds.begin(), vibratorIds.end()); + int32_t wrongId = maxIdIt == vibratorIds.end() ? 0 : *maxIdIt + 1; + + std::vector emptyIds; + std::vector wrongIds{wrongId}; + VibrationSessionConfig sessionConfig; + EXPECT_ILLEGAL_ARGUMENT(manager->startSession(emptyIds, sessionConfig, nullptr, &session)); + EXPECT_ILLEGAL_ARGUMENT(manager->startSession(wrongIds, sessionConfig, nullptr, &session)); + EXPECT_EQ(session, nullptr); +} + +TEST_P(VibratorAidl, VibrationSessionDuringPrepareSyncedFails) { + if (!(capabilities & IVibratorManager::CAP_SYNC)) return; + if (!(capabilities & IVibratorManager::CAP_START_SESSIONS)) return; + if (vibratorIds.empty()) return; + + EXPECT_OK(manager->prepareSynced(vibratorIds)); + + VibrationSessionConfig sessionConfig; + EXPECT_ILLEGAL_STATE(manager->startSession(vibratorIds, sessionConfig, nullptr, &session)); + EXPECT_EQ(session, nullptr); + + EXPECT_OK(manager->cancelSynced()); +} + +TEST_P(VibratorAidl, VibrationSessionsUnsupported) { + if (version < VIBRATION_SESSIONS_MIN_VERSION) { + EXPECT_EQ(capabilities & IVibratorManager::CAP_START_SESSIONS, 0) + << "Vibrator manager version " << version + << " should not report start session capability"; + } + if (capabilities & IVibratorManager::CAP_START_SESSIONS) return; + + VibrationSessionConfig sessionConfig; + EXPECT_UNKNOWN_OR_UNSUPPORTED( + manager->startSession(vibratorIds, sessionConfig, nullptr, &session)); + EXPECT_EQ(session, nullptr); + EXPECT_UNKNOWN_OR_UNSUPPORTED(manager->clearSessions()); +} + std::vector FindVibratorManagerNames() { std::vector names; constexpr auto callback = [](const char* instance, void* context) { @@ -219,7 +679,7 @@ INSTANTIATE_TEST_SUITE_P(Vibrator, VibratorAidl, testing::ValuesIn(FindVibratorM int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); - ABinderProcess_setThreadPoolMaxThreadCount(1); + ABinderProcess_setThreadPoolMaxThreadCount(2); ABinderProcess_startThreadPool(); return RUN_ALL_TESTS(); } diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp index bc017ae3b5439f4aff3a1194619b42a5729ff724..03ecb1a04ec35040d2cd7f0da72ba62c4f9e5da1 100644 --- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp +++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp @@ -41,12 +41,13 @@ using aidl::android::hardware::vibrator::Braking; using aidl::android::hardware::vibrator::BrakingPwle; using aidl::android::hardware::vibrator::CompositeEffect; using aidl::android::hardware::vibrator::CompositePrimitive; +using aidl::android::hardware::vibrator::CompositePwleV2; using aidl::android::hardware::vibrator::Effect; using aidl::android::hardware::vibrator::EffectStrength; +using aidl::android::hardware::vibrator::FrequencyAccelerationMapEntry; using aidl::android::hardware::vibrator::IVibrator; using aidl::android::hardware::vibrator::IVibratorManager; using aidl::android::hardware::vibrator::PrimitivePwle; -using aidl::android::hardware::vibrator::PwleV2OutputMapEntry; using aidl::android::hardware::vibrator::PwleV2Primitive; using aidl::android::hardware::vibrator::VendorEffect; using aidl::android::os::PersistableBundle; @@ -175,11 +176,23 @@ static float getResonantFrequencyHz(const std::shared_ptr& vibrator, return resonantFrequencyHz; } +static bool shouldValidateLegacyFrequencyControlResult(int32_t capabilities, int32_t version, + ndk::ScopedAStatus& status) { + bool hasFrequencyControl = capabilities & IVibrator::CAP_FREQUENCY_CONTROL; + // Legacy frequency control APIs deprecated with PWLE V2 feature. + bool isDeprecated = version >= PWLE_V2_MIN_VERSION; + bool isUnknownOrUnsupported = status.getExceptionCode() == EX_UNSUPPORTED_OPERATION || + status.getStatus() == STATUS_UNKNOWN_TRANSACTION; + + // Validate if older HAL or if result is provided, even after deprecation. + return hasFrequencyControl && (!isDeprecated || !isUnknownOrUnsupported); +} + static float getFrequencyResolutionHz(const std::shared_ptr& vibrator, - int32_t capabilities) { - float freqResolutionHz; + int32_t capabilities, int32_t version) { + float freqResolutionHz = -1; ndk::ScopedAStatus status = vibrator->getFrequencyResolution(&freqResolutionHz); - if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) { + if (shouldValidateLegacyFrequencyControlResult(capabilities, version, status)) { EXPECT_OK(std::move(status)); EXPECT_GT(freqResolutionHz, 0); } else { @@ -188,11 +201,11 @@ static float getFrequencyResolutionHz(const std::shared_ptr& vibrator return freqResolutionHz; } -static float getFrequencyMinimumHz(const std::shared_ptr& vibrator, - int32_t capabilities) { +static float getFrequencyMinimumHz(const std::shared_ptr& vibrator, int32_t capabilities, + int32_t version) { float freqMinimumHz; ndk::ScopedAStatus status = vibrator->getFrequencyMinimum(&freqMinimumHz); - if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) { + if (shouldValidateLegacyFrequencyControlResult(capabilities, version, status)) { EXPECT_OK(std::move(status)); float resonantFrequencyHz = getResonantFrequencyHz(vibrator, capabilities); @@ -205,19 +218,19 @@ static float getFrequencyMinimumHz(const std::shared_ptr& vibrator, return freqMinimumHz; } -static float getFrequencyMaximumHz(const std::shared_ptr& vibrator, - int32_t capabilities) { +static float getFrequencyMaximumHz(const std::shared_ptr& vibrator, int32_t capabilities, + int32_t version) { std::vector bandwidthAmplitudeMap; ndk::ScopedAStatus status = vibrator->getBandwidthAmplitudeMap(&bandwidthAmplitudeMap); - if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) { + if (shouldValidateLegacyFrequencyControlResult(capabilities, version, status)) { EXPECT_OK(std::move(status)); } else { EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status)); } float freqMaximumHz = ((bandwidthAmplitudeMap.size() - 1) * - getFrequencyResolutionHz(vibrator, capabilities)) + - getFrequencyMinimumHz(vibrator, capabilities); + getFrequencyResolutionHz(vibrator, capabilities, version)) + + getFrequencyMinimumHz(vibrator, capabilities, version); return freqMaximumHz; } @@ -230,12 +243,16 @@ static float getAmplitudeMax() { } static ActivePwle composeValidActivePwle(const std::shared_ptr& vibrator, - int32_t capabilities) { + int32_t capabilities, int32_t version) { float frequencyHz; if (capabilities & IVibrator::CAP_GET_RESONANT_FREQUENCY) { frequencyHz = getResonantFrequencyHz(vibrator, capabilities); } else if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) { - frequencyHz = getFrequencyMinimumHz(vibrator, capabilities); + if (version < PWLE_V2_MIN_VERSION) { + frequencyHz = getFrequencyMinimumHz(vibrator, capabilities, version); + } else { + frequencyHz = pwle_v2_utils::getPwleV2FrequencyMinHz(vibrator); + } } else { frequencyHz = 150.0; // default value commonly used } @@ -846,23 +863,24 @@ TEST_P(VibratorAidl, GetQFactor) { } TEST_P(VibratorAidl, GetFrequencyResolution) { - getFrequencyResolutionHz(vibrator, capabilities); + getFrequencyResolutionHz(vibrator, capabilities, version); } TEST_P(VibratorAidl, GetFrequencyMinimum) { - getFrequencyMinimumHz(vibrator, capabilities); + getFrequencyMinimumHz(vibrator, capabilities, version); } TEST_P(VibratorAidl, GetBandwidthAmplitudeMap) { std::vector bandwidthAmplitudeMap; ndk::ScopedAStatus status = vibrator->getBandwidthAmplitudeMap(&bandwidthAmplitudeMap); - if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) { + + if (shouldValidateLegacyFrequencyControlResult(capabilities, version, status)) { EXPECT_OK(std::move(status)); ASSERT_FALSE(bandwidthAmplitudeMap.empty()); int minMapSize = (getResonantFrequencyHz(vibrator, capabilities) - - getFrequencyMinimumHz(vibrator, capabilities)) / - getFrequencyResolutionHz(vibrator, capabilities); + getFrequencyMinimumHz(vibrator, capabilities, version)) / + getFrequencyResolutionHz(vibrator, capabilities, version); ASSERT_GT(bandwidthAmplitudeMap.size(), minMapSize); for (float e : bandwidthAmplitudeMap) { @@ -911,7 +929,7 @@ TEST_P(VibratorAidl, GetSupportedBraking) { TEST_P(VibratorAidl, ComposeValidPwle) { if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) { - ActivePwle firstActive = composeValidActivePwle(vibrator, capabilities); + ActivePwle firstActive = composeValidActivePwle(vibrator, capabilities, version); std::vector supported; EXPECT_OK(vibrator->getSupportedBraking(&supported)); @@ -921,13 +939,17 @@ TEST_P(VibratorAidl, ComposeValidPwle) { firstBraking.braking = isClabSupported ? Braking::CLAB : Braking::NONE; firstBraking.duration = 100; - ActivePwle secondActive = composeValidActivePwle(vibrator, capabilities); + ActivePwle secondActive = composeValidActivePwle(vibrator, capabilities, version); if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) { - float minFrequencyHz = getFrequencyMinimumHz(vibrator, capabilities); - float maxFrequencyHz = getFrequencyMaximumHz(vibrator, capabilities); - float freqResolutionHz = getFrequencyResolutionHz(vibrator, capabilities); - secondActive.startFrequency = minFrequencyHz + (freqResolutionHz / 2.0f); - secondActive.endFrequency = maxFrequencyHz - (freqResolutionHz / 3.0f); + float minFrequencyHz = getFrequencyMinimumHz(vibrator, capabilities, version); + float maxFrequencyHz = getFrequencyMaximumHz(vibrator, capabilities, version); + float freqResolutionHz = getFrequencyResolutionHz(vibrator, capabilities, version); + // As of API 16 these APIs are deprecated and no longer required to be implemented + // with frequency control capability. + if (minFrequencyHz >= 0 && maxFrequencyHz >= 0 && freqResolutionHz >= 0) { + secondActive.startFrequency = minFrequencyHz + (freqResolutionHz / 2.0f); + secondActive.endFrequency = maxFrequencyHz - (freqResolutionHz / 3.0f); + } } BrakingPwle secondBraking; secondBraking.braking = Braking::NONE; @@ -955,7 +977,7 @@ TEST_P(VibratorAidl, ComposeValidPwleWithCallback) { uint32_t durationMs = segmentDurationMaxMs * 2 + 100; // Sum of 2 active and 1 braking below auto timeout = std::chrono::milliseconds(durationMs) + VIBRATION_CALLBACK_TIMEOUT; - ActivePwle active = composeValidActivePwle(vibrator, capabilities); + ActivePwle active = composeValidActivePwle(vibrator, capabilities, version); std::vector supported; EXPECT_OK(vibrator->getSupportedBraking(&supported)); @@ -978,7 +1000,7 @@ TEST_P(VibratorAidl, ComposePwleSegmentBoundary) { // test empty queue EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwle(pwleQueue, nullptr)); - ActivePwle active = composeValidActivePwle(vibrator, capabilities); + ActivePwle active = composeValidActivePwle(vibrator, capabilities, version); PrimitivePwle pwle; pwle = active; @@ -996,7 +1018,7 @@ TEST_P(VibratorAidl, ComposePwleSegmentBoundary) { TEST_P(VibratorAidl, ComposePwleAmplitudeParameterBoundary) { if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) { - ActivePwle active = composeValidActivePwle(vibrator, capabilities); + ActivePwle active = composeValidActivePwle(vibrator, capabilities, version); active.startAmplitude = getAmplitudeMax() + 1.0; // Amplitude greater than allowed active.endAmplitude = getAmplitudeMax() + 1.0; // Amplitude greater than allowed @@ -1016,11 +1038,18 @@ TEST_P(VibratorAidl, ComposePwleAmplitudeParameterBoundary) { TEST_P(VibratorAidl, ComposePwleFrequencyParameterBoundary) { if ((capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) && (capabilities & IVibrator::CAP_FREQUENCY_CONTROL)) { - float freqMinimumHz = getFrequencyMinimumHz(vibrator, capabilities); - float freqMaximumHz = getFrequencyMaximumHz(vibrator, capabilities); - float freqResolutionHz = getFrequencyResolutionHz(vibrator, capabilities); + float freqMinimumHz = getFrequencyMinimumHz(vibrator, capabilities, version); + float freqMaximumHz = getFrequencyMaximumHz(vibrator, capabilities, version); + float freqResolutionHz = getFrequencyResolutionHz(vibrator, capabilities, version); + + // As of API 16 these APIs are deprecated and no longer required to be implemented with + // frequency control capability. + if (freqMinimumHz < 0 || freqMaximumHz < 0 || freqResolutionHz < 0) { + GTEST_SKIP() << "PWLE V1 is not supported, skipping test"; + return; + } - ActivePwle active = composeValidActivePwle(vibrator, capabilities); + ActivePwle active = composeValidActivePwle(vibrator, capabilities, version); active.startFrequency = freqMaximumHz + freqResolutionHz; // Frequency greater than allowed active.endFrequency = freqMaximumHz + freqResolutionHz; // Frequency greater than allowed @@ -1040,7 +1069,7 @@ TEST_P(VibratorAidl, ComposePwleFrequencyParameterBoundary) { TEST_P(VibratorAidl, ComposePwleSegmentDurationBoundary) { if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) { - ActivePwle active = composeValidActivePwle(vibrator, capabilities); + ActivePwle active = composeValidActivePwle(vibrator, capabilities, version); int32_t segmentDurationMaxMs; vibrator->getPwlePrimitiveDurationMax(&segmentDurationMaxMs); @@ -1052,15 +1081,15 @@ TEST_P(VibratorAidl, ComposePwleSegmentDurationBoundary) { } } -TEST_P(VibratorAidl, PwleV2FrequencyToOutputAccelerationMapHasValidFrequencyRange) { - if (!(capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2)) { - GTEST_SKIP() << "PWLE V2 not supported, skipping test"; +TEST_P(VibratorAidl, FrequencyToOutputAccelerationMapHasValidFrequencyRange) { + if (version < PWLE_V2_MIN_VERSION || !(capabilities & IVibrator::CAP_FREQUENCY_CONTROL)) { + GTEST_SKIP() << "Frequency control is not supported, skipping test"; return; } - std::vector frequencyToOutputAccelerationMap; + std::vector frequencyToOutputAccelerationMap; ndk::ScopedAStatus status = - vibrator->getPwleV2FrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap); + vibrator->getFrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap); EXPECT_OK(std::move(status)); ASSERT_FALSE(frequencyToOutputAccelerationMap.empty()); auto sharpnessRange = @@ -1072,6 +1101,15 @@ TEST_P(VibratorAidl, PwleV2FrequencyToOutputAccelerationMapHasValidFrequencyRang ASSERT_TRUE(sharpnessRange.first < sharpnessRange.second); } +TEST_P(VibratorAidl, FrequencyToOutputAccelerationMapUnsupported) { + if ((capabilities & IVibrator::CAP_FREQUENCY_CONTROL)) return; + + std::vector frequencyToOutputAccelerationMap; + + EXPECT_UNKNOWN_OR_UNSUPPORTED( + vibrator->getFrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap)); +} + TEST_P(VibratorAidl, GetPwleV2PrimitiveDurationMaxMillis) { if (!(capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2)) { GTEST_SKIP() << "PWLE V2 not supported, skipping test"; @@ -1111,6 +1149,17 @@ TEST_P(VibratorAidl, GetPwleV2PrimitiveDurationMinMillis) { ASSERT_LE(durationMs, pwle_v2_utils::COMPOSE_PWLE_V2_MAX_ALLOWED_PRIMITIVE_MIN_DURATION_MS); } +TEST_P(VibratorAidl, ValidatePwleV2DependencyOnFrequencyControl) { + if (!(capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2)) { + GTEST_SKIP() << "PWLE V2 not supported, skipping test"; + return; + } + + // Check if frequency control is supported + bool hasFrequencyControl = (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) != 0; + ASSERT_TRUE(hasFrequencyControl) << "Frequency control MUST be supported when PWLE V2 is."; +} + TEST_P(VibratorAidl, ComposeValidPwleV2Effect) { if (!(capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2)) { GTEST_SKIP() << "PWLE V2 not supported, skipping test"; @@ -1126,12 +1175,13 @@ TEST_P(VibratorAidl, ComposePwleV2Unsupported) { EXPECT_EQ(capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2, 0) << "Vibrator version " << version << " should not report PWLE V2 capability."; } - if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2) return; + if ((capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2)) return; - std::vector pwleEffect{ - PwleV2Primitive(/*amplitude=*/1.0f, /*frequencyHz=*/100.0f, /*timeMillis=*/50)}; + CompositePwleV2 composite; + composite.pwlePrimitives.emplace_back(/*amplitude=*/1.0f, /*frequencyHz=*/100.0f, + /*timeMillis=*/50); - EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->composePwleV2(pwleEffect, nullptr)); + EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->composePwleV2(composite, nullptr)); } TEST_P(VibratorAidl, ComposeValidPwleV2EffectWithCallback) { @@ -1150,8 +1200,10 @@ TEST_P(VibratorAidl, ComposeValidPwleV2EffectWithCallback) { auto timeout = std::chrono::milliseconds(minDuration) + VIBRATION_CALLBACK_TIMEOUT; float minFrequency = pwle_v2_utils::getPwleV2FrequencyMinHz(vibrator); - EXPECT_OK(vibrator->composePwleV2( - {PwleV2Primitive(/*amplitude=*/0.5, minFrequency, minDuration)}, callback)); + CompositePwleV2 composite; + composite.pwlePrimitives.emplace_back(/*amplitude=*/0.5, minFrequency, minDuration); + + EXPECT_OK(vibrator->composePwleV2(composite, callback)); EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready); EXPECT_OK(vibrator->off()); } @@ -1177,43 +1229,48 @@ TEST_P(VibratorAidl, composeInvalidPwleV2Effect) { EXPECT_OK(vibrator->getPwleV2PrimitiveDurationMinMillis(&minDurationMs)); EXPECT_OK(vibrator->getPwleV2PrimitiveDurationMaxMillis(&maxDurationMs)); - std::vector composePwle; + CompositePwleV2 composePwle; // Negative amplitude - composePwle.push_back(PwleV2Primitive(/*amplitude=*/-0.8f, /*frequency=*/100, minDurationMs)); + composePwle.pwlePrimitives.push_back( + PwleV2Primitive(/*amplitude=*/-0.8f, /*frequency=*/100, minDurationMs)); EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwleV2(composePwle, nullptr)) << "Composing PWLE V2 effect with negative amplitude should fail"; - composePwle.clear(); + composePwle.pwlePrimitives.clear(); // Amplitude exceeding 1.0 - composePwle.push_back(PwleV2Primitive(/*amplitude=*/1.2f, /*frequency=*/100, minDurationMs)); + composePwle.pwlePrimitives.push_back( + PwleV2Primitive(/*amplitude=*/1.2f, /*frequency=*/100, minDurationMs)); EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwleV2(composePwle, nullptr)) << "Composing PWLE V2 effect with amplitude greater than 1.0 should fail"; - composePwle.clear(); + composePwle.pwlePrimitives.clear(); // Duration exceeding maximum - composePwle.push_back( + composePwle.pwlePrimitives.push_back( PwleV2Primitive(/*amplitude=*/0.2f, /*frequency=*/100, maxDurationMs + 10)); EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwleV2(composePwle, nullptr)) << "Composing PWLE V2 effect with duration exceeding maximum should fail"; - composePwle.clear(); + composePwle.pwlePrimitives.clear(); // Negative duration - composePwle.push_back(PwleV2Primitive(/*amplitude=*/0.2f, /*frequency=*/100, /*time=*/-1)); + composePwle.pwlePrimitives.push_back( + PwleV2Primitive(/*amplitude=*/0.2f, /*frequency=*/100, /*time=*/-1)); EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwleV2(composePwle, nullptr)) << "Composing PWLE V2 effect with negative duration should fail"; - composePwle.clear(); + composePwle.pwlePrimitives.clear(); // Frequency below minimum float minFrequency = pwle_v2_utils::getPwleV2FrequencyMinHz(vibrator); - composePwle.push_back(PwleV2Primitive(/*amplitude=*/0.2f, minFrequency - 1, minDurationMs)); + composePwle.pwlePrimitives.push_back( + PwleV2Primitive(/*amplitude=*/0.2f, minFrequency - 1, minDurationMs)); EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwleV2(composePwle, nullptr)) << "Composing PWLE V2 effect with frequency below minimum should fail"; - composePwle.clear(); + composePwle.pwlePrimitives.clear(); // Frequency above maximum float maxFrequency = pwle_v2_utils::getPwleV2FrequencyMaxHz(vibrator); - composePwle.push_back(PwleV2Primitive(/*amplitude=*/0.2f, maxFrequency + 1, minDurationMs)); + composePwle.pwlePrimitives.push_back( + PwleV2Primitive(/*amplitude=*/0.2f, maxFrequency + 1, minDurationMs)); EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwleV2(composePwle, nullptr)) << "Composing PWLE V2 effect with frequency above maximum should fail"; } diff --git a/vibrator/aidl/vts/pwle_v2_utils.h b/vibrator/aidl/vts/pwle_v2_utils.h index 2163908e2acf2e7703c110be6465404be7ff462f..eaa024cf422785e26a335f47ddecb528b3cbfae0 100644 --- a/vibrator/aidl/vts/pwle_v2_utils.h +++ b/vibrator/aidl/vts/pwle_v2_utils.h @@ -20,8 +20,8 @@ #include #include "test_utils.h" +using aidl::android::hardware::vibrator::FrequencyAccelerationMapEntry; using aidl::android::hardware::vibrator::IVibrator; -using aidl::android::hardware::vibrator::PwleV2OutputMapEntry; using aidl::android::hardware::vibrator::PwleV2Primitive; namespace aidl { @@ -116,9 +116,8 @@ static float convertSensitivityLevelToAcceleration(int sl, float frequency) { } static float getPwleV2FrequencyMinHz(const std::shared_ptr& vibrator) { - std::vector frequencyToOutputAccelerationMap; - EXPECT_OK( - vibrator->getPwleV2FrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap)); + std::vector frequencyToOutputAccelerationMap; + EXPECT_OK(vibrator->getFrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap)); EXPECT_TRUE(!frequencyToOutputAccelerationMap.empty()); // We can't use ASSERT_TRUE() above because this is a non-void function, // but we need to return to assure we don't crash from a null dereference. @@ -134,9 +133,8 @@ static float getPwleV2FrequencyMinHz(const std::shared_ptr& vibrator) } static float getPwleV2FrequencyMaxHz(const std::shared_ptr& vibrator) { - std::vector frequencyToOutputAccelerationMap; - EXPECT_OK( - vibrator->getPwleV2FrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap)); + std::vector frequencyToOutputAccelerationMap; + EXPECT_OK(vibrator->getFrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap)); EXPECT_TRUE(!frequencyToOutputAccelerationMap.empty()); // We can't use ASSERT_TRUE() above because this is a non-void function, // but we need to return to assure we don't crash from a null dereference. @@ -151,8 +149,7 @@ static float getPwleV2FrequencyMaxHz(const std::shared_ptr& vibrator) return entry->frequencyHz; } -static std::vector composeValidPwleV2Effect( - const std::shared_ptr& vibrator) { +static CompositePwleV2 composeValidPwleV2Effect(const std::shared_ptr& vibrator) { int32_t minDurationMs; EXPECT_OK(vibrator->getPwleV2PrimitiveDurationMinMillis(&minDurationMs)); int32_t maxDurationMs; @@ -162,20 +159,20 @@ static std::vector composeValidPwleV2Effect( int32_t maxCompositionSize; EXPECT_OK(vibrator->getPwleV2CompositionSizeMax(&maxCompositionSize)); - std::vector pwleEffect; + CompositePwleV2 composite; - pwleEffect.emplace_back(0.1f, minFrequency, minDurationMs); - pwleEffect.emplace_back(0.5f, maxFrequency, maxDurationMs); + composite.pwlePrimitives.emplace_back(0.1f, minFrequency, minDurationMs); + composite.pwlePrimitives.emplace_back(0.5f, maxFrequency, maxDurationMs); float variedFrequency = (minFrequency + maxFrequency) / 2.0f; for (int i = 0; i < maxCompositionSize - 2; i++) { - pwleEffect.emplace_back(0.7f, variedFrequency, minDurationMs); + composite.pwlePrimitives.emplace_back(0.7f, variedFrequency, minDurationMs); } - return pwleEffect; + return composite; } -static std::vector composePwleV2EffectWithTooManyPoints( +static CompositePwleV2 composePwleV2EffectWithTooManyPoints( const std::shared_ptr& vibrator) { int32_t minDurationMs, maxCompositionSize; EXPECT_OK(vibrator->getPwleV2PrimitiveDurationMinMillis(&minDurationMs)); @@ -187,12 +184,15 @@ static std::vector composePwleV2EffectWithTooManyPoints( std::fill(pwleEffect.begin(), pwleEffect.end(), PwleV2Primitive(/*amplitude=*/0.2f, maxFrequency, minDurationMs)); - return pwleEffect; + CompositePwleV2 composite; + composite.pwlePrimitives = pwleEffect; + + return composite; } static std::pair getPwleV2SharpnessRange( const std::shared_ptr& vibrator, - std::vector freqToOutputAccelerationMap) { + std::vector freqToOutputAccelerationMap) { std::pair sharpnessRange = {-1, -1}; // Sort the entries by frequency in ascending order diff --git a/vibrator/aidl/vts/test_utils.h b/vibrator/aidl/vts/test_utils.h index aaf3211bd4c6433a58b5571c2f63b061cdc2203d..e884bbd58bb7b41182acd76eff016cc5b31d88b8 100644 --- a/vibrator/aidl/vts/test_utils.h +++ b/vibrator/aidl/vts/test_utils.h @@ -57,4 +57,17 @@ #error Macro EXPECT_ILLEGAL_ARGUMENT already defined unexpectedly #endif +#if !defined(EXPECT_ILLEGAL_STATE) +#define EXPECT_ILLEGAL_STATE(expression) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (const ::ndk::ScopedAStatus&& _status = (expression); \ + _status.getExceptionCode() == EX_ILLEGAL_STATE) \ + ; \ + else \ + ADD_FAILURE() << "Expected EX_ILLEGAL_STATE for: " << #expression \ + << "\n Actual: " << _status +#else +#error Macro EXPECT_ILLEGAL_STATE already defined unexpectedly +#endif + #endif // VIBRATOR_HAL_TEST_UTILS_H diff --git a/wifi/aidl/Android.bp b/wifi/aidl/Android.bp index 392d2e9ec64de25851e09e88ad77f78cf65fa061..4b7e3720f23376f323b72c36e753d3753c31b946 100644 --- a/wifi/aidl/Android.bp +++ b/wifi/aidl/Android.bp @@ -29,7 +29,7 @@ aidl_interface { "android/hardware/wifi/*.aidl", ], imports: [ - "android.hardware.wifi.common-V1", + "android.hardware.wifi.common-V2", ], stability: "vintf", backend: { @@ -64,5 +64,5 @@ aidl_interface { }, ], - frozen: true, + frozen: false, } diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/Akm.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/Akm.aidl new file mode 100644 index 0000000000000000000000000000000000000000..5baf2e80b4ae517011646013bb3b261eb8309d44 --- /dev/null +++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/Akm.aidl @@ -0,0 +1,46 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.wifi; +@VintfStability +parcelable Akm { + const long NONE = 0; + const long PASN = (1 << 0) /* 1 */; + const long SAE = (1 << 1) /* 2 */; + const long FT_EAP_SHA256 = (1 << 2) /* 4 */; + const long FT_PSK_SHA256 = (1 << 3) /* 8 */; + const long FT_EAP_SHA384 = (1 << 4) /* 16 */; + const long FT_PSK_SHA384 = (1 << 5) /* 32 */; + const long FILS_EAP_SHA256 = (1 << 6) /* 64 */; + const long FILS_EAP_SHA384 = (1 << 7) /* 128 */; +} diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/CipherSuite.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/CipherSuite.aidl new file mode 100644 index 0000000000000000000000000000000000000000..32fb5ba821c664e255e1afdcd907b14ce09386db --- /dev/null +++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/CipherSuite.aidl @@ -0,0 +1,42 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.wifi; +@VintfStability +parcelable CipherSuite { + const long NONE = 0; + const long CCMP_128 = (1 << 0) /* 1 */; + const long CCMP_256 = (1 << 1) /* 2 */; + const long GCMP_128 = (1 << 2) /* 4 */; + const long GCMP_256 = (1 << 3) /* 8 */; +} diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiApIface.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiApIface.aidl index e71dde40fddc4d4462c54aa051ce9252967805c1..af95bee7b9e5c74e07ab46abe30412514fe2575f 100644 --- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiApIface.aidl +++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiApIface.aidl @@ -40,4 +40,5 @@ interface IWifiApIface { void setCountryCode(in byte[2] code); void resetToFactoryMacAddress(); void setMacAddress(in byte[6] mac); + boolean usesMlo(); } diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiChip.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiChip.aidl index 5ed7517766717633f43c408539a814fab18a3d65..565f33a57adefebb1f4cec0ee53ac28f4fcb010d 100644 --- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiChip.aidl +++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiChip.aidl @@ -35,7 +35,13 @@ package android.hardware.wifi; @VintfStability interface IWifiChip { void configureChip(in int modeId); + /** + * @deprecated This method is deprecated from AIDL v3, newer HALs should use createApOrBridgedApIfaceWithParams. + */ @PropagateAllowBlocking android.hardware.wifi.IWifiApIface createApIface(); + /** + * @deprecated This method is deprecated from AIDL v3, newer HALs should use createApOrBridgedApIfaceWithParams. + */ @PropagateAllowBlocking android.hardware.wifi.IWifiApIface createBridgedApIface(); @PropagateAllowBlocking android.hardware.wifi.IWifiNanIface createNanIface(); @PropagateAllowBlocking android.hardware.wifi.IWifiP2pIface createP2pIface(); @@ -83,8 +89,12 @@ interface IWifiChip { void triggerSubsystemRestart(); void enableStaChannelForPeerNetwork(in int channelCategoryEnableFlag); void setMloMode(in android.hardware.wifi.IWifiChip.ChipMloMode mode); + /** + * @deprecated This method is deprecated from AIDL v3, newer HALs should use createApOrBridgedApIfaceWithParams. + */ @PropagateAllowBlocking android.hardware.wifi.IWifiApIface createApOrBridgedApIface(in android.hardware.wifi.IfaceConcurrencyType iface, in android.hardware.wifi.common.OuiKeyedData[] vendorData); void setVoipMode(in android.hardware.wifi.IWifiChip.VoipMode mode); + @PropagateAllowBlocking android.hardware.wifi.IWifiApIface createApOrBridgedApIfaceWithParams(in android.hardware.wifi.IWifiChip.ApIfaceParams params); const int NO_POWER_CAP_CONSTANT = 0x7FFFFFFF; @Backing(type="int") @VintfStability enum FeatureSetMask { @@ -98,6 +108,8 @@ interface IWifiChip { SET_AFC_CHANNEL_ALLOWANCE = (1 << 7) /* 128 */, T2LM_NEGOTIATION = (1 << 8) /* 256 */, SET_VOIP_MODE = (1 << 9) /* 512 */, + MLO_SAP = (1 << 10) /* 1024 */, + MULTIPLE_MLD_ON_SAP = (1 << 11) /* 2048 */, } @VintfStability parcelable ChipConcurrencyCombinationLimit { @@ -180,4 +192,10 @@ interface IWifiChip { HIGH_THROUGHPUT = 2, LOW_POWER = 3, } + @VintfStability + parcelable ApIfaceParams { + android.hardware.wifi.IfaceConcurrencyType ifaceType; + boolean usesMlo; + @nullable android.hardware.wifi.common.OuiKeyedData[] vendorData; + } } diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiNanIfaceEventCallback.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiNanIfaceEventCallback.aidl index 8c443309ee73c66007a4c851b5aefb1e7dbb00b4..9d982b85d9dd606b90ee2f874120734158b674e9 100644 --- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiNanIfaceEventCallback.aidl +++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiNanIfaceEventCallback.aidl @@ -72,4 +72,5 @@ interface IWifiNanIfaceEventCallback { oneway void notifyInitiateBootstrappingResponse(in char id, in android.hardware.wifi.NanStatus status, in int bootstrappingInstanceId); oneway void notifyRespondToBootstrappingIndicationResponse(in char id, in android.hardware.wifi.NanStatus status); oneway void notifyTerminatePairingResponse(in char id, in android.hardware.wifi.NanStatus status); + oneway void notifyRangingResults(in android.hardware.wifi.RttResult[] results, in byte discoverySessionId); } diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanCapabilities.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanCapabilities.aidl index a30893a0c2ba6f2ca4f832b09bb8fd312da29757..0722a04bdb7f51b8224521d7931e995039ce0a44 100644 --- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanCapabilities.aidl +++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanCapabilities.aidl @@ -54,4 +54,7 @@ parcelable NanCapabilities { boolean supportsPairing; boolean supportsSetClusterId; boolean supportsSuspension; + boolean supportsPeriodicRanging; + android.hardware.wifi.RttBw maxSupportedBandwidth; + int maxNumRxChainsSupported; } diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDiscoveryCommonConfig.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDiscoveryCommonConfig.aidl index 96d940ae313c5b8fe63851164fdbd72c1ef7a433..58e62db1e35cfcf8ad46015ecbbf1fede3b24f30 100644 --- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDiscoveryCommonConfig.aidl +++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDiscoveryCommonConfig.aidl @@ -55,4 +55,7 @@ parcelable NanDiscoveryCommonConfig { char distanceIngressCm; char distanceEgressCm; boolean enableSessionSuspendability; + int rttBurstSize; + android.hardware.wifi.RttPreamble preamble; + @nullable android.hardware.wifi.WifiChannelInfo channelInfo; } diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPublishRequest.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPublishRequest.aidl index bdc83579ad9bb36231923bdfec4caa2bfd74c12e..90e9a8bf36216ec27d5c3501db1d95b76d36734e 100644 --- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPublishRequest.aidl +++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPublishRequest.aidl @@ -41,4 +41,5 @@ parcelable NanPublishRequest { android.hardware.wifi.NanPairingConfig pairingConfig; byte[16] identityKey; @nullable android.hardware.wifi.common.OuiKeyedData[] vendorData; + boolean rangingResultsRequired; } diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/PasnConfig.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/PasnConfig.aidl new file mode 100644 index 0000000000000000000000000000000000000000..9b26c9734f5972914d34fe6470235a294cf14820 --- /dev/null +++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/PasnConfig.aidl @@ -0,0 +1,41 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.wifi; +@VintfStability +parcelable PasnConfig { + long baseAkm; + long cipherSuite; + @nullable byte[] passphrase; + @nullable byte[] pmkid; +} diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttCapabilities.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttCapabilities.aidl index 6c6408454a302d6c411dbde073e2949fcee3bdf3..90caa2607dc9604ac3cd56d3c24f7c938ff72d0b 100644 --- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttCapabilities.aidl +++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttCapabilities.aidl @@ -47,4 +47,9 @@ parcelable RttCapabilities { boolean ntbInitiatorSupported; boolean ntbResponderSupported; @nullable android.hardware.wifi.common.OuiKeyedData[] vendorData; + long akmsSupported; + long cipherSuitesSupported; + boolean secureHeLtfSupported; + boolean rangingFrameProtectionSupported; + int maxSupportedSecureHeLtfProtocolVersion; } diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttConfig.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttConfig.aidl index 361361609c6f006a73f616e899c6d6307d33f206..5507280c3bd1c3dea6cdec650fbeacedf9ea5e46 100644 --- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttConfig.aidl +++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttConfig.aidl @@ -51,4 +51,5 @@ parcelable RttConfig { long ntbMinMeasurementTime; long ntbMaxMeasurementTime; @nullable android.hardware.wifi.common.OuiKeyedData[] vendorData; + @nullable android.hardware.wifi.RttSecureConfig secureConfig; } diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttResult.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttResult.aidl index 13202ba3f2280d88a86bb40970472657b03d8593..9d6243106a1075dd576ad8682203e65dabf4f2ee 100644 --- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttResult.aidl +++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttResult.aidl @@ -66,4 +66,11 @@ parcelable RttResult { byte numTxSpatialStreams; byte numRxSpatialStreams; @nullable android.hardware.wifi.common.OuiKeyedData[] vendorData; + boolean isRangingFrameProtectionEnabled; + boolean isSecureLtfEnabled; + long baseAkm; + long cipherSuite; + int secureHeLtfProtocolVersion; + long pasnComebackAfterMillis; + @nullable byte[] pasnComebackCookie; } diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttSecureConfig.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttSecureConfig.aidl new file mode 100644 index 0000000000000000000000000000000000000000..5cb1aaa4afe236046fd523b094dc1e93283b83cd --- /dev/null +++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttSecureConfig.aidl @@ -0,0 +1,41 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.wifi; +@VintfStability +parcelable RttSecureConfig { + android.hardware.wifi.PasnConfig pasnConfig; + boolean enableSecureHeLtf; + boolean enableRangingFrameProtection; + @nullable byte[] pasnComebackCookie; +} diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttStatus.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttStatus.aidl index 2817497a7af33cf52aa0349ad0bc84958d04fde8..08bca77ff6e095aa26f04ad605995ec2541ff724 100644 --- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttStatus.aidl +++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttStatus.aidl @@ -52,4 +52,9 @@ enum RttStatus { FAIL_FTM_PARAM_OVERRIDE = 15, NAN_RANGING_PROTOCOL_FAILURE = 16, NAN_RANGING_CONCURRENCY_NOT_SUPPORTED = 17, + SECURE_RANGING_FAILURE_INVALID_AKM = 18, + SECURE_RANGING_FAILURE_INVALID_CIPHER = 19, + SECURE_RANGING_FAILURE_INVALID_CONFIG = 20, + SECURE_RANGING_FAILURE_REJECTED = 21, + SECURE_RANGING_FAILURE_UNKNOWN = 22, } diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttType.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttType.aidl index cb25673af37d33be9884c41bb79657e5fe5b04c0..8545d7376485e03e3929c118f7d19d9d1b9bcbae 100644 --- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttType.aidl +++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttType.aidl @@ -38,4 +38,5 @@ enum RttType { TWO_SIDED = 2, TWO_SIDED_11MC = TWO_SIDED /* 2 */, TWO_SIDED_11AZ_NTB = 3, + TWO_SIDED_11AZ_NTB_SECURE = 4, } diff --git a/wifi/aidl/android/hardware/wifi/Akm.aidl b/wifi/aidl/android/hardware/wifi/Akm.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e3a913bcc590895680fbc89397cdd41a667521f1 --- /dev/null +++ b/wifi/aidl/android/hardware/wifi/Akm.aidl @@ -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. + */ + +package android.hardware.wifi; + +/** + * Authentication and Key Management types. + */ +@VintfStability +parcelable Akm { + const long NONE = 0; + const long PASN = 1 << 0; + const long SAE = 1 << 1; + const long FT_EAP_SHA256 = 1 << 2; + const long FT_PSK_SHA256 = 1 << 3; + const long FT_EAP_SHA384 = 1 << 4; + const long FT_PSK_SHA384 = 1 << 5; + const long FILS_EAP_SHA256 = 1 << 6; + const long FILS_EAP_SHA384 = 1 << 7; +} diff --git a/wifi/aidl/android/hardware/wifi/CipherSuite.aidl b/wifi/aidl/android/hardware/wifi/CipherSuite.aidl new file mode 100644 index 0000000000000000000000000000000000000000..02b62e8a5690006fedf05599ef0b0d472bec0a33 --- /dev/null +++ b/wifi/aidl/android/hardware/wifi/CipherSuite.aidl @@ -0,0 +1,29 @@ +/* + * 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. + */ + +package android.hardware.wifi; + +/** + * Cipher Suite types. + */ +@VintfStability +parcelable CipherSuite { + const long NONE = 0; + const long CCMP_128 = 1 << 0; + const long CCMP_256 = 1 << 1; + const long GCMP_128 = 1 << 2; + const long GCMP_256 = 1 << 3; +} diff --git a/wifi/aidl/android/hardware/wifi/IWifiApIface.aidl b/wifi/aidl/android/hardware/wifi/IWifiApIface.aidl index b14a8005b51e58e33f725abbfc2e5a55f35e540b..a350e527f5883ba04d49ece4218a46fca03a13be 100644 --- a/wifi/aidl/android/hardware/wifi/IWifiApIface.aidl +++ b/wifi/aidl/android/hardware/wifi/IWifiApIface.aidl @@ -85,4 +85,11 @@ interface IWifiApIface { * |WifiStatusCode.ERROR_UNKNOWN| */ void setMacAddress(in byte[6] mac); + + /** + * Check if ApIface is for an AP using Multi-Link Operation + * + * @return true if it is MLO iface, false otherwise. + */ + boolean usesMlo(); } diff --git a/wifi/aidl/android/hardware/wifi/IWifiChip.aidl b/wifi/aidl/android/hardware/wifi/IWifiChip.aidl index d12d26c65ca2bfd095f0fc7a4b3f8712748207e6..5a5e4a784d5d3cf31ebf531d85d4416c666673e1 100644 --- a/wifi/aidl/android/hardware/wifi/IWifiChip.aidl +++ b/wifi/aidl/android/hardware/wifi/IWifiChip.aidl @@ -87,6 +87,18 @@ interface IWifiChip { * Chip supports voip mode setting. */ SET_VOIP_MODE = 1 << 9, + /** + * Chip supports Wi-Fi 7 MLO SoftAp. + */ + MLO_SAP = 1 << 10, + /** + * Chip supports multiple Wi-Fi 7 multi-link devices (MLD) on SoftAp. + * When this feature flag is enabled, it is an indication that the chip can + * support Bridged-SoftAp in 11be with separate MLD MAC addresses. + * When this feature is disabled, then only one MLD address can be used in 11be mode + * (if supported), this includes use of MLO if MLO_SAP flag is set to True. + */ + MULTIPLE_MLD_ON_SAP = 1 << 11, } /** @@ -429,6 +441,9 @@ interface IWifiChip { * reached the maximum allowed (specified in |ChipIfaceCombination|) number * of ifaces of the AP type. * + * @deprecated This method is deprecated from AIDL v3, newer HALs should use + * createApOrBridgedApIfaceWithParams. + * * @return AIDL interface object representing the iface if * successful, null otherwise. * @throws ServiceSpecificException with one of the following values: @@ -446,6 +461,9 @@ interface IWifiChip { * reached the maximum allowed (specified in |ChipIfaceCombination|) number * of ifaces of the AP type. * + * @deprecated This method is deprecated from AIDL v3, newer HALs should use + * createApOrBridgedApIfaceWithParams. + * * @return AIDL interface object representing the iface if * successful, null otherwise. * @throws ServiceSpecificException with one of the following values: @@ -1173,6 +1191,9 @@ interface IWifiChip { * reached the maximum allowed (specified in |ChipIfaceCombination|) number * of ifaces of the AP or AP_BRIDGED type. * + * @deprecated This method is deprecated from AIDL v3, newer HALs should use + * createApOrBridgedApIfaceWithParams. + * * @param iface IfaceConcurrencyType to be created. Takes one of |IfaceConcurrencyType.AP| or |IfaceConcurrencyType.AP_BRIDGED| * @param vendorData Vendor-provided configuration data as a list of |OuiKeyedData|. @@ -1206,4 +1227,42 @@ interface IWifiChip { * |WifiStatusCode.ERROR_UNKNOWN| */ void setVoipMode(in VoipMode mode); + + /** + * Parameters for setting up access point (AP) interfaces. + */ + @VintfStability + parcelable ApIfaceParams { + /** + * IfaceConcurrencyType to be created. Takes one of + * |IfaceConcurrencyType.AP| or |IfaceConcurrencyType.AP_BRIDGED| + */ + IfaceConcurrencyType ifaceType; + /** + * Whether the current iface will be operated on Multi-links on the one MLD device (MLO). + */ + boolean usesMlo; + /** + * Optional vendor-specific configuration parameters. + */ + @nullable OuiKeyedData[] vendorData; + } + + /** + * Create an AP or bridged AP iface on the chip based on ApIfaceParamss. + * + * Depending on the mode the chip is configured in, the interface creation + * may fail (code: |WifiStatusCode.ERROR_NOT_AVAILABLE|) if we've already + * reached the maximum allowed (specified in |ChipIfaceCombination|) number + * of ifaces of the AP type. + * + * @return AIDL interface object representing the iface if + * successful, null otherwise. + * @throws ServiceSpecificException with one of the following values: + * |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|, + * |WifiStatusCode.ERROR_NOT_SUPPORTED|, + * |WifiStatusCode.ERROR_NOT_AVAILABLE| + */ + @PropagateAllowBlocking + IWifiApIface createApOrBridgedApIfaceWithParams(in ApIfaceParams params); } diff --git a/wifi/aidl/android/hardware/wifi/IWifiNanIfaceEventCallback.aidl b/wifi/aidl/android/hardware/wifi/IWifiNanIfaceEventCallback.aidl index 3649b7bf73458a5057aa5a2f9649719fd049e630..376dcace13bd36762113a377de8d6866b38ddd32 100644 --- a/wifi/aidl/android/hardware/wifi/IWifiNanIfaceEventCallback.aidl +++ b/wifi/aidl/android/hardware/wifi/IWifiNanIfaceEventCallback.aidl @@ -29,6 +29,7 @@ import android.hardware.wifi.NanPairingConfirmInd; import android.hardware.wifi.NanPairingRequestInd; import android.hardware.wifi.NanStatus; import android.hardware.wifi.NanSuspensionModeChangeInd; +import android.hardware.wifi.RttResult; /** * NAN Response and Asynchronous Event Callbacks. * @@ -461,4 +462,12 @@ oneway interface IWifiNanIfaceEventCallback { * |NanStatusCode.INVALID_PAIRING_ID| */ void notifyTerminatePairingResponse(in char id, in NanStatus status); + + /** + * Callback is invoked when ranging results are available. + * + * @param results RttResult data. + * @param discoverySessionId Discovery session ID. + */ + void notifyRangingResults(in RttResult[] results, in byte discoverySessionId); } diff --git a/wifi/aidl/android/hardware/wifi/NanCapabilities.aidl b/wifi/aidl/android/hardware/wifi/NanCapabilities.aidl index f581c5e6cff3ddb80916ef7afceb6858fc6575ee..f9f825fd790269824414f3476b6c8f431ff80ad5 100644 --- a/wifi/aidl/android/hardware/wifi/NanCapabilities.aidl +++ b/wifi/aidl/android/hardware/wifi/NanCapabilities.aidl @@ -16,6 +16,8 @@ package android.hardware.wifi; +import android.hardware.wifi.RttBw; + /** * NDP Capabilities response. */ @@ -103,4 +105,16 @@ parcelable NanCapabilities { * Flag to indicate if NAN suspension is supported. */ boolean supportsSuspension; + /** + * Flag to indicate if NAN periodic ranging is supported. + */ + boolean supportsPeriodicRanging; + /** + * Maximum supported bandwidth. + */ + RttBw maxSupportedBandwidth; + /** + * Maximum number of supported receive chains. + */ + int maxNumRxChainsSupported; } diff --git a/wifi/aidl/android/hardware/wifi/NanDiscoveryCommonConfig.aidl b/wifi/aidl/android/hardware/wifi/NanDiscoveryCommonConfig.aidl index 4bedce01007345b9d115cb56083ee45808314379..725ed3caa1ff5443aeea0145f3a1d920779cd429 100644 --- a/wifi/aidl/android/hardware/wifi/NanDiscoveryCommonConfig.aidl +++ b/wifi/aidl/android/hardware/wifi/NanDiscoveryCommonConfig.aidl @@ -18,6 +18,8 @@ package android.hardware.wifi; import android.hardware.wifi.NanDataPathSecurityConfig; import android.hardware.wifi.NanMatchAlg; +import android.hardware.wifi.RttPreamble; +import android.hardware.wifi.WifiChannelInfo; /** * Configurations of NAN discovery sessions. Common to publish and subscribe discovery. @@ -136,10 +138,14 @@ parcelable NanDiscoveryCommonConfig { */ boolean rangingRequired; /** - * Interval in ms between two ranging measurements. Only relevant if |rangingRequired| is true. + * Interval in ms between two ranging measurements. Only applies to periodic ranging and is + * only relevant if |rangingRequired| is true. + * * If the Awake DW interval specified either in |discoveryWindowPeriod| or in * |NanBandSpecificConfig.discoveryWindowIntervalVal| is larger than the ranging interval then * priority is given to Awake DW interval. + * + * If this is set to 0, then only one ranging is performed. */ int rangingIntervalMs; /** @@ -162,4 +168,16 @@ parcelable NanDiscoveryCommonConfig { * |NanCapabilities.supportsSuspension| is false. */ boolean enableSessionSuspendability; + /** + * The number of FTM packets used to estimate a range. + */ + int rttBurstSize; + /** + * RTT preamble to be used in the RTT frames. + */ + RttPreamble preamble; + /** + * Channel information. + */ + @nullable WifiChannelInfo channelInfo; } diff --git a/wifi/aidl/android/hardware/wifi/NanPublishRequest.aidl b/wifi/aidl/android/hardware/wifi/NanPublishRequest.aidl index ae75caf09fdd922ae53162988c41c5795c104986..09ea496559ab0adf86b3531e338390c454a54c5b 100644 --- a/wifi/aidl/android/hardware/wifi/NanPublishRequest.aidl +++ b/wifi/aidl/android/hardware/wifi/NanPublishRequest.aidl @@ -61,4 +61,9 @@ parcelable NanPublishRequest { * that no vendor data is provided. */ @nullable OuiKeyedData[] vendorData; + /** + * If |NanCapabilities.supportsPeriodicRanging| is true, then this field specifies whether the + * ranging results need to be notified to the Publisher when they are available. + */ + boolean rangingResultsRequired; } diff --git a/wifi/aidl/android/hardware/wifi/PasnConfig.aidl b/wifi/aidl/android/hardware/wifi/PasnConfig.aidl new file mode 100644 index 0000000000000000000000000000000000000000..37ef03cbc6175d439bf1cba9f397abb03777c0e5 --- /dev/null +++ b/wifi/aidl/android/hardware/wifi/PasnConfig.aidl @@ -0,0 +1,43 @@ +/* + * 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. + */ + +package android.hardware.wifi; + +/** + * Pre-Association Security Negotiation (PASN) configuration. + */ +@VintfStability +parcelable PasnConfig { + /** + * Base Authentication and Key Management (AKM) protocol used for PASN. Represented as + * at bitmap of |Akm|. + */ + long baseAkm; + /** + * Pairwise cipher suite used for the PTKSA (Pairwise Transient Key Security Association). + * Represented as a bitmap of |CipherSuite|. + */ + long cipherSuite; + /** + * Passphrase for the base AKM. This can be null based on the AKM type. + */ + @nullable byte[] passphrase; + /** + * PMKID corresponding to the cached PMK from the base AKM. PMKID can be null if no cached PMK + * is present. + */ + @nullable byte[] pmkid; +} diff --git a/wifi/aidl/android/hardware/wifi/RttCapabilities.aidl b/wifi/aidl/android/hardware/wifi/RttCapabilities.aidl index c1939245e9b0a26342be7a0b5cb946adeab58ed8..48e211d0aaaddfee0728407302343e19b316c706 100644 --- a/wifi/aidl/android/hardware/wifi/RttCapabilities.aidl +++ b/wifi/aidl/android/hardware/wifi/RttCapabilities.aidl @@ -84,4 +84,24 @@ parcelable RttCapabilities { * that no vendor data is provided. */ @nullable OuiKeyedData[] vendorData; + /** + * Bitmap of |Akm| values indicating the set of supported AKMs. + */ + long akmsSupported; + /** + * Bitmap of |CipherSuite| values indicating the set of supported pairwise cipher suites. + */ + long cipherSuitesSupported; + /** + * Whether secure HE-LTF is supported. + */ + boolean secureHeLtfSupported; + /** + * Whether frame protection for ranging is supported. + */ + boolean rangingFrameProtectionSupported; + /** + * Maximum supported secure HE-LTF protocol version. + */ + int maxSupportedSecureHeLtfProtocolVersion; } diff --git a/wifi/aidl/android/hardware/wifi/RttConfig.aidl b/wifi/aidl/android/hardware/wifi/RttConfig.aidl index 496ffd2dbc233ca09f0030b17503090371f88372..8dfbea8b1a7ba8bd4f29e7deba7b506742322d36 100644 --- a/wifi/aidl/android/hardware/wifi/RttConfig.aidl +++ b/wifi/aidl/android/hardware/wifi/RttConfig.aidl @@ -19,6 +19,7 @@ package android.hardware.wifi; import android.hardware.wifi.RttBw; import android.hardware.wifi.RttPeerType; import android.hardware.wifi.RttPreamble; +import android.hardware.wifi.RttSecureConfig; import android.hardware.wifi.RttType; import android.hardware.wifi.WifiChannelInfo; import android.hardware.wifi.common.OuiKeyedData; @@ -140,4 +141,8 @@ parcelable RttConfig { * that no vendor data is provided. */ @nullable OuiKeyedData[] vendorData; + /** + * Secure Ranging configuration + */ + @nullable RttSecureConfig secureConfig; } diff --git a/wifi/aidl/android/hardware/wifi/RttResult.aidl b/wifi/aidl/android/hardware/wifi/RttResult.aidl index 2f9aefef2024d8e573f082252b460e797c169580..361d7e94d0e969202b8f35faa543cd0480973b70 100644 --- a/wifi/aidl/android/hardware/wifi/RttResult.aidl +++ b/wifi/aidl/android/hardware/wifi/RttResult.aidl @@ -213,4 +213,41 @@ parcelable RttResult { * that no vendor data is provided. */ @nullable OuiKeyedData[] vendorData; + /** + * Whether ranging frame protection is enabled. + */ + boolean isRangingFrameProtectionEnabled; + /** + * Whether Secure HE-LTF is enabled. + */ + boolean isSecureLtfEnabled; + /** + * Base Authentication and Key Management (AKM) protocol used for PASN. Represented as + * at bitmap of |Akm|. + */ + long baseAkm; + /** + * Pairwise cipher suite used for the PTKSA (Pairwise Transient Key Security Association). + * Represented as a bitmap of |CipherSuite|. + */ + long cipherSuite; + /** + * Secure HE-LTF protocol version used. + */ + int secureHeLtfProtocolVersion; + /** + * When an AP receives a large volume of initial PASN Authentication frames, it can use the + * comeback after field in the PASN Parameters element to indicate a deferral time and + * optionally provide a comeback cookie which is an opaque sequence of octets. This field is + * set to 0 to indicate that the subsequent ranging request can be retried with the + * |pasnComebackCookie|. + */ + long pasnComebackAfterMillis; + /** + * Comeback cookie is an opaque sequence of octects sent by the AP when PASN authentication + * needs to be deferred. The same cookie needs to be passed in |RttSecureConfig| when the + * station has to range with the AP after |RttResult.pasnComebackAfterMillis|. Maximum size of + * cookie is 255 bytes. Refer IEEE Std 802.11az‐2022, section 9.4.2.303 PASN Parameters element. + */ + @nullable byte[] pasnComebackCookie; } diff --git a/wifi/aidl/android/hardware/wifi/RttSecureConfig.aidl b/wifi/aidl/android/hardware/wifi/RttSecureConfig.aidl new file mode 100644 index 0000000000000000000000000000000000000000..0d1350ea65b3e9c267097f8a947f184ced5ec1c6 --- /dev/null +++ b/wifi/aidl/android/hardware/wifi/RttSecureConfig.aidl @@ -0,0 +1,42 @@ +/* + * 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. + */ + +package android.hardware.wifi; + +import android.hardware.wifi.PasnConfig; + +/** + * RTT secure configuration. + */ +@VintfStability +parcelable RttSecureConfig { + /** + * Pre-Association Security Negotiation (PASN) configuration. + */ + PasnConfig pasnConfig; + /** + * Enable secure HE-LTF (High Efficiency Long Training Field). + */ + boolean enableSecureHeLtf; + /** + * Enable Ranging frame protection. + */ + boolean enableRangingFrameProtection; + /** + * Comeback cookie is an opaque sequence of octets retrieved from |RttResult|. + */ + @nullable byte[] pasnComebackCookie; +} diff --git a/wifi/aidl/android/hardware/wifi/RttStatus.aidl b/wifi/aidl/android/hardware/wifi/RttStatus.aidl index 600165c5e4ddd48220657316bf28b6108bc997ef..94bc9e35ff678325a4da637e9eb186e06aacc52d 100644 --- a/wifi/aidl/android/hardware/wifi/RttStatus.aidl +++ b/wifi/aidl/android/hardware/wifi/RttStatus.aidl @@ -88,4 +88,24 @@ enum RttStatus { * NAN concurrency not supported (NDP + RTT). */ NAN_RANGING_CONCURRENCY_NOT_SUPPORTED = 17, + /** + * Secure Ranging failed due to invalid AKM (Authentication and Key Management) + */ + SECURE_RANGING_FAILURE_INVALID_AKM = 18, + /** + * Secure Ranging failed due to invalid Cipher. + */ + SECURE_RANGING_FAILURE_INVALID_CIPHER = 19, + /** + * Secure Ranging failed due to invalid configuration. + */ + SECURE_RANGING_FAILURE_INVALID_CONFIG = 20, + /** + * Secure ranging rejected by the AP. + */ + SECURE_RANGING_FAILURE_REJECTED = 21, + /** + * Secure ranging failure unknown. + */ + SECURE_RANGING_FAILURE_UNKNOWN = 22, } diff --git a/wifi/aidl/android/hardware/wifi/RttType.aidl b/wifi/aidl/android/hardware/wifi/RttType.aidl index 3f1a2f165b67271c1e256390453c7d4c88909fb1..d7cf9fe86830f35ca8feff6c09dfd3aa1ecb240b 100644 --- a/wifi/aidl/android/hardware/wifi/RttType.aidl +++ b/wifi/aidl/android/hardware/wifi/RttType.aidl @@ -37,4 +37,8 @@ enum RttType { * Two-sided RTT 11az non trigger based (non-TB) type. */ TWO_SIDED_11AZ_NTB = 3, + /** + * Two-sided RTT 11az non trigger based (non-TB) secure type. + */ + TWO_SIDED_11AZ_NTB_SECURE = 4, } diff --git a/wifi/aidl/default/Android.bp b/wifi/aidl/default/Android.bp index 3fcb77f597b974566148221d861bfa4d382697f2..c2e8541de65fb66ceeb284cf63cfa7e9f7bc0074 100644 --- a/wifi/aidl/default/Android.bp +++ b/wifi/aidl/default/Android.bp @@ -106,7 +106,7 @@ cc_library_static { "libwifi-hal", "libwifi-system-iface", "libxml2", - "android.hardware.wifi-V2-ndk", + "android.hardware.wifi-V3-ndk", ], export_include_dirs: ["."], @@ -138,7 +138,7 @@ cc_binary { "libwifi-hal", "libwifi-system-iface", "libxml2", - "android.hardware.wifi-V2-ndk", + "android.hardware.wifi-V3-ndk", ], static_libs: ["android.hardware.wifi-service-lib"], init_rc: ["android.hardware.wifi-service.rc"], @@ -167,7 +167,7 @@ cc_binary { "libwifi-hal", "libwifi-system-iface", "libxml2", - "android.hardware.wifi-V2-ndk", + "android.hardware.wifi-V3-ndk", ], static_libs: ["android.hardware.wifi-service-lib"], init_rc: ["android.hardware.wifi-service-lazy.rc"], @@ -199,8 +199,8 @@ cc_test { static_libs: [ "libgmock", "libgtest", - "android.hardware.wifi-V2-ndk", - "android.hardware.wifi.common-V1-ndk", + "android.hardware.wifi-V3-ndk", + "android.hardware.wifi.common-V2-ndk", "android.hardware.wifi-service-lib", ], shared_libs: [ diff --git a/wifi/aidl/default/aidl_callback_util.h b/wifi/aidl/default/aidl_callback_util.h index f8ba53ba811cceac7bd42fccb0f0e4119c9d5deb..d077683c4989c9ad8472cf1f42e43660c90f757a 100644 --- a/wifi/aidl/default/aidl_callback_util.h +++ b/wifi/aidl/default/aidl_callback_util.h @@ -26,6 +26,7 @@ namespace { std::unordered_map callback_handler_map_; std::mutex callback_handler_lock_; +int32_t min_callback_version_ = INT_MAX; } namespace aidl { @@ -45,6 +46,18 @@ class AidlCallbackHandler { ~AidlCallbackHandler() { invalidate(); } bool addCallback(const std::shared_ptr& cb) { + if (cb == nullptr) { + LOG(ERROR) << "Unable to register a null callback"; + return false; + } + + // Callback interface version indicates which methods are available + int callbackVersion = getCallbackInterfaceVersion(cb); + if (callbackVersion < min_callback_version_) { + LOG(INFO) << "Setting min callback version to " << callbackVersion; + min_callback_version_ = callbackVersion; + } + std::unique_lock lk(callback_handler_lock_); void* cbPtr = reinterpret_cast(cb->asBinder().get()); const auto& cbPosition = findCbInSet(cbPtr); @@ -106,6 +119,8 @@ class AidlCallbackHandler { // unique_lock unlocked here } + int32_t getMinCallbackVersion() { return min_callback_version_; } + private: std::set> cb_set_; AIBinder_DeathRecipient* death_handler_; @@ -140,6 +155,15 @@ class AidlCallbackHandler { } } + static int32_t getCallbackInterfaceVersion(std::shared_ptr callback) { + int32_t callbackVersion; + if (!callback->getInterfaceVersion(&callbackVersion).isOk()) { + LOG(ERROR) << "Unable to check the callback version"; + return INT_MAX; + } + return callbackVersion; + } + DISALLOW_COPY_AND_ASSIGN(AidlCallbackHandler); }; diff --git a/wifi/aidl/default/aidl_struct_util.cpp b/wifi/aidl/default/aidl_struct_util.cpp index d99edaab9b92b65224d2526e75531fa1e9d2ff08..75e9bfe3e68bb1da0280b916efecb94a1570705d 100644 --- a/wifi/aidl/default/aidl_struct_util.cpp +++ b/wifi/aidl/default/aidl_struct_util.cpp @@ -26,6 +26,9 @@ namespace wifi { namespace aidl_struct_util { WifiChannelWidthInMhz convertLegacyWifiChannelWidthToAidl(legacy_hal::wifi_channel_width type); +bool convertAidlWifiChannelInfoToLegacy(const WifiChannelInfo& aidl_info, + legacy_hal::wifi_channel_info* legacy_info); +RttBw convertLegacyRttBwToAidl(legacy_hal::wifi_rtt_bw type); std::string safeConvertChar(const char* str, size_t max_len) { const char* c = str; @@ -61,6 +64,8 @@ IWifiChip::FeatureSetMask convertLegacyChipFeatureToAidl(uint64_t feature) { return IWifiChip::FeatureSetMask::SET_AFC_CHANNEL_ALLOWANCE; case WIFI_FEATURE_SET_VOIP_MODE: return IWifiChip::FeatureSetMask::SET_VOIP_MODE; + case WIFI_FEATURE_MLO_SAP: + return IWifiChip::FeatureSetMask::MLO_SAP; }; CHECK(false) << "Unknown legacy feature: " << feature; return {}; @@ -1857,7 +1862,9 @@ bool convertAidlNanPublishRequestToLegacy(const NanPublishRequest& aidl_request, legacy_request->ranging_auto_response = aidl_request.baseConfigs.rangingRequired ? legacy_hal::NAN_RANGING_AUTO_RESPONSE_ENABLE : legacy_hal::NAN_RANGING_AUTO_RESPONSE_DISABLE; - legacy_request->sdea_params.range_report = legacy_hal::NAN_DISABLE_RANGE_REPORT; + legacy_request->sdea_params.range_report = aidl_request.rangingResultsRequired + ? legacy_hal::NAN_ENABLE_RANGE_REPORT + : legacy_hal::NAN_DISABLE_RANGE_REPORT; legacy_request->publish_type = convertAidlNanPublishTypeToLegacy(aidl_request.publishType); legacy_request->tx_type = convertAidlNanTxTypeToLegacy(aidl_request.txType); legacy_request->service_responder_policy = aidl_request.autoAcceptDataPathRequests @@ -1986,6 +1993,17 @@ bool convertAidlNanSubscribeRequestToLegacy(const NanSubscribeRequest& aidl_requ legacy_request->ranging_cfg.distance_ingress_mm = aidl_request.baseConfigs.distanceIngressCm * 10; legacy_request->ranging_cfg.distance_egress_mm = aidl_request.baseConfigs.distanceEgressCm * 10; + legacy_request->ranging_cfg.rtt_burst_size = aidl_request.baseConfigs.rttBurstSize; + legacy_request->ranging_cfg.preamble = + convertAidlRttPreambleToLegacy(aidl_request.baseConfigs.preamble); + if (aidl_request.baseConfigs.channelInfo.has_value()) { + if (!convertAidlWifiChannelInfoToLegacy(aidl_request.baseConfigs.channelInfo.value(), + &legacy_request->ranging_cfg.channel_info)) { + LOG(ERROR) << "convertAidlNanSubscribeRequestToLegacy: " + "Unable to convert aidl channel info to legacy"; + return false; + } + } legacy_request->ranging_auto_response = aidl_request.baseConfigs.rangingRequired ? legacy_hal::NAN_RANGING_AUTO_RESPONSE_ENABLE : legacy_hal::NAN_RANGING_AUTO_RESPONSE_DISABLE; @@ -2294,6 +2312,9 @@ bool convertLegacyNanCapabilitiesResponseToAidl(const legacy_hal::NanCapabilitie aidl_response->supportsPairing = legacy_response.is_pairing_supported; aidl_response->supportsSetClusterId = legacy_response.is_set_cluster_id_supported; aidl_response->supportsSuspension = legacy_response.is_suspension_supported; + aidl_response->supportsPeriodicRanging = legacy_response.is_periodic_ranging_supported; + aidl_response->maxSupportedBandwidth = convertLegacyRttBwToAidl(legacy_response.supported_bw); + aidl_response->maxNumRxChainsSupported = legacy_response.num_rx_chains_supported; return true; } @@ -2476,6 +2497,8 @@ legacy_hal::wifi_rtt_type convertAidlRttTypeToLegacy(RttType type) { return legacy_hal::RTT_TYPE_2_SIDED_11MC; case RttType::TWO_SIDED_11AZ_NTB: return legacy_hal::RTT_TYPE_2_SIDED_11AZ_NTB; + case RttType::TWO_SIDED_11AZ_NTB_SECURE: + return legacy_hal::RTT_TYPE_2_SIDED_11AZ_NTB_SECURE; }; CHECK(false); } @@ -2489,6 +2512,8 @@ RttType convertLegacyRttTypeToAidl(legacy_hal::wifi_rtt_type type) { return RttType::TWO_SIDED_11MC; case legacy_hal::RTT_TYPE_2_SIDED_11AZ_NTB: return RttType::TWO_SIDED_11AZ_NTB; + case legacy_hal::RTT_TYPE_2_SIDED_11AZ_NTB_SECURE: + return RttType::TWO_SIDED_11AZ_NTB_SECURE; }; CHECK(false) << "Unknown legacy type: " << type; } @@ -2721,6 +2746,16 @@ RttStatus convertLegacyRttStatusToAidl(legacy_hal::wifi_rtt_status status) { return RttStatus::NAN_RANGING_PROTOCOL_FAILURE; case legacy_hal::RTT_STATUS_NAN_RANGING_CONCURRENCY_NOT_SUPPORTED: return RttStatus::NAN_RANGING_CONCURRENCY_NOT_SUPPORTED; + case legacy_hal::RTT_STATUS_SECURE_RANGING_FAILURE_INVALID_AKM: + return RttStatus::SECURE_RANGING_FAILURE_INVALID_AKM; + case legacy_hal::RTT_STATUS_SECURE_RANGING_FAILURE_INVALID_CIPHER: + return RttStatus::SECURE_RANGING_FAILURE_INVALID_CIPHER; + case legacy_hal::RTT_STATUS_SECURE_RANGING_FAILURE_INVALID_CONFIG: + return RttStatus::SECURE_RANGING_FAILURE_INVALID_CONFIG; + case legacy_hal::RTT_STATUS_SECURE_RANGING_FAILURE_REJECTED: + return RttStatus::SECURE_RANGING_FAILURE_REJECTED; + case legacy_hal::RTT_STATUS_SECURE_RANGING_FAILURE_UNKNOWN: + return RttStatus::SECURE_RANGING_FAILURE_UNKNOWN; }; CHECK(false) << "Unknown legacy status: " << status; } diff --git a/wifi/aidl/default/aidl_struct_util.h b/wifi/aidl/default/aidl_struct_util.h index 2574f9546b831fd9d2249e68a74c5aaea520a3d4..9a3c5356b3b906c3cbc9307349abb0dbce54213f 100644 --- a/wifi/aidl/default/aidl_struct_util.h +++ b/wifi/aidl/default/aidl_struct_util.h @@ -231,6 +231,8 @@ bool convertLegacyHalTwtSessionToAidl(legacy_hal::wifi_twt_session twt_session, TwtSession* aidl_twt_session); bool convertLegacyHalTwtSessionStatsToAidl(legacy_hal::wifi_twt_session_stats twt_stats, TwtSessionStats* aidl_twt_stats); +legacy_hal::wifi_rtt_preamble convertAidlRttPreambleToLegacy(RttPreamble type); + } // namespace aidl_struct_util } // namespace wifi } // namespace hardware diff --git a/wifi/aidl/default/android.hardware.wifi-service.xml b/wifi/aidl/default/android.hardware.wifi-service.xml index 3b68c8eeb0bd969cb349122cfc9688174d6305eb..9bfffb62835a49ddf100a9bff25d73fe3e66c0f6 100644 --- a/wifi/aidl/default/android.hardware.wifi-service.xml +++ b/wifi/aidl/default/android.hardware.wifi-service.xml @@ -1,7 +1,7 @@ android.hardware.wifi - 2 + 3 IWifi/default diff --git a/wifi/aidl/default/tests/wifi_nan_iface_unit_tests.cpp b/wifi/aidl/default/tests/wifi_nan_iface_unit_tests.cpp index d58a9b0ace83217deec373f1a431f503e68ec788..513f440d239388a2eb573f38c883e83488cf4510 100644 --- a/wifi/aidl/default/tests/wifi_nan_iface_unit_tests.cpp +++ b/wifi/aidl/default/tests/wifi_nan_iface_unit_tests.cpp @@ -138,6 +138,7 @@ class MockNanIfaceEventCallback : public IWifiNanIfaceEventCallback { MOCK_METHOD2(notifyResumeResponse, ndk::ScopedAStatus(char16_t, const NanStatus&)); MOCK_METHOD2(notifyTerminatePairingResponse, ndk::ScopedAStatus(char16_t, const NanStatus&)); MOCK_METHOD1(eventSuspensionModeChanged, ndk::ScopedAStatus(const NanSuspensionModeChangeInd&)); + MOCK_METHOD2(notifyRangingResults, ndk::ScopedAStatus(const std::vector&, int8_t)); }; class WifiNanIfaceTest : public Test { diff --git a/wifi/aidl/default/wifi_ap_iface.cpp b/wifi/aidl/default/wifi_ap_iface.cpp index 77797502d3cbbc0e4ae0565cac66d46c5ebe5419..6a73cc821fee3809c3b3a47192a991c3eb1b152b 100644 --- a/wifi/aidl/default/wifi_ap_iface.cpp +++ b/wifi/aidl/default/wifi_ap_iface.cpp @@ -28,10 +28,12 @@ namespace hardware { namespace wifi { using aidl_return_util::validateAndCall; -WifiApIface::WifiApIface(const std::string& ifname, const std::vector& instances, +WifiApIface::WifiApIface(const std::string& ifname, const bool usesMlo, + const std::vector& instances, const std::weak_ptr legacy_hal, const std::weak_ptr iface_util) : ifname_(ifname), + uses_mlo_(usesMlo), instances_(instances), legacy_hal_(legacy_hal), iface_util_(iface_util), @@ -50,6 +52,10 @@ std::string WifiApIface::getName() { return ifname_; } +bool WifiApIface::usesMlo() { + return uses_mlo_; +} + void WifiApIface::removeInstance(std::string instance) { instances_.erase(std::remove(instances_.begin(), instances_.end(), instance), instances_.end()); } @@ -72,7 +78,7 @@ ndk::ScopedAStatus WifiApIface::setMacAddress(const std::array& in_m ndk::ScopedAStatus WifiApIface::getFactoryMacAddress(std::array* _aidl_return) { return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, &WifiApIface::getFactoryMacAddressInternal, _aidl_return, - instances_.size() > 0 ? instances_[0] : ifname_); + getOperatingInstanceName()); } ndk::ScopedAStatus WifiApIface::resetToFactoryMacAddress() { @@ -90,14 +96,14 @@ std::pair WifiApIface::getNameInternal() { } ndk::ScopedAStatus WifiApIface::setCountryCodeInternal(const std::array& code) { - legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->setCountryCode( - instances_.size() > 0 ? instances_[0] : ifname_, code); + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->setCountryCode(getOperatingInstanceName(), code); return createWifiStatusFromLegacyError(legacy_status); } ndk::ScopedAStatus WifiApIface::setMacAddressInternal(const std::array& mac) { // Support random MAC up to 2 interfaces - if (instances_.size() == 2) { + if (instances_.size() == 2 && !uses_mlo_) { int rbyte = 1; for (auto const& intf : instances_) { std::array rmac = mac; @@ -131,7 +137,7 @@ std::pair, ndk::ScopedAStatus> WifiApIface::getFactoryMac ndk::ScopedAStatus WifiApIface::resetToFactoryMacAddressInternal() { std::pair, ndk::ScopedAStatus> getMacResult; - if (instances_.size() == 2) { + if (instances_.size() == 2 && !uses_mlo_) { for (auto const& intf : instances_) { getMacResult = getFactoryMacAddressInternal(intf); LOG(DEBUG) << "Reset MAC to factory MAC on " << intf; @@ -166,6 +172,11 @@ std::pair, ndk::ScopedAStatus> WifiApIface::getBridgedI return {instances_, ndk::ScopedAStatus::ok()}; } +ndk::ScopedAStatus WifiApIface::usesMlo(bool* _aidl_return) { + *_aidl_return = uses_mlo_; + return ndk::ScopedAStatus::ok(); +} + } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/aidl/default/wifi_ap_iface.h b/wifi/aidl/default/wifi_ap_iface.h index 7378f98acfcf16735667a85a76c27b3f9f2649a8..e07154db14fc527559dd3159820b002b80e80281 100644 --- a/wifi/aidl/default/wifi_ap_iface.h +++ b/wifi/aidl/default/wifi_ap_iface.h @@ -33,13 +33,15 @@ namespace wifi { */ class WifiApIface : public BnWifiApIface { public: - WifiApIface(const std::string& ifname, const std::vector& instances, + WifiApIface(const std::string& ifname, const bool usesMlo, + const std::vector& instances, const std::weak_ptr legacy_hal, const std::weak_ptr iface_util); // Refer to |WifiChip::invalidate()|. void invalidate(); bool isValid(); std::string getName(); + bool usesMlo(); void removeInstance(std::string instance); // AIDL methods exposed. @@ -49,6 +51,7 @@ class WifiApIface : public BnWifiApIface { ndk::ScopedAStatus getFactoryMacAddress(std::array* _aidl_return) override; ndk::ScopedAStatus resetToFactoryMacAddress() override; ndk::ScopedAStatus getBridgedInstances(std::vector* _aidl_return) override; + ndk::ScopedAStatus usesMlo(bool* _aidl_return) override; private: // Corresponding worker functions for the AIDL methods. @@ -61,11 +64,18 @@ class WifiApIface : public BnWifiApIface { std::pair, ndk::ScopedAStatus> getBridgedInstancesInternal(); std::string ifname_; + bool uses_mlo_; std::vector instances_; std::weak_ptr legacy_hal_; std::weak_ptr iface_util_; bool is_valid_; + // The mlo is using one interface but owning two link instances. + // The operating should be based on interface. + inline std::string getOperatingInstanceName() { + return (instances_.size() > 0 && !uses_mlo_) ? instances_[0] : ifname_; + }; + DISALLOW_COPY_AND_ASSIGN(WifiApIface); }; diff --git a/wifi/aidl/default/wifi_chip.cpp b/wifi/aidl/default/wifi_chip.cpp index fccfc158594bd7e4558a22340531f26cc1cb879a..045e07d43e0ec445be5c9afde2253baa2adbb0d0 100644 --- a/wifi/aidl/default/wifi_chip.cpp +++ b/wifi/aidl/default/wifi_chip.cpp @@ -369,7 +369,7 @@ ndk::ScopedAStatus WifiChip::createApIface(std::shared_ptr* _aidl_ ndk::ScopedAStatus WifiChip::createBridgedApIface(std::shared_ptr* _aidl_return) { return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, - &WifiChip::createBridgedApIfaceInternal, _aidl_return); + &WifiChip::createBridgedApIfaceInternal, _aidl_return, false); } ndk::ScopedAStatus WifiChip::createApOrBridgedApIface( @@ -613,6 +613,13 @@ ndk::ScopedAStatus WifiChip::setVoipMode(const VoipMode in_mode) { &WifiChip::setVoipModeInternal, in_mode); } +ndk::ScopedAStatus WifiChip::createApOrBridgedApIfaceWithParams( + const ApIfaceParams& in_params, std::shared_ptr* _aidl_return) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::createApOrBridgedApIfaceWithParamsInternal, _aidl_return, + in_params); +} + void WifiChip::invalidateAndRemoveAllIfaces() { invalidateAndClearBridgedApAll(); invalidateAndClearAll(ap_ifaces_); @@ -797,15 +804,15 @@ ndk::ScopedAStatus WifiChip::createVirtualApInterface(const std::string& apVirtI return ndk::ScopedAStatus::ok(); } -std::shared_ptr WifiChip::newWifiApIface(std::string& ifname) { +std::shared_ptr WifiChip::newWifiApIface(std::string& ifname, bool usesMlo) { std::vector ap_instances; for (auto const& it : br_ifaces_ap_instances_) { if (it.first == ifname) { ap_instances = it.second; } } - std::shared_ptr iface = - ndk::SharedRefBase::make(ifname, ap_instances, legacy_hal_, iface_util_); + std::shared_ptr iface = ndk::SharedRefBase::make( + ifname, usesMlo, ap_instances, legacy_hal_, iface_util_); ap_ifaces_.push_back(iface); for (const auto& callback : event_cb_handler_.getCallbacks()) { if (!callback->onIfaceAdded(IfaceType::AP, ifname).isOk()) { @@ -826,47 +833,60 @@ std::pair, ndk::ScopedAStatus> WifiChip::createApI if (!status.isOk()) { return {std::shared_ptr(), std::move(status)}; } - std::shared_ptr iface = newWifiApIface(ifname); + std::shared_ptr iface = newWifiApIface(ifname, false); return {iface, ndk::ScopedAStatus::ok()}; } -std::pair, ndk::ScopedAStatus> -WifiChip::createBridgedApIfaceInternal() { +std::pair, ndk::ScopedAStatus> WifiChip::createBridgedApIfaceInternal( + bool usesMlo) { if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::AP_BRIDGED)) { return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)}; } - std::vector ap_instances = allocateBridgedApInstanceNames(); + std::string br_ifname; + std::vector ap_instances = allocateBridgedApInstanceNames(usesMlo); if (ap_instances.size() < 2) { LOG(ERROR) << "Fail to allocate two instances"; return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)}; } - std::string br_ifname = kApBridgeIfacePrefix + ap_instances[0]; - for (int i = 0; i < 2; i++) { - ndk::ScopedAStatus status = createVirtualApInterface(ap_instances[i]); - if (!status.isOk()) { - if (i != 0) { // The failure happened when creating second virtual - // iface. - legacy_hal_.lock()->deleteVirtualInterface( - ap_instances.front()); // Remove the first virtual iface. + if (usesMlo) { + // MLO SoftAp is using single interface with two links. So only need to create 1 interface. + br_ifname = allocateApIfaceName(); + } else { + br_ifname = kApBridgeIfacePrefix + ap_instances[0]; + for (int i = 0; i < 2; i++) { + ndk::ScopedAStatus status = createVirtualApInterface(ap_instances[i]); + if (!status.isOk()) { + if (i != 0) { // The failure happened when creating second virtual + // iface. + legacy_hal_.lock()->deleteVirtualInterface( + ap_instances.front()); // Remove the first virtual iface. + } + return {nullptr, std::move(status)}; } - return {nullptr, std::move(status)}; } } br_ifaces_ap_instances_[br_ifname] = ap_instances; - if (!iface_util_->createBridge(br_ifname)) { - LOG(ERROR) << "Failed createBridge - br_name=" << br_ifname.c_str(); - deleteApIface(br_ifname); - return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)}; - } - for (auto const& instance : ap_instances) { - // Bind ap instance interface to AP bridge - if (!iface_util_->addIfaceToBridge(br_ifname, instance)) { - LOG(ERROR) << "Failed add if to Bridge - if_name=" << instance.c_str(); + if (usesMlo) { + ndk::ScopedAStatus status = createVirtualApInterface(br_ifname); + if (!status.isOk()) { + return {nullptr, std::move(status)}; + } + } else { + if (!iface_util_->createBridge(br_ifname)) { + LOG(ERROR) << "Failed createBridge - br_name=" << br_ifname.c_str(); deleteApIface(br_ifname); return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)}; } + for (auto const& instance : ap_instances) { + // Bind ap instance interface to AP bridge + if (!iface_util_->addIfaceToBridge(br_ifname, instance)) { + LOG(ERROR) << "Failed add if to Bridge - if_name=" << instance.c_str(); + deleteApIface(br_ifname); + return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)}; + } + } } - std::shared_ptr iface = newWifiApIface(br_ifname); + std::shared_ptr iface = newWifiApIface(br_ifname, usesMlo); return {iface, ndk::ScopedAStatus::ok()}; } @@ -876,7 +896,18 @@ WifiChip::createApOrBridgedApIfaceInternal( if (ifaceType == IfaceConcurrencyType::AP) { return createApIfaceInternal(); } else if (ifaceType == IfaceConcurrencyType::AP_BRIDGED) { - return createBridgedApIfaceInternal(); + return createBridgedApIfaceInternal(false); + } else { + return {nullptr, createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)}; + } +} + +std::pair, ndk::ScopedAStatus> +WifiChip::createApOrBridgedApIfaceWithParamsInternal(const ApIfaceParams& params) { + if (params.ifaceType == IfaceConcurrencyType::AP) { + return createApIfaceInternal(); + } else if (params.ifaceType == IfaceConcurrencyType::AP_BRIDGED) { + return createBridgedApIfaceInternal(params.usesMlo); } else { return {nullptr, createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)}; } @@ -925,23 +956,28 @@ ndk::ScopedAStatus WifiChip::removeIfaceInstanceFromBridgedApIfaceInternal( if (!iface.get() || ifInstanceName.empty()) { return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); } + // Requires to remove one of the instance in bridge mode for (auto const& it : br_ifaces_ap_instances_) { if (it.first == ifname) { std::vector ap_instances = it.second; - for (auto const& iface : ap_instances) { - if (iface == ifInstanceName) { - if (!iface_util_->removeIfaceFromBridge(it.first, iface)) { - LOG(ERROR) << "Failed to remove interface: " << ifInstanceName << " from " - << ifname; - return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE); - } - legacy_hal::wifi_error legacy_status = - legacy_hal_.lock()->deleteVirtualInterface(iface); - if (legacy_status != legacy_hal::WIFI_SUCCESS) { - LOG(ERROR) << "Failed to del interface: " << iface << " " - << legacyErrorToString(legacy_status); - return createWifiStatusFromLegacyError(legacy_status); + for (auto const& instance : ap_instances) { + if (instance == ifInstanceName) { + if (iface->usesMlo()) { + LOG(INFO) << "Remove Link " << ifInstanceName << " from " << ifname; + } else { + if (!iface_util_->removeIfaceFromBridge(it.first, instance)) { + LOG(ERROR) << "Failed to remove interface: " << ifInstanceName + << " from " << ifname; + return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->deleteVirtualInterface(instance); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to del interface: " << instance << " " + << legacyErrorToString(legacy_status); + return createWifiStatusFromLegacyError(legacy_status); + } } ap_instances.erase( std::remove(ap_instances.begin(), ap_instances.end(), ifInstanceName), @@ -1729,7 +1765,7 @@ std::string WifiChip::getFirstActiveWlanIfaceName() { // If the first active wlan iface is bridged iface. // Return first instance name. for (auto const& it : br_ifaces_ap_instances_) { - if (it.first == ap_ifaces_[0]->getName()) { + if (it.first == ap_ifaces_[0]->getName() && !ap_ifaces_[0]->usesMlo()) { return it.second[0]; } } @@ -1782,9 +1818,19 @@ std::string WifiChip::allocateApIfaceName() { return allocateApOrStaIfaceName(IfaceType::AP, startIdxOfApIface()); } -std::vector WifiChip::allocateBridgedApInstanceNames() { - // Check if we have a dedicated iface for AP. - std::vector instances = getPredefinedApIfaceNames(true); +std::vector WifiChip::allocateBridgedApInstanceNames(bool usesMlo) { + std::vector instances; + if (usesMlo) { + // For MLO AP, the instances are MLO links and it will be maintained in hostapd. + // The hostapd will use 0 as an initial link id and 1 as the next. + // Considering Android didn't support link reconfiguration. Forcing to use 0 & 1 + // should work. + instances.push_back("0"); + instances.push_back("1"); + } else { + // Check if we have a dedicated iface for AP. + instances = getPredefinedApIfaceNames(true); + } if (instances.size() == 2) { return instances; } else { @@ -1856,11 +1902,14 @@ std::string WifiChip::getWlanIfaceNameWithType(IfaceType type, unsigned idx) { void WifiChip::invalidateAndClearBridgedApAll() { for (auto const& it : br_ifaces_ap_instances_) { - for (auto const& iface : it.second) { - iface_util_->removeIfaceFromBridge(it.first, iface); - legacy_hal_.lock()->deleteVirtualInterface(iface); + const auto iface = findUsingName(ap_ifaces_, it.first); + if (!iface->usesMlo()) { + for (auto const& iface : it.second) { + iface_util_->removeIfaceFromBridge(it.first, iface); + legacy_hal_.lock()->deleteVirtualInterface(iface); + } + iface_util_->deleteBridge(it.first); } - iface_util_->deleteBridge(it.first); } br_ifaces_ap_instances_.clear(); } @@ -1868,16 +1917,19 @@ void WifiChip::invalidateAndClearBridgedApAll() { void WifiChip::deleteApIface(const std::string& if_name) { if (if_name.empty()) return; // delete bridged interfaces if any - for (auto const& it : br_ifaces_ap_instances_) { - if (it.first == if_name) { - for (auto const& iface : it.second) { - iface_util_->removeIfaceFromBridge(if_name, iface); - legacy_hal_.lock()->deleteVirtualInterface(iface); + const auto iface = findUsingName(ap_ifaces_, if_name); + if (!iface->usesMlo()) { + for (auto const& it : br_ifaces_ap_instances_) { + if (it.first == if_name) { + for (auto const& instance : it.second) { + iface_util_->removeIfaceFromBridge(if_name, instance); + legacy_hal_.lock()->deleteVirtualInterface(instance); + } + iface_util_->deleteBridge(if_name); + br_ifaces_ap_instances_.erase(if_name); + // ifname is bridged AP, return here. + return; } - iface_util_->deleteBridge(if_name); - br_ifaces_ap_instances_.erase(if_name); - // ifname is bridged AP, return here. - return; } } diff --git a/wifi/aidl/default/wifi_chip.h b/wifi/aidl/default/wifi_chip.h index ffd507f801370ae9921d9580388031ee4ddf258a..24dd00d2fdc8159e5a17ed3bb5ac20992f15fc92 100644 --- a/wifi/aidl/default/wifi_chip.h +++ b/wifi/aidl/default/wifi_chip.h @@ -159,6 +159,8 @@ class WifiChip : public BnWifiChip { binder_status_t dump(int fd, const char** args, uint32_t numArgs) override; ndk::ScopedAStatus setMloMode(const ChipMloMode in_mode) override; ndk::ScopedAStatus setVoipMode(const VoipMode in_mode) override; + ndk::ScopedAStatus createApOrBridgedApIfaceWithParams( + const ApIfaceParams& in_params, std::shared_ptr* _aidl_return) override; private: void invalidateAndRemoveAllIfaces(); @@ -178,12 +180,15 @@ class WifiChip : public BnWifiChip { std::pair requestChipDebugInfoInternal(); std::pair, ndk::ScopedAStatus> requestDriverDebugDumpInternal(); std::pair, ndk::ScopedAStatus> requestFirmwareDebugDumpInternal(); - std::shared_ptr newWifiApIface(std::string& ifname); + std::shared_ptr newWifiApIface(std::string& ifname, bool usesMlo); ndk::ScopedAStatus createVirtualApInterface(const std::string& apVirtIf); std::pair, ndk::ScopedAStatus> createApIfaceInternal(); - std::pair, ndk::ScopedAStatus> createBridgedApIfaceInternal(); + std::pair, ndk::ScopedAStatus> createBridgedApIfaceInternal( + bool usesMlo); std::pair, ndk::ScopedAStatus> createApOrBridgedApIfaceInternal( IfaceConcurrencyType ifaceType, const std::vector& vendorData); + std::pair, ndk::ScopedAStatus> + createApOrBridgedApIfaceWithParamsInternal(const ApIfaceParams& params); std::pair, ndk::ScopedAStatus> getApIfaceNamesInternal(); std::pair, ndk::ScopedAStatus> getApIfaceInternal( const std::string& ifname); @@ -258,7 +263,7 @@ class WifiChip : public BnWifiChip { std::string getFirstActiveWlanIfaceName(); std::string allocateApOrStaIfaceName(IfaceType type, uint32_t start_idx); std::string allocateApIfaceName(); - std::vector allocateBridgedApInstanceNames(); + std::vector allocateBridgedApInstanceNames(bool usesMlo); std::string allocateStaIfaceName(); bool writeRingbufferFilesInternal(); std::string getWlanIfaceNameWithType(IfaceType type, unsigned idx); diff --git a/wifi/aidl/default/wifi_legacy_hal.cpp b/wifi/aidl/default/wifi_legacy_hal.cpp index bd92a20f8de5df43693b14f1195f884740f89298..8d69013dc960c7891b58160ed83e3b1631d7ea20 100644 --- a/wifi/aidl/default/wifi_legacy_hal.cpp +++ b/wifi/aidl/default/wifi_legacy_hal.cpp @@ -372,6 +372,16 @@ void onAsyncNanEventSuspensionModeChange(NanSuspensionModeChangeInd* event) { } } +std::function + on_nan_event_ranging_results_callback; +void onAsyncNanEventRangingResults(wifi_rtt_result* rtt_results[], uint32_t num_results, + uint16_t session_id) { + const auto lock = aidl_sync_util::acquireGlobalLock(); + if (on_nan_event_ranging_results_callback && rtt_results) { + on_nan_event_ranging_results_callback(rtt_results, num_results, session_id); + } +} + std::function on_nan_event_pairing_request_user_callback; void onAsyncNanEventPairingRequest(NanPairingRequestInd* event) { const auto lock = aidl_sync_util::acquireGlobalLock(); @@ -1510,6 +1520,7 @@ wifi_error WifiLegacyHal::nanRegisterCallbackHandlers(const std::string& iface_n on_nan_event_schedule_update_user_callback = user_callbacks.on_event_schedule_update; on_nan_event_suspension_mode_change_user_callback = user_callbacks.on_event_suspension_mode_change; + on_nan_event_ranging_results_callback = user_callbacks.on_ranging_results; return global_func_table_.wifi_nan_register_handler(getIfaceHandle(iface_name), {onAsyncNanNotifyResponse, @@ -1534,7 +1545,8 @@ wifi_error WifiLegacyHal::nanRegisterCallbackHandlers(const std::string& iface_n onAsyncNanEventPairingConfirm, onAsyncNanEventBootstrappingRequest, onAsyncNanEventBootstrappingConfirm, - onAsyncNanEventSuspensionModeChange}); + onAsyncNanEventSuspensionModeChange, + onAsyncNanEventRangingResults}); } wifi_error WifiLegacyHal::nanEnableRequest(const std::string& iface_name, transaction_id id, diff --git a/wifi/aidl/default/wifi_legacy_hal.h b/wifi/aidl/default/wifi_legacy_hal.h index 3fd567bc45cf199c38dcc8e5d67bfe1ef4c1b397..f603210fe320f075a497a746a2ef48ef2664f25b 100644 --- a/wifi/aidl/default/wifi_legacy_hal.h +++ b/wifi/aidl/default/wifi_legacy_hal.h @@ -63,6 +63,7 @@ using ::NAN_DP_REQUEST_ACCEPT; using ::NAN_DP_REQUEST_CHANNEL_SETUP; using ::NAN_DP_REQUEST_REJECT; using ::NAN_DP_RESPONDER_RESPONSE; +using ::NAN_ENABLE_RANGE_REPORT; using ::NAN_GET_CAPABILITIES; using ::NAN_MATCH_ALG_MATCH_CONTINUOUS; using ::NAN_MATCH_ALG_MATCH_NEVER; @@ -212,10 +213,16 @@ using ::RTT_STATUS_INVALID_REQ; using ::RTT_STATUS_NAN_RANGING_CONCURRENCY_NOT_SUPPORTED; using ::RTT_STATUS_NAN_RANGING_PROTOCOL_FAILURE; using ::RTT_STATUS_NO_WIFI; +using ::RTT_STATUS_SECURE_RANGING_FAILURE_INVALID_AKM; +using ::RTT_STATUS_SECURE_RANGING_FAILURE_INVALID_CIPHER; +using ::RTT_STATUS_SECURE_RANGING_FAILURE_INVALID_CONFIG; +using ::RTT_STATUS_SECURE_RANGING_FAILURE_REJECTED; +using ::RTT_STATUS_SECURE_RANGING_FAILURE_UNKNOWN; using ::RTT_STATUS_SUCCESS; using ::RTT_TYPE_1_SIDED; using ::RTT_TYPE_2_SIDED; using ::RTT_TYPE_2_SIDED_11AZ_NTB; +using ::RTT_TYPE_2_SIDED_11AZ_NTB_SECURE; using ::RTT_TYPE_2_SIDED_11MC; using ::RX_PKT_FATE_DRV_DROP_FILTER; using ::RX_PKT_FATE_DRV_DROP_INVALID; @@ -482,6 +489,8 @@ struct NanCallbackHandlers { std::function on_event_bootstrapping_request; std::function on_event_bootstrapping_confirm; std::function on_event_suspension_mode_change; + std::function + on_ranging_results; }; // Full scan results contain IE info and are hence passed by reference, to diff --git a/wifi/aidl/default/wifi_nan_iface.cpp b/wifi/aidl/default/wifi_nan_iface.cpp index cefe7f7695de1243861316db4a160baf78e8b1aa..950e647667efd9d6c2d72417f608756c4c06b7d3 100644 --- a/wifi/aidl/default/wifi_nan_iface.cpp +++ b/wifi/aidl/default/wifi_nan_iface.cpp @@ -613,7 +613,36 @@ void WifiNanIface::registerCallbackHandlers() { } } }; + callback_handlers.on_ranging_results = [weak_ptr_this]( + legacy_hal::wifi_rtt_result* rtt_results[], + uint32_t num_results, uint16_t session_id) { + const auto shared_ptr_this = weak_ptr_this.lock(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + if (shared_ptr_this->getMinCallbackVersion() < 3) { + LOG(INFO) << "notifyRangingResults requires callback version 3"; + return; + } + + std::vector legacy_results; + std::copy_if(rtt_results, rtt_results + num_results, back_inserter(legacy_results), + [](wifi_rtt_result* rtt_result) { return rtt_result != nullptr; }); + + std::vector aidl_results; + if (!aidl_struct_util::convertLegacyVectorOfRttResultToAidl(legacy_results, + &aidl_results)) { + LOG(ERROR) << "Failed to convert RTT results to AIDL structs"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyRangingResults(aidl_results, session_id).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->nanRegisterCallbackHandlers(ifname_, callback_handlers); if (legacy_status != legacy_hal::WIFI_SUCCESS) { @@ -672,6 +701,10 @@ std::string WifiNanIface::getName() { return ifname_; } +int32_t WifiNanIface::getMinCallbackVersion() { + return event_cb_handler_.getMinCallbackVersion(); +} + std::set> WifiNanIface::getEventCallbacks() { LOG(ERROR) << "Using original getEventCallbacks"; return event_cb_handler_.getCallbacks(); diff --git a/wifi/aidl/default/wifi_nan_iface.h b/wifi/aidl/default/wifi_nan_iface.h index a49ae8c8c3883a81b69d97fdf76304eb052c9516..d2d1d5c2375b87704edd102a7e00fa5849adf5c1 100644 --- a/wifi/aidl/default/wifi_nan_iface.h +++ b/wifi/aidl/default/wifi_nan_iface.h @@ -134,6 +134,8 @@ class WifiNanIface : public BnWifiNanIface { ndk::ScopedAStatus suspendRequestInternal(char16_t in_cmdId, int8_t sessionId); ndk::ScopedAStatus resumeRequestInternal(char16_t in_cmdId, int8_t sessionId); + int32_t getMinCallbackVersion(); + // Overridden in the gTest suite. virtual std::set> getEventCallbacks(); diff --git a/wifi/aidl/vts/functional/Android.bp b/wifi/aidl/vts/functional/Android.bp index 9994d0979a809ae4e7d9fa5e7868d9494da4d503..429c0c5fe99b6c2d70fd4b85b150f2e4d448a784 100644 --- a/wifi/aidl/vts/functional/Android.bp +++ b/wifi/aidl/vts/functional/Android.bp @@ -40,8 +40,8 @@ cc_test { ], static_libs: [ "VtsHalWifiTargetTestUtil", - "android.hardware.wifi.common-V1-ndk", - "android.hardware.wifi-V2-ndk", + "android.hardware.wifi.common-V2-ndk", + "android.hardware.wifi-V3-ndk", "libwifi-system-iface", ], test_suites: [ @@ -66,8 +66,8 @@ cc_test { ], static_libs: [ "VtsHalWifiTargetTestUtil", - "android.hardware.wifi.common-V1-ndk", - "android.hardware.wifi-V2-ndk", + "android.hardware.wifi.common-V2-ndk", + "android.hardware.wifi-V3-ndk", "libwifi-system-iface", ], test_suites: [ @@ -92,8 +92,8 @@ cc_test { ], static_libs: [ "VtsHalWifiTargetTestUtil", - "android.hardware.wifi.common-V1-ndk", - "android.hardware.wifi-V2-ndk", + "android.hardware.wifi.common-V2-ndk", + "android.hardware.wifi-V3-ndk", "libwifi-system-iface", ], test_suites: [ @@ -118,8 +118,8 @@ cc_test { ], static_libs: [ "VtsHalWifiTargetTestUtil", - "android.hardware.wifi.common-V1-ndk", - "android.hardware.wifi-V2-ndk", + "android.hardware.wifi.common-V2-ndk", + "android.hardware.wifi-V3-ndk", "libwifi-system-iface", ], test_suites: [ @@ -144,8 +144,8 @@ cc_test { ], static_libs: [ "VtsHalWifiTargetTestUtil", - "android.hardware.wifi.common-V1-ndk", - "android.hardware.wifi-V2-ndk", + "android.hardware.wifi.common-V2-ndk", + "android.hardware.wifi-V3-ndk", "libwifi-system-iface", ], test_suites: [ @@ -169,8 +169,8 @@ cc_library_static { "libnativehelper", ], static_libs: [ - "android.hardware.wifi.common-V1-ndk", - "android.hardware.wifi-V2-ndk", + "android.hardware.wifi.common-V2-ndk", + "android.hardware.wifi-V3-ndk", "libwifi-system-iface", ], } diff --git a/wifi/aidl/vts/functional/wifi_nan_iface_aidl_test.cpp b/wifi/aidl/vts/functional/wifi_nan_iface_aidl_test.cpp index bc169a45b7f9a849f5dd9ea1cc34b777e318f6d5..d6461629ed1a23edcf7b5c4ca6770c7b891db9b0 100644 --- a/wifi/aidl/vts/functional/wifi_nan_iface_aidl_test.cpp +++ b/wifi/aidl/vts/functional/wifi_nan_iface_aidl_test.cpp @@ -58,6 +58,7 @@ using aidl::android::hardware::wifi::NanStatus; using aidl::android::hardware::wifi::NanStatusCode; using aidl::android::hardware::wifi::NanSuspensionModeChangeInd; using aidl::android::hardware::wifi::NanTxType; +using aidl::android::hardware::wifi::RttResult; #define TIMEOUT_PERIOD 10 @@ -106,6 +107,7 @@ class WifiNanIfaceAidlTest : public testing::TestWithParam { NOTIFY_SUSPEND_RESPONSE, NOTIFY_RESUME_RESPONSE, NOTIFY_TERMINATE_PAIRING_RESPONSE, + NOTIFY_RANGING_RESULTS, EVENT_CLUSTER_EVENT, EVENT_DISABLED, @@ -400,6 +402,12 @@ class WifiNanIfaceAidlTest : public testing::TestWithParam { parent_.notify(NOTIFY_TERMINATE_PAIRING_RESPONSE); return ndk::ScopedAStatus::ok(); } + ::ndk::ScopedAStatus notifyRangingResults(const std::vector& /* results */, + int8_t discoverySessionId) override { + parent_.session_id_ = discoverySessionId; + parent_.notify(NOTIFY_RANGING_RESULTS); + return ndk::ScopedAStatus::ok(); + } private: WifiNanIfaceAidlTest& parent_; diff --git a/wifi/common/aidl/Android.bp b/wifi/common/aidl/Android.bp index 0920a559c33d4ca3db740307abc0cda74ce93db6..8ea54bef55dc0b5b561fa4df4295c19cbfd322eb 100644 --- a/wifi/common/aidl/Android.bp +++ b/wifi/common/aidl/Android.bp @@ -54,6 +54,6 @@ aidl_interface { imports: [], }, ], - frozen: true, + frozen: false, } diff --git a/wifi/common/aidl/aidl_api/android.hardware.wifi.common/current/android/hardware/wifi/common/DeauthenticationReasonCode.aidl b/wifi/common/aidl/aidl_api/android.hardware.wifi.common/current/android/hardware/wifi/common/DeauthenticationReasonCode.aidl new file mode 100644 index 0000000000000000000000000000000000000000..2404b2c5d415f0572efe34763189c65ec98ddab8 --- /dev/null +++ b/wifi/common/aidl/aidl_api/android.hardware.wifi.common/current/android/hardware/wifi/common/DeauthenticationReasonCode.aidl @@ -0,0 +1,99 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.wifi.common; +@Backing(type="int") @VintfStability +enum DeauthenticationReasonCode { + HOSTAPD_NO_REASON = 0, + UNSPECIFIED = 1, + PREV_AUTH_NOT_VALID = 2, + DEAUTH_LEAVING = 3, + DISASSOC_DUE_TO_INACTIVITY = 4, + DISASSOC_AP_BUSY = 5, + CLASS2_FRAME_FROM_NONAUTH_STA = 6, + CLASS3_FRAME_FROM_NONASSOC_STA = 7, + DISASSOC_STA_HAS_LEFT = 8, + STA_REQ_ASSOC_WITHOUT_AUTH = 9, + PWR_CAPABILITY_NOT_VALID = 10, + SUPPORTED_CHANNEL_NOT_VALID = 11, + BSS_TRANSITION_DISASSOC = 12, + INVALID_IE = 13, + MICHAEL_MIC_FAILURE = 14, + FOURWAY_HANDSHAKE_TIMEOUT = 15, + GROUP_KEY_UPDATE_TIMEOUT = 16, + IE_IN_4WAY_DIFFERS = 17, + GROUP_CIPHER_NOT_VALID = 18, + PAIRWISE_CIPHER_NOT_VALID = 19, + AKMP_NOT_VALID = 20, + UNSUPPORTED_RSN_IE_VERSION = 21, + INVALID_RSN_IE_CAPAB = 22, + IEEE_802_1X_AUTH_FAILED = 23, + CIPHER_SUITE_REJECTED = 24, + TDLS_TEARDOWN_UNREACHABLE = 25, + TDLS_TEARDOWN_UNSPECIFIED = 26, + SSP_REQUESTED_DISASSOC = 27, + NO_SSP_ROAMING_AGREEMENT = 28, + BAD_CIPHER_OR_AKM = 29, + NOT_AUTHORIZED_THIS_LOCATION = 30, + SERVICE_CHANGE_PRECLUDES_TS = 31, + UNSPECIFIED_QOS_REASON = 32, + NOT_ENOUGH_BANDWIDTH = 33, + DISASSOC_LOW_ACK = 34, + EXCEEDED_TXOP = 35, + STA_LEAVING = 36, + END_TS_BA_DLS = 37, + UNKNOWN_TS_BA = 38, + TIMEOUT = 39, + PEERKEY_MISMATCH = 45, + AUTHORIZED_ACCESS_LIMIT_REACHED = 46, + EXTERNAL_SERVICE_REQUIREMENTS = 47, + INVALID_FT_ACTION_FRAME_COUNT = 48, + INVALID_PMKID = 49, + INVALID_MDE = 50, + INVALID_FTE = 51, + MESH_PEERING_CANCELLED = 52, + MESH_MAX_PEERS = 53, + MESH_CONFIG_POLICY_VIOLATION = 54, + MESH_CLOSE_RCVD = 55, + MESH_MAX_RETRIES = 56, + MESH_CONFIRM_TIMEOUT = 57, + MESH_INVALID_GTK = 58, + MESH_INCONSISTENT_PARAMS = 59, + MESH_INVALID_SECURITY_CAP = 60, + MESH_PATH_ERROR_NO_PROXY_INFO = 61, + MESH_PATH_ERROR_NO_FORWARDING_INFO = 62, + MESH_PATH_ERROR_DEST_UNREACHABLE = 63, + MAC_ADDRESS_ALREADY_EXISTS_IN_MBSS = 64, + MESH_CHANNEL_SWITCH_REGULATORY_REQ = 65, + MESH_CHANNEL_SWITCH_UNSPECIFIED = 66, +} diff --git a/wifi/common/aidl/android/hardware/wifi/common/DeauthenticationReasonCode.aidl b/wifi/common/aidl/android/hardware/wifi/common/DeauthenticationReasonCode.aidl new file mode 100644 index 0000000000000000000000000000000000000000..95eb31d6f0b6f51f19e21e612b89d2498879c5d7 --- /dev/null +++ b/wifi/common/aidl/android/hardware/wifi/common/DeauthenticationReasonCode.aidl @@ -0,0 +1,90 @@ +/* + * 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. + */ + +package android.hardware.wifi.common; + +/** + * Reason codes (IEEE Std 802.11-2016, 9.4.1.7, Table 9-45). + * + * Note: HOSTAPD_NO_REASON is the default return from hostapd, even though it + * does not appear in the IEEE spec. + */ +@VintfStability +@Backing(type="int") +enum DeauthenticationReasonCode { + HOSTAPD_NO_REASON = 0, + UNSPECIFIED = 1, + PREV_AUTH_NOT_VALID = 2, + DEAUTH_LEAVING = 3, + DISASSOC_DUE_TO_INACTIVITY = 4, + DISASSOC_AP_BUSY = 5, + CLASS2_FRAME_FROM_NONAUTH_STA = 6, + CLASS3_FRAME_FROM_NONASSOC_STA = 7, + DISASSOC_STA_HAS_LEFT = 8, + STA_REQ_ASSOC_WITHOUT_AUTH = 9, + PWR_CAPABILITY_NOT_VALID = 10, + SUPPORTED_CHANNEL_NOT_VALID = 11, + BSS_TRANSITION_DISASSOC = 12, + INVALID_IE = 13, + MICHAEL_MIC_FAILURE = 14, + FOURWAY_HANDSHAKE_TIMEOUT = 15, + GROUP_KEY_UPDATE_TIMEOUT = 16, + IE_IN_4WAY_DIFFERS = 17, + GROUP_CIPHER_NOT_VALID = 18, + PAIRWISE_CIPHER_NOT_VALID = 19, + AKMP_NOT_VALID = 20, + UNSUPPORTED_RSN_IE_VERSION = 21, + INVALID_RSN_IE_CAPAB = 22, + IEEE_802_1X_AUTH_FAILED = 23, + CIPHER_SUITE_REJECTED = 24, + TDLS_TEARDOWN_UNREACHABLE = 25, + TDLS_TEARDOWN_UNSPECIFIED = 26, + SSP_REQUESTED_DISASSOC = 27, + NO_SSP_ROAMING_AGREEMENT = 28, + BAD_CIPHER_OR_AKM = 29, + NOT_AUTHORIZED_THIS_LOCATION = 30, + SERVICE_CHANGE_PRECLUDES_TS = 31, + UNSPECIFIED_QOS_REASON = 32, + NOT_ENOUGH_BANDWIDTH = 33, + DISASSOC_LOW_ACK = 34, + EXCEEDED_TXOP = 35, + STA_LEAVING = 36, + END_TS_BA_DLS = 37, + UNKNOWN_TS_BA = 38, + TIMEOUT = 39, + PEERKEY_MISMATCH = 45, + AUTHORIZED_ACCESS_LIMIT_REACHED = 46, + EXTERNAL_SERVICE_REQUIREMENTS = 47, + INVALID_FT_ACTION_FRAME_COUNT = 48, + INVALID_PMKID = 49, + INVALID_MDE = 50, + INVALID_FTE = 51, + MESH_PEERING_CANCELLED = 52, + MESH_MAX_PEERS = 53, + MESH_CONFIG_POLICY_VIOLATION = 54, + MESH_CLOSE_RCVD = 55, + MESH_MAX_RETRIES = 56, + MESH_CONFIRM_TIMEOUT = 57, + MESH_INVALID_GTK = 58, + MESH_INCONSISTENT_PARAMS = 59, + MESH_INVALID_SECURITY_CAP = 60, + MESH_PATH_ERROR_NO_PROXY_INFO = 61, + MESH_PATH_ERROR_NO_FORWARDING_INFO = 62, + MESH_PATH_ERROR_DEST_UNREACHABLE = 63, + MAC_ADDRESS_ALREADY_EXISTS_IN_MBSS = 64, + MESH_CHANNEL_SWITCH_REGULATORY_REQ = 65, + MESH_CHANNEL_SWITCH_UNSPECIFIED = 66, +} diff --git a/wifi/hostapd/aidl/Android.bp b/wifi/hostapd/aidl/Android.bp index 88f4ef22f0e4d0837c55e5ccb77b3e777c187e1f..85d71f306882ea7f031a5b93cec747865846f861 100644 --- a/wifi/hostapd/aidl/Android.bp +++ b/wifi/hostapd/aidl/Android.bp @@ -29,7 +29,7 @@ aidl_interface { "android/hardware/wifi/hostapd/*.aidl", ], imports: [ - "android.hardware.wifi.common-V1", + "android.hardware.wifi.common-V2", ], stability: "vintf", backend: { @@ -41,7 +41,9 @@ aidl_interface { ], min_sdk_version: "30", lint: { - baseline_filename: "lint-baseline.xml", + // Disable linter to avoid error about fixed size arrays. + // Interface will only be accessed on devices >= T. + enabled: false, }, }, ndk: { diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/ApInfo.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/ApInfo.aidl index 1a66105b8f8373a0c6a567bc686699623711aa09..0af90d2276d60287920b3c73e2d35b61c39b0898 100644 --- a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/ApInfo.aidl +++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/ApInfo.aidl @@ -41,4 +41,5 @@ parcelable ApInfo { android.hardware.wifi.hostapd.Generation generation; byte[] apIfaceInstanceMacAddress; @nullable android.hardware.wifi.common.OuiKeyedData[] vendorData; + @nullable byte[6] mldMacAddress; } diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/ClientInfo.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/ClientInfo.aidl index c4d62b68cc5420e1ebe92d9e99858b52ba9f7f89..c4db789bd4cfea44fa1eaf4d45eb37108483c360 100644 --- a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/ClientInfo.aidl +++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/ClientInfo.aidl @@ -38,4 +38,5 @@ parcelable ClientInfo { String apIfaceInstance; byte[] clientAddress; boolean isConnected; + android.hardware.wifi.common.DeauthenticationReasonCode disconnectReasonCode; } diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/IHostapd.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/IHostapd.aidl index ff941fdbf767a86dc0dfdadd8c206719e2f96142..3898bb86b9750ae75123b8458980f8617b7ee096 100644 --- a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/IHostapd.aidl +++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/IHostapd.aidl @@ -40,4 +40,5 @@ interface IHostapd { void removeAccessPoint(in String ifaceName); void setDebugParams(in android.hardware.wifi.hostapd.DebugLevel level); oneway void terminate(); + void removeLinkFromMultipleLinkBridgedApIface(in String ifaceName, in String linkIdentity); } diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/IfaceParams.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/IfaceParams.aidl index 8da3441d9f3e96fc18dbe2e8bb08e8aa2d0eb381..7b6710233723d1f4da0c4221374f5f553ea88372 100644 --- a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/IfaceParams.aidl +++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/IfaceParams.aidl @@ -39,5 +39,5 @@ parcelable IfaceParams { android.hardware.wifi.hostapd.ChannelParams[] channelParams; @nullable android.hardware.wifi.common.OuiKeyedData[] vendorData; @nullable String[] instanceIdentities; - boolean isMlo; + boolean usesMlo; } diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/NetworkParams.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/NetworkParams.aidl index 45542237514190490eab0f561f5c4e2a30af0b62..b6c5cf20bd6162944b56e210a754eb432a619bf6 100644 --- a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/NetworkParams.aidl +++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/NetworkParams.aidl @@ -40,4 +40,5 @@ parcelable NetworkParams { String passphrase; boolean isMetered; byte[] vendorElements; + boolean isClientIsolationEnabled; } diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/ApInfo.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/ApInfo.aidl index f2b2ee68e5a14a01c3882a39de1f5b9eae58cd7d..8aea70cf5dfa800302c6334a97b96e670dfc60bb 100644 --- a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/ApInfo.aidl +++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/ApInfo.aidl @@ -63,4 +63,9 @@ parcelable ApInfo { * Optional vendor-specific information. */ @nullable OuiKeyedData[] vendorData; + + /** + * MAC Address of the multiple link device (MLD) which apIfaceInstance is associated with. + */ + @nullable byte[6] mldMacAddress; } diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/ClientInfo.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/ClientInfo.aidl index 7bed6584f4663235e33a547fbfb8ba805e3b3c4f..a7ca1ec9c5ce2c5b973395bd8e523f4e62e19c4b 100644 --- a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/ClientInfo.aidl +++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/ClientInfo.aidl @@ -16,6 +16,8 @@ package android.hardware.wifi.hostapd; +import android.hardware.wifi.common.DeauthenticationReasonCode; + /** * Parameters to control the channel selection for the interface. */ @@ -42,4 +44,9 @@ parcelable ClientInfo { * True when client connected, false when client disconnected. */ boolean isConnected; + + /** + * Reason for client disconnect from soft ap. + */ + DeauthenticationReasonCode disconnectReasonCode; } diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/IHostapd.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/IHostapd.aidl index d2f47953ba28802921625cd9f57d39d5bcc13276..cd552ab923304cd2ad244a4e5c82f54698c8f339 100644 --- a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/IHostapd.aidl +++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/IHostapd.aidl @@ -103,4 +103,22 @@ interface IHostapd { * wait to be restarted. */ oneway void terminate(); + + /** + * Removes an existing link from multiple link device which the current AP resides on. + * + * The multiple link device is an access point which was added by |IHostapd.addAccessPoint| with + * |IfaceParams.usesMlo| set to true. + * + * @param ifaceName Name of the interface which was added by |IHostapd.addAccessPoint| + * @param linkIdentity the identity of the link which associated to the multiple link device + * that the current AP resides on. The link identity should be one of the identities provided in + * |IfaceParams.instanceIdentities| when this iface was created. + * @throws ServiceSpecificException with one of the following values: + * |HostapdStatusCode.FAILURE_UNKNOWN|, + * |HostapdStatusCode.FAILURE_ARGS_INVALID| when the linkIdentity mis-matches one of the + * identities provided in |IfaceParams.instanceIdentities|. + * |HostapdStatusCode.FAILURE_IFACE_UNKNOWN| when current existing AP isn't using mlo. + */ + void removeLinkFromMultipleLinkBridgedApIface(in String ifaceName, in String linkIdentity); } diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/IfaceParams.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/IfaceParams.aidl index bb646e308d0ae5b4bdc39d430bed0d89eaee8a1c..f4e464770c53482ddae85153bc7d084b920272c4 100644 --- a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/IfaceParams.aidl +++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/IfaceParams.aidl @@ -46,7 +46,7 @@ parcelable IfaceParams { */ @nullable String[] instanceIdentities; /** - * Whether the current iface is MLO. + * Whether the current iface is using multi-link operation. */ - boolean isMlo; + boolean usesMlo; } diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/NetworkParams.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/NetworkParams.aidl index 47d9e6f96b1ed40d25d249227d9db03b3601e41c..acc2cad7ecb40a40813d31cb36a0a18965ac4593 100644 --- a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/NetworkParams.aidl +++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/NetworkParams.aidl @@ -52,4 +52,8 @@ parcelable NetworkParams { * one or more elements). Example: byte[]{ 221, 4, 17, 34, 51, 1 } */ byte[] vendorElements; + /** + * Whether the network uses client isolation. + */ + boolean isClientIsolationEnabled; } diff --git a/wifi/hostapd/aidl/lint-baseline.xml b/wifi/hostapd/aidl/lint-baseline.xml index 4329e1219f1c3358f0d903c8562b06d272ab1eea..23fe6905ccbfba34a89d78a884f7485206dda7a3 100644 --- a/wifi/hostapd/aidl/lint-baseline.xml +++ b/wifi/hostapd/aidl/lint-baseline.xml @@ -63,4 +63,22 @@ file="out/soong/.intermediates/hardware/interfaces/wifi/hostapd/aidl/android.hardware.wifi.hostapd-V3-java-source/gen/android/hardware/wifi/hostapd/IHostapdCallback.java"/> - \ No newline at end of file + + + + + + + + + diff --git a/wifi/hostapd/aidl/vts/functional/Android.bp b/wifi/hostapd/aidl/vts/functional/Android.bp index bf1b0d0e0afadc9b8459327b7ee31ef6ba69dad5..de31e14a417c6a3ae9646e3750857b4280faff14 100644 --- a/wifi/hostapd/aidl/vts/functional/Android.bp +++ b/wifi/hostapd/aidl/vts/functional/Android.bp @@ -37,8 +37,8 @@ cc_test { "android.hardware.wifi@1.4", "android.hardware.wifi@1.5", "android.hardware.wifi@1.6", - "android.hardware.wifi.common-V1-ndk", - "android.hardware.wifi-V2-ndk", + "android.hardware.wifi.common-V2-ndk", + "android.hardware.wifi-V3-ndk", "libwifi-system", "libwifi-system-iface", "VtsHalWifiTargetTestUtil", diff --git a/wifi/legacy_headers/include/hardware_legacy/rtt.h b/wifi/legacy_headers/include/hardware_legacy/rtt.h index 426abe08541fc92dae405f7c6afda13e4f12c151..3fa4e95b902d62d20500881917bc78f279b27463 100644 --- a/wifi/legacy_headers/include/hardware_legacy/rtt.h +++ b/wifi/legacy_headers/include/hardware_legacy/rtt.h @@ -7,24 +7,33 @@ /* Ranging status */ typedef enum { - RTT_STATUS_SUCCESS = 0, - RTT_STATUS_FAILURE = 1, // general failure status - RTT_STATUS_FAIL_NO_RSP = 2, // target STA does not respond to request - RTT_STATUS_FAIL_REJECTED = 3, // request rejected. Applies to 2-sided RTT only - RTT_STATUS_FAIL_NOT_SCHEDULED_YET = 4, - RTT_STATUS_FAIL_TM_TIMEOUT = 5, // timing measurement times out - RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL = 6, // Target on different channel, cannot range - RTT_STATUS_FAIL_NO_CAPABILITY = 7, // ranging not supported - RTT_STATUS_ABORTED = 8, // request aborted for unknown reason - RTT_STATUS_FAIL_INVALID_TS = 9, // Invalid T1-T4 timestamp - RTT_STATUS_FAIL_PROTOCOL = 10, // 11mc protocol failed - RTT_STATUS_FAIL_SCHEDULE = 11, // request could not be scheduled - RTT_STATUS_FAIL_BUSY_TRY_LATER = 12, // responder cannot collaborate at time of request - RTT_STATUS_INVALID_REQ = 13, // bad request args - RTT_STATUS_NO_WIFI = 14, // WiFi not enabled - RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE = 15, // Responder overrides param info, cannot range with new params - RTT_STATUS_NAN_RANGING_PROTOCOL_FAILURE =16, //Negotiation failure - RTT_STATUS_NAN_RANGING_CONCURRENCY_NOT_SUPPORTED=17, //concurrency not supported (NDP+RTT) + RTT_STATUS_SUCCESS = 0, + RTT_STATUS_FAILURE = 1, // general failure status + RTT_STATUS_FAIL_NO_RSP = 2, // target STA does not respond to request + RTT_STATUS_FAIL_REJECTED = 3, // request rejected. Applies to 2-sided RTT only + RTT_STATUS_FAIL_NOT_SCHEDULED_YET = 4, + RTT_STATUS_FAIL_TM_TIMEOUT = 5, // timing measurement times out + RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL = 6, // Target on different channel, cannot range + RTT_STATUS_FAIL_NO_CAPABILITY = 7, // ranging not supported + RTT_STATUS_ABORTED = 8, // request aborted for unknown reason + RTT_STATUS_FAIL_INVALID_TS = 9, // Invalid T1-T4 timestamp + RTT_STATUS_FAIL_PROTOCOL = 10, // 11mc protocol failed + RTT_STATUS_FAIL_SCHEDULE = 11, // request could not be scheduled + RTT_STATUS_FAIL_BUSY_TRY_LATER = 12, // responder cannot collaborate at time of request + RTT_STATUS_INVALID_REQ = 13, // bad request args + RTT_STATUS_NO_WIFI = 14, // WiFi not enabled + RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE = + 15, // Responder overrides param info, cannot range with new params + RTT_STATUS_NAN_RANGING_PROTOCOL_FAILURE = 16, // Negotiation failure + RTT_STATUS_NAN_RANGING_CONCURRENCY_NOT_SUPPORTED = 17, // concurrency not supported (NDP+RTT) + RTT_STATUS_SECURE_RANGING_FAILURE_INVALID_AKM = 18, // Secure Ranging failed due to invalid AKM + // (Authentication and Key Management) + RTT_STATUS_SECURE_RANGING_FAILURE_INVALID_CIPHER = 19, // Secure Ranging failed due to invalid + // Cipher + RTT_STATUS_SECURE_RANGING_FAILURE_INVALID_CONFIG = 20, // Secure Ranging failed due to invalid + // configuration + RTT_STATUS_SECURE_RANGING_FAILURE_REJECTED = 21, // Secure ranging rejected by the AP.2 + RTT_STATUS_SECURE_RANGING_FAILURE_UNKNOWN = 22, // Secure ranging failure unknown } wifi_rtt_status; /* RTT peer type */ @@ -60,14 +69,60 @@ typedef enum { /* RTT Type */ typedef enum { - RTT_TYPE_1_SIDED = 0x1, + RTT_TYPE_1_SIDED = 0x1, /* Deprecated. Use RTT_TYPE_2_SIDED_11MC instead. */ - RTT_TYPE_2_SIDED = 0x2, - RTT_TYPE_2_SIDED_11MC = RTT_TYPE_2_SIDED, + RTT_TYPE_2_SIDED = 0x2, + RTT_TYPE_2_SIDED_11MC = RTT_TYPE_2_SIDED, RTT_TYPE_2_SIDED_11AZ_NTB = 0x3, - + RTT_TYPE_2_SIDED_11AZ_NTB_SECURE = 0x4, } wifi_rtt_type; +/* RTT AKM type */ +typedef enum { + WPA_KEY_MGMT_NONE = 0x0, + WPA_KEY_MGMT_PASN = 0x1, + WPA_KEY_MGMT_SAE = 0x2, + WPA_KEY_MGMT_EAP_FT_SHA256 = 0x4, + WPA_KEY_MGMT_FT_PSK_SHA256 = 0x8, + WPA_KEY_MGMT_EAP_FT_SHA384 = 0x10, + WPA_KEY_MGMT_FT_PSK_SHA384 = 0x20, + WPA_KEY_MGMT_EAP_FILS_SHA256 = 0x40, + WPA_KEY_MGMT_EAP_FILS_SHA384 = 0x80 +} wifi_rtt_akm; + +typedef enum { + WPA_CIPHER_NONE = 0x0, + WPA_CIPHER_CCMP_128 = 0x1, + WPA_CIPHER_CCMP_256 = 0x2, + WPA_CIPHER_GCMP_128 = 0x4, + WPA_CIPHER_GCMP_256 = 0x8, +} wifi_rtt_cipher_suite; + +#define RTT_SECURITY_MAX_PASSPHRASE_LEN 63 +#define PMKID_LEN 16 +#define RTT_MAX_COOKIE_LEN 255 + +typedef struct { + wifi_rtt_akm base_akm; // Base Authentication and Key Management (AKM) protocol used for PASN + wifi_rtt_cipher_suite pairwise_cipher_suite; // Pairwise cipher suite used for the PTKSA + // (Pairwise Transient Key Security Association) + u32 passphrase_len; + u8 passphrase[RTT_SECURITY_MAX_PASSPHRASE_LEN]; // Passphrase for the base AKM. This can be + // empty based on the AKM type. + u32 pmkid_len; + u8 pmkid[PMKID_LEN]; // PMKID corresponding to the cached PMK from the base AKM. PMKID can be + // null if no cached PMK is present. + u8 comeback_cookie_len; // Comeback cookie length. If the length is 0, it indicates there is no + // cookie. + u8 comeback_cookie[RTT_MAX_COOKIE_LEN]; // Comeback cookie indicated over wifi_rtt_result_v4. +} wifi_rtt_pasn_config; + +typedef struct { + wifi_rtt_pasn_config pasn_config; + bool enable_secure_he_ltf; + bool enable_ranging_frame_protection; +} wifi_rtt_secure_config; + /* RTT configuration */ typedef struct { mac_addr addr; // peer device mac address @@ -127,6 +182,11 @@ typedef struct { // units of 10 milliseconds } wifi_rtt_config_v3; +typedef struct { + wifi_rtt_config_v3 rtt_config; + wifi_rtt_secure_config rtt_secure_config; +} wifi_rtt_config_v4; + /* RTT results */ typedef struct { mac_addr addr; // device mac address @@ -197,6 +257,19 @@ typedef struct { byte num_rx_sts; // Number of receive space-time streams used. } wifi_rtt_result_v3; +typedef struct { + wifi_rtt_result_v3 rtt_result_v3; + bool is_ranging_protection_enabled; + bool is_secure_he_ltf_enabled; + wifi_rtt_akm base_akm; + wifi_rtt_cipher_suite cipher_suite; + int secure_he_ltf_protocol_version; + u16 pasn_comeback_after_millis; // The time in milliseconds after which the non-AP STA is + // requested to retry the PASN authentication. + u8 pasn_comeback_cookie_len; // Comeback cookie length. If the length is 0, it indicates there + // is no cookie. + u8 pasn_comeback_cookie[RTT_MAX_COOKIE_LEN]; // Comeback cookie octets. +} wifi_rtt_result_v4; /* RTT result callbacks */ typedef struct { @@ -234,6 +307,15 @@ typedef struct { wifi_rtt_result_v3 *rtt_result_v3[]); } wifi_rtt_event_handler_v3; +/* RTT result v4 callback (secure ranging support) */ +typedef struct { + /* + * Called when vendor implementation supports sending RTT results version 4 (Added support for + * secure 11az ranging) + */ + void (*on_rtt_results_v4)(wifi_request_id id, unsigned num_results, + wifi_rtt_result_v4* rtt_result_v4[]); +} wifi_rtt_event_handler_v4; /* v3 API to request RTT measurement(11az support). */ wifi_error wifi_rtt_range_request_v3(wifi_request_id id, @@ -242,6 +324,11 @@ wifi_error wifi_rtt_range_request_v3(wifi_request_id id, wifi_rtt_config_v3 rtt_config_v3[], wifi_rtt_event_handler_v3 handler); +/* v4 API to request RTT measurement(11az security support). */ +wifi_error wifi_rtt_range_request_v4(wifi_request_id id, wifi_interface_handle iface, + unsigned num_rtt_config, wifi_rtt_config_v4 rtt_config_v4[], + wifi_rtt_event_handler_v4 handler); + /* API to cancel RTT measurements */ wifi_error wifi_rtt_range_cancel(wifi_request_id id, wifi_interface_handle iface, unsigned num_devices, mac_addr addr[]); @@ -313,10 +400,28 @@ typedef struct { byte ntb_responder_supported; // if 11az non-TB responder is supported } wifi_rtt_capabilities_v3; +/* RTT Capabilities v4 (11az secure support) */ +typedef struct { + wifi_rtt_capabilities_v3 rtt_capab_v3; + bool secure_he_ltf_supported; + int max_supported_secure_he_ltf_protocol_ver; // Maximum supported secure HE-LTF protocol + // version. + bool ranging_fame_protection_supported; + wifi_rtt_akm supported_akms; // Bitmap of wifi_rtt_akm values indicating the set of supported + // AKMs. + wifi_rtt_cipher_suite + supported_cipher_suites; // Bitmap of wifi_rtt_cipher_suite values + // indicating the set of supported pairwise cipher suites. +} wifi_rtt_capabilities_v4; + /* RTT capabilities v3 of the device (11az support) */ wifi_error wifi_get_rtt_capabilities_v3(wifi_interface_handle iface, wifi_rtt_capabilities_v3 *capabilities); +/* RTT capabilities v4 of the device (11az secure support) */ +wifi_error wifi_get_rtt_capabilities_v4(wifi_interface_handle iface, + wifi_rtt_capabilities_v4* capabilities); + /* debugging definitions */ enum { RTT_DEBUG_DISABLE, diff --git a/wifi/legacy_headers/include/hardware_legacy/wifi_hal.h b/wifi/legacy_headers/include/hardware_legacy/wifi_hal.h index 9baa2c7809b0299e407490843703bf0ea27a2e7b..c68cdf67260045818c7fc1b690e68423d007539b 100644 --- a/wifi/legacy_headers/include/hardware_legacy/wifi_hal.h +++ b/wifi/legacy_headers/include/hardware_legacy/wifi_hal.h @@ -494,6 +494,7 @@ void wifi_get_error_info(wifi_error err, const char **msg); // return a pointer #define WIFI_FEATURE_ROAMING_MODE_CONTROL (uint64_t)0x800000000 // Support for configuring roaming mode #define WIFI_FEATURE_SET_VOIP_MODE (uint64_t)0x1000000000 // Support Voip mode setting #define WIFI_FEATURE_CACHED_SCAN_RESULTS (uint64_t)0x2000000000 // Support cached scan result report +#define WIFI_FEATURE_MLO_SAP (uint64_t)0x4000000000 // Support MLO SoftAp // Add more features here #define IS_MASK_SET(mask, flags) (((flags) & (mask)) == (mask)) diff --git a/wifi/legacy_headers/include/hardware_legacy/wifi_nan.h b/wifi/legacy_headers/include/hardware_legacy/wifi_nan.h index 4e490d98d04223e1c2e6e53829806074cac69823..cd4e86d3a02e752f814f1728cc226132df976cf5 100644 --- a/wifi/legacy_headers/include/hardware_legacy/wifi_nan.h +++ b/wifi/legacy_headers/include/hardware_legacy/wifi_nan.h @@ -19,6 +19,7 @@ #include #include +#include "rtt.h" #include "wifi_hal.h" #ifdef __cplusplus @@ -476,6 +477,9 @@ typedef struct { bool is_pairing_supported; bool is_set_cluster_id_supported; bool is_suspension_supported; + bool is_periodic_ranging_supported; + wifi_rtt_bw supported_bw; + u8 num_rx_chains_supported; } NanCapabilities; /* @@ -746,6 +750,12 @@ typedef struct { u32 distance_ingress_mm; /* Egress distance in millmilliimeters (optional) */ u32 distance_egress_mm; + /* Number of FTM frames per burst */ + u32 rtt_burst_size; + /* RTT Measurement Preamble */ + wifi_rtt_preamble preamble; + /* Channel information */ + wifi_channel_info channel_info; } NanRangingCfg; /* NAN Ranging request's response */ @@ -3103,6 +3113,7 @@ typedef struct { void (*EventBootstrappingRequest) (NanBootstrappingRequestInd* event); void (*EventBootstrappingConfirm) (NanBootstrappingConfirmInd* event); void (*EventSuspensionModeChange) (NanSuspensionModeChangeInd* event); + void (*EventRangingResults)(wifi_rtt_result* rtt_result[], u32 num_results, u16 session_id); } NanCallbackHandler; /**@brief nan_enable_request diff --git a/wifi/supplicant/aidl/Android.bp b/wifi/supplicant/aidl/Android.bp index 8d16cb79663ab57037d9b76a287cf5c83849e933..1fbe8e92824ad2cb58d8c066cb0aecd4753850ae 100644 --- a/wifi/supplicant/aidl/Android.bp +++ b/wifi/supplicant/aidl/Android.bp @@ -29,7 +29,7 @@ aidl_interface { "android/hardware/wifi/supplicant/*.aidl", ], imports: [ - "android.hardware.wifi.common-V1", + "android.hardware.wifi.common-V2", ], stability: "vintf", backend: { diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BandMask.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BandMask.aidl new file mode 100644 index 0000000000000000000000000000000000000000..6d16580d3a1127c54fd8e97243bd600de7f247aa --- /dev/null +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BandMask.aidl @@ -0,0 +1,40 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.wifi.supplicant; +@VintfStability +parcelable BandMask { + const int BAND_2_GHZ = (1 << 0) /* 1 */; + const int BAND_5_GHZ = (1 << 1) /* 2 */; + const int BAND_6_GHZ = (1 << 2) /* 4 */; +} diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl index 0b068e001f3d3ef75c76c538e29237ff1060ef3a..c584d576218f196d991b91c0306810b3d1f98261 100644 --- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl @@ -74,8 +74,14 @@ interface ISupplicantP2pIface { android.hardware.wifi.supplicant.IfaceType getType(); void invite(in String groupIfName, in byte[] goDeviceAddress, in byte[] peerAddress); int[] listNetworks(); + /** + * @deprecated This method is deprecated from AIDL v4, newer HALs should use provisionDiscoveryWithParams. + */ void provisionDiscovery(in byte[] peerAddress, in android.hardware.wifi.supplicant.WpsProvisionMethod provisionMethod); void registerCallback(in android.hardware.wifi.supplicant.ISupplicantP2pIfaceCallback callback); + /** + * @deprecated This method is deprecated from AIDL v4, newer HALs should use reinvokePersistentGroup. + */ void reinvoke(in int persistentNetworkId, in byte[] peerAddress); void reject(in byte[] peerAddress); void removeBonjourService(in byte[] query); @@ -123,4 +129,15 @@ interface ISupplicantP2pIface { void configureExtListenWithParams(in android.hardware.wifi.supplicant.P2pExtListenInfo extListenInfo); void addGroupWithConfigurationParams(in android.hardware.wifi.supplicant.P2pAddGroupConfigurationParams groupConfigurationParams); void createGroupOwner(in android.hardware.wifi.supplicant.P2pCreateGroupOwnerInfo groupOwnerInfo); + long getFeatureSet(); + int startUsdBasedServiceDiscovery(in android.hardware.wifi.supplicant.P2pUsdBasedServiceDiscoveryConfig serviceDiscoveryConfig); + void stopUsdBasedServiceDiscovery(in int sessionId); + int startUsdBasedServiceAdvertisement(in android.hardware.wifi.supplicant.P2pUsdBasedServiceAdvertisementConfig serviceAdvertisementConfig); + void stopUsdBasedServiceAdvertisement(in int sessionId); + void provisionDiscoveryWithParams(in android.hardware.wifi.supplicant.P2pProvisionDiscoveryParams params); + android.hardware.wifi.supplicant.P2pDirInfo getDirInfo(); + int validateDirInfo(in android.hardware.wifi.supplicant.P2pDirInfo dirInfo); + void reinvokePersistentGroup(in android.hardware.wifi.supplicant.P2pReinvokePersistentGroupParams reinvokeGroupParams); + const long P2P_FEATURE_V2 = (1 << 0) /* 1 */; + const long P2P_FEATURE_PCC_MODE_WPA3_COMPATIBILITY = (1 << 1) /* 2 */; } diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl index 65ad4c1407bb63ea7e2fe1fbaf230a247b3b1586..3b283b8feaed82dc57ac69fdec6c8932b0df2428 100644 --- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl @@ -80,4 +80,7 @@ interface ISupplicantP2pIfaceCallback { oneway void onDeviceFoundWithParams(in android.hardware.wifi.supplicant.P2pDeviceFoundEventParams deviceFoundEventParams); oneway void onGoNegotiationRequestWithParams(in android.hardware.wifi.supplicant.P2pGoNegotiationReqEventParams params); oneway void onInvitationReceivedWithParams(in android.hardware.wifi.supplicant.P2pInvitationEventParams params); + oneway void onUsdBasedServiceDiscoveryResult(in android.hardware.wifi.supplicant.P2pUsdBasedServiceDiscoveryResultParams params); + oneway void onUsdBasedServiceDiscoveryTerminated(in int sessionId, in android.hardware.wifi.supplicant.UsdTerminateReasonCode reasonCode); + oneway void onUsdBasedServiceAdvertisementTerminated(in int sessionId, in android.hardware.wifi.supplicant.UsdTerminateReasonCode reasonCode); } diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl index 917668e9ab03c9909558239537b4e18eed63cc0f..cb96dfcca521e33c272e3541f6415e8f6a405b4f 100644 --- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl @@ -103,5 +103,12 @@ interface ISupplicantStaIface { android.hardware.wifi.supplicant.QosPolicyScsRequestStatus[] removeQosPolicyForScs(in byte[] scsPolicyIds); void configureMscs(in android.hardware.wifi.supplicant.MscsParams params); void disableMscs(); + android.hardware.wifi.supplicant.UsdCapabilities getUsdCapabilities(); + void startUsdPublish(in int cmdId, in android.hardware.wifi.supplicant.UsdPublishConfig usdPublishConfig); + void startUsdSubscribe(in int cmdId, in android.hardware.wifi.supplicant.UsdSubscribeConfig usdSubscribeConfig); + void updateUsdPublish(in int publishId, in byte[] serviceSpecificInfo); + void cancelUsdPublish(in int publishId); + void cancelUsdSubscribe(in int subscribeId); + void sendUsdMessage(in android.hardware.wifi.supplicant.UsdMessageInfo messageInfo); const int MAX_POLICIES_PER_QOS_SCS_REQUEST = 16; } diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl index 9fa8f56cd58c0d0b4f1aef3047a919df70a3f22b..1eb07d527d4c47eeecc938accd7346789e392e52 100644 --- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl @@ -82,9 +82,19 @@ interface ISupplicantStaIfaceCallback { oneway void onSupplicantStateChanged(in android.hardware.wifi.supplicant.SupplicantStateChangeData stateChangeData); oneway void onQosPolicyResponseForScs(in android.hardware.wifi.supplicant.QosPolicyScsResponseStatus[] qosPolicyScsResponseStatus); oneway void onPmkSaCacheAdded(in android.hardware.wifi.supplicant.PmkSaCacheData pmkSaData); + oneway void onUsdPublishStarted(in int cmdId, in int publishId); + oneway void onUsdSubscribeStarted(in int cmdId, in int subscribeId); + oneway void onUsdPublishConfigFailed(in int cmdId); + oneway void onUsdSubscribeConfigFailed(in int cmdId); + oneway void onUsdPublishTerminated(in int publishId, in android.hardware.wifi.supplicant.UsdReasonCode reasonCode); + oneway void onUsdSubscribeTerminated(in int subscribeId, in android.hardware.wifi.supplicant.UsdReasonCode reasonCode); + oneway void onUsdPublishReplied(in android.hardware.wifi.supplicant.UsdServiceDiscoveryInfo info); + oneway void onUsdServiceDiscovered(in android.hardware.wifi.supplicant.UsdServiceDiscoveryInfo info); + oneway void onUsdMessageReceived(in android.hardware.wifi.supplicant.UsdMessageInfo messageInfo); @Backing(type="int") @VintfStability enum MloLinkInfoChangeReason { TID_TO_LINK_MAP = 0, MULTI_LINK_RECONFIG_AP_REMOVAL = 1, + MULTI_LINK_DYNAMIC_RECONFIG = 2, } } diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MloLink.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MloLink.aidl index 8bda3242b31e98589e4249958a698c53108e55ad..05226c8000dc2c6fe3bcfc1d8c4c84da89263fb2 100644 --- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MloLink.aidl +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MloLink.aidl @@ -40,4 +40,5 @@ parcelable MloLink { byte tidsDownlinkMap; @nullable byte[6] apLinkMacAddress; int frequencyMHz; + android.hardware.wifi.supplicant.WifiChannelWidthInMhz channelBandwidth; } diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pConnectInfo.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pConnectInfo.aidl index f4662de122dbd8553e5cca2a61917d160f464665..a88a8290dc905f8676ec192aba1c3215050f47ea 100644 --- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pConnectInfo.aidl +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pConnectInfo.aidl @@ -41,4 +41,9 @@ parcelable P2pConnectInfo { boolean persistent; int goIntent; @nullable android.hardware.wifi.common.OuiKeyedData[] vendorData; + int pairingBootstrappingMethod; + @nullable String password; + int frequencyMHz; + boolean authorizeConnectionFromPeer; + @nullable String groupInterfaceName; } diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pCreateGroupOwnerInfo.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pCreateGroupOwnerInfo.aidl index 4451fb55effa47a04c3a2fcf2edc76aaed6d099a..901b9d1dd39b2158b05985347044772c65695993 100644 --- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pCreateGroupOwnerInfo.aidl +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pCreateGroupOwnerInfo.aidl @@ -37,4 +37,5 @@ parcelable P2pCreateGroupOwnerInfo { boolean persistent; int persistentNetworkId; @nullable android.hardware.wifi.common.OuiKeyedData[] vendorData; + boolean isP2pV2; } diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pDeviceFoundEventParams.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pDeviceFoundEventParams.aidl index ee8e6dc186b800efc7ed4f3bb589c3e2b522ca02..184fbd09844aec6c251f22b8204f6b9d2bac387a 100644 --- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pDeviceFoundEventParams.aidl +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pDeviceFoundEventParams.aidl @@ -45,4 +45,6 @@ parcelable P2pDeviceFoundEventParams { byte[] wfdR2DeviceInfo; byte[] vendorElemBytes; @nullable android.hardware.wifi.common.OuiKeyedData[] vendorData; + int pairingBootstrappingMethods; + @nullable android.hardware.wifi.supplicant.P2pDirInfo dirInfo; } diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pDirInfo.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pDirInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..2c55410fe017f9d16d29f5d9c3065d24523c0afa --- /dev/null +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pDirInfo.aidl @@ -0,0 +1,46 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.wifi.supplicant; +@VintfStability +parcelable P2pDirInfo { + android.hardware.wifi.supplicant.P2pDirInfo.CipherVersion cipherVersion; + byte[6] deviceInterfaceMacAddress; + byte[] nonce; + byte[] dirTag; + @Backing(type="int") @VintfStability + enum CipherVersion { + NONE, + DIRA_CIPHER_VERSION_128_BIT, + } +} diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pGroupStartedEventParams.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pGroupStartedEventParams.aidl index e19ae4460d53c43a383ddf3070d558cc3766accd..227626c9d1a048befc807c2d498b02683870d28b 100644 --- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pGroupStartedEventParams.aidl +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pGroupStartedEventParams.aidl @@ -46,4 +46,5 @@ parcelable P2pGroupStartedEventParams { boolean isP2pClientEapolIpAddressInfoPresent; android.hardware.wifi.supplicant.P2pClientEapolIpAddressInfo p2pClientIpInfo; @nullable android.hardware.wifi.common.OuiKeyedData[] vendorData; + int keyMgmtMask; } diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pPairingBootstrappingMethodMask.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pPairingBootstrappingMethodMask.aidl new file mode 100644 index 0000000000000000000000000000000000000000..182c0914bfbe4accb716e7b7745e4bdb99975151 --- /dev/null +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pPairingBootstrappingMethodMask.aidl @@ -0,0 +1,43 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.wifi.supplicant; +@VintfStability +parcelable P2pPairingBootstrappingMethodMask { + const int BOOTSTRAPPING_OPPORTUNISTIC = (1 << 0) /* 1 */; + const int BOOTSTRAPPING_DISPLAY_PINCODE = (1 << 1) /* 2 */; + const int BOOTSTRAPPING_DISPLAY_PASSPHRASE = (1 << 2) /* 4 */; + const int BOOTSTRAPPING_KEYPAD_PINCODE = (1 << 3) /* 8 */; + const int BOOTSTRAPPING_KEYPAD_PASSPHRASE = (1 << 4) /* 16 */; + const int BOOTSTRAPPING_OUT_OF_BAND = (1 << 5) /* 32 */; +} diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pPeerClientJoinedEventParams.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pPeerClientJoinedEventParams.aidl index 40c8ff6d8a4e54c29934b361f7d07df8b5a68a08..578176a40a072f154d3f43e0be0c371b0824a617 100644 --- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pPeerClientJoinedEventParams.aidl +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pPeerClientJoinedEventParams.aidl @@ -39,4 +39,5 @@ parcelable P2pPeerClientJoinedEventParams { byte[6] clientDeviceAddress; int clientIpAddress; @nullable android.hardware.wifi.common.OuiKeyedData[] vendorData; + int keyMgmtMask; } diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pProvisionDiscoveryCompletedEventParams.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pProvisionDiscoveryCompletedEventParams.aidl index 46366cc8d3a1ed3552992209c60e27234921c9d8..60da9246cad88d5a1d6f255192d80d88cf673c7c 100644 --- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pProvisionDiscoveryCompletedEventParams.aidl +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pProvisionDiscoveryCompletedEventParams.aidl @@ -41,4 +41,6 @@ parcelable P2pProvisionDiscoveryCompletedEventParams { String generatedPin; String groupInterfaceName; @nullable android.hardware.wifi.common.OuiKeyedData[] vendorData; + int pairingBootstrappingMethod; + @nullable String password; } diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pProvisionDiscoveryParams.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pProvisionDiscoveryParams.aidl new file mode 100644 index 0000000000000000000000000000000000000000..b5dc4b14abe0afc672b4b316295aa20d6c9e6369 --- /dev/null +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pProvisionDiscoveryParams.aidl @@ -0,0 +1,40 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.wifi.supplicant; +@VintfStability +parcelable P2pProvisionDiscoveryParams { + byte[6] peerMacAddress; + android.hardware.wifi.supplicant.WpsProvisionMethod provisionMethod; + int pairingBootstrappingMethod; +} diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pReinvokePersistentGroupParams.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pReinvokePersistentGroupParams.aidl new file mode 100644 index 0000000000000000000000000000000000000000..0743a6435659c5264a868049d649a283ed0828b1 --- /dev/null +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pReinvokePersistentGroupParams.aidl @@ -0,0 +1,40 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.wifi.supplicant; +@VintfStability +parcelable P2pReinvokePersistentGroupParams { + byte[6] peerMacAddress; + int persistentNetworkId; + int deviceIdentityEntryId; +} diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pUsdBasedServiceAdvertisementConfig.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pUsdBasedServiceAdvertisementConfig.aidl new file mode 100644 index 0000000000000000000000000000000000000000..36ce742979b47105ae2fc260cb3ede19719084c8 --- /dev/null +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pUsdBasedServiceAdvertisementConfig.aidl @@ -0,0 +1,42 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.wifi.supplicant; +@VintfStability +parcelable P2pUsdBasedServiceAdvertisementConfig { + String serviceName; + int serviceProtocolType; + byte[] serviceSpecificInfo; + int frequencyMHz; + int timeoutInSeconds; +} diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pUsdBasedServiceDiscoveryConfig.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pUsdBasedServiceDiscoveryConfig.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a13d10795ec21910b77b8b2a83fe05d8e0a7254a --- /dev/null +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pUsdBasedServiceDiscoveryConfig.aidl @@ -0,0 +1,43 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.wifi.supplicant; +@VintfStability +parcelable P2pUsdBasedServiceDiscoveryConfig { + String serviceName; + int serviceProtocolType; + byte[] serviceSpecificInfo; + int bandMask; + int[] frequencyListMhz; + int timeoutInSeconds; +} diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pUsdBasedServiceDiscoveryResultParams.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pUsdBasedServiceDiscoveryResultParams.aidl new file mode 100644 index 0000000000000000000000000000000000000000..da129cf5dde872045886f98d677c027ee4aa7a84 --- /dev/null +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pUsdBasedServiceDiscoveryResultParams.aidl @@ -0,0 +1,42 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.wifi.supplicant; +@VintfStability +parcelable P2pUsdBasedServiceDiscoveryResultParams { + byte[6] peerMacAddress; + int sessionId; + int peerSessionId; + int serviceProtocolType; + byte[] serviceSpecificInfo; +} diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/PmkSaCacheData.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/PmkSaCacheData.aidl index c31b16756c8bb822c29d0a119d0482111d0376f0..b1269badda4126ff72deff0fb454ecb4e496e56e 100644 --- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/PmkSaCacheData.aidl +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/PmkSaCacheData.aidl @@ -37,4 +37,5 @@ parcelable PmkSaCacheData { byte[6] bssid; long expirationTimeInSec; byte[] serializedEntry; + @nullable byte[] pmkid; } diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/SupplicantStatusCode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/SupplicantStatusCode.aidl index d7ff7982b54cb8d87dff3a8579004a1c9d8dd472..8675ab3e0804ddc3d74aab17050c003e06cd110c 100644 --- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/SupplicantStatusCode.aidl +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/SupplicantStatusCode.aidl @@ -46,4 +46,5 @@ enum SupplicantStatusCode { FAILURE_NETWORK_UNKNOWN, FAILURE_UNSUPPORTED, FAILURE_ONGOING_REQUEST, + FAILURE_DATA_NOT_AVAILABLE, } diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdBaseConfig.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdBaseConfig.aidl new file mode 100644 index 0000000000000000000000000000000000000000..8d239227f8f73e7bd838636eeaf17535c8275bc1 --- /dev/null +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdBaseConfig.aidl @@ -0,0 +1,45 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.wifi.supplicant; +@VintfStability +parcelable UsdBaseConfig { + @utf8InCpp String serviceName; + android.hardware.wifi.supplicant.UsdServiceProtoType serviceProtoType; + byte[] serviceSpecificInfo; + @nullable byte[] txMatchFilter; + @nullable byte[] rxMatchfilter; + int ttlSec; + int defaultFreqMhz; + int[] freqsMhz; +} diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdCapabilities.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdCapabilities.aidl new file mode 100644 index 0000000000000000000000000000000000000000..1c5ad676d88d4e625e834737c185f22400ab3a8f --- /dev/null +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdCapabilities.aidl @@ -0,0 +1,44 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.wifi.supplicant; +@VintfStability +parcelable UsdCapabilities { + boolean isUsdPublisherSupported; + boolean isUsdSubscriberSupported; + int maxLocalSsiLengthBytes; + int maxServiceNameLengthBytes; + int maxMatchFilterLengthBytes; + int maxNumPublishSessions; + int maxNumSubscribeSessions; +} diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdMessageInfo.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdMessageInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..40468bd226195baca9d18a06c8ce3cf7968d4e98 --- /dev/null +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdMessageInfo.aidl @@ -0,0 +1,41 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.wifi.supplicant; +@VintfStability +parcelable UsdMessageInfo { + int ownId; + int peerId; + byte[6] peerMacAddress; + byte[] message; +} diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdPublishConfig.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdPublishConfig.aidl new file mode 100644 index 0000000000000000000000000000000000000000..791de5243a22cccfeee35fc43e5d4ae3a5be6def --- /dev/null +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdPublishConfig.aidl @@ -0,0 +1,47 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.wifi.supplicant; +@VintfStability +parcelable UsdPublishConfig { + android.hardware.wifi.supplicant.UsdBaseConfig usdBaseConfig; + android.hardware.wifi.supplicant.UsdPublishConfig.PublishType publishType; + boolean isFsd; + int announcementPeriodMillis; + android.hardware.wifi.supplicant.UsdPublishTransmissionType transmissionType; + enum PublishType { + SOLICITED_ONLY = 0, + UNSOLICITED_ONLY = 1, + SOLICITED_AND_UNSOLICITED = 2, + } +} diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdPublishTransmissionType.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdPublishTransmissionType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..9486cd0ef04dd6182a11848cd624ff7d23fdf2ae --- /dev/null +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdPublishTransmissionType.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.wifi.supplicant; +@Backing(type="int") @VintfStability +enum UsdPublishTransmissionType { + UNICAST = 0, + MULTICAST = 1, +} diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdReasonCode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdReasonCode.aidl new file mode 100644 index 0000000000000000000000000000000000000000..0600defd4e029b9e386e74da75b30e02e65dd329 --- /dev/null +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdReasonCode.aidl @@ -0,0 +1,41 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.wifi.supplicant; +@Backing(type="int") @VintfStability +enum UsdReasonCode { + FAILURE_UNKNOWN = 0, + TIMEOUT = 1, + USER_REQUESTED = 2, + INVALID_ARGS = 3, +} diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdServiceDiscoveryInfo.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdServiceDiscoveryInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..3940ece53d0902f316f003068d1e3e513a47dcce --- /dev/null +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdServiceDiscoveryInfo.aidl @@ -0,0 +1,44 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.wifi.supplicant; +@VintfStability +parcelable UsdServiceDiscoveryInfo { + int ownId; + int peerId; + byte[6] peerMacAddress; + byte[] matchFilter; + android.hardware.wifi.supplicant.UsdServiceProtoType protoType; + byte[] serviceSpecificInfo; + boolean isFsd; +} diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdServiceProtoType.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdServiceProtoType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..4d4a4f501b54b401ca633486d85a3c76a041be17 --- /dev/null +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdServiceProtoType.aidl @@ -0,0 +1,40 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.wifi.supplicant; +@Backing(type="int") @VintfStability +enum UsdServiceProtoType { + UNKNOWN = 0, + GENERIC = 1, + CSA_MATTER = 2, +} diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdSubscribeConfig.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdSubscribeConfig.aidl new file mode 100644 index 0000000000000000000000000000000000000000..6aede8c5e328e876eca52c27c611da9cd9d70f1a --- /dev/null +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdSubscribeConfig.aidl @@ -0,0 +1,44 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.wifi.supplicant; +@VintfStability +parcelable UsdSubscribeConfig { + android.hardware.wifi.supplicant.UsdBaseConfig usdBaseConfig; + android.hardware.wifi.supplicant.UsdSubscribeConfig.SubscribeType subscribeType; + int queryPeriodMillis; + enum SubscribeType { + PASSIVE_MODE = 0, + ACTIVE_MODE = 1, + } +} diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdTerminateReasonCode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdTerminateReasonCode.aidl new file mode 100644 index 0000000000000000000000000000000000000000..0f8478335766c089892ab7fc2edbdacf2eb8cb1c --- /dev/null +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdTerminateReasonCode.aidl @@ -0,0 +1,41 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.wifi.supplicant; +@Backing(type="int") @VintfStability +enum UsdTerminateReasonCode { + UNKNOWN = 0, + TIMEOUT = 1, + USER_REQUEST = 2, + FAILURE = 3, +} diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WifiChannelWidthInMhz.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WifiChannelWidthInMhz.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e36c4f2ec014048670a2ee83b223a9d3fa5bb83a --- /dev/null +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WifiChannelWidthInMhz.aidl @@ -0,0 +1,46 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.wifi.supplicant; +@Backing(type="int") @VintfStability +enum WifiChannelWidthInMhz { + WIDTH_INVALID = (-1) /* -1 */, + WIDTH_20 = 0, + WIDTH_40 = 1, + WIDTH_80 = 2, + WIDTH_160 = 3, + WIDTH_80P80 = 4, + WIDTH_5 = 5, + WIDTH_10 = 6, + WIDTH_320 = 7, +} diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsProvisionMethod.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsProvisionMethod.aidl index 177d218db3801bfb71b4264dd522e03d3f1c7dd0..58ac0eb0c72eedb3ac1d2ad962c5acf9f95ea631 100644 --- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsProvisionMethod.aidl +++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsProvisionMethod.aidl @@ -34,6 +34,7 @@ package android.hardware.wifi.supplicant; @Backing(type="int") @VintfStability enum WpsProvisionMethod { + NONE = (-1) /* -1 */, PBC, DISPLAY, KEYPAD, diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BandMask.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BandMask.aidl new file mode 100644 index 0000000000000000000000000000000000000000..6d1b2be0ae89d06986cff35e8e3078913c919f30 --- /dev/null +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BandMask.aidl @@ -0,0 +1,36 @@ +/* + * 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. + */ + +package android.hardware.wifi.supplicant; + +/** + * Wifi bands + */ +@VintfStability +parcelable BandMask { + /** + * 2.4 GHz band. + */ + const int BAND_2_GHZ = 1 << 0; + /** + * 5 GHz band. + */ + const int BAND_5_GHZ = 1 << 1; + /** + * 6 GHz band. + */ + const int BAND_6_GHZ = 1 << 2; +} diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl index 12307935ac488b43c1852faf330425f72678241a..75e65ffccc0c4ff62768b2becf4195f4c6dd56fd 100644 --- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl @@ -25,10 +25,15 @@ import android.hardware.wifi.supplicant.MiracastMode; import android.hardware.wifi.supplicant.P2pAddGroupConfigurationParams; import android.hardware.wifi.supplicant.P2pConnectInfo; import android.hardware.wifi.supplicant.P2pCreateGroupOwnerInfo; +import android.hardware.wifi.supplicant.P2pDirInfo; import android.hardware.wifi.supplicant.P2pDiscoveryInfo; import android.hardware.wifi.supplicant.P2pExtListenInfo; import android.hardware.wifi.supplicant.P2pFrameTypeMask; import android.hardware.wifi.supplicant.P2pGroupCapabilityMask; +import android.hardware.wifi.supplicant.P2pProvisionDiscoveryParams; +import android.hardware.wifi.supplicant.P2pReinvokePersistentGroupParams; +import android.hardware.wifi.supplicant.P2pUsdBasedServiceAdvertisementConfig; +import android.hardware.wifi.supplicant.P2pUsdBasedServiceDiscoveryConfig; import android.hardware.wifi.supplicant.WpsConfigMethods; import android.hardware.wifi.supplicant.WpsProvisionMethod; @@ -38,6 +43,15 @@ import android.hardware.wifi.supplicant.WpsProvisionMethod; */ @VintfStability interface ISupplicantP2pIface { + /** + * P2P features exposed by wpa_supplicant/chip. + */ + /* Support for P2P2 (Wi-Fi Alliance P2P v2.0) */ + const long P2P_FEATURE_V2 = 1 << 0; + + /* Support for WPA3 Compatibility Mode in PCC Mode */ + const long P2P_FEATURE_PCC_MODE_WPA3_COMPATIBILITY = 1 << 1; + /** * This command can be used to add a bonjour service. * @@ -398,6 +412,9 @@ interface ISupplicantP2pIface { * Send P2P provision discovery request to the specified peer. The * parameters for this command are the P2P device address of the peer and the * desired configuration method. + *

+ * @deprecated This method is deprecated from AIDL v4, newer HALs should use + * provisionDiscoveryWithParams. * * @param peerAddress MAC address of the device to send discovery. * @method provisionMethod Provisioning method to use. @@ -424,6 +441,9 @@ interface ISupplicantP2pIface { /** * Reinvoke a device from a persistent group. + *

+ * @deprecated This method is deprecated from AIDL v4, newer HALs should use + * reinvokePersistentGroup. * * @param persistentNetworkId Used to specify the persistent group. * @param peerAddress MAC address of the device to reinvoke. @@ -938,4 +958,111 @@ interface ISupplicantP2pIface { * |SupplicantStatusCode.FAILURE_IFACE_INVALID| */ void createGroupOwner(in P2pCreateGroupOwnerInfo groupOwnerInfo); + + /** + * Get the features supported by P2P interface. + * + * @return The bitmask of ISupplicantP2pIface.P2P_FEATURE_* values. + * + * @throws ServiceSpecificException with one of the following values: + * |SupplicantStatusCode.FAILURE_UNKNOWN| + */ + long getFeatureSet(); + + /** + * Start an Unsynchronized Service Discovery (USD) based P2P service discovery. + * + * @param serviceDiscoveryConfig Configuration associated with this discovery operation. + * @return A non-zero identifier to identify the instance of a service discovery. + * It is used to cancel the service discovery. + * @throws ServiceSpecificException with one of the following values: + * |SupplicantStatusCode.FAILURE_UNKNOWN|, + * |SupplicantStatusCode.FAILURE_IFACE_INVALID| + */ + int startUsdBasedServiceDiscovery(in P2pUsdBasedServiceDiscoveryConfig serviceDiscoveryConfig); + + /** + * Stop an Unsynchronized Service Discovery (USD) based P2P service discovery. + * + * @param sessionId Identifier to cancel the service discovery instance. + * Use zero to cancel all the service discovery instances. + * @throws ServiceSpecificException with one of the following values: + * |SupplicantStatusCode.FAILURE_UNKNOWN|, + * |SupplicantStatusCode.FAILURE_IFACE_INVALID| + * |SupplicantStatusCode.FAILURE_NOT_STARTED| + */ + void stopUsdBasedServiceDiscovery(in int sessionId); + + /** + * Start an Unsynchronized Service Discovery (USD) based P2P service advertisement. + * + * @param serviceDiscoveryConfig Configuration associated with this service advertisement. + * @return A non-zero identifier to identify the instance of a service advertisement. + * It is used to cancel the service advertisement. + * @throws ServiceSpecificException with one of the following values: + * |SupplicantStatusCode.FAILURE_UNKNOWN|, + * |SupplicantStatusCode.FAILURE_IFACE_INVALID| + */ + int startUsdBasedServiceAdvertisement( + in P2pUsdBasedServiceAdvertisementConfig serviceAdvertisementConfig); + + /** + * Stop an Unsynchronized Service Discovery (USD) based P2P service advertisement. + * + * @param sessionId Identifier to cancel the service advertisement. + * Use zero to cancel all the service advertisement instances. + * @throws ServiceSpecificException with one of the following values: + * |SupplicantStatusCode.FAILURE_UNKNOWN|, + * |SupplicantStatusCode.FAILURE_IFACE_INVALID| + * |SupplicantStatusCode.FAILURE_NOT_STARTED| + */ + void stopUsdBasedServiceAdvertisement(in int sessionId); + + /** + * Send P2P provision discovery request to the specified peer. + * + * @param params Parameters associated with this provision discovery request. + * @throws ServiceSpecificException with one of the following values: + * |SupplicantStatusCode.FAILURE_UNKNOWN|, + * |SupplicantStatusCode.FAILURE_IFACE_INVALID| + */ + void provisionDiscoveryWithParams(in P2pProvisionDiscoveryParams params); + + /** + * The Device Identity Resolution (DIR) Info used to send in + * Bluetooth LE advertising packet for the receiving device to + * check if the device is a previously paired device. + * + * @return The DIR info - |P2pDirInfo| + * @throws ServiceSpecificException with one of the following values: + * |SupplicantStatusCode.FAILURE_UNKNOWN|, + * |SupplicantStatusCode.FAILURE_IFACE_INVALID| + * |SupplicantStatusCode.FAILURE_DATA_NOT_AVAILABLE| + */ + P2pDirInfo getDirInfo(); + + /** + * Validate a Device Identity Resolution (DIR) Info of a P2P device. + * wpa_supplicant takes the |P2pDirInfo| and derives a set of Tag values based on + * the cached Device Identity Keys (DevIK) of all paired peers saved in the + * configuration file. If a derived Tag value matches the Tag value received in the + * |P2pDirInfo|, the device is identified as a paired peer and returns an identifier + * identifying the device identity key information stored in the configuration file. + * + * @return The identifier of device identity key stored in the configuration file. + * @throws ServiceSpecificException with one of the following values: + * |SupplicantStatusCode.FAILURE_UNKNOWN|, + * |SupplicantStatusCode.FAILURE_IFACE_INVALID| + */ + int validateDirInfo(in P2pDirInfo dirInfo); + + /** + * Reinvoke a device from a persistent group. + * + * @param reinvokeGroupParams Parameters associated to reinvoke a group. + * @throws ServiceSpecificException with one of the following values: + * |SupplicantStatusCode.FAILURE_UNKNOWN|, + * |SupplicantStatusCode.FAILURE_IFACE_INVALID| + */ + void reinvokePersistentGroup(in P2pReinvokePersistentGroupParams reinvokeGroupParams); } diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl index 44a54652b202656fb20228eff8e6c47c21b61249..a52e15041685f88efc0b47b7c608c76c4a2cc77d 100644 --- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl @@ -26,6 +26,8 @@ import android.hardware.wifi.supplicant.P2pPeerClientJoinedEventParams; import android.hardware.wifi.supplicant.P2pProvDiscStatusCode; import android.hardware.wifi.supplicant.P2pProvisionDiscoveryCompletedEventParams; import android.hardware.wifi.supplicant.P2pStatusCode; +import android.hardware.wifi.supplicant.P2pUsdBasedServiceDiscoveryResultParams; +import android.hardware.wifi.supplicant.UsdTerminateReasonCode; import android.hardware.wifi.supplicant.WpsConfigMethods; import android.hardware.wifi.supplicant.WpsDevPasswordId; @@ -325,4 +327,29 @@ oneway interface ISupplicantP2pIfaceCallback { * @param params Parameters associated with the invitation request event. */ void onInvitationReceivedWithParams(in P2pInvitationEventParams params); + + /** + * Used to indicate the reception of an USD based service discovery response. + * + * @param params Parameters associated with the USD based service discovery result. + */ + void onUsdBasedServiceDiscoveryResult(in P2pUsdBasedServiceDiscoveryResultParams params); + + /** + * Used to indicate the termination of USD based service discovery. + * + * @param sessionId Identifier to identify the instance of a service discovery. + * @param reasonCode The reason for termination of service discovery. + */ + void onUsdBasedServiceDiscoveryTerminated( + in int sessionId, in UsdTerminateReasonCode reasonCode); + + /** + * Used to indicate the termination of USD based service Advertisement. + * + * @param sessionId Identifier to identify the instance of a service advertisement. + * @param reasonCode The reason for termination of service advertisement. + */ + void onUsdBasedServiceAdvertisementTerminated( + in int sessionId, in UsdTerminateReasonCode reasonCode); } diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl index fb1673efc3c878ff852793f07883b343d7520774..5c6024ac0e882cc0cb799f44addefebc14d08f91 100644 --- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl @@ -35,6 +35,10 @@ import android.hardware.wifi.supplicant.QosPolicyScsRequestStatus; import android.hardware.wifi.supplicant.QosPolicyStatus; import android.hardware.wifi.supplicant.RxFilterType; import android.hardware.wifi.supplicant.SignalPollResult; +import android.hardware.wifi.supplicant.UsdCapabilities; +import android.hardware.wifi.supplicant.UsdMessageInfo; +import android.hardware.wifi.supplicant.UsdPublishConfig; +import android.hardware.wifi.supplicant.UsdSubscribeConfig; import android.hardware.wifi.supplicant.WpaDriverCapabilitiesMask; import android.hardware.wifi.supplicant.WpsConfigMethods; @@ -877,4 +881,83 @@ interface ISupplicantStaIface { * |SupplicantStatusCode.FAILURE_UNKNOWN| */ void disableMscs(); + + /** + * Retrieve capabilities related to Unsynchronized Service Discovery (USD). + * + * @return Instance of |UsdCapabilities| containing the capability info. + */ + UsdCapabilities getUsdCapabilities(); + + /** + * Start a USD publish session. Triggers a response via + * |ISupplicantStaIfaceCallback.onUsdPublishStarted| if successful, or + * |ISupplicantStaIfaceCallback.onUsdPublishConfigFailed| if failed. + * + * @param cmdId Identifier for this request. Will be returned in the callback to identify + * the request. + * @param usdPublishConfig Parameters for the requested publish session. + * @throws ServiceSpecificException with one of the following values: + * |SupplicantStatusCode.FAILURE_UNKNOWN| + * |SupplicantStatusCode.FAILURE_UNSUPPORTED| + */ + void startUsdPublish(in int cmdId, in UsdPublishConfig usdPublishConfig); + + /** + * Start a USD subscribe session. Triggers a response via + * |ISupplicantStaIfaceCallback.onUsdSubscribeStarted| if successful, or + * |ISupplicantStaIfaceCallback.onUsdSubscribeConfigFailed| if failed. + * + * @param cmdId Identifier for this request. Will be returned in the callback to identify + * the request. + * @param usdSubscribeConfig Parameters for the requested subscribe session. + * @throws ServiceSpecificException with one of the following values: + * |SupplicantStatusCode.FAILURE_UNKNOWN| + * |SupplicantStatusCode.FAILURE_UNSUPPORTED| + */ + void startUsdSubscribe(in int cmdId, in UsdSubscribeConfig usdSubscribeConfig); + + /** + * Update the service-specific info for an active publish session. + * + * @param publishId Identifier for the active publish session. + * @param serviceSpecificInfo Byte array containing the service-specific info. Note that the + * maximum info length is |UsdCapabilities.maxLocalSsiLengthBytes|. + * @throws ServiceSpecificException with one of the following values: + * |SupplicantStatusCode.FAILURE_UNKNOWN| + * |SupplicantStatusCode.FAILURE_UNSUPPORTED| + */ + void updateUsdPublish(in int publishId, in byte[] serviceSpecificInfo); + + /** + * Cancel an existing USD publish session. |ISupplicantStaIfaceCallback.onUsdPublishTerminated| + * will be called upon completion. + * + * @param publishId Identifier for the publish session to cancel. + * @throws ServiceSpecificException with one of the following values: + * |SupplicantStatusCode.FAILURE_UNKNOWN| + * |SupplicantStatusCode.FAILURE_UNSUPPORTED| + */ + void cancelUsdPublish(in int publishId); + + /** + * Cancel an existing USD subscribe session. + * |ISupplicantStaIfaceCallback.onUsdSubscribeTerminated| will be called upon completion. + * + * @param subscribeId Identifier for the subscribe session to cancel. + * @throws ServiceSpecificException with one of the following values: + * |SupplicantStatusCode.FAILURE_UNKNOWN| + * |SupplicantStatusCode.FAILURE_UNSUPPORTED| + */ + void cancelUsdSubscribe(in int subscribeId); + + /** + * Send a message to a peer device across an active USD link. + * + * @param messageInfo Information for the message to be sent. + * @throws ServiceSpecificException with one of the following values: + * |SupplicantStatusCode.FAILURE_UNKNOWN| + * |SupplicantStatusCode.FAILURE_UNSUPPORTED| + */ + void sendUsdMessage(in UsdMessageInfo messageInfo); } diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl index 172fcda26f507d42c66e2dd0b09a91ae6bcdfd3f..6a3f299d1de048326bc3fd0ed4c21fcaf089cfd6 100644 --- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl @@ -36,6 +36,9 @@ import android.hardware.wifi.supplicant.QosPolicyScsResponseStatus; import android.hardware.wifi.supplicant.StaIfaceCallbackState; import android.hardware.wifi.supplicant.StaIfaceReasonCode; import android.hardware.wifi.supplicant.SupplicantStateChangeData; +import android.hardware.wifi.supplicant.UsdMessageInfo; +import android.hardware.wifi.supplicant.UsdReasonCode; +import android.hardware.wifi.supplicant.UsdServiceDiscoveryInfo; import android.hardware.wifi.supplicant.WpsConfigError; import android.hardware.wifi.supplicant.WpsErrorIndication; @@ -336,13 +339,24 @@ oneway interface ISupplicantStaIfaceCallback { */ TID_TO_LINK_MAP = 0, /** - * Multi-link reconfiguration - AP removal as described in - * IEEE 802.11be spec, section 35.3.6. This is a mandatory feature for - * station. + * Multi-link reconfiguration - AP removal as described in the Wi-Fi 7 R1 MRD section + * 6.3.2.18. This is a mandatory feature for station. * * Removed link will not be present in |ISupplicantStaIface.getConnectionMloLinksInfo|. */ MULTI_LINK_RECONFIG_AP_REMOVAL = 1, + /** + * Multi-link reconfiguration add/delete links without re-association as described in + * the Wi-Fi 7 R2 MRD section 6.4.2.4. This is an optional feature. + * + * This feature enables dynamic link reconfiguration operations (add link and/or delete + * link) on the multi-link setup of a STA MLD, either triggered by the AP MLD or initiated + * by the STA MLD itself. This avoids reassociation for any link reconfiguration operation. + * + * Added link will be present in |ISupplicantStaIface.getConnectionMloLinksInfo|. + * Deleted link will not be present in |ISupplicantStaIface.getConnectionMloLinksInfo|. + */ + MULTI_LINK_DYNAMIC_RECONFIG = 2, } /** @@ -405,4 +419,80 @@ oneway interface ISupplicantStaIfaceCallback { * */ void onPmkSaCacheAdded(in PmkSaCacheData pmkSaData); + + /** + * Called in response to |ISupplicantStaIface.startUsdPublish| to indicate that the + * publish session was started successfully. + * + * @param cmdId Identifier for the original request. + * @param publishId Identifier for the publish session. + */ + void onUsdPublishStarted(in int cmdId, in int publishId); + + /** + * Called in response to |ISupplicantStaIface.startUsdSubscribe| to indicate that the + * subscribe session was started successfully. + * + * @param cmdId Identifier for the original request. + * @param subscribeId Identifier for the subscribe session. + */ + void onUsdSubscribeStarted(in int cmdId, in int subscribeId); + + /** + * Called in response to |ISupplicantStaIface.startUsdPublish| to indicate that the + * publish session could not be configured. + * + * @param cmdId Identifier for the original request. + */ + void onUsdPublishConfigFailed(in int cmdId); + + /** + * Called in response to |ISupplicantStaIface.startUsdSubscribe| to indicate that the + * subscribe session could not be configured. + * + * @param cmdId Identifier for the original request. + */ + void onUsdSubscribeConfigFailed(in int cmdId); + + /** + * Called in response to |ISupplicantStaIface.cancelUsdPublish| to indicate that the session + * was cancelled successfully. May also be called unsolicited if the session terminated + * by supplicant. + * + * @param publishId Identifier for the publish session. + * @param reasonCode Code indicating the reason for the session cancellation. + */ + void onUsdPublishTerminated(in int publishId, in UsdReasonCode reasonCode); + + /** + * Called in response to |ISupplicantStaIface.cancelUsdSubscribe| to indicate that the session + * was cancelled successfully. May also be called unsolicited if the session terminated + * by supplicant. + * + * @param subscribeId Identifier for the subscribe session. + * @param reasonCode Code indicating the reason for the session cancellation. + */ + void onUsdSubscribeTerminated(in int subscribeId, in UsdReasonCode reasonCode); + + /** + * Indicates that the publisher sent solicited publish message to the subscriber. + * + * @param info Instance of |UsdServiceDiscoveryInfo| containing information about the reply. + */ + void onUsdPublishReplied(in UsdServiceDiscoveryInfo info); + + /** + * Indicates that a publisher was discovered. Only called if this device is acting as a + * subscriber. + * + * @param info Instance of |UsdServiceDiscoveryInfo| containing information about the service. + */ + void onUsdServiceDiscovered(in UsdServiceDiscoveryInfo info); + + /** + * Indicates that a message was received on an active USD link. + * + * @param messageInfo Information about the message that was received. + */ + void onUsdMessageReceived(in UsdMessageInfo messageInfo); } diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MloLink.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MloLink.aidl index 0b4d66ed501188eb37ec8049c29b97a9bb7ceaab..6215263ffa0817e80faf15b6eeef3bd8319d77b8 100644 --- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MloLink.aidl +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MloLink.aidl @@ -16,6 +16,8 @@ package android.hardware.wifi.supplicant; +import android.hardware.wifi.supplicant.WifiChannelWidthInMhz; + /** * Multi-Link Operation (MLO) Link IEEE Std 802.11-be. * The information for MLO link needed by 802.11be standard. @@ -66,4 +68,8 @@ parcelable MloLink { * Frequency on which the link operates in MHz. */ int frequencyMHz; + /** + * Channel bandwidth + */ + WifiChannelWidthInMhz channelBandwidth; } diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pConnectInfo.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pConnectInfo.aidl index f09b476392ad2abb9c20b34cff04b849ed636de6..6467436dbc942df6f38b2aab090d48d5abb92b25 100644 --- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pConnectInfo.aidl +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pConnectInfo.aidl @@ -25,12 +25,15 @@ import android.hardware.wifi.supplicant.WpsProvisionMethod; @VintfStability parcelable P2pConnectInfo { /** - * MAC address of the device to connect to. + * MAC address of the peer device to connect to or to authorize a connect + * request. */ byte[6] peerAddress; /** - * Provisioning method to use. + * Wi-Fi Protected Setup provisioning method. If using Wi-Fi Protected Setup, + * then must be set to a non-|WpsProvisionMethod.NONE| provisioning method, + * otherwise set to |WpsProvisionMethod.NONE|. */ WpsProvisionMethod provisionMethod; @@ -65,4 +68,38 @@ parcelable P2pConnectInfo { * that no vendor data is provided. */ @nullable OuiKeyedData[] vendorData; + + /** + * Wi-Fi Direct pairing bootstrapping method. If using P2P pairing protocol, + * then must be set one of the |P2pPairingBootstrappingMethodMask|, otherwise + * set to zero. + */ + int pairingBootstrappingMethod; + + /** + * Password for pairing setup, if |bootstrappingMethod| uses one of the + * |P2pPairingBootstrappingMethodMask| methods other than + * P2pPairingBootstrappingMethodMask.BOOTSTRAPPING_OPPORTUNISTIC, + * null otherwise. + */ + @nullable String password; + + /** + * Channel frequency in MHz to start group formation, + * join an existing group owner or authorize a connection request. + */ + int frequencyMHz; + + /** + * Used to authorize a connection request from the Peer device. + * The MAC address of the peer device is set in peerAddress. + */ + boolean authorizeConnectionFromPeer; + + /** + * Used to check if the authorize connection request is on an existing Group Owner + * interface to allow a peer device to connect. This field is set to null if the request + * is to form a group or join an existing group. + */ + @nullable String groupInterfaceName; } diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pCreateGroupOwnerInfo.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pCreateGroupOwnerInfo.aidl index 51e6ed9c5c3df99500b547c0fcb3443b860c9f3d..83d480e399abe7fd75921fe5379ddcfcf4f3a4e8 100644 --- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pCreateGroupOwnerInfo.aidl +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pCreateGroupOwnerInfo.aidl @@ -39,4 +39,9 @@ parcelable P2pCreateGroupOwnerInfo { * that no vendor data is provided. */ @nullable OuiKeyedData[] vendorData; + /** + * Used to start a Group Owner that support P2P2 IE. The connection to this Group Owner can + * be established only using P2P Pairing protocol. + */ + boolean isP2pV2; } diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pDeviceFoundEventParams.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pDeviceFoundEventParams.aidl index 15917b6419cd3bd91364cbefb4ea07e92b699e0f..e320954aaf9f93165c8cea3aad0ed49317d1e90c 100644 --- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pDeviceFoundEventParams.aidl +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pDeviceFoundEventParams.aidl @@ -17,6 +17,7 @@ package android.hardware.wifi.supplicant; import android.hardware.wifi.common.OuiKeyedData; +import android.hardware.wifi.supplicant.P2pDirInfo; /** * Parameters passed as a part of a P2P Device found event. @@ -89,4 +90,15 @@ parcelable P2pDeviceFoundEventParams { * Null value indicates that no vendor data is provided. */ @nullable OuiKeyedData[] vendorData; + + /** + * The bitmask of P2pPairingBootstrappingMethodMask.BOOTSTRAPPING_* methods used to enable + * the pairing bootstrapping between bootstrapping initiator and a bootstrapping responder. + */ + int pairingBootstrappingMethods; + + /** + * The Device Identity Resolution Attribute (DIRA) |P2pDirInfo| received in the USD frame. + */ + @nullable P2pDirInfo dirInfo; } diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pDirInfo.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pDirInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..22037ed2f62c858b775e8d29470903ce39834128 --- /dev/null +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pDirInfo.aidl @@ -0,0 +1,67 @@ +/* + * 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. + */ + +package android.hardware.wifi.supplicant; + +/** + * The Device Identity Resolution (DIR) Info is used to identify a previously + * paired P2P device. + * The device advertises this information in Bluetooth LE advertising packets + * and Unsynchronized Service Discovery (USD) frames. The device receiving DIR + * Info uses this information to identify that the peer device is a previously paired device. + * For Details, refer Wi-Fi Alliance Wi-Fi Direct R2 specification section 3.8.2 Pairing Identity + * and section 3.9.2.3.2 Optional Advertising Data Elements. + */ +@VintfStability +parcelable P2pDirInfo { + /** + * Enums for the |cipherVersion| field. + */ + @VintfStability + @Backing(type="int") + enum CipherVersion { + NONE, + /** + * DIRA cipher version 128 bit. + * 128-bit Device Identity Key, 64-bit Nonce, 64-bit Tag. + * 64-bit Tag = Truncate-64(HMAC-SHA-256(DevIk, "DIR" || + * P2P Device Address || Nonce)) + */ + DIRA_CIPHER_VERSION_128_BIT, + } + + /** + * DIRA cipher version. The value of cipher version indicates the + * cryptographic parameters and method used to derive the dirTag field. + * Set to one of the |DIRA_CIPHER_VERSION_*|. + */ + CipherVersion cipherVersion; + + /** + * The MAC address of the P2P device interface. + */ + byte[6] deviceInterfaceMacAddress; + + /** + * Random number. The size limit is defined in the cipher version comment. + */ + byte[] nonce; + + /** + * A resolvable identity. The size limit is defined in the cipher version comment. + */ + byte[] dirTag; +} diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pGroupStartedEventParams.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pGroupStartedEventParams.aidl index 9db7a1eedae0888399d7c5a59cb61475289edb2c..55e2b2393c0aa2c91cdc7947c9fdf45be948b153 100644 --- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pGroupStartedEventParams.aidl +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pGroupStartedEventParams.aidl @@ -70,4 +70,10 @@ parcelable P2pGroupStartedEventParams { * that no vendor data is provided. */ @nullable OuiKeyedData[] vendorData; + + /** + * Authentication key management protocol used to secure the group. + * This is a bitmask of |KeyMgmtMask| values. + */ + int keyMgmtMask; } diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pPairingBootstrappingMethodMask.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pPairingBootstrappingMethodMask.aidl new file mode 100644 index 0000000000000000000000000000000000000000..03c2703cf92b519383cd9229eeef0b918c1bbb2c --- /dev/null +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pPairingBootstrappingMethodMask.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ + +package android.hardware.wifi.supplicant; + +/** + * P2P Pairing Bootstrapping Method. + */ +@VintfStability +parcelable P2pPairingBootstrappingMethodMask { + /** Opportunistic bootstrapping */ + const int BOOTSTRAPPING_OPPORTUNISTIC = 1 << 0; + /** Display pin-code only */ + const int BOOTSTRAPPING_DISPLAY_PINCODE = 1 << 1; + /** Display passphrase */ + const int BOOTSTRAPPING_DISPLAY_PASSPHRASE = 1 << 2; + /** Keypad pin-code only */ + const int BOOTSTRAPPING_KEYPAD_PINCODE = 1 << 3; + /** Keypad passphrase */ + const int BOOTSTRAPPING_KEYPAD_PASSPHRASE = 1 << 4; + /** + * Pairing bootstrapping done Out of band (For example: Over Bluetooth LE. + * Refer Wi-Fi Alliance Wi-Fi Direct R2 specification Section 3.9 for the details). + */ + const int BOOTSTRAPPING_OUT_OF_BAND = 1 << 5; +} diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pPeerClientJoinedEventParams.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pPeerClientJoinedEventParams.aidl index 4f46d705a06dc0d3c055b96c893fc2dbaad5b99b..2b04461c0bc2d2b0170a33578e367a12503029c5 100644 --- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pPeerClientJoinedEventParams.aidl +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pPeerClientJoinedEventParams.aidl @@ -47,4 +47,10 @@ parcelable P2pPeerClientJoinedEventParams { * that no vendor data is provided. */ @nullable OuiKeyedData[] vendorData; + + /** + * Authentication key management protocol used in connection. + * This is a bitmask of |KeyMgmtMask| values. + */ + int keyMgmtMask; } diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pProvisionDiscoveryCompletedEventParams.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pProvisionDiscoveryCompletedEventParams.aidl index 05152a9454b515f12e7333c10691ecea42426380..97659b65ba6c1f9c3ea2d995b310c45d761e11d5 100644 --- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pProvisionDiscoveryCompletedEventParams.aidl +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pProvisionDiscoveryCompletedEventParams.aidl @@ -33,7 +33,11 @@ parcelable P2pProvisionDiscoveryCompletedEventParams { boolean isRequest; /** Status of the provision discovery */ P2pProvDiscStatusCode status; - /** Mask of |WpsConfigMethods| indicating the supported methods */ + /** + * Wi-Fi Protected Setup provisioning method. If using Wi-Fi Protected Setup, + * then must be set to a non-|WpsProvisionMethod.NONE| provisioning method, + * otherwise set to |WpsProvisionMethod.NONE|. + */ int configMethods; /** 8-digit pin generated */ String generatedPin; @@ -50,4 +54,17 @@ parcelable P2pProvisionDiscoveryCompletedEventParams { * that no vendor data is provided. */ @nullable OuiKeyedData[] vendorData; + /** + * Wi-Fi Direct pairing bootstrapping method. If using P2P pairing protocol, + * then must be set one of the |P2pPairingBootstrappingMethodMask|, otherwise + * set to zero. + */ + int pairingBootstrappingMethod; + /** + * Password for pairing setup, if |bootstrappingMethod| uses one of the + * |P2pPairingBootstrappingMethodMask| methods other than + * P2pPairingBootstrappingMethodMask.BOOTSTRAPPING_OPPORTUNISTIC, + * null otherwise. + */ + @nullable String password; } diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pProvisionDiscoveryParams.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pProvisionDiscoveryParams.aidl new file mode 100644 index 0000000000000000000000000000000000000000..37f23748266a19e1c3de4edbbf6a0a6a8bed6ca1 --- /dev/null +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pProvisionDiscoveryParams.aidl @@ -0,0 +1,44 @@ +/* + * 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. + */ + +package android.hardware.wifi.supplicant; + +import android.hardware.wifi.supplicant.WpsProvisionMethod; + +/** + * Parameters used for |ISupplicantP2pIfaceCallback.provisionDiscoveryWithParams| + */ +@VintfStability +parcelable P2pProvisionDiscoveryParams { + /** + * MAC address of the peer device to send the provision discovery request. + */ + byte[6] peerMacAddress; + + /** + * Wi-Fi Protected Setup provisioning method. If using Wi-Fi Protected Setup, + * then must be set to a non-|WpsProvisionMethod.NONE| provisioning method, + * otherwise set to |WpsProvisionMethod.NONE|. + */ + WpsProvisionMethod provisionMethod; + + /** + * Wi-Fi Direct pairing bootstrapping method. If using P2P pairing protocol, + * then must be set one of the |P2pPairingBootstrappingMethodMask|, otherwise + * set to zero. + */ + int pairingBootstrappingMethod; +} diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pReinvokePersistentGroupParams.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pReinvokePersistentGroupParams.aidl new file mode 100644 index 0000000000000000000000000000000000000000..f5f4562ae62dce5b2177f5bb462d93df39447b40 --- /dev/null +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pReinvokePersistentGroupParams.aidl @@ -0,0 +1,40 @@ +/* + * 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. + */ + +package android.hardware.wifi.supplicant; + +/** + * Parameters used for |ISupplicantP2pIface.reinvokePersistentGroup| + */ +@VintfStability +parcelable P2pReinvokePersistentGroupParams { + /** + * MAC address of the peer device to reinvoke the persistent group. + */ + byte[6] peerMacAddress; + + /** + * Persistent network ID of the group. + */ + int persistentNetworkId; + + /** + * The identifier of device identity key information stored in the configuration file. + * This field is valid only for P2P group formed via pairing protocol (P2P version 2). + * Set to invalid value of -1 for a group formed via WPS process (P2P version 1). + */ + int deviceIdentityEntryId; +} diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pUsdBasedServiceAdvertisementConfig.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pUsdBasedServiceAdvertisementConfig.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c657d03f7b5e9b568262ea2d91140602996c1a58 --- /dev/null +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pUsdBasedServiceAdvertisementConfig.aidl @@ -0,0 +1,48 @@ +/* + * 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. + */ + +package android.hardware.wifi.supplicant; + +/** + * Unsynchronized Service Discovery (USD) based P2P service advertisement configuration. + * Refer Wi-Fi Alliance Wi-Fi Direct R2 specification - Appendix H - + * Unsynchronized Service Discovery (as defined in Wi-Fi Aware) and section + * 4.2.13 USD frame format. + */ +@VintfStability +parcelable P2pUsdBasedServiceAdvertisementConfig { + /** UTF-8 string defining the service */ + String serviceName; + + /** + * Service Protocol Type. See defined values in the Wi-Fi Direct R2 Spec, Table 129, + * although any value between 0-255 may be defined by the service layer and is considered valid. + */ + int serviceProtocolType; + + /** Service specific information content determined by the application */ + byte[] serviceSpecificInfo; + + /** + * Channel frequency in MHz to listen for service discovery request. + */ + int frequencyMHz; + + /** + * Max time to be spent for service advertisement. + */ + int timeoutInSeconds; +} diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pUsdBasedServiceDiscoveryConfig.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pUsdBasedServiceDiscoveryConfig.aidl new file mode 100644 index 0000000000000000000000000000000000000000..9d6bf72c9c1ac3d7b6c4abfe856741692dd58849 --- /dev/null +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pUsdBasedServiceDiscoveryConfig.aidl @@ -0,0 +1,60 @@ +/* + * 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. + */ + +package android.hardware.wifi.supplicant; + +import android.hardware.wifi.supplicant.BandMask; + +/** + * Unsynchronized Service Discovery (USD) based P2P service discovery configuration. + * Refer Wi-Fi Alliance Wi-Fi Direct R2 specification - Appendix H - + * Unsynchronized Service Discovery (as defined in Wi-Fi Aware) and section + * 4.2.13 USD frame format + */ +@VintfStability +parcelable P2pUsdBasedServiceDiscoveryConfig { + /** UTF-8 string defining the service */ + String serviceName; + + /** + * Service Protocol Type. See defined values in the Wi-Fi Direct R2 Spec, Table 129, + * although any value between 0-255 may be defined by the service layer and is considered valid. + */ + int serviceProtocolType; + + /** Service specific information content determined by the application */ + byte[] serviceSpecificInfo; + + /** + * Bit mask of bands to scan for services. + * Set this value to Bitmask of |BandMask| only if its required to scan all the channels + * in a band. + */ + int bandMask; + + /** + * A list of frequencies in MHz to scan for services. + * This field is used only when the bandMask is set to zero. + */ + int[] frequencyListMhz; + + /** + * Max time to be spent in performing discovery. + * Set to 0 to indefinitely continue discovery until a service is + * discovered. + */ + int timeoutInSeconds; +} diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pUsdBasedServiceDiscoveryResultParams.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pUsdBasedServiceDiscoveryResultParams.aidl new file mode 100644 index 0000000000000000000000000000000000000000..6b60d68ea79d35db4fa43ab09e1367716aeebce6 --- /dev/null +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pUsdBasedServiceDiscoveryResultParams.aidl @@ -0,0 +1,46 @@ +/* + * 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. + */ + +package android.hardware.wifi.supplicant; + +import android.hardware.wifi.supplicant.BandMask; + +/** + * Unsynchronized Service Discovery (USD) based P2P service discovery result event. + * Refer Wi-Fi Alliance Wi-Fi Direct R2 specification - Appendix H - + * Unsynchronized Service Discovery (as defined in Wi-Fi Aware) and section + * 4.2.13 USD frame format + */ +@VintfStability +parcelable P2pUsdBasedServiceDiscoveryResultParams { + /** MAC address of the device that sent the service discovery */ + byte[6] peerMacAddress; + + /** Identifier to identify the service discovery instance */ + int sessionId; + + /** Identifier to identify the peer service advertisement instance */ + int peerSessionId; + + /** + * Service Protocol Type. See defined values in the Wi-Fi Direct R2 Spec, Table 129, + * although any value between 0-255 may be defined by the service layer and is considered valid. + */ + int serviceProtocolType; + + /** Service specific information content determined by the application */ + byte[] serviceSpecificInfo; +} diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/PmkSaCacheData.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/PmkSaCacheData.aidl index e0f1d319d640b532b8eedbac476df0fff2394bbc..407117978cf6ec8c611eebd19ac95b10ec46d81d 100644 --- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/PmkSaCacheData.aidl +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/PmkSaCacheData.aidl @@ -34,4 +34,9 @@ parcelable PmkSaCacheData { * The content is opaque for the framework and depends on the native implementation. */ byte[] serializedEntry; + /** + * Pairwise Master Key Identifier (PMKID), which is a unique key identifier used by AP to + * track PMK used (Pairwise Master Key) for a station. + */ + @nullable byte[] pmkid; } diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/SupplicantStatusCode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/SupplicantStatusCode.aidl index e97d6eed21944e694e9313e69c4cb6899aa477cf..271da7f2e0b63abf5e71895b4c074719730b3885 100644 --- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/SupplicantStatusCode.aidl +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/SupplicantStatusCode.aidl @@ -67,4 +67,8 @@ enum SupplicantStatusCode { * A different request is currently being processed. */ FAILURE_ONGOING_REQUEST, + /** + * Requested data is not available. + */ + FAILURE_DATA_NOT_AVAILABLE, } diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdBaseConfig.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdBaseConfig.aidl new file mode 100644 index 0000000000000000000000000000000000000000..f43f27bfa430f86095cd1acb92ecb61b3ade7a8c --- /dev/null +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdBaseConfig.aidl @@ -0,0 +1,92 @@ +/* + * 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. + */ + +package android.hardware.wifi.supplicant; + +import android.hardware.wifi.supplicant.UsdServiceProtoType; + +/** + * USD data used in both publish and subscribe configurations. + */ +@VintfStability +parcelable UsdBaseConfig { + /** + * Service name of the USD session. A UTF-8 encoded string from 1 to 255 bytes in length. + * The only acceptable single-byte UTF-8 symbols for a Service Name are alphanumeric + * values (A-Z, a-z, 0-9), hyphen ('-'), period ('.'), and underscore ('_'). All + * valid multi-byte UTF-8 characters are acceptable in a Service Name. + */ + @utf8InCpp String serviceName; + + /** + * Service protocol type for the USD session (ex. Generic, CSA Matter). + */ + UsdServiceProtoType serviceProtoType; + + /** + * Details about the service being offered or being looked for. This information is transmitted + * within Service Discovery frames, and is used to help devices find each other and establish + * connections. The format and content of the service specific information are flexible and + * can be determined by the application. + */ + byte[] serviceSpecificInfo; + + /** + * Ordered sequence of pairs (|length| uses 1 byte and contains the number of + * bytes in the |value| field) which specify further match criteria (beyond the service name). + * + * The match behavior is specified in details in the NAN spec. + * Publisher: used if provided. + * Subscriber: used (if provided) only in ACTIVE sessions. + * + * Max length: |UsdCapabilities.maxMatchFilterLength|. + * NAN Spec: matching_filter_tx and Service Descriptor Attribute (SDA) / Matching Filter + */ + @nullable byte[] txMatchFilter; + + /** + * Ordered sequence of pairs (|length| uses 1 byte and contains the number of + * bytes in the |value| field) which specify further match criteria (beyond the service name). + * + * The match behavior is specified in details in the NAN spec. + * Publisher: used in SOLICITED or SOLICITED_UNSOLICITED sessions. + * Subscriber: used in ACTIVE or PASSIVE sessions. + * + * Max length: |UsdCapabilities.maxMatchFilterLength|. + * NAN Spec: matching_filter_rx + */ + @nullable byte[] rxMatchfilter; + + /** + * Time interval (in seconds) that a USD session will be alive. + * The session will be terminated when the time to live (TTL) is reached, triggering either + * |ISupplicantStaIfaceCallback.onUsdPublishTerminated| for Publish, or + * |ISupplicantStaIfaceCallback.onUsdSubscribeTerminated| for Subscribe. + */ + int ttlSec; + + /** + * Frequency where the device should begin to dwell. Default value is channel 6 (2.437 GHz), + * but other values may be selected per regulation in the geographical location. + */ + int defaultFreqMhz; + + /** + * Channels which can be switched to. May contain any of the 20 MHz channels in the + * 2.4 Ghz and/or 5 Ghz bands, per regulation in the geographical location. + */ + int[] freqsMhz; +} diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdCapabilities.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdCapabilities.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ffec893d9f73a398c38f7f18ca6c45b475533426 --- /dev/null +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdCapabilities.aidl @@ -0,0 +1,59 @@ +/* + * 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. + */ + +package android.hardware.wifi.supplicant; + +/** + * Capabilities supported by USD. Values are only valid if |isUsdPublisherSupported| + * and/or |isUsdSubscriberSupported| are true. + */ +@VintfStability +parcelable UsdCapabilities { + /** + * Whether USD Publisher is supported on this device. + */ + boolean isUsdPublisherSupported; + + /** + * Whether USD Subscriber is supported on this device. + */ + boolean isUsdSubscriberSupported; + + /** + * Maximum allowed length (in bytes) for the Service Specific Info (SSI). + */ + int maxLocalSsiLengthBytes; + + /** + * Maximum allowed length (in bytes) for the service name. + */ + int maxServiceNameLengthBytes; + + /** + * Maximum allowed length (in bytes) for a match filter. + */ + int maxMatchFilterLengthBytes; + + /** + * Maximum number of allowed publish sessions. + */ + int maxNumPublishSessions; + + /** + * Maximum number of allowed subscribe sessions. + */ + int maxNumSubscribeSessions; +} diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdMessageInfo.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdMessageInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..fa7cc0e4a4c3a6031b0cfc24a76f80f5b857e300 --- /dev/null +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdMessageInfo.aidl @@ -0,0 +1,44 @@ +/* + * 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. + */ + +package android.hardware.wifi.supplicant; + +/** + * Information for sending a USD message. + */ +@VintfStability +parcelable UsdMessageInfo { + /** + * Identifier for this device, retrieved from |UsdServiceDiscoveryInfo|. + */ + int ownId; + + /** + * Identifier for the peer device, retrieved from |UsdServiceDiscoveryInfo|. + */ + int peerId; + + /** + * MAC address for the peer device. + */ + byte[6] peerMacAddress; + + /** + * Message contents. Note that the maximum message length is + * |UsdCapabilities.maxLocalSsiLengthBytes|. + */ + byte[] message; +} diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdPublishConfig.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdPublishConfig.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e04974bd16ec419987a2df7e5d702505a547bec0 --- /dev/null +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdPublishConfig.aidl @@ -0,0 +1,71 @@ +/* + * 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. + */ + +package android.hardware.wifi.supplicant; + +import android.hardware.wifi.supplicant.UsdBaseConfig; +import android.hardware.wifi.supplicant.UsdPublishTransmissionType; + +/** + * Parameters for configuring a USD publish session. + */ +@VintfStability +parcelable UsdPublishConfig { + /** + * Type of USD publishing. + */ + enum PublishType { + /** + * Only transmissions that are triggered by a specific event. + */ + SOLICITED_ONLY = 0, + + /** + * Only transmissions that are not requested. + */ + UNSOLICITED_ONLY = 1, + + /** + * Both solicited and unsolicited transmissions. + */ + SOLICITED_AND_UNSOLICITED = 2, + } + + /** + * Base USD session parameters. + */ + UsdBaseConfig usdBaseConfig; + + /** + * Types of transmissions (solicited vs. unsolicited) which should be generated. + */ + PublishType publishType; + + /** + * Whether Further Service Discovery (FSD) is enabled. + */ + boolean isFsd; + + /** + * Interval (in milliseconds) for sending unsolicited publish transmissions. + */ + int announcementPeriodMillis; + + /** + * Type of the publish transmission (ex. unicast, multicast). + */ + UsdPublishTransmissionType transmissionType; +} diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdPublishTransmissionType.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdPublishTransmissionType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..45a3cf4bf4475e5ba9d59bf03a3f873620cdbfa2 --- /dev/null +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdPublishTransmissionType.aidl @@ -0,0 +1,34 @@ +/* + * 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. + */ + +package android.hardware.wifi.supplicant; + +/** + * Types of USD publish transmissions. + */ +@VintfStability +@Backing(type="int") +enum UsdPublishTransmissionType { + /** + * Sends data from one device to a single, specific destination device. + */ + UNICAST = 0, + + /** + * Sends data from one device to a group of devices on the network simultaneously. + */ + MULTICAST = 1, +} diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdReasonCode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdReasonCode.aidl new file mode 100644 index 0000000000000000000000000000000000000000..4b1aab0c00649e2f771b66d2255f155ec2f989b6 --- /dev/null +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdReasonCode.aidl @@ -0,0 +1,44 @@ +/* + * 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. + */ + +package android.hardware.wifi.supplicant; + +/** + * Codes indicating the status of USD operations. + */ +@VintfStability +@Backing(type="int") +enum UsdReasonCode { + /** + * Unknown failure occurred. + */ + FAILURE_UNKNOWN = 0, + + /** + * The operation timed out. + */ + TIMEOUT = 1, + + /** + * The operation was requested by the user. + */ + USER_REQUESTED = 2, + + /** + * Invalid arguments were provided. + */ + INVALID_ARGS = 3 +} diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdServiceDiscoveryInfo.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdServiceDiscoveryInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..4f6eaf1f2d1925fc214f85b558a7cc16dfb0fcaf --- /dev/null +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdServiceDiscoveryInfo.aidl @@ -0,0 +1,62 @@ +/* + * 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. + */ + +package android.hardware.wifi.supplicant; + +import android.hardware.wifi.supplicant.UsdServiceProtoType; + +/** + * Information about a USD discovery session with a specific peer. + */ +@VintfStability +parcelable UsdServiceDiscoveryInfo { + /** + * Identifier for this device. + */ + int ownId; + + /** + * Identifier for the discovered peer device. + */ + int peerId; + + /** + * MAC address of the discovered peer device. + */ + byte[6] peerMacAddress; + + /** + * Match filter from the discovery packet (publish or subscribe) which caused service discovery. + */ + byte[] matchFilter; + + /** + * Service protocol that is being used (ex. Generic, CSA Matter). + */ + UsdServiceProtoType protoType; + + /** + * Arbitrary service specific information communicated in discovery packets. + * There is no semantic meaning to these bytes. They are passed-through from publisher to + * subscriber as-is with no parsing. + */ + byte[] serviceSpecificInfo; + + /** + * Whether Further Service Discovery (FSD) is enabled. + */ + boolean isFsd; +} diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdServiceProtoType.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdServiceProtoType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..de9beb55a7370626fbf4387d8b2a7f918954b839 --- /dev/null +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdServiceProtoType.aidl @@ -0,0 +1,42 @@ +/* + * 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. + */ + +package android.hardware.wifi.supplicant; + +/** + * Service protocols that use USD. + */ +@VintfStability +@Backing(type="int") +enum UsdServiceProtoType { + /** + * Unknown service type. + */ + UNKNOWN = 0, + + /** + * Generic service. + */ + GENERIC = 1, + + /** + * CSA (Connectivity Standards Alliance) Matter. + * + * Note: CSA Matter is an open-source, royalty-free standard for smart home technology that + * allows devices to work with any Matter-certified ecosystem. + */ + CSA_MATTER = 2, +} diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdSubscribeConfig.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdSubscribeConfig.aidl new file mode 100644 index 0000000000000000000000000000000000000000..4e8893e2e6bf43333cf185fbba8aa7ed75763fa1 --- /dev/null +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdSubscribeConfig.aidl @@ -0,0 +1,56 @@ +/* + * 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. + */ + +package android.hardware.wifi.supplicant; + +import android.hardware.wifi.supplicant.UsdBaseConfig; + +/** + * Parameters for configuring a USD subscribe session. + */ +@VintfStability +parcelable UsdSubscribeConfig { + /** + * Subscribe modes that this session can be configured in. + */ + enum SubscribeType { + /** + * Subscribe function does not request transmission of any Subscribe messages, but checks + * for matches in received Publish messages. + */ + PASSIVE_MODE = 0, + /** + * Subscribe function additionally requests transmission of Subscribe messages and processes + * Publish messages. + */ + ACTIVE_MODE = 1, + } + + /** + * Base USD session parameters. + */ + UsdBaseConfig usdBaseConfig; + + /** + * Subscribe mode that this session should be configured in. + */ + SubscribeType subscribeType; + + /** + * Recommended periodicity (in milliseconds) of query transmissions for the session. + */ + int queryPeriodMillis; +} diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdTerminateReasonCode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdTerminateReasonCode.aidl new file mode 100644 index 0000000000000000000000000000000000000000..6725c3d3583514a7c7f32d4ee57868ae364c7e2b --- /dev/null +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdTerminateReasonCode.aidl @@ -0,0 +1,29 @@ +/* + * 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. + */ + +package android.hardware.wifi.supplicant; + +/** + * Status codes for P2P operations. + */ +@VintfStability +@Backing(type="int") +enum UsdTerminateReasonCode { + UNKNOWN = 0, + TIMEOUT = 1, + USER_REQUEST = 2, + FAILURE = 3, +} diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WifiChannelWidthInMhz.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WifiChannelWidthInMhz.aidl new file mode 100644 index 0000000000000000000000000000000000000000..39c7eba0e6beadb3ffafa6565a5ec4544b0d24d2 --- /dev/null +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WifiChannelWidthInMhz.aidl @@ -0,0 +1,37 @@ +/* + * 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. + */ + +package android.hardware.wifi.supplicant; + +/** + * Channel operating width in Mhz. + */ +@VintfStability +@Backing(type="int") +enum WifiChannelWidthInMhz { + WIDTH_INVALID = -1, + WIDTH_20 = 0, + WIDTH_40 = 1, + WIDTH_80 = 2, + WIDTH_160 = 3, + WIDTH_80P80 = 4, + WIDTH_5 = 5, + WIDTH_10 = 6, + /** + * 320 MHz + */ + WIDTH_320 = 7, +} diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsProvisionMethod.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsProvisionMethod.aidl index 5b59392b71d85d44b99645e2587865db6e749076..b8ad3b826f3e146716c557a08a110e5552742291 100644 --- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsProvisionMethod.aidl +++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsProvisionMethod.aidl @@ -19,6 +19,7 @@ package android.hardware.wifi.supplicant; @VintfStability @Backing(type="int") enum WpsProvisionMethod { + NONE = -1, /** * Push button method. */ diff --git a/wifi/supplicant/aidl/vts/functional/Android.bp b/wifi/supplicant/aidl/vts/functional/Android.bp index 4ffec3f433c68f8861052a6c654cdc51f3e76018..f94eb46bd16c3e7fb51608eda87a1565ba92471b 100644 --- a/wifi/supplicant/aidl/vts/functional/Android.bp +++ b/wifi/supplicant/aidl/vts/functional/Android.bp @@ -43,7 +43,7 @@ cc_test { "android.hardware.wifi@1.3", "android.hardware.wifi@1.4", "android.hardware.wifi@1.5", - "android.hardware.wifi.common-V1-ndk", + "android.hardware.wifi.common-V2-ndk", "android.hardware.wifi.supplicant@1.0", "android.hardware.wifi.supplicant@1.1", "android.hardware.wifi.supplicant-V4-ndk", @@ -52,8 +52,8 @@ cc_test { "VtsHalWifiV1_0TargetTestUtil", "VtsHalWifiV1_5TargetTestUtil", "VtsHalWifiSupplicantV1_0TargetTestUtil", - "android.hardware.wifi.common-V1-ndk", - "android.hardware.wifi-V2-ndk", + "android.hardware.wifi.common-V2-ndk", + "android.hardware.wifi-V3-ndk", "VtsHalWifiTargetTestUtil", ], test_suites: [ @@ -81,7 +81,7 @@ cc_test { "android.hardware.wifi@1.3", "android.hardware.wifi@1.4", "android.hardware.wifi@1.5", - "android.hardware.wifi.common-V1-ndk", + "android.hardware.wifi.common-V2-ndk", "android.hardware.wifi.supplicant@1.0", "android.hardware.wifi.supplicant@1.1", "android.hardware.wifi.supplicant-V4-ndk", @@ -90,8 +90,8 @@ cc_test { "VtsHalWifiV1_0TargetTestUtil", "VtsHalWifiV1_5TargetTestUtil", "VtsHalWifiSupplicantV1_0TargetTestUtil", - "android.hardware.wifi.common-V1-ndk", - "android.hardware.wifi-V2-ndk", + "android.hardware.wifi.common-V2-ndk", + "android.hardware.wifi-V3-ndk", "VtsHalWifiTargetTestUtil", ], test_suites: [ @@ -119,7 +119,7 @@ cc_test { "android.hardware.wifi@1.3", "android.hardware.wifi@1.4", "android.hardware.wifi@1.5", - "android.hardware.wifi.common-V1-ndk", + "android.hardware.wifi.common-V2-ndk", "android.hardware.wifi.supplicant@1.0", "android.hardware.wifi.supplicant@1.1", "android.hardware.wifi.supplicant-V4-ndk", @@ -128,8 +128,8 @@ cc_test { "VtsHalWifiV1_0TargetTestUtil", "VtsHalWifiV1_5TargetTestUtil", "VtsHalWifiSupplicantV1_0TargetTestUtil", - "android.hardware.wifi.common-V1-ndk", - "android.hardware.wifi-V2-ndk", + "android.hardware.wifi.common-V2-ndk", + "android.hardware.wifi-V3-ndk", "VtsHalWifiTargetTestUtil", ], test_suites: [ diff --git a/wifi/supplicant/aidl/vts/functional/supplicant_p2p_iface_aidl_test.cpp b/wifi/supplicant/aidl/vts/functional/supplicant_p2p_iface_aidl_test.cpp index 8f1c4bdee52bb8be3cc0ecb9c3f6ab31602938d0..3638ac5eebdfdfaa85221bdd4196c54dcfc029de 100644 --- a/wifi/supplicant/aidl/vts/functional/supplicant_p2p_iface_aidl_test.cpp +++ b/wifi/supplicant/aidl/vts/functional/supplicant_p2p_iface_aidl_test.cpp @@ -17,8 +17,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -29,6 +31,7 @@ #include "supplicant_test_utils.h" #include "wifi_aidl_test_utils.h" +using aidl::android::hardware::wifi::supplicant::BandMask; using aidl::android::hardware::wifi::supplicant::BnSupplicantP2pIfaceCallback; using aidl::android::hardware::wifi::supplicant::DebugLevel; using aidl::android::hardware::wifi::supplicant::FreqRange; @@ -40,6 +43,7 @@ using aidl::android::hardware::wifi::supplicant::P2pAddGroupConfigurationParams; using aidl::android::hardware::wifi::supplicant::P2pConnectInfo; using aidl::android::hardware::wifi::supplicant::P2pCreateGroupOwnerInfo; using aidl::android::hardware::wifi::supplicant::P2pDeviceFoundEventParams; +using aidl::android::hardware::wifi::supplicant::P2pDirInfo; using aidl::android::hardware::wifi::supplicant::P2pDiscoveryInfo; using aidl::android::hardware::wifi::supplicant::P2pExtListenInfo; using aidl::android::hardware::wifi::supplicant::P2pFrameTypeMask; @@ -47,13 +51,20 @@ using aidl::android::hardware::wifi::supplicant::P2pGoNegotiationReqEventParams; using aidl::android::hardware::wifi::supplicant::P2pGroupCapabilityMask; using aidl::android::hardware::wifi::supplicant::P2pGroupStartedEventParams; using aidl::android::hardware::wifi::supplicant::P2pInvitationEventParams; +using aidl::android::hardware::wifi::supplicant::P2pPairingBootstrappingMethodMask; using aidl::android::hardware::wifi::supplicant::P2pPeerClientDisconnectedEventParams; using aidl::android::hardware::wifi::supplicant::P2pPeerClientJoinedEventParams; using aidl::android::hardware::wifi::supplicant::P2pProvDiscStatusCode; using aidl::android::hardware::wifi::supplicant::P2pProvisionDiscoveryCompletedEventParams; +using aidl::android::hardware::wifi::supplicant::P2pProvisionDiscoveryParams; +using aidl::android::hardware::wifi::supplicant::P2pReinvokePersistentGroupParams; using aidl::android::hardware::wifi::supplicant::P2pScanType; using aidl::android::hardware::wifi::supplicant::P2pStatusCode; +using aidl::android::hardware::wifi::supplicant::P2pUsdBasedServiceAdvertisementConfig; +using aidl::android::hardware::wifi::supplicant::P2pUsdBasedServiceDiscoveryConfig; +using aidl::android::hardware::wifi::supplicant::P2pUsdBasedServiceDiscoveryResultParams; using aidl::android::hardware::wifi::supplicant::SupplicantStatusCode; +using aidl::android::hardware::wifi::supplicant::UsdTerminateReasonCode; using aidl::android::hardware::wifi::supplicant::WpsConfigMethods; using aidl::android::hardware::wifi::supplicant::WpsDevPasswordId; using aidl::android::hardware::wifi::supplicant::WpsProvisionMethod; @@ -67,13 +78,20 @@ const std::vector kTestMacAddr = {0x56, 0x67, 0x67, 0xf4, 0x56, 0x92}; const std::vector kTestPeerMacAddr = {0x56, 0x67, 0x55, 0xf4, 0x56, 0x92}; const std::vector kTestZeroMacAddr = std::vector(6, 0); +const std::string kTestServiceSpecificInfoStr = "TestServiceSpecificInfo"; +const std::vector kTestServiceSpecificInfo = std::vector( + kTestServiceSpecificInfoStr.begin(), kTestServiceSpecificInfoStr.end()); +const std::vector kTestNonce = {0x11, 0x22, 0x33, 0x44, 0x55, 0x92, 0x22, 0x33}; +const std::vector kTestDirTag = {0xaa, 0x22, 0x55, 0x44, 0x55, 0x92, 0x22, 0x33}; const std::string kTestPassphrase = "P2pWorld1234"; const std::string kTestConnectPin = "34556665"; const std::string kTestGroupIfName = "TestGroup"; +const std::string kTestServiceName = "TestServiceName"; const uint32_t kTestFindTimeout = 5; const uint32_t kTestConnectGoIntent = 6; const uint32_t kTestNetworkId = 7; const uint32_t kTestGroupFreq = 0; +const uint32_t kTestServiceProtocolType = 1; const bool kTestGroupPersistent = false; const bool kTestGroupIsJoin = false; const auto& kTestVendorDataOptional = generateOuiKeyedDataListOptional(5); @@ -222,6 +240,18 @@ class SupplicantP2pIfaceCallback : public BnSupplicantP2pIfaceCallback { const P2pInvitationEventParams& /* invitationEventParams */) override { return ndk::ScopedAStatus::ok(); } + ::ndk::ScopedAStatus onUsdBasedServiceDiscoveryResult( + const P2pUsdBasedServiceDiscoveryResultParams& /* discoveryResultParams*/) override { + return ndk::ScopedAStatus::ok(); + } + ::ndk::ScopedAStatus onUsdBasedServiceDiscoveryTerminated( + int32_t /* sessionId */, UsdTerminateReasonCode /* reasonCode */) override { + return ndk::ScopedAStatus::ok(); + } + ::ndk::ScopedAStatus onUsdBasedServiceAdvertisementTerminated( + int32_t /* sessionId */, UsdTerminateReasonCode /* reasonCode */) override { + return ndk::ScopedAStatus::ok(); + } }; class SupplicantP2pIfaceAidlTest : public testing::TestWithParam { @@ -246,6 +276,9 @@ class SupplicantP2pIfaceAidlTest : public testing::TestWithParam { EXPECT_TRUE(supplicant_->getP2pInterface(getP2pIfaceName(), &p2p_iface_) .isOk()); ASSERT_NE(p2p_iface_, nullptr); + if (interface_version_ >= 4) { + EXPECT_TRUE(p2p_iface_->getFeatureSet(&supported_features_).isOk()); + } } void TearDown() override { @@ -257,6 +290,7 @@ class SupplicantP2pIfaceAidlTest : public testing::TestWithParam { std::shared_ptr supplicant_; std::shared_ptr p2p_iface_; int interface_version_; + int64_t supported_features_; }; /* @@ -814,6 +848,139 @@ TEST_P(SupplicantP2pIfaceAidlTest, SetVendorElements) { LOG(INFO) << "SupplicantP2pIfaceAidlTest::SetVendorElements end"; } +/* + * GetFeatureSet + */ +TEST_P(SupplicantP2pIfaceAidlTest, gGetFeatureSet) { + if (interface_version_ < 4) { + GTEST_SKIP() << "getFeatureSet is available as of Supplicant V4"; + } + int64_t featureSet; + EXPECT_TRUE(p2p_iface_->getFeatureSet(&featureSet).isOk()); +} + +/* + * StartUsdBasedServiceDiscovery/stopUsdBasedServiceDiscovery + */ +TEST_P(SupplicantP2pIfaceAidlTest, StartStopUsdBasedServiceDiscovery) { + if (interface_version_ < 4) { + GTEST_SKIP() << "Start/Stop UsdBasedServiceDiscovery is available as of Supplicant V4"; + } + if (!(supported_features_ & ISupplicantP2pIface::P2P_FEATURE_V2)) { + GTEST_SKIP() << "P2P2 is not supported"; + } + + int32_t sessionId; + P2pUsdBasedServiceDiscoveryConfig config; + config.serviceName = kTestServiceName; + config.serviceProtocolType = kTestServiceProtocolType; + config.serviceSpecificInfo = kTestServiceSpecificInfo; + config.bandMask = BandMask::BAND_2_GHZ; + config.timeoutInSeconds = 30; + + EXPECT_TRUE(p2p_iface_->startUsdBasedServiceDiscovery(config, &sessionId).isOk()); + sleep(1); + EXPECT_TRUE(p2p_iface_->stopUsdBasedServiceDiscovery(sessionId).isOk()); +} + +/* + * StartUsdBasedServiceAdvertisement/StopUsdBasedServiceAdvertisement + */ +TEST_P(SupplicantP2pIfaceAidlTest, StartStopUsdBasedServiceAdvertisement) { + if (interface_version_ < 4) { + GTEST_SKIP() << "start/Stop UsdBasedServiceAdvertisement is available as of Supplicant V4"; + } + if (!(supported_features_ & ISupplicantP2pIface::P2P_FEATURE_V2)) { + GTEST_SKIP() << "P2P2 is not supported"; + } + + int32_t sessionId; + P2pUsdBasedServiceAdvertisementConfig config; + config.serviceName = kTestServiceName; + config.serviceProtocolType = kTestServiceProtocolType; + config.serviceSpecificInfo = kTestServiceSpecificInfo; + config.frequencyMHz = 2412; + config.timeoutInSeconds = 30; + + EXPECT_TRUE(p2p_iface_->startUsdBasedServiceAdvertisement(config, &sessionId).isOk()); + sleep(1); + EXPECT_TRUE(p2p_iface_->stopUsdBasedServiceAdvertisement(sessionId).isOk()); +} + +/* + * ProvisionDiscoveryWithParams + */ +TEST_P(SupplicantP2pIfaceAidlTest, ProvisionDiscoveryWithParams) { + if (interface_version_ < 4) { + GTEST_SKIP() << "ProvisionDiscoveryWithParams is available as of Supplicant V4"; + } + if (!(supported_features_ & ISupplicantP2pIface::P2P_FEATURE_V2)) { + GTEST_SKIP() << "P2P2 is not supported"; + } + + P2pProvisionDiscoveryParams params; + params.peerMacAddress = vecToArrayMacAddr(kTestMacAddr); + params.provisionMethod = WpsProvisionMethod::NONE; + params.pairingBootstrappingMethod = + P2pPairingBootstrappingMethodMask::BOOTSTRAPPING_OPPORTUNISTIC; + + EXPECT_TRUE(p2p_iface_->provisionDiscoveryWithParams(params).isOk()); +} + +/* + * ValidateDirInfo + */ +TEST_P(SupplicantP2pIfaceAidlTest, ValidateDirInfo) { + if (interface_version_ < 4) { + GTEST_SKIP() << "ValidateDirInfo is available as of Supplicant V4"; + } + if (!(supported_features_ & ISupplicantP2pIface::P2P_FEATURE_V2)) { + GTEST_SKIP() << "P2P2 is not supported"; + } + + int32_t ret; + P2pDirInfo dirInfo; + dirInfo.cipherVersion = P2pDirInfo::CipherVersion::DIRA_CIPHER_VERSION_128_BIT; + dirInfo.deviceInterfaceMacAddress = vecToArrayMacAddr(kTestMacAddr); + dirInfo.nonce = kTestNonce; + dirInfo.dirTag = kTestDirTag; + EXPECT_TRUE(p2p_iface_->validateDirInfo(dirInfo, &ret).isOk()); +} + +/* + * GetDirInfo + */ +TEST_P(SupplicantP2pIfaceAidlTest, GetDirInfo) { + if (interface_version_ < 4) { + GTEST_SKIP() << "GetDirInfo is available as of Supplicant V4"; + } + if (!(supported_features_ & ISupplicantP2pIface::P2P_FEATURE_V2)) { + GTEST_SKIP() << "P2P2 is not supported"; + } + + P2pDirInfo dirInfo; + EXPECT_TRUE(p2p_iface_->getDirInfo(&dirInfo).isOk()); +} + +/* + * ReinvokePersistentGroup + */ +TEST_P(SupplicantP2pIfaceAidlTest, ReinvokePersistentGroup) { + if (interface_version_ < 4) { + GTEST_SKIP() << "ReinvokePersistentGroup is available as of Supplicant V4"; + } + if (!(supported_features_ & ISupplicantP2pIface::P2P_FEATURE_V2)) { + GTEST_SKIP() << "P2P2 is not supported"; + } + + P2pReinvokePersistentGroupParams params; + params.peerMacAddress = vecToArrayMacAddr(kTestMacAddr); + params.persistentNetworkId = 0; + params.deviceIdentityEntryId = 0; + + EXPECT_TRUE(p2p_iface_->reinvokePersistentGroup(params).isOk()); +} + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantP2pIfaceAidlTest); INSTANTIATE_TEST_SUITE_P(Supplicant, SupplicantP2pIfaceAidlTest, testing::ValuesIn(android::getAidlHalInstanceNames( diff --git a/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp b/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp index 6b04aa98ee073d6b964f4cf0bde537530531990e..c9ad498a2232340cab91cf6f8e9af676baad77ca 100644 --- a/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp +++ b/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp @@ -47,6 +47,9 @@ using aidl::android::hardware::wifi::supplicant::MscsParams; using aidl::android::hardware::wifi::supplicant::QosCharacteristics; using aidl::android::hardware::wifi::supplicant::QosPolicyScsData; using aidl::android::hardware::wifi::supplicant::QosPolicyScsRequestStatus; +using aidl::android::hardware::wifi::supplicant::UsdMessageInfo; +using aidl::android::hardware::wifi::supplicant::UsdReasonCode; +using aidl::android::hardware::wifi::supplicant::UsdServiceDiscoveryInfo; using aidl::android::hardware::wifi::supplicant::WpaDriverCapabilitiesMask; using aidl::android::hardware::wifi::supplicant::WpsConfigMethods; using android::ProcessState; @@ -243,6 +246,38 @@ class SupplicantStaIfaceCallback : public BnSupplicantStaIfaceCallback { override { return ndk::ScopedAStatus::ok(); } + ::ndk::ScopedAStatus onUsdPublishStarted(int32_t /* cmdId */, + int32_t /* publishId */) override { + return ndk::ScopedAStatus::ok(); + } + ::ndk::ScopedAStatus onUsdSubscribeStarted(int32_t /* cmdId */, + int32_t /* subscribeId */) override { + return ndk::ScopedAStatus::ok(); + } + ::ndk::ScopedAStatus onUsdPublishConfigFailed(int32_t /* cmdId */) override { + return ndk::ScopedAStatus::ok(); + } + ::ndk::ScopedAStatus onUsdSubscribeConfigFailed(int32_t /* cmdId */) override { + return ndk::ScopedAStatus::ok(); + } + ::ndk::ScopedAStatus onUsdPublishTerminated(int32_t /* publishId */, + UsdReasonCode /* reasonCode */) override { + return ndk::ScopedAStatus::ok(); + } + ::ndk::ScopedAStatus onUsdSubscribeTerminated(int32_t /* subscribeId */, + UsdReasonCode /* reasonCode */) override { + return ndk::ScopedAStatus::ok(); + } + ::ndk::ScopedAStatus onUsdPublishReplied(const UsdServiceDiscoveryInfo& /* info */) override { + return ndk::ScopedAStatus::ok(); + } + ::ndk::ScopedAStatus onUsdServiceDiscovered( + const UsdServiceDiscoveryInfo& /* info */) override { + return ndk::ScopedAStatus::ok(); + } + ::ndk::ScopedAStatus onUsdMessageReceived(const UsdMessageInfo& /* messageInfo */) override { + return ndk::ScopedAStatus::ok(); + } }; class SupplicantStaIfaceAidlTest : public testing::TestWithParam {