Merge "Virtual Face: use file_contexts in system/sepolicy" into main am: 9cc048b171 am: 205cdad160
Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/3431788
Change-Id: I9bbef0f52e558e58d26689cc7cb9053d49a8a4ef
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Spatializer.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Spatializer.aidl
index 98ecee0..efc1ab2 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Spatializer.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Spatializer.aidl
@@ -42,6 +42,7 @@
android.media.audio.common.HeadTracking.Mode headTrackingMode;
android.media.audio.common.HeadTracking.ConnectionMode headTrackingConnectionMode;
android.media.audio.common.HeadTracking.SensorData headTrackingSensorData;
+ android.media.audio.common.AudioChannelLayout[] spatializedChannelLayout;
@VintfStability
union Id {
android.hardware.audio.effect.VendorExtension vendorExtensionTag;
diff --git a/audio/aidl/android/hardware/audio/effect/IFactory.aidl b/audio/aidl/android/hardware/audio/effect/IFactory.aidl
index b80e6ac..75d4d9e 100644
--- a/audio/aidl/android/hardware/audio/effect/IFactory.aidl
+++ b/audio/aidl/android/hardware/audio/effect/IFactory.aidl
@@ -74,13 +74,18 @@
/**
* Called by the framework to destroy the effect and free up all currently allocated resources.
- * It is recommended to destroy the effect from the client side as soon as it is becomes unused.
+ * This method can be called at any time to destroy an effect instance. It is recommended to
+ * destroy the effect from the client side as soon as it becomes unused to free up resources.
*
- * The client must ensure effect instance is closed before destroy.
+ * The effect instance must handle any necessary cleanup and resource deallocation.
+ * If the effect is in the **PROCESSING** or **DRAINING** state, it must gracefully stop
+ * processing before destruction.
+ * The effect must ensure that all internal states are properly cleaned up to prevent resource
+ * leaks.
*
* @param handle The handle of effect instance to be destroyed.
* @throws EX_ILLEGAL_ARGUMENT if the effect handle is not valid.
- * @throws EX_ILLEGAL_STATE if the effect instance is not in a proper state to be destroyed.
+ * @throws EX_ILLEGAL_STATE if the effect instance can not be destroyed.
*/
void destroyEffect(in IEffect handle);
}
diff --git a/audio/aidl/android/hardware/audio/effect/Spatializer.aidl b/audio/aidl/android/hardware/audio/effect/Spatializer.aidl
index 71e3ffe..e86452d 100644
--- a/audio/aidl/android/hardware/audio/effect/Spatializer.aidl
+++ b/audio/aidl/android/hardware/audio/effect/Spatializer.aidl
@@ -86,4 +86,20 @@
* Headtracking sensor data.
*/
HeadTracking.SensorData headTrackingSensorData;
+
+ /**
+ * Spatialized channel layouts.
+ * A spatialized channel layout is one where each virtual speaker position is rendered
+ * at its corresponding virtual position, and is not downmixed with any other.
+ * For instance if a spatializer is only capable of distinct positions for 5.1, it would only
+ * return 5.1:
+ * - the list wouldn't include 4.0, because that mask is "contained" within 5.1
+ * - the list wouldn't include 7.1 (and so on) because the side and rear channels would be
+ * downmixed together.
+ * Another example is a spatializer that can only spatialize up to 9 channels (not counting .1)
+ * and that supports 5.1.4, and 7.1.2, the list should include both.
+ * The values must also be part of the values reported by supportedChannelLayout.
+ * The array containing the values cannot be empty.
+ */
+ AudioChannelLayout[] spatializedChannelLayout;
}
diff --git a/audio/aidl/android/hardware/audio/effect/State.aidl b/audio/aidl/android/hardware/audio/effect/State.aidl
index 1b698d7..ecd1bbe 100644
--- a/audio/aidl/android/hardware/audio/effect/State.aidl
+++ b/audio/aidl/android/hardware/audio/effect/State.aidl
@@ -24,6 +24,8 @@
* it should transfer to IDLE state after handle the command successfully. Effect instance should
* consume minimal resource and transfer to INIT state after it was close().
*
+ * An effect instance can be destroyed from any state using `IFactory.destroyEffect()`.
+ *
* Refer to the state machine diagram `state.gv` for a detailed state diagram.
*/
@VintfStability
@@ -66,6 +68,7 @@
* - Transitions to **INIT** on `IEffect.close()`.
* - Remains in **IDLE** on `IEffect.getParameter()`, `IEffect.setParameter()`,
* `IEffect.getDescriptor()`, `IEffect.command(CommandId.RESET)`, and `IEffect.reopen()`.
+ * - Transitions to the final state on `IFactory.destroyEffect()`.
*/
IDLE,
@@ -98,6 +101,7 @@
* stop processing with `CommandId.STOP` before closing.
* - If `IEffect.close()` is called in this state, the effect instance should stop processing,
* transition to **IDLE**, and then close.
+ * - Transitions to the final state on `IFactory.destroyEffect()`.
*/
PROCESSING,
@@ -123,6 +127,7 @@
* - If not implemented, the effect instance may transition directly from **PROCESSING** to
* **IDLE** without this intermediate state.
* - Any `CommandId.STOP` commands received during **DRAINING** should be ignored.
+ * - Transitions to the final state on `IFactory.destroyEffect()`.
*/
DRAINING,
}
diff --git a/audio/aidl/android/hardware/audio/effect/state.gv b/audio/aidl/android/hardware/audio/effect/state.gv
index 2a8194e..8590296 100644
--- a/audio/aidl/android/hardware/audio/effect/state.gv
+++ b/audio/aidl/android/hardware/audio/effect/state.gv
@@ -13,8 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-// To render: "dot -Tpng state.gv -o state.png"
+// To render: "dot -Tpng state.gv -o state.png"
digraph effect_state_machine {
rankdir=LR; // Left to Right layout
@@ -29,40 +29,30 @@
I [shape=point, fillcolor=black, width=0.2];
// Final state node
- F [shape=doublecircle, fillcolor=white, width=0.2];
+ F [shape=doublecircle, label="Destroyed"];
// Define other nodes with colors
- INIT [shape=ellipse, fillcolor=lightgreen];
- IDLE [shape=ellipse, fillcolor=lightblue];
- PROCESSING [shape=ellipse, fillcolor=lightyellow];
- DRAINING [shape=ellipse, fillcolor=lightgrey];
+ INIT [shape=ellipse, fillcolor=lightgreen, label="INIT"];
+ IDLE [shape=ellipse, fillcolor=lightblue, label="IDLE"];
+ PROCESSING [shape=ellipse, fillcolor=lightyellow, label="PROCESSING"];
+ DRAINING [shape=ellipse, fillcolor=lightgrey, label="DRAINING"];
+ ANY_STATE [shape=ellipse, style=dashed, label="Any State", fillcolor=white];
- // Transitions
+ // Main transitions
I -> INIT [label="IFactory.createEffect", fontcolor="navy"];
-
- INIT -> F [label="IFactory.destroyEffect"];
-
INIT -> IDLE [label="IEffect.open()", fontcolor="lime"];
-
IDLE -> PROCESSING [label="IEffect.command(START)"];
-
- PROCESSING -> IDLE [label="IEffect.command(STOP)\nIEffect.command(RESET)"];
-
- PROCESSING -> DRAINING [label="IEffect.command(STOP)", fontcolor="orange"];
-
- DRAINING -> IDLE [label="Draining complete\n(IEffect.command(RESET)\nautomatic)"];
-
- DRAINING -> PROCESSING [label="IEffect.command(START)\n(Interrupt draining)"];
-
+ PROCESSING -> IDLE [label="IEffect.command(STOP) (if draining not required)\nIEffect.command(RESET)"];
+ PROCESSING -> DRAINING [label="IEffect.command(STOP) (if draining required)", fontcolor="orange"];
+ DRAINING -> IDLE [label="IEffect.command(RESET)\nDraining complete (automatic transition)"];
+ DRAINING -> PROCESSING [label="IEffect.command(START) (Interrupt draining)"];
IDLE -> INIT [label="IEffect.close()"];
- // Self-loops
- INIT -> INIT [label="IEffect.getState\nIEffect.getDescriptor"];
-
- IDLE -> IDLE [label="IEffect.getParameter\nIEffect.setParameter\nIEffect.getDescriptor\nIEffect.command(RESET)\nIEffect.reopen"];
-
- PROCESSING -> PROCESSING [label="IEffect.getParameter\nIEffect.setParameter\nIEffect.getDescriptor\nIEffect.reopen"];
-
- DRAINING -> DRAINING [label="IEffect.getParameter\nIEffect.setParameter\nIEffect.getDescriptor\nIEffect.reopen\nFading"];
-
+ // Global transitions
+ subgraph cluster_global_transitions {
+ label="Global Transitions (Any State)";
+ style=dashed;
+ ANY_STATE -> F [label="IFactory.destroyEffect", style="bold"];
+ ANY_STATE -> ANY_STATE [label="IEffect.getParameter\nIEffect.setParameter\nIEffect.getDescriptor\nIEffect.getState\nIEffect.reopen", fontsize=10];
+ }
}
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
index 73d7626..687d8fc 100644
--- a/audio/aidl/default/Android.bp
+++ b/audio/aidl/default/Android.bp
@@ -121,6 +121,52 @@
],
}
+cc_library {
+ name: "libeffectconfig",
+ srcs: [
+ "EffectConfig.cpp",
+ ],
+ defaults: [
+ "latest_android_hardware_audio_effect_ndk_shared",
+ "latest_android_media_audio_common_types_ndk_shared",
+ ],
+ shared_libs: [
+ "libaudioutils",
+ "libaudio_aidl_conversion_common_ndk",
+ "libbase",
+ "libbinder_ndk",
+ "liblog",
+ "libmedia_helper",
+ "libtinyxml2",
+ "libutils",
+ ],
+ header_libs: [
+ "libaudio_system_headers",
+ "libaudioaidl_headers",
+ ],
+ export_shared_lib_headers: [
+ "libtinyxml2",
+ ],
+ export_include_dirs: [
+ "include",
+ ],
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ "-DBACKEND_NDK",
+ ],
+ vendor: true,
+ host_supported: true,
+ target: {
+ android: {
+ shared_libs: [
+ "libapexsupport",
+ ],
+ },
+ },
+}
+
cc_binary {
name: "android.hardware.audio.service-aidl.example",
relative_install_path: "hw",
@@ -200,6 +246,47 @@
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: [
@@ -249,10 +336,9 @@
defaults: ["aidlaudioeffectservice_defaults"],
shared_libs: [
"libapexsupport",
- "libtinyxml2",
+ "libeffectconfig",
],
srcs: [
- "EffectConfig.cpp",
"EffectFactory.cpp",
"EffectMain.cpp",
],
diff --git a/audio/aidl/default/EffectConfig.cpp b/audio/aidl/default/EffectConfig.cpp
index 9c335ba..fa12056 100644
--- a/audio/aidl/default/EffectConfig.cpp
+++ b/audio/aidl/default/EffectConfig.cpp
@@ -106,6 +106,7 @@
}
bool EffectConfig::resolveLibrary(const std::string& path, std::string* resolvedPath) {
+#ifdef __ANDROID_APEX__
if constexpr (__ANDROID_VENDOR_API__ >= 202404) {
AApexInfo *apexInfo;
if (AApexInfo_create(&apexInfo) == AAPEXINFO_OK) {
@@ -122,6 +123,7 @@
} else {
LOG(DEBUG) << __func__ << " libapexsupport is not supported";
}
+#endif
// If audio effects libs are not in vendor apex, locate them in kEffectLibPath
for (auto* libraryDirectory : kEffectLibPath) {
diff --git a/audio/aidl/default/EffectImpl.cpp b/audio/aidl/default/EffectImpl.cpp
index 7857f53..97f7286 100644
--- a/audio/aidl/default/EffectImpl.cpp
+++ b/audio/aidl/default/EffectImpl.cpp
@@ -22,7 +22,10 @@
#include "effect-impl/EffectTypes.h"
#include "include/effect-impl/EffectTypes.h"
+using aidl::android::hardware::audio::effect::CommandId;
+using aidl::android::hardware::audio::effect::Descriptor;
using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::kDestroyAnyStateSupportedVersion;
using aidl::android::hardware::audio::effect::kEventFlagDataMqNotEmpty;
using aidl::android::hardware::audio::effect::kEventFlagNotEmpty;
using aidl::android::hardware::audio::effect::kReopenSupportedVersion;
@@ -31,13 +34,45 @@
using ::android::hardware::EventFlag;
extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
- State state;
- ndk::ScopedAStatus status = instanceSp->getState(&state);
- if (!status.isOk() || State::INIT != state) {
+ if (!instanceSp) {
+ LOG(ERROR) << __func__ << " nullptr";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+
+ Descriptor desc;
+ ndk::ScopedAStatus status = instanceSp->getDescriptor(&desc);
+ if (!status.isOk()) {
LOG(ERROR) << __func__ << " instance " << instanceSp.get()
+ << " failed to get descriptor, status: " << status.getDescription();
+ return EX_ILLEGAL_STATE;
+ }
+
+ State state;
+ status = instanceSp->getState(&state);
+ if (!status.isOk()) {
+ LOG(ERROR) << __func__ << " " << desc.common.name << " instance " << instanceSp.get()
<< " in state: " << toString(state) << ", status: " << status.getDescription();
return EX_ILLEGAL_STATE;
}
+
+ int effectVersion = 0;
+ if (!instanceSp->getInterfaceVersion(&effectVersion).isOk()) {
+ LOG(WARNING) << __func__ << " " << desc.common.name << " failed to get interface version";
+ }
+
+ if (effectVersion < kDestroyAnyStateSupportedVersion) {
+ if (State::INIT != state) {
+ LOG(ERROR) << __func__ << " " << desc.common.name << " can not destroy instance "
+ << instanceSp.get() << " in state: " << toString(state);
+ return EX_ILLEGAL_STATE;
+ }
+ } else {
+ instanceSp->command(CommandId::RESET);
+ instanceSp->close();
+ }
+
+ LOG(DEBUG) << __func__ << " " << desc.common.name << " instance " << instanceSp.get()
+ << " destroyed";
return EX_NONE;
}
diff --git a/audio/aidl/default/alsa/Utils.cpp b/audio/aidl/default/alsa/Utils.cpp
index 10374f2..77e4f65 100644
--- a/audio/aidl/default/alsa/Utils.cpp
+++ b/audio/aidl/default/alsa/Utils.cpp
@@ -39,6 +39,8 @@
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 @@
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 @@
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<int16_t>(vl)) >> 12;
+ *intBuffer++ = clamp16(mono);
+ } while (--numFrames);
+ } else {
+ do {
+ int32_t mono = mul(*intBuffer, static_cast<int16_t>(vl)) >> 12;
+ *intBuffer++ = static_cast<int16_t>(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 @@
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 @@
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<int16_t>(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<int32_t[]> 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 3814fe6..c675820 100644
--- a/audio/aidl/default/config/audioPolicy/api/current.txt
+++ b/audio/aidl/default/config/audioPolicy/api/current.txt
@@ -144,6 +144,7 @@
enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_HEARING_AID;
enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_IP;
enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_LINE;
+ enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_MULTICHANNEL_GROUP;
enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_PROXY;
enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_SPDIF;
@@ -222,6 +223,18 @@
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 cfe0a6e..94856a5 100644
--- a/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
+++ b/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
@@ -262,6 +262,7 @@
<xs:enumeration value="AUDIO_DEVICE_OUT_AUX_LINE"/>
<xs:enumeration value="AUDIO_DEVICE_OUT_SPEAKER_SAFE"/>
<xs:enumeration value="AUDIO_DEVICE_OUT_IP"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_MULTICHANNEL_GROUP"/>
<xs:enumeration value="AUDIO_DEVICE_OUT_BUS"/>
<xs:enumeration value="AUDIO_DEVICE_OUT_PROXY"/>
<xs:enumeration value="AUDIO_DEVICE_OUT_USB_HEADSET"/>
@@ -416,6 +417,18 @@
<xs:enumeration value="AUDIO_FORMAT_APTX_ADAPTIVE_R4"/>
<xs:enumeration value="AUDIO_FORMAT_DTS_HD_MA"/>
<xs:enumeration value="AUDIO_FORMAT_DTS_UHD_P2"/>
+ <xs:enumeration value="AUDIO_FORMAT_IAMF_SIMPLE_OPUS"/>
+ <xs:enumeration value="AUDIO_FORMAT_IAMF_SIMPLE_AAC"/>
+ <xs:enumeration value="AUDIO_FORMAT_IAMF_SIMPLE_PCM"/>
+ <xs:enumeration value="AUDIO_FORMAT_IAMF_SIMPLE_FLAC"/>
+ <xs:enumeration value="AUDIO_FORMAT_IAMF_BASE_OPUS"/>
+ <xs:enumeration value="AUDIO_FORMAT_IAMF_BASE_AAC"/>
+ <xs:enumeration value="AUDIO_FORMAT_IAMF_BASE_PCM"/>
+ <xs:enumeration value="AUDIO_FORMAT_IAMF_BASE_FLAC"/>
+ <xs:enumeration value="AUDIO_FORMAT_IAMF_BASE_ENHANCED_OPUS"/>
+ <xs:enumeration value="AUDIO_FORMAT_IAMF_BASE_ENHANCED_AAC"/>
+ <xs:enumeration value="AUDIO_FORMAT_IAMF_BASE_ENHANCED_PCM"/>
+ <xs:enumeration value="AUDIO_FORMAT_IAMF_BASE_ENHANCED_FLAC"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="extendableAudioFormat">
diff --git a/audio/aidl/default/config/audioPolicy/engine/api/current.txt b/audio/aidl/default/config/audioPolicy/engine/api/current.txt
index 017362f..41cfb44 100644
--- a/audio/aidl/default/config/audioPolicy/engine/api/current.txt
+++ b/audio/aidl/default/config/audioPolicy/engine/api/current.txt
@@ -266,6 +266,7 @@
enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_NOTIFICATION_EVENT;
enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_SAFETY;
+ enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_SPEAKER_CLEANUP;
enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_UNKNOWN;
enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_VEHICLE_STATUS;
enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_VIRTUAL_SOURCE;
diff --git a/audio/aidl/default/config/audioPolicy/engine/audio_policy_engine_configuration.xsd b/audio/aidl/default/config/audioPolicy/engine/audio_policy_engine_configuration.xsd
index cfd99eb..02250c7 100644
--- a/audio/aidl/default/config/audioPolicy/engine/audio_policy_engine_configuration.xsd
+++ b/audio/aidl/default/config/audioPolicy/engine/audio_policy_engine_configuration.xsd
@@ -376,6 +376,7 @@
<xs:enumeration value="AUDIO_USAGE_SAFETY" />
<xs:enumeration value="AUDIO_USAGE_VEHICLE_STATUS" />
<xs:enumeration value="AUDIO_USAGE_ANNOUNCEMENT" />
+ <xs:enumeration value="AUDIO_USAGE_SPEAKER_CLEANUP" />
</xs:restriction>
</xs:simpleType>
diff --git a/audio/aidl/default/tests/AlsaUtilsTest.cpp b/audio/aidl/default/tests/AlsaUtilsTest.cpp
new file mode 100644
index 0000000..226eea0
--- /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 <alsa/Utils.h>
+#include <android-base/macros.h>
+#include <audio_utils/primitives.h>
+#include <gtest/gtest.h>
+#include <log/log.h>
+
+extern "C" {
+#include <tinyalsa/pcm.h>
+}
+
+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<int16_t> kInt16Buffer = {10000, 100, 0, INT16_MAX,
+ INT16_MIN, -2500, 1000, -5800};
+const static std::vector<float> kFloatBuffer = {0.5, -0.6, kFloatMin, 0.01, kFloatMax, 0.0};
+const static std::vector<int32_t> kInt32Buffer = {100, 0, 8000, INT32_MAX, INT32_MIN, -300};
+const static std::vector<int32_t> kQ8_23Buffer = {
+ kQ8_23Min, kQ8_23Max, 0x00000000, 0x00000001, 0x00400000, static_cast<int32_t>(0xFFD33333)};
+const static std::vector<int32_t> kInt24Buffer = {200, 10, -100, 0, kInt24Min, kInt24Max};
+
+template <typename T>
+void* CopyToBuffer(int& bytesToTransfer, std::vector<T>& destBuffer,
+ const std::vector<T>& srcBuffer) {
+ bytesToTransfer = srcBuffer.size() * sizeof(T);
+ destBuffer = srcBuffer;
+ return destBuffer.data();
+}
+
+template <typename T>
+void VerifyTypedBufferResults(const std::vector<T>& bufferWithGain, const std::vector<T>& srcBuffer,
+ float gain, float tolerance) {
+ for (size_t i = 0; i < srcBuffer.size(); i++) {
+ EXPECT_NEAR(srcBuffer[i] * gain, static_cast<float>(bufferWithGain[i]), tolerance);
+ }
+}
+
+template <typename T>
+void VerifyTypedBufferResultsWithClamp(const std::vector<T>& bufferWithGain,
+ const std::vector<T>& 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<float>(minValue),
+ static_cast<float>(maxValue));
+ EXPECT_NEAR(expectedResult, static_cast<float>(bufferWithGain[i]), tolerance);
+ }
+}
+
+} // namespace
+
+using ApplyGainTestParameters = std::tuple<pcm_format, int, float>;
+enum { INDEX_PCM_FORMAT, INDEX_CHANNEL_COUNT, INDEX_GAIN };
+
+class ApplyGainTest : public ::testing::TestWithParam<ApplyGainTestParameters> {
+ 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<int16_t> mInt16BufferToConvert;
+ std::vector<float> mFloatBufferToConvert;
+ std::vector<int32_t> mInt32BufferToConvert;
+ std::vector<int32_t> mQ8_23BufferToConvert;
+ std::vector<int32_t> mInt24BufferToConvert;
+};
+
+void ApplyGainTest::SetUp() {
+ mPcmFormat = std::get<INDEX_PCM_FORMAT>(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<int32_t> original32BitBuffer(kInt24Buffer.begin(), kInt24Buffer.end());
+ for (auto& val : original32BitBuffer) {
+ val <<= 8;
+ }
+ mInt24BufferToConvert = std::vector<int32_t>(kInt24Buffer.size());
+ mBufferSizeBytes = kInt24Buffer.size() * 3 * sizeof(uint8_t);
+ memcpy_to_p24_from_i32(reinterpret_cast<uint8_t*>(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>(float_from_q8_23(mQ8_23BufferToConvert[i])),
+ kFloatTolerance);
+ }
+ } break;
+ case PCM_FORMAT_S24_3LE: {
+ size_t bufferSize = kInt24Buffer.size();
+ std::vector<int32_t> result32BitBuffer(bufferSize);
+ memcpy_to_i32_from_p24(result32BitBuffer.data(),
+ reinterpret_cast<uint8_t*>(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_t>(INT16_MIN),
+ static_cast<int16_t>(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>(float_from_q8_23(mQ8_23BufferToConvert[i])),
+ kFloatTolerance);
+ }
+ } break;
+ case PCM_FORMAT_S24_3LE: {
+ size_t bufferSize = kInt24Buffer.size();
+ std::vector<int32_t> result32BitBuffer(bufferSize);
+ memcpy_to_i32_from_p24(result32BitBuffer.data(),
+ reinterpret_cast<uint8_t*>(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<INDEX_GAIN>(GetParam());
+ int channelCount = std::get<INDEX_CHANNEL_COUNT>(GetParam());
+
+ alsa::applyGain(mBuffer, gain, mBufferSizeBytes, mPcmFormat, channelCount);
+
+ if (gain <= kUnityGain) {
+ VerifyBufferResult(mPcmFormat, gain);
+ } else {
+ VerifyBufferResultWithClamp(mPcmFormat, gain);
+ }
+}
+
+std::string GetApplyGainTestName(const testing::TestParamInfo<ApplyGainTestParameters>& info) {
+ std::string testNameStr;
+ switch (std::get<INDEX_PCM_FORMAT>(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<INDEX_CHANNEL_COUNT>(info.param) == 1 ? "_Mono_" : "_Stereo_";
+ testNameStr += std::get<INDEX_GAIN>(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/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp
index 5f0a608..14e70ef 100644
--- a/audio/aidl/vts/Android.bp
+++ b/audio/aidl/vts/Android.bp
@@ -31,6 +31,7 @@
],
header_libs: [
"libaudioaidl_headers",
+ "libaudioutils_headers",
"libexpectedutils_headers",
],
cflags: [
diff --git a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
index d23bdc9..5b78981 100644
--- a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
@@ -42,6 +42,7 @@
using aidl::android::hardware::audio::effect::Flags;
using aidl::android::hardware::audio::effect::IEffect;
using aidl::android::hardware::audio::effect::IFactory;
+using aidl::android::hardware::audio::effect::kDestroyAnyStateSupportedVersion;
using aidl::android::hardware::audio::effect::Parameter;
using aidl::android::hardware::audio::effect::State;
using aidl::android::media::audio::common::AudioDeviceDescription;
@@ -316,28 +317,39 @@
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
-// Expect EX_ILLEGAL_STATE if the effect instance is not in a proper state to be destroyed.
+// Expect EX_ILLEGAL_STATE if the effect instance is not in a proper state to be destroyed before
+// `kDestroyAnyStateSupportedVersion`.
+// For any version after `kDestroyAnyStateSupportedVersion`, expect `destroy` to always success.
TEST_P(AudioEffectTest, DestroyOpenEffects) {
ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
ASSERT_NO_FATAL_FAILURE(open(mEffect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect, EX_ILLEGAL_STATE));
-
- // cleanup
- ASSERT_NO_FATAL_FAILURE(close(mEffect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+ if (mVersion < kDestroyAnyStateSupportedVersion) {
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect, EX_ILLEGAL_STATE));
+ // cleanup
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+ } else {
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+ }
}
-// Expect EX_ILLEGAL_STATE if the effect instance is not in a proper state to be destroyed.
+// Expect EX_ILLEGAL_STATE if the effect instance is not in a proper state to be destroyed before
+// `kDestroyAnyStateSupportedVersion`.
+// For any version after `kDestroyAnyStateSupportedVersion`, expect `destroy` to always success.
TEST_P(AudioEffectTest, DestroyProcessingEffects) {
ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
ASSERT_NO_FATAL_FAILURE(open(mEffect));
ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect, EX_ILLEGAL_STATE));
- // cleanup
- ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(close(mEffect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+ if (mVersion < kDestroyAnyStateSupportedVersion) {
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect, EX_ILLEGAL_STATE));
+ // cleanup
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+ } else {
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+ }
}
TEST_P(AudioEffectTest, NormalSequenceStates) {
diff --git a/automotive/TEST_MAPPING b/automotive/TEST_MAPPING
index 483a85f..2b2f6b0 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 0000000..2685f58
--- /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 <name>-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 0000000..0a3c677
--- /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 <name>-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<android.media.audio.common.AudioAttributes> unfadableAudioAttributes;
+ List<android.hardware.automotive.audiocontrol.FadeConfiguration> fadeOutConfigurations;
+ List<android.hardware.automotive.audiocontrol.FadeConfiguration> 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 58a3667..8eab521 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 @@
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 0000000..57a9812
--- /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 <name>-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<android.hardware.automotive.audiocontrol.AudioZoneConfig> audioZoneConfigs;
+ List<android.media.audio.common.AudioPort> 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 0000000..3fd37bc
--- /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 <name>-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<android.hardware.automotive.audiocontrol.VolumeGroupConfig> 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 0000000..0f8b946
--- /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 <name>-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<android.hardware.automotive.audiocontrol.AudioZoneContextInfo> 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 0000000..01ab1be
--- /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 <name>-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<android.media.audio.common.AudioAttributes> 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 0000000..f3f32bf
--- /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 <name>-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<android.hardware.automotive.audiocontrol.TransientFadeConfigurationEntry> 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 0000000..923b0bd
--- /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 <name>-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<String> 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 0000000..2c978e7
--- /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 <name>-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 0000000..9b25dfb
--- /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 <name>-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 ffd575d..fe39f92 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 @@
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<android.media.audio.common.AudioPort> getOutputMirroringDevices();
+ List<android.hardware.automotive.audiocontrol.AudioZone> 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 c1e22d4..8d66985 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 0000000..901078c
--- /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 <name>-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 0000000..72b247b
--- /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 <name>-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 0000000..50b76a1
--- /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 <name>-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<android.hardware.automotive.audiocontrol.VolumeActivationConfigurationEntry> 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 0000000..d457e57
--- /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 <name>-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 0000000..cc90bbe
--- /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 <name>-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<android.hardware.automotive.audiocontrol.DeviceToContextEntry> 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 0000000..8ce8491
--- /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 <name>-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 0000000..9b5e724
--- /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 0000000..4190c46
--- /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
+ *
+ * <p>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
+ *
+ * <p>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
+ *
+ * <p>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.
+ *
+ *<p>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.
+ *
+ **<p>The list can be empty in cases where there are no unfadeable content types.
+ *
+ *<p>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.
+ *
+ *<p>The list can be empty in cases where there are no unfadeable attributes
+ */
+ List<AudioAttributes> unfadableAudioAttributes;
+
+ /**
+ * List of fade out configutions which should apply to this audio fade configurations
+ *
+ *<p>The list can be empty in cases where there are no fade out configurations.
+ */
+ List<FadeConfiguration> fadeOutConfigurations;
+
+ /**
+ * List of fade in configutions which should apply to this audio fade configurations
+ *
+ *<p>The list can be empty in cases where there are no fade out configurations
+ */
+ List<FadeConfiguration> 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 0000000..d31d6fd
--- /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.
+ *
+ * <p>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.
+ *
+ * <p>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.
+ *
+ * <p>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<AudioZoneConfig> audioZoneConfigs;
+
+ /**
+ * List of input audio devices used for this zone
+ */
+ List<AudioPort> 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 0000000..6822da5
--- /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
+ *
+ * <p>Must be non-empty and unique among the configurations within a zone.
+ */
+ String name;
+
+ /**
+ * Determines if the audio configuration is the default configuration.
+ *
+ * <p>There can only be a single default configuration per zone.
+ */
+ boolean isDefault;
+
+ /**
+ * List car volume group that should be managed within this configuration
+ */
+ List<VolumeGroupConfig> 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 0000000..390cb09
--- /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.
+ *
+ * <p>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<AudioZoneContextInfo> 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 0000000..0ca425c
--- /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.
+ *
+ * <P>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
+ *
+ * <P>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> 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 0000000..a604214
--- /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.
+ *
+ * <p>The list can be empty if the fade configuration for the zone does not have transient fade
+ * configurations.
+ */
+ List<TransientFadeConfigurationEntry> 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 0000000..bcb5ee7
--- /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.
+ *
+ * <p>The names must match a {@link AudioZoneContextInfo#name} in the corresponding
+ * {@link AudioZone#audioZoneContext).
+ *
+ * <p>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<String> contextNames;
+
+ /**
+ * Audio port where contexts should be routed.
+ *
+ * <p>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 0000000..e700d6c
--- /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 0000000..346caae
--- /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 9564efc..1202b4c 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 @@
* 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 @@
* @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.
+ *
+ * <p>If this method is not supported, car audio service will attempt to configure the car audio
+ * service properties based on previously supported mechanisms.
+ *
+ * <p>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<AudioPort> getOutputMirroringDevices();
+
+ /**
+ * List of audio zones used to configure car audio service at bootup.
+ *
+ * <p>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<AudioZone> 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 0000000..2d17540
--- /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.
+ *
+ * <p>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.
+ *
+ * <p>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.
+ *
+ * <p>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 0000000..1984236
--- /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 0000000..edc5f60
--- /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.
+ *
+ * <p>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.
+ *
+ * <P>Car audio service currently only uses the first activation config on the list.
+ */
+ List<VolumeActivationConfigurationEntry> 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 0000000..7072a2c
--- /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.
+ *
+ * <p> 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.
+ *
+ * <p>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.
+ *
+ * <p>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 0000000..bea80ce
--- /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.
+ *
+ * <p>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.
+ *
+ * <p>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<DeviceToContextEntry> 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 0000000..0323505
--- /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 fd7e167..1c11c989 100644
--- a/automotive/audiocontrol/aidl/default/Android.bp
+++ b/automotive/audiocontrol/aidl/default/Android.bp
@@ -31,13 +31,19 @@
"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 7e7e145..9ae422b 100644
--- a/automotive/audiocontrol/aidl/default/AudioControl.cpp
+++ b/automotive/audiocontrol/aidl/default/AudioControl.cpp
@@ -19,6 +19,7 @@
#include "AudioControl.h"
+#include <aidl/android/hardware/automotive/audiocontrol/AudioDeviceConfiguration.h>
#include <aidl/android/hardware/automotive/audiocontrol/AudioFocusChange.h>
#include <aidl/android/hardware/automotive/audiocontrol/DuckingInfo.h>
#include <aidl/android/hardware/automotive/audiocontrol/IFocusListener.h>
@@ -27,8 +28,8 @@
#include <android-base/parsebool.h>
#include <android-base/parseint.h>
#include <android-base/strings.h>
-
#include <android_audio_policy_configuration_V7_0-enums.h>
+
#include <private/android_filesystem_config.h>
#include <numeric>
@@ -41,16 +42,18 @@
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 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 @@
}
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::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<int32_t>& channelLayouts,
const std::vector<int32_t>& sampleRates, AudioProfile* profile) {
@@ -162,6 +215,12 @@
}
} // namespace
+AudioControl::AudioControl() : AudioControl(kAudioConfigFile, kFadeConfigFile) {}
+
+AudioControl::AudioControl(const std::string& carAudioConfig, const std::string& audioFadeConfig)
+ : mCarAudioConfigurationConverter(std::make_shared<CarAudioConfigurationXmlConverter>(
+ carAudioConfig, audioFadeConfig)) {}
+
ndk::ScopedAStatus AudioControl::registerFocusListener(
const shared_ptr<IFocusListener>& in_listener) {
LOG(DEBUG) << "registering focus listener";
@@ -245,14 +304,23 @@
static inline std::string toString(const std::vector<aidl_type>& 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 <typename aidl_enum_type>
static inline std::string toEnumString(const std::vector<aidl_enum_type>& 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 <typename aidl_type>
+static inline std::string toString(const std::vector<std::optional<aidl_type>>& in_values) {
+ return std::accumulate(std::begin(in_values), std::end(in_values), std::string{},
+ [](const std::string& ls, const std::optional<aidl_type>& rs) {
+ return ls + (ls.empty() ? "" : ", ") +
+ (rs.has_value() ? rs.value().toString() : "empty");
});
}
@@ -309,6 +377,50 @@
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<AudioPort>* 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<AudioZone>* 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 @@
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<AudioZone> 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<AudioPort> 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 7eca446..0425570 100644
--- a/automotive/audiocontrol/aidl/default/AudioControl.h
+++ b/automotive/audiocontrol/aidl/default/AudioControl.h
@@ -35,13 +35,17 @@
#include <aidl/android/media/audio/common/AudioIoFlags.h>
#include <aidl/android/media/audio/common/AudioOutputFlags.h>
+#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 @@
ndk::ScopedAStatus setModuleChangeCallback(
const std::shared_ptr<IModuleChangeCallback>& 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<AudioZone>* audioZones) override;
binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
@@ -81,6 +90,9 @@
std::shared_ptr<IModuleChangeCallback> 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 bcb5669..ffef7fc 100644
--- a/automotive/audiocontrol/aidl/default/audiocontrol-default.xml
+++ b/automotive/audiocontrol/aidl/default/audiocontrol-default.xml
@@ -1,7 +1,7 @@
<manifest version="2.0" type="device">
<hal format="aidl">
<name>android.hardware.automotive.audiocontrol</name>
- <version>4</version>
+ <version>5</version>
<fqname>IAudioControl/default</fqname>
</hal>
</manifest>
diff --git a/automotive/audiocontrol/aidl/default/converter/Android.bp b/automotive/audiocontrol/aidl/default/converter/Android.bp
new file mode 100644
index 0000000..c00afa2
--- /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 0000000..29fec0b
--- /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 <string>
+
+#include <aidl/android/hardware/automotive/audiocontrol/AudioZoneContext.h>
+#include <aidl/android/hardware/automotive/audiocontrol/AudioZoneContextInfo.h>
+
+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 0000000..ed29172
--- /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 <string>
+
+#include "../include/CarAudioConfigurationUtils.h"
+
+#include <aidl/android/hardware/automotive/audiocontrol/AudioDeviceConfiguration.h>
+#include <aidl/android/hardware/automotive/audiocontrol/AudioZone.h>
+#include <aidl/android/hardware/automotive/audiocontrol/AudioZoneContext.h>
+
+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<std::string,
+ ::aidl::android::hardware::automotive::audiocontrol::AudioFadeConfiguration>
+ 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 0000000..e2f8191
--- /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 <android-base/logging.h>
+
+#include "../include/CarAudioConfigurationUtils.h"
+
+#include <aidl/android/media/audio/common/AudioAttributes.h>
+#include <aidl/android/media/audio/common/AudioUsage.h>
+
+#include <tuple>
+#include <vector>
+
+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<AudioAttributes> createAudioAttributes(const std::vector<AudioUsage>& usages) {
+ std::vector<AudioAttributes> 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<AudioUsage>& usages) {
+ AudioZoneContextInfo info;
+ info.name = name;
+ info.id = id;
+ info.audioAttributes = createAudioAttributes(usages);
+ return info;
+}
+
+AudioZoneContext createAudioZoneContextInfo(const std::vector<AudioZoneContextInfo>& 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 0000000..f4e8123
--- /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 <android-base/logging.h>
+
+#include "../include/CarAudioConfigurationXmlConverter.h"
+
+#include <aidl/android/hardware/automotive/audiocontrol/RoutingDeviceConfiguration.h>
+#include <android-base/parsebool.h>
+#include <android_hardware_automotive_audiocontrol.h>
+#include <android_hardware_automotive_audiocontrol_fade.h>
+
+#include <android-base/parseint.h>
+#include <android-base/strings.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/TypeConverter.h>
+#include <media/convert.h>
+#include <system/audio.h>
+#include <unistd.h>
+#include <unordered_map>
+
+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<std::string, api::VolumeActivationConfiguration>;
+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<AudioUsage> 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<xsd::UsageType>& usages,
+ std::vector<AudioAttributes>& 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<AudioContentType> 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<xsd::AttributesType>& xsdAttributes,
+ std::vector<AudioAttributes>& 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>& 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<AudioDeviceDescription> 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<AudioDeviceAddress::Tag::id>(address);
+ }
+ device.type = result.value();
+
+ port.ext = AudioPortExt::make<AudioPortExt::Tag::device>(device);
+
+ return true;
+}
+
+std::string outTypeToOutAudioDevice(const std::string& device) {
+ const static std::unordered_map<std::string, std::string> 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<xsd::DeviceRoutesType> deviceRoutesTypes,
+ std::vector<api::DeviceToContextEntry>& 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<api::VolumeGroupConfig>& 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<AudioUsage>& 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<api::AudioZoneFadeConfiguration>& 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<api::AudioZoneConfig>& 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<AudioPort>& 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<int>(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<api::AudioZone>& 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<std::string,
+ std::function<void(const std::string&, api::AudioDeviceConfiguration&)>>
+getConfigsParsers() {
+ static const std::unordered_map<
+ std::string, std::function<void(const std::string&, api::AudioDeviceConfiguration&)>>
+ 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<xsd::ActivationVolumeConfigEntryType>& xsdEntries,
+ std::vector<api::VolumeActivationConfigurationEntry>& 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<AudioPort>& 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<AudioUsage>& 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>& 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>& audioAttributes) {
+ if (!fadeAttributes.hasAudioAttributes()) {
+ return;
+ }
+ parseFadeAudioAttribute(*fadeAttributes.getFirstAudioAttributes(), audioAttributes);
+}
+
+void parseUnfadeableContentType(const fade::UnfadeableContentTypesType& fadeTypes,
+ std::optional<std::vector<AudioContentType>>& contentTypes) {
+ if (!fadeTypes.hasContentType()) {
+ return;
+ }
+ std::vector<AudioContentType> 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<api::FadeConfiguration>& 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<api::FadeConfiguration::AudioAttributesOrUsage::fadeAttribute>(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<api::FadeConfiguration::AudioAttributesOrUsage::usage>(usage);
+ fadeInConfigurations.push_back(fadeConfiguration);
+ }
+ }
+}
+void parseFadeConfiguration(const fade::FadeConfigurationType& fadeConfigurationType,
+ std::vector<api::FadeConfiguration>& fadeConfigurations) {
+ if (!fadeConfigurationType.hasFadeDurationMillis() ||
+ !fadeConfigurationType.hasAudioAttributes() ||
+ fadeConfigurationType.getAudioAttributes().empty()) {
+ return;
+ }
+
+ int64_t fadeDurationMillis = 0L;
+
+ if (!ParseInt(fadeConfigurationType.getFadeDurationMillis().c_str(), &fadeDurationMillis,
+ static_cast<int64_t>(0))) {
+ return;
+ }
+ parseFadeConfigAudioAttributes(*fadeConfigurationType.getFirstAudioAttributes(),
+ fadeDurationMillis, fadeConfigurations);
+}
+
+void parseFadeInConfigurations(const fade::FadeInConfigurationsType& fadeInConfigurationsType,
+ std::vector<api::FadeConfiguration>& fadeInConfigurations) {
+ if (!fadeInConfigurationsType.hasFadeConfiguration()) {
+ return;
+ }
+ for (const auto& fadeConfigurationType : fadeInConfigurationsType.getFadeConfiguration()) {
+ parseFadeConfiguration(fadeConfigurationType, fadeInConfigurations);
+ }
+}
+
+void parseFadeOutConfigurations(const fade::FadeOutConfigurationsType& fadeOutConfigurationsType,
+ std::vector<api::FadeConfiguration>& 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<int64_t>(0));
+ }
+ if (fadeConfig.hasDefaultFadeInDurationInMillis()) {
+ ParseInt(fadeConfig.getDefaultFadeInDurationInMillis().c_str(),
+ &configuration.fadeInDurationMs, static_cast<int64_t>(0));
+ }
+ if (fadeConfig.hasDefaultFadeInDelayForOffenders()) {
+ ParseInt(fadeConfig.getDefaultFadeInDelayForOffenders().c_str(),
+ &configuration.fadeInDelayedForOffendersMs, static_cast<int64_t>(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<fade::FadeConfigurationConfig>& fadeConfigTypes,
+ std::vector<api::AudioFadeConfiguration>& 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<api::AudioFadeConfiguration>& 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<api::AudioFadeConfiguration> 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<api::AudioZone> 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 0000000..70d4a20
--- /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 0000000..d11a59a
--- /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 <android-base/file.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <memory>
+#include <string>
+#include <utility>
+
+#include <CarAudioConfigurationXmlConverter.h>
+#include <aidl/android/hardware/automotive/audiocontrol/AudioDeviceConfiguration.h>
+
+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<AudioAttributes>& 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<AudioUsage>& usages,
+ const int id = -1) {
+ std::vector<AudioAttributes> 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<AudioDeviceAddress::Tag::id>(address);
+
+ AudioDeviceDescription description;
+ description.type = type;
+ description.connection = connection;
+ device.type = description;
+
+ port.ext = AudioPortExt::make<AudioPortExt::Tag::device>(device);
+
+ return port;
+}
+
+api::DeviceToContextEntry createRoutes(const AudioPort& port,
+ const std::vector<std::string>& 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<api::DeviceToContextEntry>& 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<api::VolumeGroupConfig>& 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<api::FadeConfiguration::AudioAttributesOrUsage::Tag::fadeAttribute>(
+ audioAttributes);
+ return configuration;
+}
+
+api::FadeConfiguration createFadeConfiguration(const long& fadeDurationsMillis,
+ const AudioUsage& audioUsage) {
+ api::FadeConfiguration configuration;
+ configuration.fadeDurationMillis = fadeDurationsMillis;
+ configuration.audioAttributesOrUsage
+ .set<api::FadeConfiguration::AudioAttributesOrUsage::Tag::usage>(audioUsage);
+ return configuration;
+}
+
+api::AudioFadeConfiguration createAudioFadeConfiguration(
+ const std::string& name, const api::FadeState& state,
+ const std::vector<AudioUsage>& fadeableUsages = std::vector<AudioUsage>(),
+ const std::optional<std::vector<AudioContentType>>& unfadeableContentTypes = std::nullopt,
+ const std::vector<AudioAttributes> unfadeableAudioAttributes =
+ std::vector<AudioAttributes>(),
+ const std::vector<api::FadeConfiguration> fadeOutConfigurations =
+ std::vector<api::FadeConfiguration>(),
+ const std::vector<api::FadeConfiguration> fadeInConfigurations =
+ std::vector<api::FadeConfiguration>(),
+ 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<AudioUsage>& usages) {
+ api::TransientFadeConfigurationEntry entry;
+ entry.transientFadeConfiguration = fadeConfig;
+ entry.transientUsages = usages;
+ return entry;
+}
+
+api::AudioZoneFadeConfiguration createAudioZoneFadeConfiguration(
+ const api::AudioFadeConfiguration& defaultConfig,
+ const std::vector<api::TransientFadeConfigurationEntry>& 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<api::AudioZoneContextInfo>& contexts,
+ const std::vector<api::AudioZoneConfig>& 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<AudioUsage> kFadeableUsages = {AudioUsage::MEDIA,
+ AudioUsage::GAME,
+ AudioUsage::ASSISTANCE_SONIFICATION,
+ AudioUsage::ASSISTANCE_ACCESSIBILITY,
+ AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE,
+ AudioUsage::ASSISTANT,
+ AudioUsage::NOTIFICATION,
+ AudioUsage::ANNOUNCEMENT};
+
+const std::vector<AudioAttributes> kUnfadeableAudioAttributes = {
+ createAudioAttributes(AudioUsage::MEDIA, AudioContentType::UNKNOWN, "oem_specific_tag1")};
+
+const std::vector<api::FadeConfiguration> 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<api::FadeConfiguration> 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<std::vector<AudioContentType>>(
+ {AudioContentType::SPEECH, AudioContentType::SONIFICATION}),
+ kUnfadeableAudioAttributes, kFadeOutConfigurations, kFadeInConfigurations, 800, 500, 10000);
+
+const std::vector<AudioAttributes> kAggressiveUnfadeableAudioAttributes = {
+ createAudioAttributes(AudioUsage::MEDIA, AudioContentType::UNKNOWN, "oem_specific_tag1"),
+ createAudioAttributes(AudioUsage::ASSISTANT, AudioContentType::UNKNOWN,
+ "oem_projection_service"),
+};
+
+const std::vector<api::FadeConfiguration> 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<api::FadeConfiguration> 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<std::vector<AudioContentType>>(
+ {AudioContentType::SPEECH, AudioContentType::MUSIC}),
+ kAggressiveUnfadeableAudioAttributes, kAggressiveFadeOutConfigurations,
+ kAggressiveFadeInConfigurations);
+
+const api::AudioFadeConfiguration kDisabledFading =
+ createAudioFadeConfiguration("disabled fading", api::FadeState::FADE_STATE_DISABLED);
+
+const std::vector<api::FadeConfiguration> 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<api::FadeConfiguration> 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<std::vector<AudioContentType>>(
+ {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<api::AudioZoneContextInfo> 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<api::AudioZoneContextInfo> 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<AudioPort> 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<AudioPort> 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<AudioPort> 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<std::string, api::AudioZoneConfig> 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<int>(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<int>(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<int>(AudioHalProductStrategy::ZoneId::DEFAULT) + 2,
+ kSimpleCarAudioConfigurationContext, {kRearZoneConfig});
+
+std::vector<api::AudioZone> 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<api::AudioZoneFadeConfiguration>& actual,
+ const std::optional<api::AudioZoneFadeConfiguration>& 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::CarAudioConfigurationXmlConverter> converter;
+
+ protected:
+ virtual std::string getCarAudioConfiguration() = 0;
+ virtual std::string getCarFadeConfiguration() = 0;
+};
+
+void CarAudioConfigurationTest::SetUp() {
+ converter = std::make_unique<converter::CarAudioConfigurationXmlConverter>(
+ 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<int>(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<int>(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::CarAudioConfigurationXmlConverter> converter;
+};
+
+void MalformedCarAudioConfigurationTest::TearDown() {
+ converter.reset();
+}
+
+TEST_F(MalformedCarAudioConfigurationTest, TestLoadEmptyConfiguration) {
+ converter =
+ std::make_unique<converter::CarAudioConfigurationXmlConverter>(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<converter::CarAudioConfigurationXmlConverter>(
+ 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<converter::CarAudioConfigurationXmlConverter>(
+ 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<converter::CarAudioConfigurationXmlConverter>(
+ 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<converter::CarAudioConfigurationXmlConverter>(
+ 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 0000000..80cb5cd
--- /dev/null
+++ b/automotive/audiocontrol/aidl/default/converter/test/car_audio_configuration_with_default_context.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<carAudioConfiguration version="4">
+ <zones>
+ <zone name="primary zone" isPrimary="true">
+ <zoneConfigs>
+ <zoneConfig name="primary zone config" isDefault="true">
+ <volumeGroups>
+ <group name="entertainment" >
+ <device address="BUS00_MEDIA">
+ <context context="MUSIC"/>
+ </device>
+ </group>
+ <group name="navvoicecommand" >
+ <device address="BUS02_NAV_GUIDANCE">
+ <context context="NAVIGATION"/>
+ <context context="VOICE_COMMAND"/>
+ </device>
+ </group>
+ <group name="telringvol" >
+ <device address="BUS03_PHONE">
+ <context context="CALL"/>
+ <context context="CALL_RING"/>
+ </device>
+ </group>
+ <group name="alarm" >
+ <device address="BUS01_NOTIFICATION">
+ <context context="ALARM"/>
+ <context context="NOTIFICATION"/>
+ </device>
+ </group>
+ <group name="system" >
+ <device address="BUS05_SYSTEM">
+ <context context="SYSTEM_SOUND"/>
+ <context context="EMERGENCY"/>
+ <context context="SAFETY"/>
+ <context context="VEHICLE_STATUS"/>
+ <context context="ANNOUNCEMENT"/>
+ </device>
+ </group>
+ </volumeGroups>
+ </zoneConfig>
+ </zoneConfigs>
+ </zone>
+ </zones>
+</carAudioConfiguration>
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 0000000..a5880b3
--- /dev/null
+++ b/automotive/audiocontrol/aidl/default/converter/test/car_audio_configuration_with_missing_zones.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<carAudioConfiguration version="4">
+ <deviceConfigurations>
+ <deviceConfiguration name="useHalDuckingSignals" value="true" />
+ <deviceConfiguration name="useCoreAudioRouting" value="false" />
+ <deviceConfiguration name="useCoreAudioVolume" value="false" />
+ <deviceConfiguration name="useCarVolumeGroupMuting" value="true" />
+ </deviceConfigurations>
+ <oemContexts>
+ <oemContext name="oem_context">
+ <audioAttributes>
+ <audioAttribute usage="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"
+ contentType="AUDIO_CONTENT_TYPE_SPEECH"
+ tags="oem=extension_8675309" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_music">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_MEDIA" />
+ <usage value="AUDIO_USAGE_GAME" />
+ <usage value="AUDIO_USAGE_UNKNOWN" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_notification">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_NOTIFICATION" />
+ <usage value="AUDIO_USAGE_NOTIFICATION_EVENT" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_voice_command">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_ASSISTANT" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_call">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_VOICE_COMMUNICATION" />
+ <usage value="AUDIO_USAGE_CALL_ASSISTANT" />
+ <usage value="AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_call_ring">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_alarm">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_ALARM" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_system_sound">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION" />
+ <usage value="AUDIO_USAGE_EMERGENCY" />
+ <usage value="AUDIO_USAGE_SAFETY" />
+ <usage value="AUDIO_USAGE_VEHICLE_STATUS" />
+ <usage value="AUDIO_USAGE_ANNOUNCEMENT" />
+ </audioAttributes>
+ </oemContext>
+ </oemContexts>
+ <activationVolumeConfigs>
+ <activationVolumeConfig name="on_boot_config">
+ <activationVolumeConfigEntry maxActivationVolumePercentage="80" invocationType="onBoot" />
+ </activationVolumeConfig>
+ <activationVolumeConfig name="on_source_changed_config">
+ <activationVolumeConfigEntry minActivationVolumePercentage="20" maxActivationVolumePercentage="80" invocationType="onSourceChanged" />
+ </activationVolumeConfig>
+ <activationVolumeConfig name="on_playback_changed_config">
+ <activationVolumeConfigEntry minActivationVolumePercentage="10" maxActivationVolumePercentage="90" invocationType="onPlaybackChanged" />
+ </activationVolumeConfig>
+ </activationVolumeConfigs>
+ <mirroringDevices>
+ <mirroringDevice address="mirror_bus_device_1"/>
+ <mirroringDevice address="mirror_bus_device_2"/>
+ </mirroringDevices>
+ <zones>
+ </zones>
+</carAudioConfiguration>
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 0000000..1e50e6e
--- /dev/null
+++ b/automotive/audiocontrol/aidl/default/converter/test/car_audio_configuration_without_audio_zone.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<carAudioConfiguration version="4">
+ <deviceConfigurations>
+ <deviceConfiguration name="useHalDuckingSignals" value="true" />
+ <deviceConfiguration name="useCoreAudioRouting" value="false" />
+ <deviceConfiguration name="useCoreAudioVolume" value="false" />
+ <deviceConfiguration name="useCarVolumeGroupMuting" value="true" />
+ </deviceConfigurations>
+ <oemContexts>
+ <oemContext name="oem_context">
+ <audioAttributes>
+ <audioAttribute usage="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"
+ contentType="AUDIO_CONTENT_TYPE_SPEECH"
+ tags="oem=extension_8675309" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_music">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_MEDIA" />
+ <usage value="AUDIO_USAGE_GAME" />
+ <usage value="AUDIO_USAGE_UNKNOWN" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_notification">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_NOTIFICATION" />
+ <usage value="AUDIO_USAGE_NOTIFICATION_EVENT" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_voice_command">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_ASSISTANT" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_call">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_VOICE_COMMUNICATION" />
+ <usage value="AUDIO_USAGE_CALL_ASSISTANT" />
+ <usage value="AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_call_ring">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_alarm">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_ALARM" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_system_sound">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION" />
+ <usage value="AUDIO_USAGE_EMERGENCY" />
+ <usage value="AUDIO_USAGE_SAFETY" />
+ <usage value="AUDIO_USAGE_VEHICLE_STATUS" />
+ <usage value="AUDIO_USAGE_ANNOUNCEMENT" />
+ </audioAttributes>
+ </oemContext>
+ </oemContexts>
+ <activationVolumeConfigs>
+ <activationVolumeConfig name="on_boot_config">
+ <activationVolumeConfigEntry maxActivationVolumePercentage="80" invocationType="onBoot" />
+ </activationVolumeConfig>
+ <activationVolumeConfig name="on_source_changed_config">
+ <activationVolumeConfigEntry minActivationVolumePercentage="20" maxActivationVolumePercentage="80" invocationType="onSourceChanged" />
+ </activationVolumeConfig>
+ <activationVolumeConfig name="on_playback_changed_config">
+ <activationVolumeConfigEntry minActivationVolumePercentage="10" maxActivationVolumePercentage="90" invocationType="onPlaybackChanged" />
+ </activationVolumeConfig>
+ </activationVolumeConfigs>
+ <mirroringDevices>
+ <mirroringDevice address="mirror_bus_device_1"/>
+ <mirroringDevice address="mirror_bus_device_2"/>
+ </mirroringDevices>
+</carAudioConfiguration>
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 0000000..4f50ca2
--- /dev/null
+++ b/automotive/audiocontrol/aidl/default/converter/test/car_audio_configuration_without_configuration.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<nonCarAudioConfiguration version="4">
+
+</nonCarAudioConfiguration>
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 0000000..249f915
--- /dev/null
+++ b/automotive/audiocontrol/aidl/default/converter/test/car_audio_fade_configuration.xml
@@ -0,0 +1,191 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<carAudioFadeConfiguration version="1">
+ <configs>
+ <config name="relaxed fading" defaultFadeOutDurationInMillis="800" defaultFadeInDurationInMillis="500" defaultFadeInDelayForOffenders="10000" >
+ <fadeState value="1" />
+ <fadeableUsages>
+ <usage value="AUDIO_USAGE_MEDIA" />
+ <usage value="AUDIO_USAGE_GAME" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE" />
+ <usage value="AUDIO_USAGE_ASSISTANT" />
+ <usage value="AUDIO_USAGE_NOTIFICATION" />
+ <usage value="AUDIO_USAGE_ANNOUNCEMENT"/>
+ </fadeableUsages>
+ <unfadeableContentTypes>
+ <contentType value="AUDIO_CONTENT_TYPE_SPEECH" />
+ <contentType value="AUDIO_CONTENT_TYPE_SONIFICATION" />
+ </unfadeableContentTypes>
+ <unfadeableAudioAttributes>
+ <audioAttributes>
+ <audioAttribute usage="AUDIO_USAGE_MEDIA" tags="oem_specific_tag1" />
+ </audioAttributes>
+ </unfadeableAudioAttributes>
+ <fadeOutConfigurations>
+ <fadeConfiguration fadeDurationMillis="500">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_MEDIA" />
+ <usage value="AUDIO_USAGE_GAME" />
+ <audioAttribute usage="AUDIO_USAGE_ASSISTANT" tags="oem_specific_tag2" />
+ </audioAttributes>
+ </fadeConfiguration>
+ <fadeConfiguration fadeDurationMillis="800">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE" />
+ <usage value="AUDIO_USAGE_ASSISTANT" />
+ <usage value="AUDIO_USAGE_ANNOUNCEMENT"/>
+ </audioAttributes>
+ </fadeConfiguration>
+ </fadeOutConfigurations>
+ <fadeInConfigurations>
+ <fadeConfiguration fadeDurationMillis="1000">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_MEDIA" />
+ <usage value="AUDIO_USAGE_GAME" />
+ <audioAttribute usage="AUDIO_USAGE_ASSISTANT" tags="oem_specific_tag2" />
+ </audioAttributes>
+ </fadeConfiguration>
+ <fadeConfiguration fadeDurationMillis="800">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE" />
+ <usage value="AUDIO_USAGE_ASSISTANT" />
+ <usage value="AUDIO_USAGE_ANNOUNCEMENT"/>
+ </audioAttributes>
+ </fadeConfiguration>
+ </fadeInConfigurations>
+ </config>
+ <config name="aggressive fading">
+ <fadeState value="FADE_STATE_ENABLED_DEFAULT" />
+ <fadeableUsages>
+ <usage value="AUDIO_USAGE_MEDIA" />
+ <usage value="AUDIO_USAGE_GAME" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE" />
+ <usage value="AUDIO_USAGE_ASSISTANT" />
+ <usage value="AUDIO_USAGE_NOTIFICATION" />
+ <usage value="AUDIO_USAGE_ANNOUNCEMENT"/>
+ </fadeableUsages>
+ <unfadeableContentTypes>
+ <contentType value="AUDIO_CONTENT_TYPE_SPEECH" />
+ <contentType value="AUDIO_CONTENT_TYPE_MUSIC" />
+ </unfadeableContentTypes>
+ <unfadeableAudioAttributes>
+ <audioAttributes>
+ <audioAttribute usage="AUDIO_USAGE_MEDIA" tags="oem_specific_tag1" />
+ <audioAttribute usage="AUDIO_USAGE_ASSISTANT" tags="oem_projection_service" />
+ </audioAttributes>
+ </unfadeableAudioAttributes>
+ <fadeOutConfigurations>
+ <fadeConfiguration fadeDurationMillis="150">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_MEDIA" />
+ <usage value="AUDIO_USAGE_GAME" />
+ </audioAttributes>
+ </fadeConfiguration>
+ <fadeConfiguration fadeDurationMillis="400">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE" />
+ <usage value="AUDIO_USAGE_ASSISTANT" />
+ <usage value="AUDIO_USAGE_ANNOUNCEMENT"/>
+ </audioAttributes>
+ </fadeConfiguration>
+ </fadeOutConfigurations>
+ <fadeInConfigurations>
+ <fadeConfiguration fadeDurationMillis="300">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_MEDIA" />
+ <usage value="AUDIO_USAGE_GAME" />
+ </audioAttributes>
+ </fadeConfiguration>
+ <fadeConfiguration fadeDurationMillis="550">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE" />
+ <usage value="AUDIO_USAGE_ASSISTANT" />
+ <usage value="AUDIO_USAGE_ANNOUNCEMENT"/>
+ </audioAttributes>
+ </fadeConfiguration>
+ </fadeInConfigurations>
+ </config>
+ <config name="disabled fading">
+ <fadeState value="0" />
+ </config>
+ <config name="dynamic fading" defaultFadeOutDurationInMillis="800" defaultFadeInDurationInMillis="500">
+ <fadeState value="1" />
+ <fadeableUsages>
+ <usage value="AUDIO_USAGE_MEDIA" />
+ <usage value="AUDIO_USAGE_GAME" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE" />
+ <usage value="AUDIO_USAGE_ASSISTANT" />
+ <usage value="AUDIO_USAGE_NOTIFICATION" />
+ <usage value="AUDIO_USAGE_ANNOUNCEMENT"/>
+ </fadeableUsages>
+ <unfadeableContentTypes>
+ <contentType value="AUDIO_CONTENT_TYPE_SPEECH" />
+ <contentType value="AUDIO_CONTENT_TYPE_MOVIE" />
+ </unfadeableContentTypes>
+ <unfadeableAudioAttributes>
+ <audioAttributes>
+ <audioAttribute usage="AUDIO_USAGE_MEDIA" tags="oem_specific_tag1" />
+ </audioAttributes>
+ </unfadeableAudioAttributes>
+ <fadeOutConfigurations>
+ <fadeConfiguration fadeDurationMillis="500">
+ <audioAttributes>
+ <audioAttribute usage="AUDIO_USAGE_ASSISTANT" tags="oem_specific_tag2" />
+ </audioAttributes>
+ </fadeConfiguration>
+ <fadeConfiguration fadeDurationMillis="800">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE" />
+ <usage value="AUDIO_USAGE_ASSISTANT" />
+ <usage value="AUDIO_USAGE_ANNOUNCEMENT"/>
+ </audioAttributes>
+ </fadeConfiguration>
+ </fadeOutConfigurations>
+ <fadeInConfigurations>
+ <fadeConfiguration fadeDurationMillis="1000">
+ <audioAttributes>
+ <audioAttribute usage="AUDIO_USAGE_ASSISTANT" tags="oem_specific_tag2" />
+ </audioAttributes>
+ </fadeConfiguration>
+ <fadeConfiguration fadeDurationMillis="800">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE" />
+ <usage value="AUDIO_USAGE_ASSISTANT" />
+ <usage value="AUDIO_USAGE_ANNOUNCEMENT"/>
+ </audioAttributes>
+ </fadeConfiguration>
+ </fadeInConfigurations>
+ </config>
+ </configs>
+</carAudioFadeConfiguration>
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 0000000..f0c9081
--- /dev/null
+++ b/automotive/audiocontrol/aidl/default/converter/test/multi_zone_car_audio_configuration.xml
@@ -0,0 +1,196 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<carAudioConfiguration version="4">
+ <deviceConfigurations>
+ <deviceConfiguration name="useHalDuckingSignals" value="false" />
+ <deviceConfiguration name="useCoreAudioRouting" value="true" />
+ <deviceConfiguration name="useCoreAudioVolume" value="true" />
+ <deviceConfiguration name="useCarVolumeGroupMuting" value="false" />
+ </deviceConfigurations>
+ <oemContexts>
+ <oemContext name="oem_context">
+ <audioAttributes>
+ <audioAttribute usage="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"
+ contentType="AUDIO_CONTENT_TYPE_SPEECH"
+ tags="oem=extension_8675309" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_music">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_MEDIA" />
+ <usage value="AUDIO_USAGE_GAME" />
+ <usage value="AUDIO_USAGE_UNKNOWN" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_notification">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_NOTIFICATION" />
+ <usage value="AUDIO_USAGE_NOTIFICATION_EVENT" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_voice_command">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_ASSISTANT" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_call">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_VOICE_COMMUNICATION" />
+ <usage value="AUDIO_USAGE_CALL_ASSISTANT" />
+ <usage value="AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_call_ring">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_alarm">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_ALARM" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_system_sound">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION" />
+ <usage value="AUDIO_USAGE_EMERGENCY" />
+ <usage value="AUDIO_USAGE_SAFETY" />
+ <usage value="AUDIO_USAGE_VEHICLE_STATUS" />
+ <usage value="AUDIO_USAGE_ANNOUNCEMENT" />
+ </audioAttributes>
+ </oemContext>
+ </oemContexts>
+ <activationVolumeConfigs>
+ <activationVolumeConfig name="on_boot_config">
+ <activationVolumeConfigEntry maxActivationVolumePercentage="80" invocationType="onBoot" />
+ </activationVolumeConfig>
+ <activationVolumeConfig name="on_source_changed_config">
+ <activationVolumeConfigEntry minActivationVolumePercentage="20" maxActivationVolumePercentage="80" invocationType="onSourceChanged" />
+ </activationVolumeConfig>
+ <activationVolumeConfig name="on_playback_changed_config">
+ <activationVolumeConfigEntry minActivationVolumePercentage="10" maxActivationVolumePercentage="90" invocationType="onPlaybackChanged" />
+ </activationVolumeConfig>
+ </activationVolumeConfigs>
+ <mirroringDevices>
+ <mirroringDevice address="mirror_bus_device_three"/>
+ <mirroringDevice address="mirror_bus_device_four"/>
+ </mirroringDevices>
+ <zones>
+ <zone name="driver zone" isPrimary="true" audioZoneId="0" occupantZoneId="0">
+ <zoneConfigs>
+ <zoneConfig name="driver zone config 0" isDefault="true">
+ <volumeGroups>
+ <group name="entertainment" activationConfig="on_boot_config">
+ <device address="BUS00_MEDIA">
+ <context context="oem_music"/>
+ </device>
+ </group>
+ <group name="navvoicecommand" activationConfig="on_source_changed_config">
+ <device address="BUS02_NAV_GUIDANCE">
+ <context context="oem_voice_command"/>
+ </device>
+ </group>
+ <group name="telringvol" activationConfig="on_playback_changed_config">
+ <device address="BUS03_PHONE">
+ <context context="oem_call"/>
+ <context context="oem_call_ring"/>
+ </device>
+ </group>
+ <group name="systemalarm" activationConfig="on_source_changed_config">
+ <device address="BUS01_SYS_NOTIFICATION">
+ <context context="oem_alarm"/>
+ <context context="oem_system_sound"/>
+ <context context="oem_notification"/>
+ </device>
+ </group>
+ </volumeGroups>
+ <applyFadeConfigs>
+ <fadeConfig name="relaxed fading" isDefault="true">
+ </fadeConfig>
+ <fadeConfig name="aggressive fading">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_VOICE_COMMUNICATION" />
+ <usage value="AUDIO_USAGE_ANNOUNCEMENT" />
+ <usage value="AUDIO_USAGE_VEHICLE_STATUS" />
+ <usage value="AUDIO_USAGE_SAFETY" />
+ </audioAttributes>
+ </fadeConfig>
+ <fadeConfig name="disabled fading">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_EMERGENCY" />
+ </audioAttributes>
+ </fadeConfig>
+ </applyFadeConfigs>
+ </zoneConfig>
+ </zoneConfigs>
+ </zone>
+ <zone name="front passenger zone" audioZoneId="1" occupantZoneId="1">
+ <zoneConfigs>
+ <zoneConfig name="front passenger config 0" isDefault="true">
+ <volumeGroups>
+ <group name="entertainment" activationConfig="on_boot_config">
+ <device address="BUS_FRONT">
+ <context context="oem_music"/>
+ <context context="oem_voice_command"/>
+ <context context="oem_call"/>
+ <context context="oem_call_ring"/>
+ <context context="oem_alarm"/>
+ <context context="oem_system_sound"/>
+ <context context="oem_notification"/>
+ </device>
+ </group>
+ </volumeGroups>
+ <applyFadeConfigs>
+ <fadeConfig name="relaxed fading" isDefault="true">
+ </fadeConfig>
+ <fadeConfig name="disabled fading">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_EMERGENCY" />
+ </audioAttributes>
+ </fadeConfig>
+ </applyFadeConfigs>
+ </zoneConfig>
+ </zoneConfigs>
+ </zone>
+ <zone name="rear seat zone" audioZoneId="2" occupantZoneId="2">
+ <zoneConfigs>
+ <zoneConfig name="rear seat config 0" isDefault="true">
+ <volumeGroups>
+ <group name="entertainment" activationConfig="on_boot_config">
+ <device address="BUS_REAR">
+ <context context="oem_music"/>
+ <context context="oem_voice_command"/>
+ <context context="oem_call"/>
+ <context context="oem_call_ring"/>
+ <context context="oem_alarm"/>
+ <context context="oem_system_sound"/>
+ <context context="oem_notification"/>
+ </device>
+ </group>
+ </volumeGroups>
+ <applyFadeConfigs>
+ <fadeConfig name="relaxed fading" isDefault="true">
+ </fadeConfig>
+ <fadeConfig name="disabled fading">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_EMERGENCY" />
+ </audioAttributes>
+ </fadeConfig>
+ </applyFadeConfigs>
+ </zoneConfig>
+ </zoneConfigs>
+ </zone>
+ </zones>
+</carAudioConfiguration>
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 0000000..a6f5317
--- /dev/null
+++ b/automotive/audiocontrol/aidl/default/converter/test/simple_car_audio_configuration.xml
@@ -0,0 +1,233 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<carAudioConfiguration version="4">
+ <deviceConfigurations>
+ <deviceConfiguration name="useHalDuckingSignals" value="true" />
+ <deviceConfiguration name="useCoreAudioRouting" value="false" />
+ <deviceConfiguration name="useCoreAudioVolume" value="false" />
+ <deviceConfiguration name="useCarVolumeGroupMuting" value="true" />
+ </deviceConfigurations>
+ <oemContexts>
+ <oemContext name="oem_context">
+ <audioAttributes>
+ <audioAttribute usage="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"
+ contentType="AUDIO_CONTENT_TYPE_SPEECH"
+ tags="oem=extension_8675309" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_music">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_MEDIA" />
+ <usage value="AUDIO_USAGE_GAME" />
+ <usage value="AUDIO_USAGE_UNKNOWN" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_notification">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_NOTIFICATION" />
+ <usage value="AUDIO_USAGE_NOTIFICATION_EVENT" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_voice_command">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_ASSISTANT" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_call">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_VOICE_COMMUNICATION" />
+ <usage value="AUDIO_USAGE_CALL_ASSISTANT" />
+ <usage value="AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_call_ring">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_alarm">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_ALARM" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_system_sound">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION" />
+ <usage value="AUDIO_USAGE_EMERGENCY" />
+ <usage value="AUDIO_USAGE_SAFETY" />
+ <usage value="AUDIO_USAGE_VEHICLE_STATUS" />
+ <usage value="AUDIO_USAGE_ANNOUNCEMENT" />
+ </audioAttributes>
+ </oemContext>
+ </oemContexts>
+ <activationVolumeConfigs>
+ <activationVolumeConfig name="on_boot_config">
+ <activationVolumeConfigEntry maxActivationVolumePercentage="80" invocationType="onBoot" />
+ </activationVolumeConfig>
+ <activationVolumeConfig name="on_source_changed_config">
+ <activationVolumeConfigEntry minActivationVolumePercentage="20" maxActivationVolumePercentage="80" invocationType="onSourceChanged" />
+ </activationVolumeConfig>
+ <activationVolumeConfig name="on_playback_changed_config">
+ <activationVolumeConfigEntry minActivationVolumePercentage="10" maxActivationVolumePercentage="90" invocationType="onPlaybackChanged" />
+ </activationVolumeConfig>
+ </activationVolumeConfigs>
+ <mirroringDevices>
+ <mirroringDevice address="mirror_bus_device_1"/>
+ <mirroringDevice address="mirror_bus_device_2"/>
+ </mirroringDevices>
+ <zones>
+ <zone name="primary zone" isPrimary="true" audioZoneId="0" occupantZoneId="0">
+ <inputDevices>
+ <inputDevice address="fm_tuner" type="AUDIO_DEVICE_IN_FM_TUNER" />
+ <inputDevice address="built_in_mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" />
+ <inputDevice address="in_bus_device" type="AUDIO_DEVICE_IN_BUS" />
+ </inputDevices>
+ <zoneConfigs>
+ <zoneConfig name="primary zone config 0" isDefault="true">
+ <volumeGroups>
+ <group name="entertainment" activationConfig="on_boot_config">
+ <device address="BUS00_MEDIA">
+ <context context="oem_music"/>
+ </device>
+ </group>
+ <group name="navvoicecommand" activationConfig="on_source_changed_config">
+ <device address="BUS02_NAV_GUIDANCE">
+ <context context="oem_voice_command"/>
+ </device>
+ </group>
+ <group name="telringvol" activationConfig="on_playback_changed_config">
+ <device address="BUS03_PHONE">
+ <context context="oem_call"/>
+ <context context="oem_call_ring"/>
+ </device>
+ </group>
+ <group name="systemalarm" activationConfig="on_source_changed_config">
+ <device address="BUS01_SYS_NOTIFICATION">
+ <context context="oem_alarm"/>
+ <context context="oem_system_sound"/>
+ <context context="oem_notification"/>
+ </device>
+ </group>
+ </volumeGroups>
+ <applyFadeConfigs>
+ <fadeConfig name="relaxed fading" isDefault="true">
+ </fadeConfig>
+ <fadeConfig name="aggressive fading">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_VOICE_COMMUNICATION" />
+ <usage value="AUDIO_USAGE_ANNOUNCEMENT" />
+ <usage value="AUDIO_USAGE_VEHICLE_STATUS" />
+ <usage value="AUDIO_USAGE_SAFETY" />
+ </audioAttributes>
+ </fadeConfig>
+ <fadeConfig name="disabled fading">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_EMERGENCY" />
+ </audioAttributes>
+ </fadeConfig>
+ </applyFadeConfigs>
+ </zoneConfig>
+ <zoneConfig name="primary zone BT media">
+ <volumeGroups>
+ <group name="entertainment" activationConfig="on_boot_config">
+ <device type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP" address="temp">
+ <context context="oem_music"/>
+ </device>
+ </group>
+ <group name="navvoicecommand" activationConfig="on_source_changed_config">
+ <device address="BUS02_NAV_GUIDANCE">
+ <context context="oem_voice_command"/>
+ </device>
+ </group>
+ <group name="telringvol" activationConfig="on_playback_changed_config">
+ <device address="BUS03_PHONE">
+ <context context="oem_call"/>
+ <context context="oem_call_ring"/>
+ </device>
+ </group>
+ <group name="systemalarm" activationConfig="on_source_changed_config">
+ <device address="BUS01_SYS_NOTIFICATION">
+ <context context="oem_alarm"/>
+ <context context="oem_system_sound"/>
+ <context context="oem_notification"/>
+ </device>
+ </group>
+ </volumeGroups>
+ <applyFadeConfigs>
+ <fadeConfig name="dynamic fading" isDefault="true">
+ </fadeConfig>
+ <fadeConfig name="aggressive fading">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_VOICE_COMMUNICATION" />
+ <usage value="AUDIO_USAGE_ANNOUNCEMENT" />
+ <usage value="AUDIO_USAGE_VEHICLE_STATUS" />
+ <usage value="AUDIO_USAGE_SAFETY" />
+ </audioAttributes>
+ </fadeConfig>
+ <fadeConfig name="disabled fading">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_EMERGENCY" />
+ </audioAttributes>
+ </fadeConfig>
+ </applyFadeConfigs>
+ </zoneConfig>
+ <zoneConfig name="primary zone USB media">
+ <volumeGroups>
+ <group name="entertainment" activationConfig="on_boot_config">
+ <device type="AUDIO_DEVICE_OUT_USB_HEADSET">
+ <context context="oem_music"/>
+ </device>
+ </group>
+ <group name="navvoicecommand" activationConfig="on_source_changed_config">
+ <device address="BUS02_NAV_GUIDANCE">
+ <context context="oem_voice_command"/>
+ </device>
+ </group>
+ <group name="telringvol" activationConfig="on_playback_changed_config">
+ <device address="BUS03_PHONE">
+ <context context="oem_call"/>
+ <context context="oem_call_ring"/>
+ </device>
+ </group>
+ <group name="systemalarm" activationConfig="on_source_changed_config">
+ <device address="BUS01_SYS_NOTIFICATION">
+ <context context="oem_alarm"/>
+ <context context="oem_system_sound"/>
+ <context context="oem_notification"/>
+ </device>
+ </group>
+ </volumeGroups>
+ <applyFadeConfigs>
+ <fadeConfig name="dynamic fading" isDefault="true">
+ </fadeConfig>
+ <fadeConfig name="aggressive fading">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_VOICE_COMMUNICATION" />
+ <usage value="AUDIO_USAGE_ANNOUNCEMENT" />
+ <usage value="AUDIO_USAGE_VEHICLE_STATUS" />
+ <usage value="AUDIO_USAGE_SAFETY" />
+ </audioAttributes>
+ </fadeConfig>
+ <fadeConfig name="disabled fading">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_EMERGENCY" />
+ </audioAttributes>
+ </fadeConfig>
+ </applyFadeConfigs>
+ </zoneConfig>
+ </zoneConfigs>
+ </zone>
+ </zones>
+</carAudioConfiguration>
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 0000000..eec9db9
--- /dev/null
+++ b/automotive/audiocontrol/aidl/default/converter/test/simple_car_audio_configuration_with_device_type.xml
@@ -0,0 +1,233 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<carAudioConfiguration version="4">
+ <deviceConfigurations>
+ <deviceConfiguration name="useHalDuckingSignals" value="true" />
+ <deviceConfiguration name="useCoreAudioRouting" value="false" />
+ <deviceConfiguration name="useCoreAudioVolume" value="false" />
+ <deviceConfiguration name="useCarVolumeGroupMuting" value="true" />
+ </deviceConfigurations>
+ <oemContexts>
+ <oemContext name="oem_context">
+ <audioAttributes>
+ <audioAttribute usage="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"
+ contentType="AUDIO_CONTENT_TYPE_SPEECH"
+ tags="oem=extension_8675309" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_music">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_MEDIA" />
+ <usage value="AUDIO_USAGE_GAME" />
+ <usage value="AUDIO_USAGE_UNKNOWN" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_notification">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_NOTIFICATION" />
+ <usage value="AUDIO_USAGE_NOTIFICATION_EVENT" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_voice_command">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_ASSISTANT" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY" />
+ <usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_call">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_VOICE_COMMUNICATION" />
+ <usage value="AUDIO_USAGE_CALL_ASSISTANT" />
+ <usage value="AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_call_ring">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_alarm">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_ALARM" />
+ </audioAttributes>
+ </oemContext>
+ <oemContext name="oem_system_sound">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION" />
+ <usage value="AUDIO_USAGE_EMERGENCY" />
+ <usage value="AUDIO_USAGE_SAFETY" />
+ <usage value="AUDIO_USAGE_VEHICLE_STATUS" />
+ <usage value="AUDIO_USAGE_ANNOUNCEMENT" />
+ </audioAttributes>
+ </oemContext>
+ </oemContexts>
+ <activationVolumeConfigs>
+ <activationVolumeConfig name="on_boot_config">
+ <activationVolumeConfigEntry maxActivationVolumePercentage="80" invocationType="onBoot" />
+ </activationVolumeConfig>
+ <activationVolumeConfig name="on_source_changed_config">
+ <activationVolumeConfigEntry minActivationVolumePercentage="20" maxActivationVolumePercentage="80" invocationType="onSourceChanged" />
+ </activationVolumeConfig>
+ <activationVolumeConfig name="on_playback_changed_config">
+ <activationVolumeConfigEntry minActivationVolumePercentage="10" maxActivationVolumePercentage="90" invocationType="onPlaybackChanged" />
+ </activationVolumeConfig>
+ </activationVolumeConfigs>
+ <mirroringDevices>
+ <mirroringDevice address="mirror_bus_device_1"/>
+ <mirroringDevice address="mirror_bus_device_2"/>
+ </mirroringDevices>
+ <zones>
+ <zone name="primary zone" isPrimary="true" audioZoneId="0" occupantZoneId="0">
+ <inputDevices>
+ <inputDevice address="fm_tuner" type="AUDIO_DEVICE_IN_FM_TUNER" />
+ <inputDevice address="built_in_mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" />
+ <inputDevice address="in_bus_device" type="AUDIO_DEVICE_IN_BUS" />
+ </inputDevices>
+ <zoneConfigs>
+ <zoneConfig name="primary zone config 0" isDefault="true">
+ <volumeGroups>
+ <group name="entertainment" activationConfig="on_boot_config">
+ <device address="BUS00_MEDIA">
+ <context context="oem_music"/>
+ </device>
+ </group>
+ <group name="navvoicecommand" activationConfig="on_source_changed_config">
+ <device address="BUS02_NAV_GUIDANCE">
+ <context context="oem_voice_command"/>
+ </device>
+ </group>
+ <group name="telringvol" activationConfig="on_playback_changed_config">
+ <device address="BUS03_PHONE">
+ <context context="oem_call"/>
+ <context context="oem_call_ring"/>
+ </device>
+ </group>
+ <group name="systemalarm" activationConfig="on_source_changed_config">
+ <device address="BUS01_SYS_NOTIFICATION">
+ <context context="oem_alarm"/>
+ <context context="oem_system_sound"/>
+ <context context="oem_notification"/>
+ </device>
+ </group>
+ </volumeGroups>
+ <applyFadeConfigs>
+ <fadeConfig name="relaxed fading" isDefault="true">
+ </fadeConfig>
+ <fadeConfig name="aggressive fading">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_VOICE_COMMUNICATION" />
+ <usage value="AUDIO_USAGE_ANNOUNCEMENT" />
+ <usage value="AUDIO_USAGE_VEHICLE_STATUS" />
+ <usage value="AUDIO_USAGE_SAFETY" />
+ </audioAttributes>
+ </fadeConfig>
+ <fadeConfig name="disabled fading">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_EMERGENCY" />
+ </audioAttributes>
+ </fadeConfig>
+ </applyFadeConfigs>
+ </zoneConfig>
+ <zoneConfig name="primary zone BT media">
+ <volumeGroups>
+ <group name="entertainment" activationConfig="on_boot_config">
+ <device type="TYPE_BLUETOOTH_A2DP" address="temp">
+ <context context="oem_music"/>
+ </device>
+ </group>
+ <group name="navvoicecommand" activationConfig="on_source_changed_config">
+ <device address="BUS02_NAV_GUIDANCE">
+ <context context="oem_voice_command"/>
+ </device>
+ </group>
+ <group name="telringvol" activationConfig="on_playback_changed_config">
+ <device address="BUS03_PHONE">
+ <context context="oem_call"/>
+ <context context="oem_call_ring"/>
+ </device>
+ </group>
+ <group name="systemalarm" activationConfig="on_source_changed_config">
+ <device address="BUS01_SYS_NOTIFICATION">
+ <context context="oem_alarm"/>
+ <context context="oem_system_sound"/>
+ <context context="oem_notification"/>
+ </device>
+ </group>
+ </volumeGroups>
+ <applyFadeConfigs>
+ <fadeConfig name="dynamic fading" isDefault="true">
+ </fadeConfig>
+ <fadeConfig name="aggressive fading">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_VOICE_COMMUNICATION" />
+ <usage value="AUDIO_USAGE_ANNOUNCEMENT" />
+ <usage value="AUDIO_USAGE_VEHICLE_STATUS" />
+ <usage value="AUDIO_USAGE_SAFETY" />
+ </audioAttributes>
+ </fadeConfig>
+ <fadeConfig name="disabled fading">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_EMERGENCY" />
+ </audioAttributes>
+ </fadeConfig>
+ </applyFadeConfigs>
+ </zoneConfig>
+ <zoneConfig name="primary zone USB media">
+ <volumeGroups>
+ <group name="entertainment" activationConfig="on_boot_config">
+ <device type="TYPE_USB_HEADSET">
+ <context context="oem_music"/>
+ </device>
+ </group>
+ <group name="navvoicecommand" activationConfig="on_source_changed_config">
+ <device address="BUS02_NAV_GUIDANCE">
+ <context context="oem_voice_command"/>
+ </device>
+ </group>
+ <group name="telringvol" activationConfig="on_playback_changed_config">
+ <device address="BUS03_PHONE">
+ <context context="oem_call"/>
+ <context context="oem_call_ring"/>
+ </device>
+ </group>
+ <group name="systemalarm" activationConfig="on_source_changed_config">
+ <device address="BUS01_SYS_NOTIFICATION">
+ <context context="oem_alarm"/>
+ <context context="oem_system_sound"/>
+ <context context="oem_notification"/>
+ </device>
+ </group>
+ </volumeGroups>
+ <applyFadeConfigs>
+ <fadeConfig name="dynamic fading" isDefault="true">
+ </fadeConfig>
+ <fadeConfig name="aggressive fading">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_VOICE_COMMUNICATION" />
+ <usage value="AUDIO_USAGE_ANNOUNCEMENT" />
+ <usage value="AUDIO_USAGE_VEHICLE_STATUS" />
+ <usage value="AUDIO_USAGE_SAFETY" />
+ </audioAttributes>
+ </fadeConfig>
+ <fadeConfig name="disabled fading">
+ <audioAttributes>
+ <usage value="AUDIO_USAGE_EMERGENCY" />
+ </audioAttributes>
+ </fadeConfig>
+ </applyFadeConfigs>
+ </zoneConfig>
+ </zoneConfigs>
+ </zone>
+ </zones>
+</carAudioConfiguration>
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 0000000..0d5eb81
--- /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 0000000..c87b8c6
--- /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<android.hardware.automotive.audiocontrol.ActivationVolumeConfigEntryType> getActivationVolumeConfigEntry();
+ method @Nullable public String getName();
+ method public void setName(@Nullable String);
+ }
+
+ public class ActivationVolumeConfigsType {
+ ctor public ActivationVolumeConfigsType();
+ method @Nullable public java.util.List<android.hardware.automotive.audiocontrol.ActivationVolumeConfigType> getActivationVolumeConfig();
+ }
+
+ public class ApplyFadeConfigType {
+ ctor public ApplyFadeConfigType();
+ method @Nullable public java.util.List<android.hardware.automotive.audiocontrol.AudioAttributeUsagesType> 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<android.hardware.automotive.audiocontrol.ApplyFadeConfigType> 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<android.hardware.automotive.audiocontrol.UsageType> getUsage();
+ }
+
+ public class AudioAttributesUsagesType {
+ ctor public AudioAttributesUsagesType();
+ method @Nullable public java.util.List<android.hardware.automotive.audiocontrol.AttributesType> getAudioAttribute_optional();
+ method @Nullable public java.util.List<android.hardware.automotive.audiocontrol.UsageType> 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<android.hardware.automotive.audiocontrol.DeviceConfigurationType> getDeviceConfiguration();
+ }
+
+ public class DeviceRoutesType {
+ ctor public DeviceRoutesType();
+ method @Nullable public String getAddress();
+ method @Nullable public java.util.List<android.hardware.automotive.audiocontrol.ContextNameType> 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<android.hardware.automotive.audiocontrol.InputDeviceType> 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<android.hardware.automotive.audiocontrol.MirroringDevice> 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<android.hardware.automotive.audiocontrol.OemContextType> 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<android.hardware.automotive.audiocontrol.DeviceRoutesType> 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<android.hardware.automotive.audiocontrol.VolumeGroupType> 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<android.hardware.automotive.audiocontrol.ZoneType> 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 0000000..e69de29
--- /dev/null
+++ b/automotive/audiocontrol/aidl/default/loaders/config/api/last_current.txt
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 0000000..e69de29
--- /dev/null
+++ b/automotive/audiocontrol/aidl/default/loaders/config/api/last_removed.txt
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 0000000..d802177
--- /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 0000000..634aeda
--- /dev/null
+++ b/automotive/audiocontrol/aidl/default/loaders/config/car_audio_configuration.xsd
@@ -0,0 +1,248 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<xs:schema version="2.0" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:element name="carAudioConfiguration" type="CarAudioConfigurationType" minOccurs="1" maxOccurs="1" />
+ <xs:complexType name="CarAudioConfigurationType">
+ <xs:attribute name="version" type="xs:string" use="required" />
+ <xs:sequence>
+ <xs:element name="mirroringDevices" type="MirroringDevicesType" minOccurs="0" />
+ <xs:element name="deviceConfigurations" type="DeviceConfigurationsType" minOccurs="0" />
+ <xs:element name="oemContexts" type="OemContextsType" />
+ <xs:element name="activationVolumeConfigs" type="ActivationVolumeConfigsType" minOccurs="0" />
+ <xs:element name="zones" type="ZonesType" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="ZonesType">
+ <xs:element name="zone" type="ZoneType" minOccurs="1" maxOccurs="unbounded" />
+ </xs:complexType>
+ <xs:complexType name="ActivationVolumeConfigsType">
+ <xs:element name="activationVolumeConfig" type="ActivationVolumeConfigType" maxOccurs="unbounded" />
+ </xs:complexType>
+ <xs:complexType name="OemContextsType">
+ <xs:element name="oemContext" type="OemContextType" minOccurs="1" maxOccurs="unbounded" />
+ </xs:complexType>
+ <xs:complexType name="DeviceConfigurationsType">
+ <xs:element name="deviceConfiguration" type="DeviceConfigurationType" minOccurs="0" maxOccurs="unbounded" />
+ </xs:complexType>
+ <xs:complexType name="ZoneType">
+ <xs:attribute name="name" type="xs:string" />
+ <xs:attribute name="audioZoneId" type="xs:string" use="required" />
+ <xs:attribute name="isPrimary" type="xs:boolean" />
+ <xs:attribute name="occupantZoneId" type="xs:string" />
+ <xs:element name="inputDevices" type="InputDevicesType" />
+ <xs:element name="zoneConfigs" type="ZoneConfigsType" />
+ </xs:complexType>
+ <xs:complexType name="ZoneConfigsType">
+ <xs:element name="zoneConfig" type="ZoneConfigType"/>
+ </xs:complexType>
+ <xs:complexType name="ZoneConfigType">
+ <xs:attribute name="name" type="xs:string" />
+ <xs:attribute name="isDefault" type="xs:boolean" />
+ <xs:element name="volumeGroups" type="VolumeGroupsType" />
+ <xs:element name="applyFadeConfigs" type="ApplyFadeConfigsType" />
+ </xs:complexType>
+ <xs:complexType name="ApplyFadeConfigsType">
+ <xs:element name="fadeConfig" type="ApplyFadeConfigType" minOccurs="0" maxOccurs="unbounded" />
+ </xs:complexType>
+ <xs:complexType name="ApplyFadeConfigType">
+ <xs:attribute name="name" type="xs:string" />
+ <xs:attribute name="isDefault" type="xs:boolean" />
+ <xs:element name="audioAttributes" type="AudioAttributeUsagesType" minOccurs="0" maxOccurs="unbounded" />
+ </xs:complexType>
+ <xs:complexType name="AudioAttributeUsagesType">
+ <xs:element name="usage" type="UsageType" maxOccurs="unbounded" />
+ </xs:complexType>
+ <xs:complexType name="VolumeGroupsType">
+ <xs:element name="group" type="VolumeGroupType" minOccurs="1" maxOccurs="unbounded" />
+ </xs:complexType>
+ <xs:complexType name="VolumeGroupType">
+ <xs:attribute name="name" type="xs:string" />
+ <xs:attribute name="activationConfig" type="xs:string" />
+ <xs:element name="device" type="DeviceRoutesType" minOccurts="1" maxOccurs="unbounded" />
+ </xs:complexType>
+ <xs:complexType name="DeviceRoutesType" >
+ <xs:attribute name="address" type="xs:string" />
+ <xs:attribute name="type" type="OutDeviceType" />
+ <xs:element name="context" type="ContextNameType" mixOccurs="1" maxOccurs="unbounded" />
+ </xs:complexType>
+ <xs:complexType name="ContextNameType">
+ <xs:attribute name="context" type="xs:string"/>
+ </xs:complexType>
+ <xs:complexType name="OemContextType">
+ <xs:attribute name="name" type="xs:string" />
+ <xs:attribute name="id" type="xs:string" />
+ <xs:element name="audioAttributes" type="AudioAttributesUsagesType" minOccurs="1" maxOccurs="1" />
+ </xs:complexType>
+ <xs:complexType name="AudioAttributesUsagesType" >
+ <xs:choice minOccurs="0" maxOccurs="unbounded" >
+ <xs:element name="audioAttribute" type="AttributesType" />
+ <xs:element name="usage" type="UsageType" />
+ </xs:choice>
+ </xs:complexType>
+ <xs:complexType name="AttributesType">
+ <xs:attribute name="contentType" type="contentTypeEnum" />
+ <xs:attribute name="usage" type="usageEnumType" />
+ <xs:attribute name="tags" type="xs:string" />
+ </xs:complexType>
+ <xs:complexType name="DeviceConfigurationType">
+ <xs:attribute name="name" type="xs:string" />
+ <xs:attribute name="value" type="xs:string" />
+ </xs:complexType>
+ <xs:complexType name="ContentType" >
+ <xs:attribute name="value" type="contentTypeEnum" use="required" />
+ </xs:complexType>
+ <xs:complexType name="UsageType">
+ <xs:attribute name="value" type="usageEnumType" use="required" />
+ </xs:complexType>
+ <xs:simpleType name="contentTypeEnum">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AUDIO_CONTENT_TYPE_UNKNOWN"/>
+ <xs:enumeration value="AUDIO_CONTENT_TYPE_SPEECH"/>
+ <xs:enumeration value="AUDIO_CONTENT_TYPE_MUSIC"/>
+ <xs:enumeration value="AUDIO_CONTENT_TYPE_MOVIE"/>
+ <xs:enumeration value="AUDIO_CONTENT_TYPE_SONIFICATION"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="usageEnumType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AUDIO_USAGE_UNKNOWN"/>
+ <xs:enumeration value="AUDIO_USAGE_MEDIA"/>
+ <xs:enumeration value="AUDIO_USAGE_VOICE_COMMUNICATION"/>
+ <xs:enumeration value="AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING"/>
+ <xs:enumeration value="AUDIO_USAGE_ALARM"/>
+ <xs:enumeration value="AUDIO_USAGE_NOTIFICATION"/>
+ <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE"/>
+ <!-- Note: the following 3 values were deprecated in Android T (13) SDK -->
+ <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST"/>
+ <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT"/>
+ <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED"/>
+ <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_EVENT"/>
+ <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY"/>
+ <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
+ <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_SONIFICATION"/>
+ <xs:enumeration value="AUDIO_USAGE_GAME"/>
+ <xs:enumeration value="AUDIO_USAGE_VIRTUAL_SOURCE"/>
+ <xs:enumeration value="AUDIO_USAGE_ASSISTANT"/>
+ <xs:enumeration value="AUDIO_USAGE_CALL_ASSISTANT"/>
+ <xs:enumeration value="AUDIO_USAGE_EMERGENCY" />
+ <xs:enumeration value="AUDIO_USAGE_SAFETY" />
+ <xs:enumeration value="AUDIO_USAGE_VEHICLE_STATUS" />
+ <xs:enumeration value="AUDIO_USAGE_ANNOUNCEMENT" />
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="ActivationVolumeConfigType">
+ <xs:attribute name="name" type="xs:string" />
+ <xs:element name="activationVolumeConfigEntry" type="ActivationVolumeConfigEntryType" maxOccurs="unbounded" />
+ </xs:complexType>
+ <xs:complexType name="ActivationVolumeConfigEntryType">
+ <xs:attribute name="maxActivationVolumePercentage" type="xs:string" />
+ <xs:attribute name="minActivationVolumePercentage" type="xs:string" />
+ <xs:attribute name="invocationType" type="ActivationType" />
+ </xs:complexType>
+ <xs:simpleType name="ActivationType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="onBoot"/>
+ <xs:enumeration value="onSourceChanged"/>
+ <xs:enumeration value="onPlaybackChanged"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="OutDeviceType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AUDIO_DEVICE_OUT_SPEAKER"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_WIRED_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_WIRED_HEADPHONE"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_HDMI"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_HDMI_EARC"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_AUX_DIGITAL"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_USB_ACCESSORY"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_USB_DEVICE"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_LINE"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_HDMI_ARC"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_AUX_LINE"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_SPEAKER_SAFE"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BUS"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_USB_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLE_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLE_SPEAKER"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLE_BROADCAST"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_DEFAULT"/>
+ <!-- Added to support legacy files -->
+ <xs:enumeration value="TYPE_BUILTIN_SPEAKER"/>
+ <xs:enumeration value="TYPE_WIRED_HEADSET"/>
+ <xs:enumeration value="TYPE_WIRED_HEADPHONES"/>
+ <xs:enumeration value="TYPE_BLUETOOTH_A2DP"/>
+ <xs:enumeration value="TYPE_HDMI"/>
+ <xs:enumeration value="TYPE_USB_ACCESSORY"/>
+ <xs:enumeration value="TYPE_USB_DEVICE"/>
+ <xs:enumeration value="TYPE_USB_HEADSET"/>
+ <xs:enumeration value="TYPE_AUX_LINE"/>
+ <xs:enumeration value="TYPE_BUS"/>
+ <xs:enumeration value="TYPE_BLE_HEADSET"/>
+ <xs:enumeration value="TYPE_BLE_SPEAKER"/>
+ <xs:enumeration value="TYPE_BLE_BROADCAST"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="MirroringDevicesType">
+ <xs:element name="mirroringDevice" type="MirroringDevice" maxOccurs="unbounded" />
+ </xs:complexType>
+ <xs:complexType name="MirroringDevice">
+ <xs:attribute name="address" type="xs:string" />
+ </xs:complexType>
+ <xs:complexType name="InputDevicesType">
+ <xs:element name="inputDevice" type="InputDeviceType" maxOccurs="unbounded" />
+ </xs:complexType>
+ <xs:complexType name="InputDeviceType">
+ <xs:attribute name="address" type="xs:string" />
+ <xs:attribute name="type" type="InDeviceType" />
+ </xs:complexType>
+ <xs:simpleType name="InDeviceType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AUDIO_DEVICE_IN_COMMUNICATION"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_AMBIENT"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BUILTIN_MIC"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_WIRED_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_AUX_DIGITAL"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_HDMI"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_VOICE_CALL"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_TELEPHONY_RX"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BACK_MIC"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_REMOTE_SUBMIX"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_USB_ACCESSORY"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_USB_DEVICE"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_FM_TUNER"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_TV_TUNER"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_LINE"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_SPDIF"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BLUETOOTH_A2DP"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_LOOPBACK"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_IP"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BUS"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_PROXY"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_USB_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BLUETOOTH_BLE"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_HDMI_ARC"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_ECHO_REFERENCE"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_DEFAULT"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_STUB"/>
+ </xs:restriction>
+ </xs:simpleType>
+</xs:schema>
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 0000000..3dbc2f1
--- /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 0000000..f40f1be
--- /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<android.hardware.automotive.audiocontrol.fade.AttributesType> getAudioAttribute_optional();
+ method @Nullable public java.util.List<android.hardware.automotive.audiocontrol.fade.UsageType> 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<android.hardware.automotive.audiocontrol.fade.FadeConfigurationConfig> 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<android.hardware.automotive.audiocontrol.fade.UsageType> 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<android.hardware.automotive.audiocontrol.fade.ContentType> 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 0000000..e69de29
--- /dev/null
+++ b/automotive/audiocontrol/aidl/default/loaders/fade/api/last_current.txt
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 0000000..e69de29
--- /dev/null
+++ b/automotive/audiocontrol/aidl/default/loaders/fade/api/last_removed.txt
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 0000000..d802177
--- /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 0000000..051be7e
--- /dev/null
+++ b/automotive/audiocontrol/aidl/default/loaders/fade/car_fade_audio_configuration.xsd
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" version="2.0">
+ <xs:element name="carAudioFadeConfiguration" type="CarAudioFadeConfigurationType" />
+ <xs:complexType name="CarAudioFadeConfigurationType">
+ <xs:element name="configs" type="FadeConfigurationConfigs" />
+ </xs:complexType>
+ <xs:complexType name="FadeConfigurationConfigs">
+ <xs:element name="config" type="FadeConfigurationConfig" maxOccurs="unbounded" />
+ </xs:complexType>
+ <xs:complexType name="FadeConfigurationConfig">
+ <xs:attribute name="name" type="xs:string" />
+ <xs:attribute name="defaultFadeOutDurationInMillis" type="xs:string" />
+ <xs:attribute name="defaultFadeInDurationInMillis" type="xs:string" />
+ <xs:attribute name="defaultFadeInDelayForOffenders" type="xs:string" />
+ <xs:element name="fadeState" type="FadeStateType" />
+ <xs:element name="fadeableUsages" type="FadeableUsagesType" />
+ <xs:element name="unfadeableContentTypes" type="UnfadeableContentTypesType" />
+ <xs:element name="unfadeableAudioAttributes" type="UnfadeableAudioAttributesType" />
+ <xs:element name="fadeOutConfigurations" type="FadeOutConfigurationsType" />
+ <xs:element name="fadeInConfigurations" type="FadeInConfigurationsType" />
+ </xs:complexType>
+ <xs:complexType name="FadeStateType">
+ <xs:attribute name="value" type="fadeStateEnumType" />
+ </xs:complexType>
+ <xs:simpleType name="fadeStateEnumType" >
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="0" />
+ <xs:enumeration value="1" />
+ <xs:enumeration value="FADE_STATE_DISABLED" />
+ <xs:enumeration value="FADE_STATE_ENABLED_DEFAULT" />
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="FadeableUsagesType">
+ <xs:element name="usage" type="UsageType" maxOccurs="unbounded" />
+ </xs:complexType>
+ <xs:complexType name="UsageType">
+ <xs:attribute name="value" type="usageEnumType" />
+ </xs:complexType>
+ <xs:simpleType name="usageEnumType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AUDIO_USAGE_UNKNOWN"/>
+ <xs:enumeration value="AUDIO_USAGE_MEDIA"/>
+ <xs:enumeration value="AUDIO_USAGE_VOICE_COMMUNICATION"/>
+ <xs:enumeration value="AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING"/>
+ <xs:enumeration value="AUDIO_USAGE_ALARM"/>
+ <xs:enumeration value="AUDIO_USAGE_NOTIFICATION"/>
+ <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE"/>
+ <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST"/>
+ <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT"/>
+ <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED"/>
+ <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_EVENT"/>
+ <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY"/>
+ <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
+ <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_SONIFICATION"/>
+ <xs:enumeration value="AUDIO_USAGE_GAME"/>
+ <xs:enumeration value="AUDIO_USAGE_VIRTUAL_SOURCE"/>
+ <xs:enumeration value="AUDIO_USAGE_ASSISTANT"/>
+ <xs:enumeration value="AUDIO_USAGE_CALL_ASSISTANT"/>
+ <xs:enumeration value="AUDIO_USAGE_EMERGENCY" />
+ <xs:enumeration value="AUDIO_USAGE_SAFETY" />
+ <xs:enumeration value="AUDIO_USAGE_VEHICLE_STATUS" />
+ <xs:enumeration value="AUDIO_USAGE_ANNOUNCEMENT" />
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="UnfadeableContentTypesType">
+ <xs:element name="contentType" type="ContentType" maxOccurs="unbounded" />
+ </xs:complexType>
+ <xs:complexType name="ContentType">
+ <xs:attribute name="value" type="contentTypeEnum" />
+ </xs:complexType>
+ <xs:simpleType name="contentTypeEnum">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AUDIO_CONTENT_TYPE_UNKNOWN"/>
+ <xs:enumeration value="AUDIO_CONTENT_TYPE_SPEECH"/>
+ <xs:enumeration value="AUDIO_CONTENT_TYPE_MUSIC"/>
+ <xs:enumeration value="AUDIO_CONTENT_TYPE_MOVIE"/>
+ <xs:enumeration value="AUDIO_CONTENT_TYPE_SONIFICATION"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="UnfadeableAudioAttributesType">
+ <xs:element name="audioAttributes" type="AudioAttributesUsagesType" />
+ </xs:complexType>
+ <xs:complexType name="AudioAttributesUsagesType" >
+ <xs:choice minOccurs="0" maxOccurs="unbounded" >
+ <xs:element name="audioAttribute" type="AttributesType" />
+ <xs:element name="usage" type="UsageType" />
+ </xs:choice>
+ </xs:complexType>
+ <xs:complexType name="AttributesType">
+ <xs:attribute name="contentType" type="contentTypeEnum" />
+ <xs:attribute name="usage" type="usageEnumType" />
+ <xs:attribute name="tags" type="xs:string" />
+ </xs:complexType>
+ <xs:complexType name="FadeOutConfigurationsType">
+ <xs:element name="fadeConfiguration" type="FadeConfigurationType" />
+ </xs:complexType>
+ <xs:complexType name="FadeConfigurationType">
+ <xs:attribute name="fadeDurationMillis" type="xs:string" />
+ <xs:element name="audioAttributes" type="AudioAttributesUsagesType" />
+ </xs:complexType>
+ <xs:complexType name="FadeInConfigurationsType">
+ <xs:element name="fadeConfiguration" type="FadeConfigurationType" />
+ </xs:complexType>
+</xs:schema>
diff --git a/automotive/audiocontrol/aidl/rust_impl/Android.bp b/automotive/audiocontrol/aidl/rust_impl/Android.bp
index 062d989..f9d07b2 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 @@
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 ed22356..b68daf3 100644
--- a/automotive/audiocontrol/aidl/rust_impl/README.md
+++ b/automotive/audiocontrol/aidl/rust_impl/README.md
@@ -6,7 +6,7 @@
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 ba0ca23..8184c43 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 @@
IModuleChangeCallback::IModuleChangeCallback,
MutingInfo::MutingInfo,
Reasons::Reasons,
+ AudioDeviceConfiguration::AudioDeviceConfiguration,
+ AudioZone::AudioZone
};
-use android_hardware_audio_common::aidl::android::hardware::audio::common::PlaybackTrackMetadata::PlaybackTrackMetadata;
+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 binder::{Interface, Result as BinderResult, StatusCode, Strong};
/// This struct is defined to implement IAudioControl AIDL interface.
@@ -81,4 +88,16 @@
fn clearModuleChangeCallback(&self) -> BinderResult<()> {
Err(StatusCode::UNKNOWN_ERROR.into())
}
+
+ fn getAudioDeviceConfiguration(&self) -> std::result::Result<AudioDeviceConfiguration, binder::Status> {
+ Err(binder::StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn getOutputMirroringDevices(&self) -> std::result::Result<std::vec::Vec<AudioPort>, binder::Status> {
+ Err(binder::StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn getCarAudioZones(&self) -> std::result::Result<std::vec::Vec<AudioZone>, 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 d94ad55..57c6ae4 100644
--- a/automotive/audiocontrol/aidl/vts/Android.bp
+++ b/automotive/audiocontrol/aidl/vts/Android.bp
@@ -22,6 +22,25 @@
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 @@
"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 4e7e963..f01f04d 100644
--- a/automotive/audiocontrol/aidl/vts/VtsHalAudioControlTargetTest.cpp
+++ b/automotive/audiocontrol/aidl/vts/VtsHalAudioControlTargetTest.cpp
@@ -18,32 +18,62 @@
#include <aidl/Gtest.h>
#include <aidl/Vintf.h>
#include <gmock/gmock.h>
+#include <utils/String16.h>
+#include <set>
#include <android/hardware/automotive/audiocontrol/BnAudioGainCallback.h>
#include <android/hardware/automotive/audiocontrol/BnFocusListener.h>
#include <android/hardware/automotive/audiocontrol/BnModuleChangeCallback.h>
#include <android/hardware/automotive/audiocontrol/IAudioControl.h>
#include <android/log.h>
+#include <android/media/audio/common/AudioHalProductStrategy.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
+#include <include/AudioControlTestUtils.h>
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 @@
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<std::string>& groupDevices) {
+ if (entry.contextNames.empty()) {
+ message = " Contexts can not be empty for DeviceToContextEntry";
+ return false;
+ }
+ std::set<std::string> 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<std::string>& groupDevices, std::set<int>& 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<audiomediacommon::AudioUsage> 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<std::string> contextInfoNames;
+ EXPECT_FALSE(audioZoneConfig.volumeGroups.empty())
+ << "Volume groups for zone config " << zoneConfigName.c_str();
+ std::set<std::string> groupDevices;
+ std::set<int> 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<std::string> 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<std::string, AudioZoneContextInfo> 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<AudioZoneContextInfo> 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<std::string> {
public:
virtual void SetUp() override {
@@ -292,12 +542,193 @@
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<AudioZone> 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<AudioZone> 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<int> zoneIds;
+ std::set<int> occupantIds;
+ std::set<android::String16> zoneNames;
+ std::set<std::string> deviceAddresses;
+ for (const auto& zone : audioZones) {
+ if (zone.id == static_cast<int>(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<android::String16> 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<audiomediacommon::AudioPort> 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 0000000..46fdce2
--- /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 <android/hardware/automotive/audiocontrol/IAudioControl.h>
+#include <string>
+#include <vector>
+
+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<std::string> getDeviceAddressesForVolumeGroup(
+ const android::hardware::automotive::audiocontrol::VolumeGroupConfig& config);
+
+std::vector<std::string> getDeviceAddressesForZoneConfig(
+ const android::hardware::automotive::audiocontrol::AudioZoneConfig& config);
+
+std::vector<std::string> getDeviceAddressesForZone(
+ const android::hardware::automotive::audiocontrol::AudioZone& config);
+
+bool contextInfosContainAllAudioAttributeUsages(
+ const std::vector<android::hardware::automotive::audiocontrol::AudioZoneContextInfo>& infos,
+ std::string& message);
+
+bool contextContainsAllAudioAttributeUsages(
+ const android::hardware::automotive::audiocontrol::AudioZoneContext& context,
+ std::string& message);
+
+std::vector<std::string> 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 0000000..7b7c896
--- /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 <set>
+
+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<audiomediacommon::AudioPortExt::Tag::device>().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<audiomediacommon::AudioPortExt::Tag::device>().device;
+
+ switch (audioDevice.address.getTag()) {
+ case audiomediacommon::AudioDeviceAddress::Tag::id:
+ address = audioDevice.address.get<audiomediacommon::AudioDeviceAddress::Tag::id>();
+ return true;
+ case audiomediacommon::AudioDeviceAddress::Tag::alsa:
+ address = android::internal::ToString(
+ audioDevice.address.get<audiomediacommon::AudioDeviceAddress::Tag::alsa>());
+ return true;
+ case audiomediacommon::AudioDeviceAddress::Tag::mac:
+ address = android::internal::ToString(
+ audioDevice.address.get<audiomediacommon::AudioDeviceAddress::Tag::mac>());
+ return true;
+ case audiomediacommon::AudioDeviceAddress::Tag::ipv4:
+ address = android::internal::ToString(
+ audioDevice.address.get<audiomediacommon::AudioDeviceAddress::Tag::ipv4>());
+ return true;
+ case audiomediacommon::AudioDeviceAddress::Tag::ipv6:
+ address = android::internal::ToString(
+ audioDevice.address.get<audiomediacommon::AudioDeviceAddress::Tag::ipv6>());
+ 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<std::string> getDeviceAddressesForVolumeGroup(const VolumeGroupConfig& config) {
+ std::vector<std::string> addresses;
+ for (const auto& route : config.carAudioRoutes) {
+ std::string address;
+ if (!getAddressForAudioDevice(route, address)) {
+ continue;
+ }
+ addresses.push_back(address);
+ }
+ return addresses;
+}
+
+std::vector<std::string> getDeviceAddressesForZoneConfig(const AudioZoneConfig& config) {
+ std::vector<std::string> addresses;
+ for (const auto& volumeGroup : config.volumeGroups) {
+ const auto groupAddresses = getDeviceAddressesForVolumeGroup(volumeGroup);
+ addresses.insert(addresses.begin(), groupAddresses.begin(), groupAddresses.end());
+ }
+ return addresses;
+}
+
+std::vector<std::string> getDeviceAddressesForZone(const AudioZone& config) {
+ std::vector<std::string> 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<audiomediacommon::AudioUsage>& contextUsages) {
+ for (const auto& audioAttribute : info.audioAttributes) {
+ contextUsages.insert(audioAttribute.usage);
+ }
+}
+
+bool contextInfosContainAllAudioAttributeUsages(const std::vector<AudioZoneContextInfo>& infos,
+ std::string& message) {
+ static const std::vector<audiomediacommon::AudioUsage> 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<audiomediacommon::AudioUsage> 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<std::string> getContextInfoNamesForAudioRoute(const DeviceToContextEntry& route) {
+ std::vector<std::string> contextInfoNames;
+ contextInfoNames.reserve(route.contextNames.size());
+ for (const auto& contextName : route.contextNames) {
+ contextInfoNames.push_back(android::internal::ToString(contextName));
+ }
+ return contextInfoNames;
+}
+
+std::vector<std::string> getContextInfoNamesForVolumeGroup(const VolumeGroupConfig& group) {
+ std::vector<std::string> contextInfoNames;
+ for (const auto& route : group.carAudioRoutes) {
+ std::vector<std::string> 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 b42893e..4131a65 100644
--- a/automotive/can/1.0/default/libnetdevice/Android.bp
+++ b/automotive/can/1.0/default/libnetdevice/Android.bp
@@ -25,6 +25,7 @@
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 2a0545a..9cf0253 100644
--- a/automotive/can/1.0/default/libnetdevice/can.cpp
+++ b/automotive/can/1.0/default/libnetdevice/can.cpp
@@ -33,7 +33,7 @@
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 @@
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<ifinfomsg> req(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_ACK);
+ nl::MessageFactory<ifinfomsg> 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 28e50af..22add65 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 661e3f8..e73c581 100644
--- a/automotive/can/1.0/default/libnetdevice/common.h
+++ b/automotive/can/1.0/default/libnetdevice/common.h
@@ -32,6 +32,6 @@
* \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 762ef5c..b0f88c7 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 <linux/ethtool.h>
+#include <linux/sockios.h>
namespace android::netdevice::ethtool {
-std::optional<uint32_t> getValue(const std::string& ifname, uint32_t command) {
+std::optional<uint32_t> 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<caddr_t>(&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<caddr_t>(&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 8471173..2e6ad41 100644
--- a/automotive/can/1.0/default/libnetdevice/ifreqs.cpp
+++ b/automotive/can/1.0/default/libnetdevice/ifreqs.cpp
@@ -21,6 +21,8 @@
#include <android-base/logging.h>
#include <android-base/unique_fd.h>
+#include <sys/ioctl.h>
+
#include <map>
namespace android::netdevice::ifreqs {
@@ -68,9 +70,11 @@
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<size_t>(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 aa7030b..f9d8d3b 100644
--- a/automotive/can/1.0/default/libnetdevice/ifreqs.h
+++ b/automotive/can/1.0/default/libnetdevice/ifreqs.h
@@ -52,6 +52,6 @@
* \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 3886acf..6045733 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 @@
* \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 @@
* \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 26bfdce..416108f 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 @@
* \param command Fetch command (ETHTOOL_G*)
* \return value, or nullopt if fetch failed
*/
-std::optional<uint32_t> getValue(const std::string& ifname, uint32_t command);
+std::optional<uint32_t> getValue(std::string_view ifname, uint32_t command);
/**
* Set a single value with ethtool_value.
@@ -40,6 +40,6 @@
* \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 657f9b2..15ff491 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 @@
* \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 @@
* \param ifname Interface to check
* \return true/false if the check succeeded, nullopt otherwise
*/
-std::optional<bool> isUp(std::string ifname);
+std::optional<bool> isUp(std::string_view ifname);
/**
* Interface condition to wait for.
@@ -101,7 +101,7 @@
* \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 @@
* \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<std::string> 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<uint8_t> 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 @@
* \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 @@
* \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 @@
* \param ifname Interface name
* \return Hardware address (MAC address) or nullopt if the lookup failed
*/
-std::optional<hwaddr_t> getHwAddr(const std::string& ifname);
+std::optional<hwaddr_t> getHwAddr(std::string_view ifname);
/**
* Changes interface's hardware address.
@@ -142,7 +174,7 @@
* \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 3e1b736..884b704 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 413b4b1..9bb1a57 100644
--- a/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp
+++ b/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp
@@ -23,9 +23,13 @@
#include <libnl++/MessageFactory.h>
#include <libnl++/Socket.h>
+#include <arpa/inet.h>
+#include <ifaddrs.h>
#include <linux/can.h>
#include <linux/rtnetlink.h>
#include <net/if.h>
+#include <netdb.h>
+#include <sys/ioctl.h>
#include <algorithm>
#include <iterator>
@@ -37,27 +41,102 @@
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<ifinfomsg> 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<ifaddrs, decltype(&freeifaddrs)> getifaddrs() {
+ ifaddrs* addrs = nullptr;
+ CHECK(getifaddrs(&addrs) == 0) << "getifaddrs failed: " << strerror(errno);
+ return {addrs, freeifaddrs};
+}
+
+std::set<std::string> getAllAddr4(std::string_view ifname) {
+ std::set<std::string> 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<uint8_t> prefixlen) {
+ auto ifr = ifreqs::fromName(ifname);
+ auto ifrAddr = reinterpret_cast<sockaddr_in*>(&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<sockaddr_in*>(&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<ifaddrmsg> 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<ifinfomsg> req(RTM_NEWLINK, nl::kCreateFlags);
req.add(IFLA_IFNAME, dev);
{
@@ -69,15 +148,15 @@
return sock.send(req) && sock.receiveAck(req);
}
-bool del(std::string dev) {
- nl::MessageFactory<ifinfomsg> req(RTM_DELLINK, NLM_F_REQUEST | NLM_F_ACK);
+bool del(std::string_view dev) {
+ nl::MessageFactory<ifinfomsg> req(RTM_DELLINK);
req.add(IFLA_IFNAME, dev);
nl::Socket sock(NETLINK_ROUTE);
return sock.send(req) && sock.receiveAck(req);
}
-std::optional<hwaddr_t> getHwAddr(const std::string& ifname) {
+std::optional<hwaddr_t> getHwAddr(std::string_view ifname) {
auto ifr = ifreqs::fromName(ifname);
if (!ifreqs::send(SIOCGIFHWADDR, ifr)) return std::nullopt;
@@ -86,7 +165,7 @@
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 @@
return ifreqs::send(SIOCSIFHWADDR, ifr);
}
-std::optional<bool> isUp(std::string ifname) {
+std::optional<bool> 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 35b21b8..e5b5a61 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<ifinfomsg> req(RTM_NEWLINK,
- NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK);
+ nl::MessageFactory<ifinfomsg> req(RTM_NEWLINK, nl::kCreateFlags);
req.add(IFLA_IFNAME, vlan);
req.add<uint32_t>(IFLA_LINK, ethidx);
diff --git a/automotive/can/1.0/default/libnl++/Android.bp b/automotive/can/1.0/default/libnl++/Android.bp
index d929d84..ade4ae0 100644
--- a/automotive/can/1.0/default/libnl++/Android.bp
+++ b/automotive/can/1.0/default/libnl++/Android.bp
@@ -25,6 +25,7 @@
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 221063d..a5a782c 100644
--- a/automotive/can/1.0/default/libnl++/Socket.cpp
+++ b/automotive/can/1.0/default/libnl++/Socket.cpp
@@ -20,6 +20,9 @@
#include <android-base/logging.h>
+// 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 a5a425e..f65f055 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 @@
* \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 d540482..8c7c476 100644
--- a/automotive/can/1.0/default/libnl++/printer.cpp
+++ b/automotive/can/1.0/default/libnl++/printer.cpp
@@ -26,6 +26,12 @@
#include <iomanip>
#include <sstream>
+// 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 77451ed..277f19d 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 <map>
+#include <linux/netlink.h>
+#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 3ad101e..eebd1f1 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 <android-base/logging.h>
+// should be in linux/genetlink.h
+#define GENL_START_ALLOC (NLMSG_MIN_TYPE + 3)
+
namespace android::nl::generic {
bool FamilyTracker::track(const Buffer<nlmsghdr>& 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 024d389..5bd6262 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 69d9b81..c81ee27 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 <linux/rtnetlink.h>
#include <net/if.h>
+#include <linux/if_link.h>
+#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 c969a6c..410c42e 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 @@
<< 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 37a17dc..f6ba2f2 100644
--- a/automotive/evs/aidl/impl/default/include/ConfigManager.h
+++ b/automotive/evs/aidl/impl/default/include/ConfigManager.h
@@ -50,6 +50,7 @@
class ConfigManager final {
public:
static std::unique_ptr<ConfigManager> Create();
+ static std::unique_ptr<ConfigManager> Create(const std::string path);
ConfigManager(const ConfigManager&) = delete;
ConfigManager& operator=(const ConfigManager&) = delete;
@@ -65,6 +66,15 @@
UNKNOWN = std::numeric_limits<std::underlying_type_t<DeviceType>>::max(),
};
+ enum class PixelFormat : std::int32_t {
+ NV12 = 0,
+ NV21 = 1,
+ YV12 = 2,
+ I420 = 3,
+
+ UNKNOWN = std::numeric_limits<std::underlying_type_t<DeviceType>>::max(),
+ };
+
CameraInfo() : characteristics(nullptr) {}
virtual ~CameraInfo();
@@ -82,6 +92,8 @@
static DeviceType deviceTypeFromSV(const std::string_view sv);
+ static PixelFormat pixelFormatFromSV(const std::string_view sv);
+
DeviceType deviceType{DeviceType::NONE};
/*
@@ -105,6 +117,11 @@
/* 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 @@
* @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 c3e9dfc..d9180e8 100644
--- a/automotive/evs/aidl/impl/default/include/EvsCameraBase.h
+++ b/automotive/evs/aidl/impl/default/include/EvsCameraBase.h
@@ -30,6 +30,7 @@
~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 cd68532..67de8dc 100644
--- a/automotive/evs/aidl/impl/default/include/EvsMockCamera.h
+++ b/automotive/evs/aidl/impl/default/include/EvsMockCamera.h
@@ -65,7 +65,9 @@
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<EvsMockCamera> Create(const char* deviceName);
static std::shared_ptr<EvsMockCamera> Create(
diff --git a/automotive/evs/aidl/impl/default/include/EvsVideoEmulatedCamera.h b/automotive/evs/aidl/impl/default/include/EvsVideoEmulatedCamera.h
index 9d1610a..dc70a43 100644
--- a/automotive/evs/aidl/impl/default/include/EvsVideoEmulatedCamera.h
+++ b/automotive/evs/aidl/impl/default/include/EvsVideoEmulatedCamera.h
@@ -27,7 +27,6 @@
#include <aidl/android/hardware/automotive/evs/ParameterRange.h>
#include <aidl/android/hardware/automotive/evs/Stream.h>
#include <media/NdkMediaExtractor.h>
-
#include <ui/GraphicBuffer.h>
#include <cstdint>
@@ -70,6 +69,8 @@
// Methods from EvsCameraBase follow.
void shutdown() override;
+ std::string getId() override { return mDescription.id; }
+
const evs::CameraDesc& getDesc() { return mDescription; }
static std::shared_ptr<EvsVideoEmulatedCamera> Create(const char* deviceName);
@@ -117,6 +118,10 @@
bool postVideoStreamStop_locked(ndk::ScopedAStatus& status,
std::unique_lock<std::mutex>& 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 @@
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<CameraParam, std::shared_ptr<CameraParameterDesc>> mParams;
diff --git a/automotive/evs/aidl/impl/default/src/ConfigManager.cpp b/automotive/evs/aidl/impl/default/src/ConfigManager.cpp
index d8961d0..eea80f4 100644
--- a/automotive/evs/aidl/impl/default/src/ConfigManager.cpp
+++ b/automotive/evs/aidl/impl/default/src/ConfigManager.cpp
@@ -52,6 +52,25 @@
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<std::string_view, PixelFormat> 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 @@
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 @@
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 @@
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 @@
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 @@
}
std::unique_ptr<ConfigManager> ConfigManager::Create() {
+ std::unique_ptr<ConfigManager> 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> ConfigManager::Create(const std::string path) {
std::unique_ptr<ConfigManager> cfgMgr(new ConfigManager());
/*
@@ -968,7 +996,7 @@
* 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 005c71f..c28f86f 100644
--- a/automotive/evs/aidl/impl/default/src/EvsCamera.cpp
+++ b/automotive/evs/aidl/impl/default/src/EvsCamera.cpp
@@ -205,7 +205,8 @@
}
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 480c28d..7574a34 100644
--- a/automotive/evs/aidl/impl/default/src/EvsVideoEmulatedCamera.cpp
+++ b/automotive/evs/aidl/impl/default/src/EvsVideoEmulatedCamera.cpp
@@ -26,6 +26,7 @@
#include <utils/SystemClock.h>
#include <fcntl.h>
+#include <libyuv.h>
#include <sys/types.h>
#include <unistd.h>
@@ -35,12 +36,45 @@
#include <tuple>
#include <utility>
+// 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 @@
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 @@
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 @@
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<std::size_t>(-1);
buffer_handle_t renderBufferHandle = nullptr;
{
@@ -200,7 +280,7 @@
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<BufferDesc> renderBufferDescs;
@@ -236,19 +316,51 @@
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 @@
::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 @@
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 @@
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 @@
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 8b4676e..ce0e776 100644
--- a/automotive/evs/aidl/impl/default/tests/EvsCameraBufferTest.cpp
+++ b/automotive/evs/aidl/impl/default/tests/EvsCameraBufferTest.cpp
@@ -92,6 +92,7 @@
(override));
MOCK_METHOD(bool, stopVideoStreamImpl_locked,
(ndk::ScopedAStatus & status, std::unique_lock<std::mutex>& 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 1925c79..c517e34 100644
--- a/automotive/evs/aidl/impl/default/tests/EvsCameraStateTest.cpp
+++ b/automotive/evs/aidl/impl/default/tests/EvsCameraStateTest.cpp
@@ -141,6 +141,7 @@
(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 @@
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 606e108..d549a82 100644
--- a/automotive/vehicle/Android.bp
+++ b/automotive/vehicle/Android.bp
@@ -19,13 +19,21 @@
}
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 @@
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 d848774..56bc047 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 ce9e7a1..4b2d2b8 100644
--- a/automotive/vehicle/aidl/Android.bp
+++ b/automotive/vehicle/aidl/Android.bp
@@ -27,7 +27,7 @@
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 0000000..e9633cc
--- /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 <name>-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 b5f62aa..ee58416 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 @@
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<android.hardware.automotive.vehicle.PropIdAreaId> propIdAreaIds);
+ android.hardware.automotive.vehicle.MinMaxSupportedValueResults getMinMaxSupportedValue(in List<android.hardware.automotive.vehicle.PropIdAreaId> propIdAreaIds);
+ void registerSupportedValueChangeCallback(in android.hardware.automotive.vehicle.IVehicleCallback callback, in List<android.hardware.automotive.vehicle.PropIdAreaId> propIdAreaIds);
+ void unregisterSupportedValueChangeCallback(in android.hardware.automotive.vehicle.IVehicleCallback callback, in List<android.hardware.automotive.vehicle.PropIdAreaId> 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 2c5a333..50a8e76 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 @@
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<android.hardware.automotive.vehicle.PropIdAreaId> 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 0000000..a004b79
--- /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 <name>-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 0000000..914d9c6
--- /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 <name>-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 0000000..83e9c15
--- /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 <name>-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 f7e8c5a..8651c30 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 @@
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 0000000..f348dcb
--- /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 <name>-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<android.hardware.automotive.vehicle.RawPropValues> 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 0000000..08af47c
--- /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 <name>-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 eb3028e..e3f8605 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 @@
@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 642ce83..cc88e70 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 @@
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 1e43070..8edd636 100644
--- a/automotive/vehicle/aidl/aidl_test/Android.bp
+++ b/automotive/vehicle/aidl/aidl_test/Android.bp
@@ -52,7 +52,7 @@
":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 0000000..991631b
--- /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 c896d14..cdf9066 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 @@
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.
@@ -234,6 +237,8 @@
* {@link StatusCode#INVALID_ARG}. If a specified propId was not subscribed
* before, this method must ignore that propId.
*
+ * Unsubscribe a not-subscribed property ID must do nothing.
+ *
* If error is returned, some of the properties failed to unsubscribe.
* Caller is safe to try again, since unsubscribing an already unsubscribed
* property is okay.
@@ -260,4 +265,118 @@
* the used shared memory file to return.
*/
void returnSharedMemory(in IVehicleCallback callback, long sharedMemoryId);
+
+ /**
+ * Gets the supported values lists for [propId, areaId]s.
+ *
+ * This is only supported for [propId, areaId]s that have non-null
+ * {@code hasSupportedValueInfo} for their {@code VehicleAreaConfig}.
+ *
+ * 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<PropIdAreaId> propIdAreaIds);
+
+ /**
+ * Gets the min/max supported values for [propId, areaId]s.
+ *
+ * This is only supported for [propId, areaId]s that have non-null
+ * {@code hasSupportedValueInfo} for their {@code VehicleAreaConfig}.
+ *
+ * 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<PropIdAreaId> propIdAreaIds);
+
+ /**
+ * Registers the supported value change callback.
+ *
+ * This is only supported for [propId, areaId]s that have non-null
+ * {@code hasSupportedValueInfo} for their {@code VehicleAreaConfig}.
+ *
+ * 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<PropIdAreaId> propIdAreaIds);
+
+ /**
+ * Unregisters the supported value change callback.
+ *
+ * This is only supported for [propId, areaId]s that have non-null
+ * {@code hasSupportedValueInfo} for their {@code VehicleAreaConfig}.
+ *
+ * @param callback The callback to unregister.
+ * @param propIdAreaIds A list of [propId, areaId]s to unregister.
+ */
+ void unregisterSupportedValueChangeCallback(
+ in IVehicleCallback callback, in List<PropIdAreaId> propIdAreaIds);
}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicleCallback.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicleCallback.aidl
index 2b50321..7230d09 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 @@
* 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<PropIdAreaId> 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 0000000..a3508ee
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/MinMaxSupportedValueResult.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.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}.
+ *
+ * This must be ignored if status is not {@code StatusCode.OK}.
+ */
+ @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 0000000..3579979
--- /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 0000000..ea47350
--- /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 fd4b199..3fb4532 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 @@
* 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 0000000..8800b0b
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SupportedValuesListResult.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.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}.
+ *
+ * This must be ignored if status is not {@code StatusCode.OK}.
+ */
+ @nullable List<RawPropValues> 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 0000000..da84871
--- /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 9387965..c6b8cd1 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 @@
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 @@
/**
* 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,19 @@
* so this should be false if the property is large (e.g. a byte array of 1k in size).
*/
boolean supportVariableUpdateRate;
+
+ /**
+ * This specifies whether this property may have min/max supported value or supported values
+ * list for [propId, areaId] that supports new supported values APIs.
+ *
+ * If this is not {@code null}. The client may use {@code getMinMaxSupportedValue},
+ * {@code getSupportedValuesLists}, {@code subscribeSupportedValueChange},
+ * {@code unsubscribeSupportedValueChange}.
+ *
+ * If this is {@code null} for legacy properties, the APIs mentioned before are not supported.
+ * Client must fallback to use static supported value information in {@code VehicleAreaConfig}.
+ *
+ * For VHAL implementation < V4, this is always {@code null}.
+ */
+ @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 400e256..4b1dcdb 100644
--- a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyStatus.aidl
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyStatus.aidl
@@ -22,9 +22,15 @@
@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
* implementation (e.g. hardware or driver). It MUST NOT be used to
@@ -34,8 +40,45 @@
* 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.
*/
- UNAVAILABLE = 0x01,
- /** There is an error with this property. */
+ NOT_AVAILABLE_GENERAL = 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 8ef440d..da73b03 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
@@ -93,6 +93,20 @@
"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,
"description": "Current odometer value of the vehicle"
@@ -118,6 +132,16 @@
"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,
"description": "Temperature of engine coolant"
@@ -194,7 +218,7 @@
{
"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\nEach tire is identified by its areaConfig.areaId config and its minFloatValue\/maxFloatValue are used to store OEM recommended pressure range.\nThe minFloatValue and maxFloatValue in VehicleAreaConfig must be defined.\nThe minFloatValue in the areaConfig data represents the lower bound of the recommended tire pressure.\nThe maxFloatValue in the areaConfig data represents the upper bound of the recommended tire pressure.\nFor example:\nThe following areaConfig indicates the recommended tire pressure of the left_front tire is from 200.0 KILOPASCAL to 240.0 KILOPASCAL. .areaConfigs = { VehicleAreaConfig { .areaId = VehicleAreaWheel::LEFT_FRONT, .minFloatValue = 200.0, .maxFloatValue = 240.0, } }\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minFloatValue. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxFloatValue. 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. At boot, minFloatValue is equal to minSupportedValue, maxFloatValue is equal to maxSupportedValue."
},
{
"name": "Critically low tire pressure",
@@ -202,6 +226,31 @@
"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,
"description": "Represents feature for engine idle automatic stop.\nIf true, the vehicle may automatically shut off the engine when it is not needed and then automatically restart it when needed.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
@@ -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), the VehicleAreaConfig#supportedEnumValues array must be defined unless all bit flags of ImpactSensorLocation are supported.\nIf {@code HasSupportedValueInfo} is not {@code null} 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. At boot, supportedEnumValues is equal to the supported values list."
+ },
+ {
+ "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.\nValues in the config array must represent the list of supported gears for this vehicle at boot time. For example, config array 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 contain {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.\nIf {@code HasSupportedValueInfo} is not {@code null} for the global area ID (0): {@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\"), the GEAR_SELECTION property value must be set to the specific gear selected by the driver instead of simply GEAR_DRIVE. At boot, the config array's values are equal to the supported values list."
},
{
"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.\nValues in the config array must represent the list of supported gears for this vehicle at boot time. For example, config array for an automatic transmission must contain {GEAR_NEUTRAL, GEAR_REVERSE, GEAR_PARK, GEAR_1, GEAR_2,...} and for manual transmission the list must contain {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.\nIf {@code HasSupportedValueInfo} is not {@code null} for the global area ID (0): {@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. At boot, the config array's values are equal to the supported values list."
},
{
"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\nThe minInt32Value and maxInt32Value in VehicleAreaConfig must be defined. All values between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the setting for no regenerative braking, must be 0.\nThe maxInt32Value indicates the setting for the maximum amount of energy regenerated from braking.\nAll values between min and max supported value must be supported.\nIf {@code HasSupportedValueInfo} is not {@code null} for the global area ID (0): {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for global area ID(0) {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\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), the VehicleAreaConfig#supportedEnumValues must be defined unless all enum values of EvStoppingMode are supported.\nIf {@code HasSupportedValueInfo} is not {@code null} for the global area ID (0): 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. At boot, supportedEnumValues is equal to the supported values list.\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,12 +362,30 @@
"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), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of both ElectronicStabilityControlState (including OTHER, which is not recommended) and ErrorState are supported.\nIf {@code HasSupportedValueInfo} is not {@code null} for the global area ID (0): 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. At boot, supportedEnumValues is equal to the supported values list."
+ },
+ {
+ "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",
"value": 356517120,
- "description": "Fan speed setting\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the lowest fan speed. The maxInt32Value indicates the highest fan speed.\nThis property is not in any particular unit but in a specified range of relative speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Fan speed setting\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the lowest fan speed.\nThe maxInt32Value indicates the highest fan speed.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the specific area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Fan direction 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.",
@@ -332,7 +404,7 @@
{
"name": "HVAC_TEMPERATURE_SET",
"value": 358614275,
- "description": "HVAC target temperature set in Celsius.\nThe minFloatValue and maxFloatValue in VehicleAreaConfig must be defined.\nThe minFloatValue indicates the minimum temperature setting in Celsius. The maxFloatValue indicates the maximum temperature setting in Celsius.\nIf all the values between minFloatValue and maxFloatValue are not supported, the configArray can be used to list the valid temperature values that can be set. It also describes a lookup table to convert the temperature from Celsius to Fahrenheit and vice versa for this vehicle. The configArray must be defined if standard unit conversion is not supported on this vehicle.\nThe configArray is set as follows: configArray[0] = [the lower bound of the supported temperature in Celsius] * 10. configArray[1] = [the upper bound of the supported temperature in Celsius] * 10. configArray[2] = [the increment in Celsius] * 10. configArray[3] = [the lower bound of the supported temperature in Fahrenheit] * 10. configArray[4] = [the upper bound of the supported temperature in Fahrenheit] * 10. configArray[5] = [the increment in Fahrenheit] * 10.\nThe minFloatValue and maxFloatValue in VehicleAreaConfig must be equal to configArray[0] and configArray[1] respectively.\nFor example, if the vehicle supports temperature values as: [16.0, 16.5, 17.0 ,..., 28.0] in Celsius [60.5, 61.5, 62.5 ,..., 84.5] in Fahrenheit The configArray should be configArray = {160, 280, 5, 605, 845, 10}.\nIdeally, the ratio of the Celsius increment to the Fahrenheit increment should be as close to the actual ratio of 1 degree Celsius to 1.8 degrees Fahrenheit.\nThere must be a one to one mapping of all Celsius values to Fahrenheit values defined by the configArray. The configArray will be used by clients to convert this property's temperature from Celsius to Fahrenheit. Also, it will let clients know what Celsius value to set the property to achieve their desired Fahreneheit value for the system. If the ECU does not have a one to one mapping of all Celsius values to Fahrenheit values, then the config array should only define the list of Celsius and Fahrenheit values that do have a one to one mapping.\nFor example, if the ECU supports Celsius values from 16 to 28 and Fahrenheit values from 60 to 85 both with an increment of 1, then one possible configArray would be {160, 280, 10, 600, 840, 20}. In this case, 85 would not be a supported temperature.\nAny value set in between a valid value should be rounded to the closest valid value.\nIt is highly recommended that the OEM also implement the HVAC_TEMPERATURE_VALUE_SUGGESTION vehicle property because it provides applications a simple method for determining temperature values that can be set for this vehicle and for converting values between Celsius and Fahrenheit.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "HVAC target temperature set in Celsius.\nThe minFloatValue and maxFloatValue in VehicleAreaConfig must be defined.\nThe minFloatValue indicates the minimum temperature setting in Celsius.\nThe maxFloatValue indicates the maximum temperature setting in Celsius.\nIf all the values between minFloatValue and maxFloatValue are not supported, the configArray can be used to list the valid temperature values that can be set. It also describes a lookup table to convert the temperature from Celsius to Fahrenheit and vice versa for this vehicle. The configArray must be defined if standard unit conversion is not supported on this vehicle.\nThe configArray is set as follows: configArray[0] = [the lower bound of the supported temperature in Celsius] * 10. configArray[1] = [the upper bound of the supported temperature in Celsius] * 10. configArray[2] = [the increment in Celsius] * 10. configArray[3] = [the lower bound of the supported temperature in Fahrenheit] * 10. configArray[4] = [the upper bound of the supported temperature in Fahrenheit] * 10. configArray[5] = [the increment in Fahrenheit] * 10.\nThe minFloatValue and maxFloatValue in VehicleAreaConfig must be equal to configArray[0] and configArray[1] respectively.\nFor example, if the vehicle supports temperature values as: [16.0, 16.5, 17.0 ,..., 28.0] in Celsius [60.5, 61.5, 62.5 ,..., 84.5] in Fahrenheit The configArray should be configArray = {160, 280, 5, 605, 845, 10}.\nIdeally, the ratio of the Celsius increment to the Fahrenheit increment should be as close to the actual ratio of 1 degree Celsius to 1.8 degrees Fahrenheit.\nThere must be a one to one mapping of all Celsius values to Fahrenheit values defined by the configArray. The configArray will be used by clients to convert this property's temperature from Celsius to Fahrenheit. Also, it will let clients know what Celsius value to set the property to achieve their desired Fahreneheit value for the system. If the ECU does not have a one to one mapping of all Celsius values to Fahrenheit values, then the config array should only define the list of Celsius and Fahrenheit values that do have a one to one mapping.\nFor example, if the ECU supports Celsius values from 16 to 28 and Fahrenheit values from 60 to 85 both with an increment of 1, then one possible configArray would be {160, 280, 10, 600, 840, 20}. In this case, 85 would not be a supported temperature.\nAny value set in between a valid value should be rounded to the closest valid value.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the specific area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minFloatValue. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxFloatValue. If not all the values between minSupportedValue and maxSupportedValue are supported, {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} for the specified area ID. At boot, supportedValuesList must be equal to what is described in config array. At boot, minFloatValue is equal to minSupportedValue, maxFloatValue is equal to maxSupportedValue.\nIt is highly recommended that the OEM also implement the HVAC_TEMPERATURE_VALUE_SUGGESTION vehicle property because it provides applications a simple method for determining temperature values that can be set for this vehicle and for converting values between Celsius and Fahrenheit.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "HVAC_DEFROSTER",
@@ -372,17 +444,17 @@
{
"name": "Seat heating\/cooling",
"value": 356517131,
- "description": "Seat heating\/cooling\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe maxInt32Value indicates the maximum seat temperature heating setting. The minInt32Value must be 0, unless the vehicle supports seat cooling as well. In this case, minInt32Value indicates the maximum seat temperature cooling setting.\nThis property is not in any particular unit, but in a specified range of relative temperature settings.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Seat heating\/cooling\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value must be 0, unless the vehicle supports seat cooling as well. In this case, minInt32Value indicates the maximum seat temperature cooling setting.\nThe maxInt32Value indicates the maximum seat temperature heating setting.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the specified area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit, but in a specified range of relative temperature settings.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Side Mirror Heat",
"value": 339739916,
- "description": "Side Mirror Heat\nIncreasing values denote higher heating levels for side mirrors.\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe maxInt32Value in the config data represents the maximum heating level. The minInt32Value in the config data MUST be zero and indicates no heating.\nThis property is not in any particular unit but in a specified range of relative heating settings.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Side Mirror Heat\nIncreasing values denote higher heating levels for side mirrors.\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value in the config data MUST be zero and indicates no heating.\nThe maxInt32Value in the config data represents the maximum heating level.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the specified area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative heating settings.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Steering Wheel Heating\/Cooling",
"value": 289408269,
- "description": "Steering Wheel Heating\/Cooling\nSets the amount of heating\/cooling for the steering wheel.\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe maxInt32Value indicates the maximum steering wheel heating setting. The minInt32Value should be 0, unless the vehicle supports steering wheel cooling as well. In such a case, the minInt32Value indicates the maximum steering wheel cooling setting.\nThis property is not in any particular unit but in a specified range of heating settings.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Steering Wheel Heating\/Cooling\nSets the amount of heating\/cooling for the steering wheel.\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value should be 0, unless the vehicle supports steering wheel cooling as well. In such a case, the minInt32Value indicates the maximum steering wheel cooling setting.\nThe maxInt32Value indicates the maximum steering wheel heating setting.\nIf {@code HasSupportedValueInfo} is not null for the global area ID (0): {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true}. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of heating settings.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Temperature units for display",
@@ -391,7 +463,7 @@
"VehicleUnit"
],
"data_enum": "VehicleUnit",
- "description": "Temperature units for display\nIndicates whether the vehicle is displaying temperature to the user as Celsius or Fahrenheit. VehiclePropConfig.configArray is used to indicate the supported temperature display units. For example: configArray[0] = CELSIUS configArray[1] = FAHRENHEIT\nThis parameter MAY be used for displaying any HVAC temperature in the system. Values must be one of VehicleUnit.CELSIUS or VehicleUnit.FAHRENHEIT Note that internally, all temperatures are represented in floating point Celsius.\nIf updating HVAC_TEMPERATURE_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."
+ "description": "Temperature units for display\nIndicates whether the vehicle is displaying temperature to the user as Celsius or Fahrenheit.\nVehiclePropConfig.configArray is used to indicate the supported temperature display units.\nFor example: configArray[0] = CELSIUS configArray[1] = FAHRENHEIT\nIf {@code HasSupportedValueInfo} is not {@code null} for the global area ID (0): {@code VehicleAreaConfig.HasSupportedValueInfo.hasSupportedValuesList} for the global area ID (0) must be {@code true}. {@code getSupportedValuesLists} for [HVAC_TEMPERATURE_DISPLAY_UNITS, areaId=0] must return a {@code SupportedValuesListResult} that contains non-null {@code supportedValuesList}, e.g. [CELSIUS, FAHRENHEIT]. At boot, the values in the config array are equal to the supported values list.\nThis parameter MAY be used for displaying any HVAC temperature in the system. Values must be one of VehicleUnit.CELSIUS or VehicleUnit.FAHRENHEIT Note that internally, all temperatures are represented in floating point Celsius.\nIf updating HVAC_TEMPERATURE_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": "Actual fan speed",
@@ -420,7 +492,7 @@
{
"name": "Seat ventilation",
"value": 356517139,
- "description": "Seat ventilation\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value must be 0. The maxInt32Value indicates the maximum ventilation setting available for the seat.\nThis property is not in any particular unit but in the specified range of ventilation settings.\nUsed by HVAC apps and Assistant to enable, change, or read state of seat ventilation. This is different than seating cooling. It can be on at the same time as cooling, or not.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Seat ventilation\nThe minInt32Value and maxInt32Value in VehicleAreaConfig must be defined.\nAll integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value must be 0.\nThe maxInt32Value indicates the maximum ventilation setting available for the seat.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the specified area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in the specified range of ventilation settings.\nUsed by HVAC apps and Assistant to enable, change, or read state of seat ventilation. This is different than seating cooling. It can be on at the same time as cooling, or not.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Electric defrosters' status",
@@ -439,7 +511,7 @@
"VehicleUnit"
],
"data_enum": "VehicleUnit",
- "description": "Distance units for display\nIndicates which units the car is using to display distances to the user. Eg. Mile, Meter Kilometer.\nDistance units are defined in VehicleUnit. VehiclePropConfig.configArray is used to indicate the supported distance display units. For example: configArray[0] = METER configArray[1] = KILOMETER configArray[2] = MILE\nIf updating DISTANCE_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."
+ "description": "Distance units for display\nIndicates which units the car is using to display distances to the user. Eg. Mile, Meter Kilometer.\nDistance units are defined in VehicleUnit. VehiclePropConfig.configArray is used to indicate the supported distance display units. For example: configArray[0] = METER configArray[1] = KILOMETER configArray[2] = MILE\nIf {@code HasSupportedValueInfo} is not {@code null} for the global area ID (0): {@code VehicleAreaConfig.HasSupportedValueInfo.hasSupportedValuesList} for the global area ID (0) must be {@code true}. {@code getSupportedValuesLists} for [DISTANCE_DISPLAY_UNITS, areaId=0] must returns a {@code SupportedValuesListResult} that contains non-null {@code supportedValuesList}, e.g. [METER, KILOMETER, MILE]. At boot, the values in the config array are equal to the supported values list.\nIf updating DISTANCE_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": "Fuel volume units for display",
@@ -448,7 +520,7 @@
"VehicleUnit"
],
"data_enum": "VehicleUnit",
- "description": "Fuel volume units for display\nIndicates which units the car is using to display fuel volume to the user. Eg. Liter or Gallon.\nVehiclePropConfig.configArray is used to indicate the supported fuel volume display units. Volume units are defined in VehicleUnit. For example: configArray[0] = LITER configArray[1] = GALLON\nIf updating FUEL_VOLUME_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."
+ "description": "Fuel volume units for display\nIndicates which units the car is using to display fuel volume to the user. Eg. Liter or Gallon.\nVehiclePropConfig.configArray is used to indicate the supported fuel volume display units. Volume units are defined in VehicleUnit. For example: configArray[0] = LITER configArray[1] = GALLON\nIf {@code HasSupportedValueInfo} is not {@code null} for the global area ID (0): {@code VehicleAreaConfig.HasSupportedValueInfo.hasSupportedValuesList} for the global area ID (0) must be {@code true}. {@code getSupportedValuesLists} for [FUEL_VOLUME_DISPLAY_UNITS, areaId=0] must return a {@code SupportedValuesListResult} that contains non-null {@code supportedValuesList}, e.g. [LITER, GALLON]. At boot, the values in the config array are equal to the supported values list.\nIf updating FUEL_VOLUME_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": "TIRE_PRESSURE_DISPLAY_UNITS",
@@ -457,7 +529,7 @@
"VehicleUnit"
],
"data_enum": "VehicleUnit",
- "description": "Tire pressure units for display\nIndicates which units the car is using to display tire pressure to the user. Eg. PSI, Bar or Kilopascal.\nVehiclePropConfig.configArray is used to indicate the supported pressure display units. Pressure units are defined in VehicleUnit. For example: configArray[0] = KILOPASCAL configArray[1] = PSI configArray[2] = BAR\nIf updating TIRE_PRESSURE_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."
+ "description": "Tire pressure units for display\nIndicates which units the car is using to display tire pressure to the user. Eg. PSI, Bar or Kilopascal.\nVehiclePropConfig.configArray is used to indicate the supported pressure display units. Pressure units are defined in VehicleUnit. For example: configArray[0] = KILOPASCAL configArray[1] = PSI configArray[2] = BAR\nIf {@code HasSupportedValueInfo} is not {@code null} for the global area ID (0): {@code VehicleAreaConfig.HasSupportedValueInfo.hasSupportedValuesList} for the global area ID (0) must be {@code true}. {@code getSupportedValuesLists} for [TIRE_PRESSURE_DISPLAY_UNITS, areaId=0] must return a {@code SupportedValuesListResult} that contains non-null {@code supportedValuesList}, e.g. [KILOPASCAL, PSI, BAR]. At boot, the values in the config array are equal to the supported values list.\nIf updating TIRE_PRESSURE_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": "EV battery units for display",
@@ -466,7 +538,7 @@
"VehicleUnit"
],
"data_enum": "VehicleUnit",
- "description": "EV battery units for display\nIndicates which units the car is using to display EV battery information to the user. Eg. watt-hours(Wh), kilowatt-hours(kWh) or ampere-hours(Ah).\nVehiclePropConfig.configArray is used to indicate the supported electrical energy units. Electrical energy units are defined in VehicleUnit. For example: configArray[0] = WATT_HOUR configArray[1] = AMPERE_HOURS configArray[2] = KILOWATT_HOUR\nIf updating EV_BATTERY_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."
+ "description": "EV battery units for display\nIndicates which units the car is using to display EV battery information to the user. Eg. watt-hours(Wh), kilowatt-hours(kWh) or ampere-hours(Ah).\nVehiclePropConfig.configArray is used to indicate the supported electrical energy units. Electrical energy units are defined in VehicleUnit. For example: configArray[0] = WATT_HOUR configArray[1] = AMPERE_HOURS configArray[2] = KILOWATT_HOUR\nIf {@code HasSupportedValueInfo} is not {@code null} for the global area ID (0): {@code VehicleAreaConfig.HasSupportedValueInfo.hasSupportedValuesList} for the global area ID (0) must be {@code true}. {@code getSupportedValuesLists} for [EV_BATTERY_DISPLAY_UNITS, areaId=0] must return a {@code SupportedValuesListResult} that contains non-null {@code supportedValuesList}, e.g. [WATT_HOUR, AMPERE_HOURS, KILOWATT_HOUR]. At boot, the values in the config array are equal to the supported values list.\nIf updating EV_BATTERY_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": "FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME",
@@ -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.\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 {@code HasSupportedValueInfo} is not {@code null} for the global area ID (0): {@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]. At boot, the values in the config array are equal to the supported values list.\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",
@@ -569,12 +645,12 @@
{
"name": "Door position",
"value": 373295872,
- "description": "Door position\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the door is closed. The minInt32Value must be 0. The maxInt32Value indicates the door is fully open.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the closed and fully open positions.\nThis property is not in any particular unit but in a specified range of relative positions.\nSome vehicles (minivans) can open the door electronically. Hence, the ability to write this property.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Door position\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the door is closed. The minInt32Value must be 0.\nThe maxInt32Value indicates the door is fully open.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the closed and fully open positions.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative positions.\nSome vehicles (minivans) can open the door electronically. Hence, the ability to write this property.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Door move",
"value": 373295873,
- "description": "Door move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe maxInt32Value represents the maximum movement speed of the door while opening. The minInt32Value represents the maximum movement speed of the door while closing.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the door reaches the positional limit, the value must reset to 0. If DOOR_MOVE's value is currently 0, then that means there is no movement currently occurring.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Door move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value represents the maximum movement speed of the door while closing.\nThe maxInt32Value represents the maximum movement speed of the door while opening.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the door reaches the positional limit, the value must reset to 0. If DOOR_MOVE's value is currently 0, then that means there is no movement currently occurring.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Door lock",
@@ -589,22 +665,22 @@
{
"name": "Mirror Z Position",
"value": 339741504,
- "description": "Mirror Z Position\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the mirror is tilted completely downwards. This must be a non-positive value. The maxInt32Value indicates the mirror is tilted completely upwards. This must be a non-negative value. 0 indicates the mirror is not tilted in either direction.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the fully downward and fully upwards positions.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Mirror Z Position\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the mirror is tilted completely downwards. This must be a non-positive value.\nThe maxInt32Value indicates the mirror is tilted completely upwards. This must be a non-negative value.\n0 indicates the mirror is not tilted in either direction.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the fully downward and fully upwards positions.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. Values in between minSupportedValue and maxSupportedValue indicate a transition state between the fully downward and fully upwards positions. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Mirror Z Move",
"value": 339741505,
- "description": "Mirror Z Move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe maxInt32Value represents the maximum movement speed of the mirror while tilting upwards. The minInt32Value represents the maximum movement speed of the mirror while tilting downwards.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the mirror reaches the positional limit, the value must reset to 0. If MIRROR_Z_MOVE's value is currently 0, then that means there is no movement currently occurring.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Mirror Z Move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value represents the maximum movement speed of the mirror while tilting downwards.\nThe maxInt32Value represents the maximum movement speed of the mirror while tilting upwards.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the mirror reaches the positional limit, the value must reset to 0. If MIRROR_Z_MOVE's value is currently 0, then that means there is no movement currently occurring.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Mirror Y Position",
"value": 339741506,
- "description": "Mirror Y Position\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the mirror is tilted completely to the left. This must be a non-positive value. The maxInt32Value indicates the mirror is tilted completely to the right. This must be a non-negative value. 0 indicates the mirror is not tilted in either direction.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the left extreme and right extreme positions.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Mirror Y Position\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the mirror is tilted completely to the left. This must be a non-positive value.\nThe maxInt32Value indicates the mirror is tilted completely to the right. This must be a non-negative value.\n0 indicates the mirror is not tilted in either direction.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the left extreme and right extreme positions.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. Values in between minSupportedValue and maxSupportedValue indicate a transition state between the fully downward and fully upwards positions. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Mirror Y Move",
"value": 339741507,
- "description": "Mirror Y Move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe maxInt32Value represents the maximum movement speed of the mirror while tilting right. The minInt32Value represents the maximum movement speed of the mirror while tilting left.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the mirror reaches the positional limit, the value must reset to 0. If MIRROR_Y_MOVE's value is currently 0, then that means there is no movement currently occurring.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Mirror Y Move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value represents the maximum movement speed of the mirror while tilting left.\nThe maxInt32Value represents the maximum movement speed of the mirror while tilting right.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the mirror reaches the positional limit, the value must reset to 0. If MIRROR_Y_MOVE's value is currently 0, then that means there is no movement currently occurring.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Mirror Lock",
@@ -629,12 +705,12 @@
{
"name": "Seat memory select",
"value": 356518784,
- "description": "Seat memory select\nThis parameter selects the memory preset to use to select the seat position. The maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported. The minInt32Value is always 0, and the maxInt32Value determines the number of seat preset memory slots available (i.e. numSeatPresets - 1).\nFor instance, if the driver's seat has 3 memory presets, the maxInt32Value will be 2. When the user wants to select a preset, the desired preset number (0, 1, or 2) is set."
+ "description": "Seat memory select\nThis parameter selects the memory preset to use to select the seat position.\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined.\nAll integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value is always 0, and the maxInt32Value determines the number of seat preset memory slots available (i.e. numSeatPresets - 1).\nFor instance, if the driver's seat has 3 memory presets, the maxInt32Value will be 2. When the user wants to select a preset, the desired preset number (0, 1, or 2) is set.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue."
},
{
"name": "Seat memory set",
"value": 356518785,
- "description": "Seat memory set\nThis setting allows the user to save the current seat position settings into the selected preset slot. The maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. The minInt32Value must be 0, and the maxInt32Value for each seat position must match the maxInt32Value for SEAT_MEMORY_SELECT."
+ "description": "Seat memory set\nThis setting allows the user to save the current seat position settings into the selected preset slot.\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined.\nThe minInt32Value must be 0, and the maxInt32Value for each seat position must match the maxInt32Value for SEAT_MEMORY_SELECT.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue."
},
{
"name": "Seatbelt buckled",
@@ -644,92 +720,92 @@
{
"name": "Seatbelt height position",
"value": 356518787,
- "description": "Seatbelt height position\nAdjusts the shoulder belt anchor point.\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the seat belt's shoulder anchor is at its lowest position. The maxInt32Value indicates the seat belt's shoulder anchor is at its highest position.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the lowest and highest positions.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Seatbelt height position\nAdjusts the shoulder belt anchor point.\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the seat belt's shoulder anchor is at its lowest position.\nThe maxInt32Value indicates the seat belt's shoulder anchor is at its highest position.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the lowest and highest positions.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. Values in between minSupportedValue and maxSupportedValue indicate a transition state between the lowest and highest positions. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Seatbelt height move",
"value": 356518788,
- "description": "Seatbelt height move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe maxInt32Value represents the maximum movement speed of the seat belt's shoulder anchor while moving upwards. The minInt32Value represents the maximum movement speed of the seat belt's shoulder anchor while moving downwards.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the seat belt reaches the positional limit, the value must reset to 0. If SEAT_BELT_HEIGHT_MOVE's value is currently 0, then that means there is no movement currently occurring.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Seatbelt height move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value represents the maximum movement speed of the seat belt's shoulder anchor while moving downwards.\nThe maxInt32Value represents the maximum movement speed of the seat belt's shoulder anchor while moving upwards.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the seat belt reaches the positional limit, the value must reset to 0. If SEAT_BELT_HEIGHT_MOVE's value is currently 0, then that means there is no movement currently occurring.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Seat fore\/aft position",
"value": 356518789,
- "description": "Seat fore\/aft position\nSets the seat position forward and backwards.\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the seat is at its rearward-most linear position. The maxInt32Value indicates the seat is at its forward-most linear position.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the closest and farthest positions.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Seat fore\/aft position\nSets the seat position forward and backwards.\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the seat is at its rearward-most linear position.\nThe maxInt32Value indicates the seat is at its forward-most linear position.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the closest and farthest positions.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Seat fore\/aft move",
"value": 356518790,
- "description": "Seat fore\/aft move\nThis property moves the entire seat forward\/backward in the direction that it is facing.\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe maxInt32Value represents the maximum movement speed of the seat while moving forward. The minInt32Value represents the maximum movement speed of the seat while moving backward.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the seat reaches the positional limit, the value must reset to 0. If SEAT_FORE_AFT_MOVE's value is currently 0, then that means there is no movement currently occurring.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Seat fore\/aft move\nThis property moves the entire seat forward\/backward in the direction that it is facing.\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value represents the maximum movement speed of the seat while moving backward.\nThe maxInt32Value represents the maximum movement speed of the seat while moving forward.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the seat reaches the positional limit, the value must reset to 0. If SEAT_FORE_AFT_MOVE's value is currently 0, then that means there is no movement currently occurring.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Seat backrest angle 1 position",
"value": 356518791,
- "description": "Seat backrest angle 1 position\nBackrest angle 1 is the actuator closest to the bottom of the seat.\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the seat backrest's full recline position w.r.t the actuator at the bottom of the seat. The maxInt32Value indicates the seat backrest's most upright\/forward position w.r.t the actuator at the bottom of the seat.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the full recline and upright\/forward positions.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Seat backrest angle 1 position\nBackrest angle 1 is the actuator closest to the bottom of the seat.\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the seat backrest's full recline position w.r.t the actuator at the bottom of the seat.\nThe maxInt32Value indicates the seat backrest's most upright\/forward position w.r.t the actuator at the bottom of the seat.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the full recline and upright\/forward positions.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. Values in between minSupportedValue and maxSupportedValue indicate a transition state between the full recline and upright\/forward positions. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Seat backrest angle 1 move",
"value": 356518792,
- "description": "Seat backrest angle 1 move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe maxInt32Value represents the maximum movement speed of the seat backrest while angling forward. The minInt32Value represents the maximum movement speed of the seat backrest while reclining.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the seat backrest reaches the positional limit, the value must reset to 0. If SEAT_BACKREST_ANGLE_1_MOVE's value is currently 0, then that means there is no movement currently occurring.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Seat backrest angle 1 move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value represents the maximum movement speed of the seat backrest while reclining.\nThe maxInt32Value represents the maximum movement speed of the seat backrest while angling forward.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the seat backrest reaches the positional limit, the value must reset to 0. If SEAT_BACKREST_ANGLE_1_MOVE's value is currently 0, then that means there is no movement currently occurring.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Seat backrest angle 2 position",
"value": 356518793,
- "description": "Seat backrest angle 2 position\nBackrest angle 2 is the next actuator up from the bottom of the seat.\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the seat backrest's full recline position w.r.t the next actuator in the backrest from the one at the bottom of the seat (see SEAT_BACKREST_ANGLE_1_POS for additional details). The maxInt32Value indicates the seat backrest's most upright\/forward position w.r.t the next actuator in the backrest from the one at the bottom of the seat(see SEAT_BACKREST_ANGLE_1_POS for additional details).\nValues in between minInt32Value and maxInt32Value indicate a transition state between the full recline and upright\/forward positions.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Seat backrest angle 2 position\nBackrest angle 2 is the next actuator up from the bottom of the seat.\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the seat backrest's full recline position w.r.t the next actuator in the backrest from the one at the bottom of the seat (see SEAT_BACKREST_ANGLE_1_POS for additional details).\nThe maxInt32Value indicates the seat backrest's most upright\/forward position w.r.t the next actuator in the backrest from the one at the bottom of the seat(see SEAT_BACKREST_ANGLE_1_POS for additional details).\nValues in between minInt32Value and maxInt32Value indicate a transition state between the full recline and upright\/forward positions.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} ihas the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. Values in between minSupportedValue and maxSupportedValue indicate a transition state between the full recline and upright\/forward positions. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Seat backrest angle 2 move",
"value": 356518794,
- "description": "Seat backrest angle 2 move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe maxInt32Value represents the maximum movement speed of the seat backrest while angling forward. The minInt32Value represents the maximum movement speed of the seat backrest while reclining.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the seat backrest reaches the positional limit, the value must reset to 0. If SEAT_BACKREST_ANGLE_2_MOVE's value is currently 0, then that means there is no movement currently occurring.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Seat backrest angle 2 move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value represents the maximum movement speed of the seat backrest while reclining.\nThe maxInt32Value represents the maximum movement speed of the seat backrest while angling forward.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the seat backrest reaches the positional limit, the value must reset to 0. If SEAT_BACKREST_ANGLE_2_MOVE's value is currently 0, then that means there is no movement currently occurring.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Seat height position",
"value": 356518795,
- "description": "Seat height position\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the seat is in its lowest position. The maxInt32Value indicates the seat is in its highest position.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the lowest and highest positions.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Seat height position\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the seat is in its lowest position.\nThe maxInt32Value indicates the seat is in its highest position.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the lowest and highest positions.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. position. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Seat height move",
"value": 356518796,
- "description": "Seat height move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe maxInt32Value represents the maximum movement speed of the seat while moving upward. The minInt32Value represents the maximum movement speed of the seat while moving downward.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the seat reaches the positional limit, the value must reset to 0. If SEAT_HEIGHT_MOVE's value is currently 0, then that means there is no movement currently occurring.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Seat height move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value represents the maximum movement speed of the seat while moving downward.\nThe maxInt32Value represents the maximum movement speed of the seat while moving upward.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the seat reaches the positional limit, the value must reset to 0. If SEAT_HEIGHT_MOVE's value is currently 0, then that means there is no movement currently occurring.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Seat depth position",
"value": 356518797,
- "description": "Seat depth position\nSets the seat depth, distance from back rest to front edge of seat.\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the seat is in its shallowest position (i.e. the position with the smallest distance between the front edge of the seat cushion and the rear end of the seat). The maxInt32Value indicates the seat is in its deepest position (i.e. the position with the largest distance between the front edge of the seat cushion and the rear end of the seat).\nValues in between minInt32Value and maxInt32Value indicate a transition state between the shallowest and deepest positions.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Seat depth position\nSets the seat depth, distance from back rest to front edge of seat.\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the seat is in its shallowest position (i.e. the position with the smallest distance between the front edge of the seat cushion and the rear end of the seat).\nThe maxInt32Value indicates the seat is in its deepest position (i.e. the position with the largest distance between the front edge of the seat cushion and the rear end of the seat).\nValues in between minInt32Value and maxInt32Value indicate a transition state between the shallowest and deepest positions.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Seat depth move",
"value": 356518798,
- "description": "Seat depth move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe maxInt32Value represents the maximum movement speed of the seat while getting deeper The minInt32Value represents the maximum movement speed of the seat while getting shallower.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the seat backrest reaches the positional limit, the value must reset to 0. If SEAT_DEPTH_MOVE's value is currently 0, then that means there is no movement currently occurring.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Seat depth move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value represents the maximum movement speed of the seat while getting shallower.\nThe maxInt32Value represents the maximum movement speed of the seat while getting deeper.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the seat backrest reaches the positional limit, the value must reset to 0. If SEAT_DEPTH_MOVE's value is currently 0, then that means there is no movement currently occurring.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Seat tilt position",
"value": 356518799,
- "description": "Seat tilt position\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the seat bottom is angled at its lowest angular position. This corresponds to the seat's front edge at its lowest possible position relative to the rear end of the seat. The maxInt32Value indicates the seat bottom is angled at its highest angular position. This corresponds to the seat's front edge at its highest possible position relative to the rear end of the seat.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the lowest and highest positions.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Seat tilt position\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the seat bottom is angled at its lowest angular position. This corresponds to the seat's front edge at its lowest possible position relative to the rear end of the seat.\nThe maxInt32Value indicates the seat bottom is angled at its highest angular position. This corresponds to the seat's front edge at its highest possible position relative to the rear end of the seat.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the lowest and highest positions.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Seat tilt move",
"value": 356518800,
- "description": "Seat tilt move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe maxInt32Value represents the maximum movement speed of the front edge of the seat while moving upward. The minInt32Value represents the maximum movement speed of the front edge of the seat while moving downward.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the seat bottom reaches the positional limit, the value must reset to 0. If SEAT_TILT_MOVE's value is currently 0, then that means there is no movement currently occurring.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Seat tilt move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value represents the maximum movement speed of the front edge of the seat while moving downward.\nThe maxInt32Value represents the maximum movement speed of the front edge of the seat while moving upward.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the seat bottom reaches the positional limit, the value must reset to 0. If SEAT_TILT_MOVE's value is currently 0, then that means there is no movement currently occurring.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Lumber fore\/aft position",
"value": 356518801,
- "description": "Lumber fore\/aft position\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the lumbar support is in its rearward most position (i.e. least supportive position). The maxInt32Value indicates the lumbar support is in its forward most position (i.e. most supportive position).\nValues in between minInt32Value and maxInt32Value indicate a transition state between the forward and rearward positions.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Lumber fore\/aft position\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the lumbar support is in its rearward most position (i.e. least supportive position).\nThe maxInt32Value indicates the lumbar support is in its forward most position (i.e. most supportive position).\nValues in between minInt32Value and maxInt32Value indicate a transition state between the forward and rearward positions.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Lumbar fore\/aft move",
"value": 356518802,
- "description": "Lumbar fore\/aft move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe maxInt32Value represents the maximum movement speed of the seat's lumbar support while moving forward. The minInt32Value represents the maximum movement speed of the seat's lumbar support while moving backward.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the seat's lumbar support reaches the positional limit, the value must reset to 0. If SEAT_LUMBAR_FORE_AFT_MOVE's value is currently 0, then that means there is no movement currently occurring.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Lumbar fore\/aft move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value represents the maximum movement speed of the seat's lumbar support while moving backward.\nThe maxInt32Value represents the maximum movement speed of the seat's lumbar support while moving forward.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the seat's lumbar support reaches the positional limit, the value must reset to 0. If SEAT_LUMBAR_FORE_AFT_MOVE's value is currently 0, then that means there is no movement currently occurring.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Lumbar side support position",
"value": 356518803,
- "description": "Lumbar side support position\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the lumbar side support is in its thinnest position (i.e. most support). The maxInt32Value indicates the lumbar side support is in its widest position (i.e. least support).\nValues in between minInt32Value and maxInt32Value indicate a transition state between the thinnest and widest positions.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Lumbar side support position\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the lumbar side support is in its thinnest position (i.e. most support).\nThe maxInt32Value indicates the lumbar side support is in its widest position (i.e. least support).\nValues in between minInt32Value and maxInt32Value indicate a transition state between the thinnest and widest positions.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Lumbar side support move",
"value": 356518804,
- "description": "Lumbar side support move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe maxInt32Value represents the maximum movement speed of the seat's lumbar side support while getting wider. The minInt32Value represents the maximum movement speed of the seat's lumbar side support while getting thinner.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the seat's lumbar side support reaches the positional limit, the value must reset to 0. If SEAT_LUMBAR_SIDE_SUPPORT_MOVE's value is currently 0, then that means there is no movement currently occurring.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Lumbar side support move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value represents the maximum movement speed of the seat's lumbar side support while getting thinner.\nThe maxInt32Value represents the maximum movement speed of the seat's lumbar side support while getting wider.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the seat's lumbar side support reaches the positional limit, the value must reset to 0. If SEAT_LUMBAR_SIDE_SUPPORT_MOVE's value is currently 0, then that means there is no movement currently occurring.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "SEAT_HEADREST_HEIGHT_POS",
@@ -739,32 +815,32 @@
{
"name": "Headrest height position",
"value": 356518820,
- "description": "Headrest height position\nSets the headrest height for supported seats. VehiclePropConfig.areaConfigs specifies which seats are supported.\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the headrest is in its lowest position. The maxInt32Value indicates the headrest is in its highest position.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the lowest and highest positions.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Headrest height position\nSets the headrest height for supported seats. VehiclePropConfig.areaConfigs specifies which seats are supported.\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the headrest is in its lowest position.\nThe maxInt32Value indicates the headrest is in its highest position.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the lowest and highest positions.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Headrest height move",
"value": 356518806,
- "description": "Headrest height move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe maxInt32Value represents the maximum movement speed of the seat's headrest while moving up. The minInt32Value represents the maximum movement speed of the seat's headrest while moving down.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the seat's headrest reaches the positional limit, the value must reset to 0. If SEAT_HEADREST_HEIGHT_MOVE's value is currently 0, then that means there is no movement currently occurring.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Headrest height move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value represents the maximum movement speed of the seat's headrest while moving down.\nThe maxInt32Value represents the maximum movement speed of the seat's headrest while moving up.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the seat's headrest reaches the positional limit, the value must reset to 0. If SEAT_HEADREST_HEIGHT_MOVE's value is currently 0, then that means there is no movement currently occurring.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Headrest angle position",
"value": 356518807,
- "description": "Headrest angle position\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the headrest is in its full recline position. The maxInt32Value indicates the headrest is in its most upright\/forward position.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the full recline and most upright\/forward positions.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Headrest angle position\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the headrest is in its full recline position.\nThe maxInt32Value indicates the headrest is in its most upright\/forward position.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the full recline and most upright\/forward positions.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Headrest angle move",
"value": 356518808,
- "description": "Headrest angle move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe maxInt32Value represents the maximum movement speed of the seat's headrest while moving into an upright\/forward position. The minInt32Value represents the maximum movement speed of the seat's headrest while moving into a shallow position.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the seat's headrest reaches the positional limit, the value must reset to 0. If SEAT_HEADREST_ANGLE_MOVE's value is currently 0, then that means there is no movement currently occurring.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Headrest angle move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value represents the maximum movement speed of the seat's headrest while moving into a shallow position.\nThe maxInt32Value represents the maximum movement speed of the seat's headrest while moving into an upright\/forward position.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the seat's headrest reaches the positional limit, the value must reset to 0. If SEAT_HEADREST_ANGLE_MOVE's value is currently 0, then that means there is no movement currently occurring.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Headrest fore\/aft position",
"value": 356518809,
- "description": "Headrest fore\/aft position\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the headrest is in its rearward-most linear position. The maxInt32Value indicates the headrest is in its forward-most linear position.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the forward and rearward positions.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Headrest fore\/aft position\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the headrest is in its rearward-most linear position.\nThe maxInt32Value indicates the headrest is in its forward-most linear position.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the forward and rearward positions.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Headrest fore\/aft move",
"value": 356518810,
- "description": "Headrest fore\/aft move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe maxInt32Value represents the maximum movement speed of the seat's headrest while moving forward. The minInt32Value represents the maximum movement speed of the seat's headrest while moving backward.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the seat's headrest reaches the positional limit, the value must reset to 0. If SEAT_HEADREST_FORE_AFT_MOVE's value is currently 0, then that means there is no movement currently occurring.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Headrest fore\/aft move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value represents the maximum movement speed of the seat's headrest while moving backward.\nThe maxInt32Value represents the maximum movement speed of the seat's headrest while moving forward.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the seat's headrest reaches the positional limit, the value must reset to 0. If SEAT_HEADREST_FORE_AFT_MOVE's value is currently 0, then that means there is no movement currently occurring.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "SEAT_FOOTWELL_LIGHTS_STATE",
@@ -773,7 +849,7 @@
"VehicleLightState"
],
"data_enum": "VehicleLightState",
- "description": "Represents property for the seat footwell lights state.\nSEAT_FOOTWELL_LIGHTS_STATE reflects the current state of the lights at any point in time. This is different from the function of SEAT_FOOTWELL_LIGHTS_SWITCH which represents the position of the switch controlling the lights. Therefore, SEAT_FOOTWELL_LIGHTS_STATE may not match the value of SEAT_FOOTWELL_LIGHTS_SWITCH (e.g. SEAT_FOOTWELL_LIGHTS_SWITCH=AUTOMATIC and SEAT_FOOTWELL_LIGHTS_STATE=ON).\nThis property should only be implemented if SEAT_FOOTWELL_LIGHTS_STATE's value may be different from that of CABIN_LIGHTS_STATE.\nFor each supported area ID, the VehicleAreaConfig#supportedEnumValues must be defined unless all enum values of VehicleLightState are supported."
+ "description": "Represents property for the seat footwell lights state.\nSEAT_FOOTWELL_LIGHTS_STATE reflects the current state of the lights at any point in time. This is different from the function of SEAT_FOOTWELL_LIGHTS_SWITCH which represents the position of the switch controlling the lights. Therefore, SEAT_FOOTWELL_LIGHTS_STATE may not match the value of SEAT_FOOTWELL_LIGHTS_SWITCH (e.g. SEAT_FOOTWELL_LIGHTS_SWITCH=AUTOMATIC and SEAT_FOOTWELL_LIGHTS_STATE=ON).\nThis property should only be implemented if SEAT_FOOTWELL_LIGHTS_STATE's value may be different from that of CABIN_LIGHTS_STATE.\nFor each supported area ID, the VehicleAreaConfig#supportedEnumValues must be defined unless all enum values of VehicleLightState are supported.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} for the area ID unless all enum values of VehicleLightState are supported. At boot, the supported values list is the same as supportedEnumValues."
},
{
"name": "SEAT_FOOTWELL_LIGHTS_SWITCH",
@@ -782,7 +858,7 @@
"VehicleLightSwitch"
],
"data_enum": "VehicleLightSwitch",
- "description": "Represents property for the seat footwell lights switch.\nSEAT_FOOTWELL_LIGHTS_SWITCH represents the position of the switch controlling the lights. This is different from the function of SEAT_FOOTWELL_LIGHTS_STATE which reflects the current state of the lights at any point in time. Therefore, SEAT_FOOTWELL_LIGHTS_SWITCH may not match the value of SEAT_FOOTWELL_LIGHTS_STATE (e.g. SEAT_FOOTWELL_LIGHTS_SWITCH=AUTOMATIC and SEAT_FOOTWELL_LIGHTS_STATE=ON).\nThis property should only be implemented if SEAT_FOOTWELL_LIGHTS_SWITCH's value may be different from that of CABIN_LIGHTS_SWITCH.\nFor each supported area ID, the VehicleAreaConfig#supportedEnumValues must be defined unless all enum values of VehicleLightSwitch are supported.\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 seat footwell lights switch.\nSEAT_FOOTWELL_LIGHTS_SWITCH represents the position of the switch controlling the lights. This is different from the function of SEAT_FOOTWELL_LIGHTS_STATE which reflects the current state of the lights at any point in time. Therefore, SEAT_FOOTWELL_LIGHTS_SWITCH may not match the value of SEAT_FOOTWELL_LIGHTS_STATE (e.g. SEAT_FOOTWELL_LIGHTS_SWITCH=AUTOMATIC and SEAT_FOOTWELL_LIGHTS_STATE=ON).\nThis property should only be implemented if SEAT_FOOTWELL_LIGHTS_SWITCH's value may be different from that of CABIN_LIGHTS_SWITCH.\nFor each supported area ID, the VehicleAreaConfig#supportedEnumValues must be defined unless all enum values of VehicleLightSwitch are supported.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} for the area ID unless all enum values of VehicleLightSwitch are supported. At boot, the supported values list is the same as supportedEnumValues.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "SEAT_EASY_ACCESS_ENABLED",
@@ -801,32 +877,32 @@
"VehicleAirbagLocation"
],
"data_enum": "VehicleAirbagLocation",
- "description": "Seat airbags deployed\nBit flag property to relay information on which airbags have been deployed in the vehicle at each seat, vs which ones are currently still armed. If SEAT_AIRBAG_ENABLED is set to false at a particular areaId, this property should return status code UNAVAILABLE at that areaId.\nEnums apply to each seat, not the global vehicle. For example, VehicleAirbagsLocation#CURTAIN at the driver seat areaId represents whether the driver side curtain airbag has been deployed. Multiple bit flags can be set to indicate that multiple different airbags have been deployed for the seat.\nFor each seat area ID, the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of VehicleAirbagLocation are supported (including OTHER, which is not recommended)."
+ "description": "Seat airbags deployed\nBit flag property to relay information on which airbags have been deployed in the vehicle at each seat, vs which ones are currently still armed. If SEAT_AIRBAG_ENABLED is set to false at a particular areaId, this property should return status code UNAVAILABLE at that areaId.\nEnums apply to each seat, not the global vehicle. For example, VehicleAirbagsLocation#CURTAIN at the driver seat areaId represents whether the driver side curtain airbag has been deployed. Multiple bit flags can be set to indicate that multiple different airbags have been deployed for the seat.\nFor each seat area ID, the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of VehicleAirbagLocation are supported (including OTHER, which is not recommended).\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} for the area ID unless all states of VehicleAirbagLocation are supported (including OTHER, which is not recommended). At boot, the supported values list is the same as supportedEnumValues."
},
{
"name": "SEAT_CUSHION_SIDE_SUPPORT_POS",
"value": 356518815,
- "description": "Represents property for seat’s hipside (bottom cushion’s side) support position.\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe maxInt32Value indicates the seat cushion side support is in its widest position (i.e. least support). The minInt32Value indicates the seat cushion side support is in its thinnest position (i.e. most support).\nValues in between minInt32Value and maxInt32Value indicate a transition state between the thinnest and widest positions.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Represents property for seat’s hipside (bottom cushion’s side) support position.\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the seat cushion side support is in its thinnest position (i.e. most support).\nThe maxInt32Value indicates the seat cushion side support is in its widest position (i.e. least support).\nValues in between minInt32Value and maxInt32Value indicate a transition state between the thinnest and widest positions.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "SEAT_CUSHION_SIDE_SUPPORT_MOVE",
"value": 356518816,
- "description": "Represents property for movement direction and speed of seat cushion side support.\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe maxInt32Value represents the maximum movement speed of the seat cushion side support when growing wider (i.e. support is decreasing). The minInt32Value represents the maximum movement speed of the seat cushion side support when growing thinner (i.e. support is increasing).\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the seat cushion side support reaches the positional limit, the value must reset to 0. If SEAT_CUSHION_SIDE_SUPPORT_MOVE's value is currently 0, then that means there is no movement currently occurring.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Represents property for movement direction and speed of seat cushion side support.\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value represents the maximum movement speed of the seat cushion side support when growing thinner (i.e. support is increasing).\nThe maxInt32Value represents the maximum movement speed of the seat cushion side support when growing wider (i.e. support is decreasing).\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the seat cushion side support reaches the positional limit, the value must reset to 0. If SEAT_CUSHION_SIDE_SUPPORT_MOVE's value is currently 0, then that means there is no movement currently occurring.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "SEAT_LUMBAR_VERTICAL_POS",
"value": 356518817,
- "description": "Represents property for seat’s lumbar support vertical position.\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe maxInt32Value indicates the lumbar support's highest position. The minInt32Value indicates the lumbar support's lowest position.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the lowest and highest positions.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Represents property for seat’s lumbar support vertical position.\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the lumbar support's lowest position.\nThe maxInt32Value indicates the lumbar support's highest position.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the lowest and highest positions.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "SEAT_LUMBAR_VERTICAL_MOVE",
"value": 356518818,
- "description": "Represents property for vertical movement direction and speed of seat lumbar support.\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe maxInt32Value indicates the lumbar support is moving at the fastest upward speed. The minInt32Value indicates the lumbar support is moving at the fastest downward speed.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the seat cushion side support reaches the positional limit, the value must reset to 0. If SEAT_LUMBAR_VERTICAL_MOVE's value is currently 0, then that means there is no movement currently occurring.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Represents property for vertical movement direction and speed of seat lumbar support.\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the lumbar support is moving at the fastest downward speed.\nThe maxInt32Value indicates the lumbar support is moving at the fastest upward speed.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the seat cushion side support reaches the positional limit, the value must reset to 0. If SEAT_LUMBAR_VERTICAL_MOVE's value is currently 0, then that means there is no movement currently occurring.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "SEAT_WALK_IN_POS",
"value": 356518819,
- "description": "Represents property that indicates the current walk-in position of the seat.\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the normal seat position. The minInt32Value must be 0. The maxInt32Value indicates the seat is in the full walk-in position.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the normal and walk-in positions.\nThis property is not in any particular unit but in a specified range of relative positions.\nThe area ID must match the seat that actually moves when the walk-in feature activates, not the intended seat the passengers will sit in.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Represents property that indicates the current walk-in position of the seat.\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the normal seat position. The minInt32Value must be 0.\nThe maxInt32Value indicates the seat is in the full walk-in position.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the normal and walk-in positions.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative positions.\nThe area ID must match the seat that actually moves when the walk-in feature activates, not the intended seat the passengers will sit in.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "SEAT_BELT_PRETENSIONER_DEPLOYED",
@@ -845,12 +921,12 @@
{
"name": "Window Position",
"value": 322964416,
- "description": "Window Position\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the window is closed\/fully open out of plane. If the window cannot open out of plane, then minInt32Value is the position of the window when fully closed and must be 0. If the window can open out of plane, the minInt32Value indicates the window is fully open in its position out of plane and will be a negative value. See the example below for a more detailed explanation. The maxInt32Value indicates the window is fully open.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the closed\/fully open out-of-plane and fully open positions.\nThis property is not in any particular unit but in a specified range of relative positions.\nFor example, this is how the property should work for a window that can move out of plane: For a window that may open out of plane (i.e. vent mode of sunroof) this parameter will work with negative values as follows: Max = sunroof completely open 0 = sunroof closed. Min = sunroof vent completely open\nNote that in this mode, 0 indicates the window is closed.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Window Position\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined.\nAll integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the window is closed\/fully open out of plane. If the window cannot open out of plane, then minInt32Value is the position of the window when fully closed and must be 0. If the window can open out of plane, the minInt32Value indicates the window is fully open in its position out of plane and will be a negative value. See the example below for a more detailed explanation.\nThe maxInt32Value indicates the window is fully open.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the closed\/fully open out-of-plane and fully open positions.\nThis property is not in any particular unit but in a specified range of relative positions.\nFor example, this is how the property should work for a window that can move out of plane: For a window that may open out of plane (i.e. vent mode of sunroof) this parameter will work with negative values as follows: Max = sunroof completely open 0 = sunroof closed. Min = sunroof vent completely open\nNote that in this mode, 0 indicates the window is closed.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Window Move",
"value": 322964417,
- "description": "Window Move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe maxInt32Value indicates the window is opening in plane\/closing in the out of plane direction at the fastest speed. The minInt32Value indicates the window is closing in plane\/opening in the out of plane direction at the fastest speed.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the window reaches the positional limit, the value must reset to 0. If WINDOW_MOVE's value is currently 0, then that means there is no movement currently occurring.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nFor a window that may open out of plane (i.e. vent mode of sunroof) this parameter will work as follows:\nIf sunroof is open: Max = open the sunroof further, automatically stop when fully open. Min = close the sunroof, automatically stop when sunroof is closed.\nIf vent is open: Max = close the vent, automatically stop when vent is closed. Min = open the vent further, automatically stop when vent is fully open.\nIf sunroof is in the closed position: Max = open the sunroof, automatically stop when sunroof is fully open. Min = open the vent, automatically stop when vent is fully open.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Window Move\nThe maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the window is closing in plane\/opening in the out of plane direction at the fastest speed.\nThe maxInt32Value indicates the window is opening in plane\/closing in the out of plane direction at the fastest speed.\nLarger absolute values, either positive or negative, indicate a faster movement speed. Once the window reaches the positional limit, the value must reset to 0. If WINDOW_MOVE's value is currently 0, then that means there is no movement currently occurring.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nFor a window that may open out of plane (i.e. vent mode of sunroof) this parameter will work as follows:\nIf sunroof is open: Max = open the sunroof further, automatically stop when fully open. Min = close the sunroof, automatically stop when sunroof is closed.\nIf vent is open: Max = close the vent, automatically stop when vent is closed. Min = open the vent further, automatically stop when vent is fully open.\nIf sunroof is in the closed position: Max = open the sunroof, automatically stop when sunroof is fully open. Min = open the vent, automatically stop when vent is fully open.\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Window Child Lock",
@@ -860,7 +936,7 @@
{
"name": "WINDSHIELD_WIPERS_PERIOD",
"value": 322964421,
- "description": "Windshield wipers period (milliseconds).\nReturns the instantaneous time period for 1 full cycle of the windshield wipers in milliseconds. A full cycle is defined as a wiper moving from and returning to its rest position.\nWhen an intermittent wiper setting is selected, this property value must be set to 0 during the \"pause\" period of the intermittent wiping.\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. The maxInt32Value for each area ID must specify the longest wiper period. The minInt32Value must be set to 0 for each area ID."
+ "description": "Windshield wipers period (milliseconds).\nReturns the instantaneous time period for 1 full cycle of the windshield wipers in milliseconds. A full cycle is defined as a wiper moving from and returning to its rest position.\nWhen an intermittent wiper setting is selected, this property value must be set to 0 during the \"pause\" period of the intermittent wiping.\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined.\nThe minInt32Value must be set to 0 for each area ID.\nThe maxInt32Value for each area ID must specify the longest wiper period.\nIf {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true}. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue."
},
{
"name": "Windshield wipers state.",
@@ -869,7 +945,7 @@
"WindshieldWipersState"
],
"data_enum": "WindshieldWipersState",
- "description": "Windshield wipers state.\nReturns the current state of the windshield wipers. The value of WINDSHIELD_WIPERS_STATE may not match the value of WINDSHIELD_WIPERS_SWITCH. (e.g. WINDSHIELD_WIPERS_STATE = ON and WINDSHIELD_WIPERS_SWITCH = WindshieldWipersSwitch#AUTO).\nIf WINDSHIELD_WIPERS_STATE = ON and WINDSHIELD_WIPERS_PERIOD is implemented, then WINDSHIELD_WIPERS_PERIOD must reflect the time period of 1 full cycle of the wipers.\nFor each supported area ID, the VehicleAreaConfig#supportedEnumValues array must be defined unless all states in WindshieldWipersState are supported (including OTHER, which is not recommended)."
+ "description": "Windshield wipers state.\nReturns the current state of the windshield wipers. The value of WINDSHIELD_WIPERS_STATE may not match the value of WINDSHIELD_WIPERS_SWITCH. (e.g. WINDSHIELD_WIPERS_STATE = ON and WINDSHIELD_WIPERS_SWITCH = WindshieldWipersSwitch#AUTO).\nIf WINDSHIELD_WIPERS_STATE = ON and WINDSHIELD_WIPERS_PERIOD is implemented, then WINDSHIELD_WIPERS_PERIOD must reflect the time period of 1 full cycle of the wipers.\nFor each supported area ID, the VehicleAreaConfig#supportedEnumValues array must be defined unless all states in WindshieldWipersState are supported (including OTHER, which is not recommended).\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} for the area ID unless all states in WindshieldWipersState are supported (including OTHER, which is not recommended). At boot, the supported values list is the same as supportedEnumValues."
},
{
"name": "Windshield wipers switch.",
@@ -878,27 +954,27 @@
"WindshieldWipersSwitch"
],
"data_enum": "WindshieldWipersSwitch",
- "description": "Windshield wipers switch.\nRepresents the position of the switch controlling the windshield wipers. The value of WINDSHIELD_WIPERS_SWITCH may not match the value of WINDSHIELD_WIPERS_STATE (e.g. WINDSHIELD_WIPERS_SWITCH = AUTO and WINDSHIELD_WIPERS_STATE = WindshieldWipersState#ON).\nFor each supported area ID, the VehicleAreaConfig#supportedEnumValues array must be defined unless all states in WindshieldWipersSwitch are supported (including OTHER, which is not recommended).\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only.\nIf this property is implemented as VehiclePropertyAccess.READ_WRITE and the OTHER state is listed in the VehicleAreaConfig#supportedEnumValues array, then OTHER is not a supported value for writing. It is only a supported value for reading."
+ "description": "Windshield wipers switch.\nRepresents the position of the switch controlling the windshield wipers. The value of WINDSHIELD_WIPERS_SWITCH may not match the value of WINDSHIELD_WIPERS_STATE (e.g. WINDSHIELD_WIPERS_SWITCH = AUTO and WINDSHIELD_WIPERS_STATE = WindshieldWipersState#ON).\nFor each supported area ID, the VehicleAreaConfig#supportedEnumValues array must be defined unless all states in WindshieldWipersSwitch are supported (including OTHER, which is not recommended).\nIf {@code HasSupportedValueInfo} for a specific area ID is not {@code null}: {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} for the area ID unless all states in WindshieldWipersSwitch are supported (including OTHER, which is not recommended). At boot, the supported values list is the same as supportedEnumValues.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only.\nIf this property is implemented as VehiclePropertyAccess.READ_WRITE and the OTHER state is listed in the VehicleAreaConfig#supportedEnumValues array, then OTHER is not a supported value for writing. It is only a supported value for reading."
},
{
"name": "Steering wheel depth position",
"value": 289410016,
- "description": "Steering wheel depth position\nAll steering wheel properties' unique ids start from 0x0BE0.\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All values between minInt32Value and maxInt32Value must be supported.\nThe maxInt32Value indicates the steering wheel position furthest from the driver. The minInt32Value indicates the steering wheel position closest to the driver.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the closest and furthest positions.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Steering wheel depth position\nAll steering wheel properties' unique ids start from 0x0BE0.\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All values between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the steering wheel position closest to the driver.\nThe maxInt32Value indicates the steering wheel position furthest from the driver.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the closest and furthest positions.\nIf {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true}. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Steering wheel depth movement",
"value": 289410017,
- "description": "Steering wheel depth movement\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All values between minInt32Value and maxInt32Value must be supported.\nThe maxInt32Value indicates the steering wheel moving away from the driver. The minInt32Value indicates the steering wheel moving towards the driver.\nLarger integers, either positive or negative, indicate a faster movement speed. Once the steering wheel reaches the positional limit, the value must reset to 0. If STEERING_WHEEL_DEPTH_MOVE's value is currently 0, then that means there is no movement currently occurring.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Steering wheel depth movement\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All values between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the steering wheel moving towards the driver.\nThe maxInt32Value indicates the steering wheel moving away from the driver.\nLarger integers, either positive or negative, indicate a faster movement speed. Once the steering wheel reaches the positional limit, the value must reset to 0. If STEERING_WHEEL_DEPTH_MOVE's value is currently 0, then that means there is no movement currently occurring.\nIf {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true}. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Steering wheel height position",
"value": 289410018,
- "description": "Steering wheel height position\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All values between minInt32Value and maxInt32Value must be supported.\nThe maxInt32Value indicates the steering wheel being in the highest position. The minInt32Value indicates the steering wheel being in the lowest position.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the lowest and highest positions.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Steering wheel height position\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All values between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the steering wheel being in the lowest position.\nThe maxInt32Value indicates the steering wheel being in the highest position.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the lowest and highest positions.\nIf {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true}. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative positions.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Steering wheel height movement",
"value": 289410019,
- "description": "Steering wheel height movement\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All values between minInt32Value and maxInt32Value must be supported.\nThe maxInt32Value indicates the steering wheel moving upwards. The minInt32Value indicates the steering wheel moving downwards.\nLarger integers, either positive or negative, indicate a faster movement speed. Once the steering wheel reaches the positional limit, the value must reset to 0. If STEERING_WHEEL_HEIGHT_MOVE's value is currently 0, then that means there is no movement currently occurring.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Steering wheel height movement\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All values between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates the steering wheel moving downwards.\nThe maxInt32Value indicates the steering wheel moving upwards.\nLarger integers, either positive or negative, indicate a faster movement speed. Once the steering wheel reaches the positional limit, the value must reset to 0. If STEERING_WHEEL_HEIGHT_MOVE's value is currently 0, then that means there is no movement currently occurring.\nIf {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true}. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative movement speeds.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "STEERING_WHEEL_THEFT_LOCK_ENABLED",
@@ -918,7 +994,7 @@
{
"name": "GLOVE_BOX_DOOR_POS",
"value": 356518896,
- "description": "Property that represents the current position of the glove box door.\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates that the glove box door is closed. The minInt32Value must be 0. The maxInt32Value indicates that the glove box door is in the fully open position.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the closed and fully open positions.\nThis property is not in any particular unit but in a specified range of relative positions.\nThe area ID must match the seat by which the glove box is intended to be used (e.g. if the front right dashboard has a glove box embedded in it, then the area ID should be SEAT_1_RIGHT).\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Property that represents the current position of the glove box door.\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between minInt32Value and maxInt32Value must be supported.\nThe minInt32Value indicates that the glove box door is closed. The minInt32Value must be 0.\nThe maxInt32Value indicates that the glove box door is in the fully open position.\nValues in between minInt32Value and maxInt32Value indicate a transition state between the closed and fully open positions.\nIf {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}: {@code HasSupportedValueInfo.hasMinSupportedValue} and {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true}. {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value. {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value. All integers between minSupportedValue and maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to maxSupportedValue.\nThis property is not in any particular unit but in a specified range of relative positions.\nThe area ID must match the seat by which the glove box is intended to be used (e.g. if the front right dashboard has a glove box embedded in it, then the area ID should be SEAT_1_RIGHT).\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Lock or unlock the glove box.",
@@ -1100,7 +1176,7 @@
"VehicleLightState"
],
"data_enum": "VehicleLightState",
- "description": "Steering wheel lights state\nRepresents the current state of the steering wheel lights. This is different from STEERING_WHEEL_LIGHTS_SWITCH which represents the position of the switch controlling the lights. Therefore, STEERING_WHEEL_LIGHTS_STATE may not match the value of STEERING_WHEEL_LIGHTS_SWITCH (e.g. STEERING_WHEEL_LIGHTS_SWITCH=AUTOMATIC and STEERING_WHEEL_LIGHTS_STATE=ON).\nThis property should only be implemented if STEERING_WHEEL_LIGHTS_STATE's value may be different from that of CABIN_LIGHTS_STATE.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues must be defined unless all enum values of VehicleLightState are supported."
+ "description": "Steering wheel lights state\nRepresents the current state of the steering wheel lights. This is different from STEERING_WHEEL_LIGHTS_SWITCH which represents the position of the switch controlling the lights. Therefore, STEERING_WHEEL_LIGHTS_STATE may not match the value of STEERING_WHEEL_LIGHTS_SWITCH (e.g. STEERING_WHEEL_LIGHTS_SWITCH=AUTOMATIC and STEERING_WHEEL_LIGHTS_STATE=ON).\nThis property should only be implemented if STEERING_WHEEL_LIGHTS_STATE's value may be different from that of CABIN_LIGHTS_STATE.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues must be defined unless all enum values of VehicleLightState are supported.\nIf {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}: {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} unless all enum values of VehicleLightState are supported. At boot, the supported values list is the same as supportedEnumValues."
},
{
"name": "Steering wheel lights switch",
@@ -1109,7 +1185,7 @@
"VehicleLightSwitch"
],
"data_enum": "VehicleLightSwitch",
- "description": "Steering wheel lights switch\nRepresents the position of the switch controlling the steering wheel lights. This is different from STEERING_WHEEL_LIGHTS_STATE which represents the current state of the steering wheel lights. Therefore, STEERING_WHEEL_LIGHTS_SWITCH may not match the value of STEERING_WHEEL_LIGHTS_STATE (e.g. STEERING_WHEEL_LIGHTS_SWITCH=AUTOMATIC and STEERING_WHEEL_LIGHTS_STATE=ON).\nThis property should only be implemented if STEERING_WHEEL_LIGHTS_SWITCH's value may be different from that of CABIN_LIGHTS_SWITCH.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues must be defined unless all enum values of VehicleLightSwitch are supported.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Steering wheel lights switch\nRepresents the position of the switch controlling the steering wheel lights. This is different from STEERING_WHEEL_LIGHTS_STATE which represents the current state of the steering wheel lights. Therefore, STEERING_WHEEL_LIGHTS_SWITCH may not match the value of STEERING_WHEEL_LIGHTS_STATE (e.g. STEERING_WHEEL_LIGHTS_SWITCH=AUTOMATIC and STEERING_WHEEL_LIGHTS_STATE=ON).\nThis property should only be implemented if STEERING_WHEEL_LIGHTS_SWITCH's value may be different from that of CABIN_LIGHTS_SWITCH.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues must be defined unless all enum values of VehicleLightSwitch are supported.\nIf {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}: {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} unless all enum values of VehicleLightSwitch are supported. At boot, the supported values list is the same as supportedEnumValues.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "SUPPORT_CUSTOMIZE_VENDOR_PERMISSION",
@@ -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.\nIf {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}: {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} unless all enum values of VehicleAutonomousState are supported. At boot, the supported values list is the same as supportedEnumValues."
+ },
+ {
+ "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",
@@ -1381,7 +1466,7 @@
"ErrorState"
],
"data_enum": "AutomaticEmergencyBrakingState",
- "description": "Automatic Emergency Braking (AEB) state.\nReturns the current state of AEB. This property must always return a valid state defined in AutomaticEmergencyBrakingState or ErrorState. It must not surface errors through StatusCode and must use the supported error states instead. This property should apply for higher speed applications only. For representing the state of the low speed automatic emergency braking system, LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE should be used.\nIf AEB includes forward collision warnings before activating the brakes, those warnings must be surfaced through the Forward Collision Warning (FCW) properties.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of both AutomaticEmergencyBrakingState (including OTHER, which is not recommended) and ErrorState are supported."
+ "description": "Automatic Emergency Braking (AEB) state.\nReturns the current state of AEB. This property must always return a valid state defined in AutomaticEmergencyBrakingState or ErrorState. It must not surface errors through StatusCode and must use the supported error states instead. This property should apply for higher speed applications only. For representing the state of the low speed automatic emergency braking system, LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE should be used.\nIf AEB includes forward collision warnings before activating the brakes, those warnings must be surfaced through the Forward Collision Warning (FCW) properties.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of both AutomaticEmergencyBrakingState (including OTHER, which is not recommended) and ErrorState are supported.\nIf {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}: {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} unless all states of both AutomaticEmergencyBrakingState (including OTHER, which is not recommended) and ErrorState are supported. At boot, the supported values list is the same as supportedEnumValues."
},
{
"name": "FORWARD_COLLISION_WARNING_ENABLED",
@@ -1396,7 +1481,7 @@
"ErrorState"
],
"data_enum": "ForwardCollisionWarningState",
- "description": "Forward Collision Warning (FCW) state.\nReturns the current state of FCW. This property must always return a valid state defined in ForwardCollisionWarningState 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 ForwardCollisionWarningState (including OTHER, which is not recommended) and ErrorState are supported."
+ "description": "Forward Collision Warning (FCW) state.\nReturns the current state of FCW. This property must always return a valid state defined in ForwardCollisionWarningState 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 ForwardCollisionWarningState (including OTHER, which is not recommended) and ErrorState are supported.\nIf {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}: {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} unless all states of both ForwardCollisionWarningState (including OTHER, which is not recommended) and ErrorState are supported. At boot, the supported values list is the same as supportedEnumValues."
},
{
"name": "BLIND_SPOT_WARNING_ENABLED",
@@ -1411,7 +1496,7 @@
"ErrorState"
],
"data_enum": "BlindSpotWarningState",
- "description": "Blind Spot Warning (BSW) state.\nReturns the current state of BSW. This property must always return a valid state defined in BlindSpotWarningState or ErrorState. It must not surface errors through StatusCode and must use the supported error states instead.\nFor each supported area ID, the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of both BlindSpotWarningState (including OTHER, which is not recommended) and ErrorState are supported."
+ "description": "Blind Spot Warning (BSW) state.\nReturns the current state of BSW. This property must always return a valid state defined in BlindSpotWarningState or ErrorState. It must not surface errors through StatusCode and must use the supported error states instead.\nFor each supported area ID, the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of both BlindSpotWarningState (including OTHER, which is not recommended) and ErrorState are supported.\nIf {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}: {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} unless all states of both BlindSpotWarningState (including OTHER, which is not recommended) and ErrorState are supported. At boot, the supported values list is the same as supportedEnumValues."
},
{
"name": "LANE_DEPARTURE_WARNING_ENABLED",
@@ -1426,7 +1511,7 @@
"ErrorState"
],
"data_enum": "LaneDepartureWarningState",
- "description": "Lane Departure Warning (LDW) state.\nReturns the current state of LDW. This property must always return a valid state defined in LaneDepartureWarningState 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 LaneDepartureWarningState (including OTHER, which is not recommended) and ErrorState are supported."
+ "description": "Lane Departure Warning (LDW) state.\nReturns the current state of LDW. This property must always return a valid state defined in LaneDepartureWarningState 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 LaneDepartureWarningState (including OTHER, which is not recommended) and ErrorState are supported.\nIf {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}: {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} unless all states of both LaneDepartureWarningState (including OTHER, which is not recommended) and ErrorState are supported. At boot, the supported values list is the same as supportedEnumValues."
},
{
"name": "LANE_KEEP_ASSIST_ENABLED",
@@ -1441,7 +1526,7 @@
"ErrorState"
],
"data_enum": "LaneKeepAssistState",
- "description": "Lane Keep Assist (LKA) state.\nReturns the current state of LKA. This property must always return a valid state defined in LaneKeepAssistState or ErrorState. It must not surface errors through StatusCode and must use the supported error states instead.\nIf LKA includes lane departure warnings before applying steering corrections, those warnings must be surfaced through the Lane Departure Warning (LDW) properties.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of both LaneKeepAssistState (including OTHER, which is not recommended) and ErrorState are supported."
+ "description": "Lane Keep Assist (LKA) state.\nReturns the current state of LKA. This property must always return a valid state defined in LaneKeepAssistState or ErrorState. It must not surface errors through StatusCode and must use the supported error states instead.\nIf LKA includes lane departure warnings before applying steering corrections, those warnings must be surfaced through the Lane Departure Warning (LDW) properties.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of both LaneKeepAssistState (including OTHER, which is not recommended) and ErrorState are supported.\nIf {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}: {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} unless all states of both LaneKeepAssistState (including OTHER, which is not recommended) and ErrorState are supported. At boot, the supported values list is the same as supportedEnumValues."
},
{
"name": "LANE_CENTERING_ASSIST_ENABLED",
@@ -1455,7 +1540,7 @@
"LaneCenteringAssistCommand"
],
"data_enum": "LaneCenteringAssistCommand",
- "description": "Lane Centering Assist (LCA) commands.\nCommands to activate and suspend LCA.\nWhen the command ACTIVATE from LaneCenteringAssistCommand is sent, LANE_CENTERING_ASSIST_STATE must be set to LaneCenteringAssistState#ACTIVATION_REQUESTED. When the ACTIVATE command succeeds, LANE_CENTERING_ASSIST_STATE must be set to LaneCenteringAssistState#ACTIVATED. When the command DEACTIVATE from LaneCenteringAssistCommand succeeds, LANE_CENTERING_ASSIST_STATE must be set to LaneCenteringAssistState#ENABLED.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues must be defined unless all enum values of LaneCenteringAssistCommand are supported.\nWhen this property is not available because LCA is disabled (i.e. LANE_CENTERING_ASSIST_ENABLED is false), this property must return StatusCode#NOT_AVAILABLE_DISABLED. If LANE_CENTERING_ASSIST_STATE is implemented and the state is set to an ErrorState value, then this property must return a StatusCode that aligns with the ErrorState value. For example, if LANE_CENTERING_ASSIST_STATE is set to ErrorState#NOT_AVAILABLE_SPEED_LOW, then this property must return StatusCode#NOT_AVAILABLE_SPEED_LOW."
+ "description": "Lane Centering Assist (LCA) commands.\nCommands to activate and suspend LCA.\nWhen the command ACTIVATE from LaneCenteringAssistCommand is sent, LANE_CENTERING_ASSIST_STATE must be set to LaneCenteringAssistState#ACTIVATION_REQUESTED. When the ACTIVATE command succeeds, LANE_CENTERING_ASSIST_STATE must be set to LaneCenteringAssistState#ACTIVATED. When the command DEACTIVATE from LaneCenteringAssistCommand succeeds, LANE_CENTERING_ASSIST_STATE must be set to LaneCenteringAssistState#ENABLED.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues must be defined unless all enum values of LaneCenteringAssistCommand are supported.\nIf {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}: {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} unless all enum values of LaneCenteringAssistCommand are supported. At boot, the supported values list is the same as supportedEnumValues.\nWhen this property is not available because LCA is disabled (i.e. LANE_CENTERING_ASSIST_ENABLED is false), this property must return StatusCode#NOT_AVAILABLE_DISABLED. If LANE_CENTERING_ASSIST_STATE is implemented and the state is set to an ErrorState value, then this property must return a StatusCode that aligns with the ErrorState value. For example, if LANE_CENTERING_ASSIST_STATE is set to ErrorState#NOT_AVAILABLE_SPEED_LOW, then this property must return StatusCode#NOT_AVAILABLE_SPEED_LOW."
},
{
"name": "LANE_CENTERING_ASSIST_STATE",
@@ -1465,7 +1550,7 @@
"ErrorState"
],
"data_enum": "LaneCenteringAssistState",
- "description": "Lane Centering Assist (LCA) state.\nReturns the current state of LCA. This property must always return a valid state defined in LaneCenteringAssistState or ErrorState. It must not surface errors through StatusCode and must use the supported error states instead.\nIf LCA includes lane departure warnings, those warnings must be surfaced through the Lane Departure Warning (LDW) properties.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of both LaneCenteringAssistState (including OTHER, which is not recommended) and ErrorState are supported."
+ "description": "Lane Centering Assist (LCA) state.\nReturns the current state of LCA. This property must always return a valid state defined in LaneCenteringAssistState or ErrorState. It must not surface errors through StatusCode and must use the supported error states instead.\nIf LCA includes lane departure warnings, those warnings must be surfaced through the Lane Departure Warning (LDW) properties.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of both LaneCenteringAssistState (including OTHER, which is not recommended) and ErrorState are supported.\nIf {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}: {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} unless all states of both LaneCenteringAssistState (including OTHER, which is not recommended) and ErrorState are supported. At boot, the supported values list is the same as supportedEnumValues."
},
{
"name": "EMERGENCY_LANE_KEEP_ASSIST_ENABLED",
@@ -1480,7 +1565,7 @@
"ErrorState"
],
"data_enum": "EmergencyLaneKeepAssistState",
- "description": "Emergency Lane Keep Assist (ELKA) state.\nReturns the current state of ELKA. Generally, this property should return a valid state defined in the EmergencyLaneKeepAssistState or ErrorState. For example, if the feature is not available due to some temporary state, that information should be conveyed through ErrorState.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of EmergencyLaneKeepAssistState (including OTHER, which is not recommended) and ErrorState are supported."
+ "description": "Emergency Lane Keep Assist (ELKA) state.\nReturns the current state of ELKA. Generally, this property should return a valid state defined in the EmergencyLaneKeepAssistState or ErrorState. For example, if the feature is not available due to some temporary state, that information should be conveyed through ErrorState.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of EmergencyLaneKeepAssistState (including OTHER, which is not recommended) and ErrorState are supported.\nIf {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}: {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} unless all states of EmergencyLaneKeepAssistState (including OTHER, which is not recommended) and ErrorState are supported. At boot, the supported values list is the same as supportedEnumValues."
},
{
"name": "CRUISE_CONTROL_ENABLED",
@@ -1495,7 +1580,7 @@
"ErrorState"
],
"data_enum": "CruiseControlType",
- "description": "Current type of Cruise Control (CC).\nWhen CRUISE_CONTROL_ENABLED is true, this property returns the type of CC that is currently enabled (for example, standard CC, adaptive CC, predictive CC, etc.). Generally, this property should return a valid state defined in the CruiseControlType or ErrorState. For example, if the feature is not available due to some temporary state, that information should be conveyed through ErrorState.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of CruiseControlType (including OTHER, which is not recommended) and ErrorState are supported.\nTrying to write CruiseControlType#OTHER or an ErrorState to this property will throw an IllegalArgumentException.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
+ "description": "Current type of Cruise Control (CC).\nWhen CRUISE_CONTROL_ENABLED is true, this property returns the type of CC that is currently enabled (for example, standard CC, adaptive CC, predictive CC, etc.). Generally, this property should return a valid state defined in the CruiseControlType or ErrorState. For example, if the feature is not available due to some temporary state, that information should be conveyed through ErrorState.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of CruiseControlType (including OTHER, which is not recommended) and ErrorState are supported.\nIf {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}: {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} unless all states of CruiseControlType (including OTHER, which is not recommended) and ErrorState are supported. At boot, the supported values list is the same as supportedEnumValues.\nTrying to write CruiseControlType#OTHER or an ErrorState to this property will throw an IllegalArgumentException.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "CRUISE_CONTROL_STATE",
@@ -1505,7 +1590,7 @@
"ErrorState"
],
"data_enum": "CruiseControlState",
- "description": "Current state of Cruise Control (CC).\nThis property returns the current state of CC. Generally, this property should return a valid state defined in the CruiseControlState or ErrorState. For example, if the feature is not available due to some temporary state, that information should be conveyed through ErrorState.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of CruiseControlState (including OTHER, which is not recommended) and ErrorState are supported."
+ "description": "Current state of Cruise Control (CC).\nThis property returns the current state of CC. Generally, this property should return a valid state defined in the CruiseControlState or ErrorState. For example, if the feature is not available due to some temporary state, that information should be conveyed through ErrorState.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of CruiseControlState (including OTHER, which is not recommended) and ErrorState are supported.\nIf {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}: {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} unless all states of CruiseControlState (including OTHER, which is not recommended) and ErrorState are supported. At boot, the supported values list is the same as supportedEnumValues."
},
{
"name": "CRUISE_CONTROL_COMMAND",
@@ -1514,7 +1599,7 @@
"CruiseControlCommand"
],
"data_enum": "CruiseControlCommand",
- "description": "Write Cruise Control (CC) commands.\nSee CruiseControlCommand for the details about each supported command.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of CruiseControlState are supported. Any unsupported commands sent through this property must return StatusCode#INVALID_ARG.\nWhen this property is not available because CC is disabled (i.e. CRUISE_CONTROL_ENABLED is false), this property must return StatusCode#NOT_AVAILABLE_DISABLED. If CRUISE_CONTROL_STATE is implemented and the state is set to an ErrorState value, then this property must return a StatusCode that aligns with the ErrorState value. For example, if CRUISE_CONTROL_STATE is set to ErrorState#NOT_AVAILABLE_SPEED_LOW, then this property must return StatusCode#NOT_AVAILABLE_SPEED_LOW."
+ "description": "Write Cruise Control (CC) commands.\nSee CruiseControlCommand for the details about each supported command.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of CruiseControlState are supported. Any unsupported commands sent through this property must return StatusCode#INVALID_ARG.\nIf {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}: {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} unless all states of CruiseControlState are supported. At boot, the supported values list is the same as supportedEnumValues.\nWhen this property is not available because CC is disabled (i.e. CRUISE_CONTROL_ENABLED is false), this property must return StatusCode#NOT_AVAILABLE_DISABLED. If CRUISE_CONTROL_STATE is implemented and the state is set to an ErrorState value, then this property must return a StatusCode that aligns with the ErrorState value. For example, if CRUISE_CONTROL_STATE is set to ErrorState#NOT_AVAILABLE_SPEED_LOW, then this property must return StatusCode#NOT_AVAILABLE_SPEED_LOW."
},
{
"name": "CRUISE_CONTROL_TARGET_SPEED",
@@ -1544,7 +1629,7 @@
"ErrorState"
],
"data_enum": "HandsOnDetectionDriverState",
- "description": "Hands On Detection (HOD) driver state.\nReturns whether the driver's hands are on the steering wheel. Generally, this property should return a valid state defined in the HandsOnDetectionDriverState or ErrorState. For example, if the feature is not available due to some temporary state, that information should be conveyed through ErrorState.\nIf the vehicle wants to send a warning to the user because the driver's hands have been off the steering wheel for too long, the warning should be surfaced through HANDS_ON_DETECTION_WARNING.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of both HandsOnDetectionDriverState (including OTHER, which is not recommended) and ErrorState are supported."
+ "description": "Hands On Detection (HOD) driver state.\nReturns whether the driver's hands are on the steering wheel. Generally, this property should return a valid state defined in the HandsOnDetectionDriverState or ErrorState. For example, if the feature is not available due to some temporary state, that information should be conveyed through ErrorState.\nIf the vehicle wants to send a warning to the user because the driver's hands have been off the steering wheel for too long, the warning should be surfaced through HANDS_ON_DETECTION_WARNING.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of both HandsOnDetectionDriverState (including OTHER, which is not recommended) and ErrorState are supported.\nIf {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}: {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} unless all states of both HandsOnDetectionDriverState (including OTHER, which is not recommended) and ErrorState are supported. At boot, the supported values list is the same as supportedEnumValues."
},
{
"name": "HANDS_ON_DETECTION_WARNING",
@@ -1554,7 +1639,7 @@
"ErrorState"
],
"data_enum": "HandsOnDetectionWarning",
- "description": "Hands On Detection (HOD) warning.\nReturns whether a warning is being sent to the driver for having their hands off the wheel for too long a duration.\nGenerally, this property should return a valid state defined in HandsOnDetectionWarning or ErrorState. For example, if the feature is not available due to some temporary state, that information should be conveyed through an ErrorState.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of both HandsOnDetectionWarning (including OTHER, which is not recommended) and ErrorState are supported."
+ "description": "Hands On Detection (HOD) warning.\nReturns whether a warning is being sent to the driver for having their hands off the wheel for too long a duration.\nGenerally, this property should return a valid state defined in HandsOnDetectionWarning or ErrorState. For example, if the feature is not available due to some temporary state, that information should be conveyed through an ErrorState.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of both HandsOnDetectionWarning (including OTHER, which is not recommended) and ErrorState are supported.\nIf {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}: {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} unless all states of both HandsOnDetectionWarning (including OTHER, which is not recommended) and ErrorState are supported. At boot, the supported values list is the same as supportedEnumValues."
},
{
"name": "DRIVER_DROWSINESS_ATTENTION_SYSTEM_ENABLED",
@@ -1569,7 +1654,7 @@
"ErrorState"
],
"data_enum": "DriverDrowsinessAttentionState",
- "description": "Driver drowsiness and attention level state.\nReturns the current detected state of driver drowiness and attention level based on the Karolinska Sleepiness scale. If alternative measurement methods are used, the value should be translated to the Karolinska Sleepiness Scale equivalent.\nGenerally, this property should return a valid state defined in the DriverDrowsinessAttentionState or ErrorState. For example, if the feature is not available due to some temporary state, that information should be conveyed through ErrorState.\nIf the vehicle is sending a warning to the user because the driver is too drowsy, the warning should be surfaced through {@link #DRIVER_DROWSINESS_ATTENTION_WARNING}.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of both DriverDrowsinessAttentionState (including OTHER, which is not recommended) and ErrorState are supported."
+ "description": "Driver drowsiness and attention level state.\nReturns the current detected state of driver drowiness and attention level based on the Karolinska Sleepiness scale. If alternative measurement methods are used, the value should be translated to the Karolinska Sleepiness Scale equivalent.\nGenerally, this property should return a valid state defined in the DriverDrowsinessAttentionState or ErrorState. For example, if the feature is not available due to some temporary state, that information should be conveyed through ErrorState.\nIf the vehicle is sending a warning to the user because the driver is too drowsy, the warning should be surfaced through {@link #DRIVER_DROWSINESS_ATTENTION_WARNING}.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of both DriverDrowsinessAttentionState (including OTHER, which is not recommended) and ErrorState are supported.\nIf {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}: {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} unless all states of both DriverDrowsinessAttentionState (including OTHER, which is not recommended) and ErrorState are supported. At boot, the supported values list is the same as supportedEnumValues."
},
{
"name": "DRIVER_DROWSINESS_ATTENTION_WARNING_ENABLED",
@@ -1584,7 +1669,7 @@
"ErrorState"
],
"data_enum": "DriverDrowsinessAttentionWarning",
- "description": "Driver drowsiness and attention warning.\nReturns whether a warning is being sent to the driver for being drowsy or not attentive.\nGenerally, this property should return a valid state defined in DriverDrowsinessAttentionWarning or ErrorState. For example, if the feature is not available due to some temporary state, that information should be conveyed through an ErrorState.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of both DriverDrowsinessAttentionWarning (including OTHER, which is not recommended) and ErrorState are supported."
+ "description": "Driver drowsiness and attention warning.\nReturns whether a warning is being sent to the driver for being drowsy or not attentive.\nGenerally, this property should return a valid state defined in DriverDrowsinessAttentionWarning or ErrorState. For example, if the feature is not available due to some temporary state, that information should be conveyed through an ErrorState.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of both DriverDrowsinessAttentionWarning (including OTHER, which is not recommended) and ErrorState are supported.\nIf {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}: {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} unless all states of both DriverDrowsinessAttentionWarning (including OTHER, which is not recommended) and ErrorState are supported. At boot, the supported values list is the same as supportedEnumValues."
},
{
"name": "DRIVER_DISTRACTION_SYSTEM_ENABLED",
@@ -1599,7 +1684,7 @@
"ErrorState"
],
"data_enum": "DriverDistractionState",
- "description": "Driver distraction state.\nReturns the current detected driver distraction state.\nGenerally, this property should return a valid state defined in the DriverDistractionState or ErrorState. For example, if the feature is not available due to some temporary state, that information should be conveyed through ErrorState.\nIf the vehicle is sending a warning to the user because the driver is too distracted, the warning should be surfaced through {@link #DRIVER_DISTRACTION_WARNING}.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of both DriverDistractionState (including OTHER, which is not recommended) and ErrorState are supported."
+ "description": "Driver distraction state.\nReturns the current detected driver distraction state.\nGenerally, this property should return a valid state defined in the DriverDistractionState or ErrorState. For example, if the feature is not available due to some temporary state, that information should be conveyed through ErrorState.\nIf the vehicle is sending a warning to the user because the driver is too distracted, the warning should be surfaced through {@link #DRIVER_DISTRACTION_WARNING}.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of both DriverDistractionState (including OTHER, which is not recommended) and ErrorState are supported.\nIf {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}: {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} unless all states of both DriverDistractionState (including OTHER, which is not recommended) and ErrorState are supported. At boot, the supported values list is the same as supportedEnumValues."
},
{
"name": "DRIVER_DISTRACTION_WARNING_ENABLED",
@@ -1614,7 +1699,7 @@
"ErrorState"
],
"data_enum": "DriverDistractionWarning",
- "description": "Driver distraction warning.\nReturns whether a warning is being sent to the driver for being distracted.\nGenerally, this property should return a valid state defined in DriverDistractionWarning or ErrorState. For example, if the feature is not available due to some temporary state, that information should be conveyed through an ErrorState.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of both DriverDistractionWarning (including OTHER, which is not recommended) and ErrorState are supported."
+ "description": "Driver distraction warning.\nReturns whether a warning is being sent to the driver for being distracted.\nGenerally, this property should return a valid state defined in DriverDistractionWarning or ErrorState. For example, if the feature is not available due to some temporary state, that information should be conveyed through an ErrorState.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of both DriverDistractionWarning (including OTHER, which is not recommended) and ErrorState are supported.\nIf {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}: {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} unless all states of both DriverDistractionWarning (including OTHER, which is not recommended) and ErrorState are supported. At boot, the supported values list is the same as supportedEnumValues."
},
{
"name": "LOW_SPEED_COLLISION_WARNING_ENABLED",
@@ -1629,7 +1714,7 @@
"ErrorState"
],
"data_enum": "LowSpeedCollisionWarningState",
- "description": "Low Speed Collision Warning state.\nReturns the current state of Low Speed Collision Warning. This property must always return a valid state defined in LowSpeedCollisionWarningState or ErrorState. It must not surface errors through StatusCode and must use the supported error states instead. This property is different from the pre-existing FORWARD_COLLISION_WARNING_STATE, which should apply to higher speed applications only. If the vehicle doesn't have a separate collision detection system for low speed environments, this property should not be implemented.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of both LowSpeedCollisionWarningState (including OTHER, which is not recommended) and ErrorState are supported."
+ "description": "Low Speed Collision Warning state.\nReturns the current state of Low Speed Collision Warning. This property must always return a valid state defined in LowSpeedCollisionWarningState or ErrorState. It must not surface errors through StatusCode and must use the supported error states instead. This property is different from the pre-existing FORWARD_COLLISION_WARNING_STATE, which should apply to higher speed applications only. If the vehicle doesn't have a separate collision detection system for low speed environments, this property should not be implemented.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of both LowSpeedCollisionWarningState (including OTHER, which is not recommended) and ErrorState are supported.\nIf {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}: {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} unless all states of both LowSpeedCollisionWarningState (including OTHER, which is not recommended) and ErrorState are supported. At boot, the supported values list is the same as supportedEnumValues."
},
{
"name": "CROSS_TRAFFIC_MONITORING_ENABLED",
@@ -1644,7 +1729,7 @@
"ErrorState"
],
"data_enum": "CrossTrafficMonitoringWarningState",
- "description": "Cross Traffic Monitoring warning state.\nReturns the current state of Cross Traffic Monitoring Warning. This property must always return a valid state defined in CrossTrafficMonitoringWarningState 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 CrossTrafficMonitoringWarningState (including OTHER, which is not recommended) and ErrorState are supported."
+ "description": "Cross Traffic Monitoring warning state.\nReturns the current state of Cross Traffic Monitoring Warning. This property must always return a valid state defined in CrossTrafficMonitoringWarningState 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 CrossTrafficMonitoringWarningState (including OTHER, which is not recommended) and ErrorState are supported.\nIf {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}: {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} unless all states of both CrossTrafficMonitoringWarningState (including OTHER, which is not recommended) and ErrorState are supported. At boot, the supported values list is the same as supportedEnumValues."
},
{
"name": "LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED",
@@ -1659,7 +1744,7 @@
"ErrorState"
],
"data_enum": "LowSpeedAutomaticEmergencyBrakingState",
- "description": "Low Speed Automatic Emergency Braking state.\nReturns the current state of Low Speed Automatic Emergency Braking. This property must always return a valid state defined in LowSpeedAutomaticEmergencyBrakingState or ErrorState. It must not surface errors through StatusCode and must use the supported error states instead. This property is different from the pre-existing AUTOMATIC_EMERGENCY_BRAKING_STATE, which should apply to higher speed applications only. If the vehicle doesn't have a separate collision avoidance system for low speed environments, this property should not be implemented.\nIf Low Speed Automatic Emergency Braking includes collision warnings before activating the brakes, those warnings must be surfaced through use of LOW_SPEED_COLLISION_WARNING_ENABLED and LOW_SPEED_COLLISION_WARNING_STATE.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of both LowSpeedAutomaticEmergencyBrakingState (including OTHER, which is not recommended) and ErrorState are supported."
+ "description": "Low Speed Automatic Emergency Braking state.\nReturns the current state of Low Speed Automatic Emergency Braking. This property must always return a valid state defined in LowSpeedAutomaticEmergencyBrakingState or ErrorState. It must not surface errors through StatusCode and must use the supported error states instead. This property is different from the pre-existing AUTOMATIC_EMERGENCY_BRAKING_STATE, which should apply to higher speed applications only. If the vehicle doesn't have a separate collision avoidance system for low speed environments, this property should not be implemented.\nIf Low Speed Automatic Emergency Braking includes collision warnings before activating the brakes, those warnings must be surfaced through use of LOW_SPEED_COLLISION_WARNING_ENABLED and LOW_SPEED_COLLISION_WARNING_STATE.\nFor the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined unless all states of both LowSpeedAutomaticEmergencyBrakingState (including OTHER, which is not recommended) and ErrorState are supported.\nIf {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}: {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} unless all states of both LowSpeedAutomaticEmergencyBrakingState (including OTHER, which is not recommended) and ErrorState are supported. At boot, the supported values list is the same as supportedEnumValues."
}
]
},
@@ -2192,6 +2277,14 @@
"value": 11
},
{
+ "name": "SAE_J3400_AC",
+ "value": 8
+ },
+ {
+ "name": "SAE_J3400_DC",
+ "value": 9
+ },
+ {
"name": "OTHER",
"value": 101
}
@@ -2950,6 +3043,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",
"values": [
diff --git a/automotive/vehicle/aidl/generated_lib/3/cpp/Android.bp b/automotive/vehicle/aidl/generated_lib/3/cpp/Android.bp
index 7ff27a4..612ed64 100644
--- a/automotive/vehicle/aidl/generated_lib/3/cpp/Android.bp
+++ b/automotive/vehicle/aidl/generated_lib/3/cpp/Android.bp
@@ -19,10 +19,19 @@
}
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 6d07fe5..8441af3 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 @@
{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 @@
{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 @@
{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 @@
{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 5ecee95..3775f18 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 @@
{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 @@
{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 @@
{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 @@
{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 8b9c1bd..0a28b68 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 @@
{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 @@
{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 @@
{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 @@
{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 e9f35a5..1a68d4d 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 @@
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 @@
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 @@
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 @@
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 3fb52b7..a0dab66 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 @@
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 @@
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 @@
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 @@
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 0f86bfa..7ab14ec 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 @@
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 @@
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 @@
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 @@
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 0000000..e575061
--- /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 0000000..bf80122
--- /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 0000000..727c193
--- /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 0000000..1ed4df7
--- /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 0000000..bf1aa90
--- /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 0000000..d125d43
--- /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 0000000..10e4b7e
--- /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 0000000..623417b
--- /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%
copy from automotive/vehicle/aidl/impl/fake_impl/hardware/test/fakedata/prop.json
copy 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 0000000..38cd86b
--- /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 0000000..5e1df94
--- /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 0000000..9b9b4f4
--- /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 0000000..fbd20c5
--- /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 <FakeObd2Frame.h>
+#include <JsonFakeValueGenerator.h>
+#include <LinearFakeValueGenerator.h>
+#include <PropertyUtils.h>
+#include <VehicleHalTypes.h>
+#include <VehicleUtils.h>
+
+#include <android-base/file.h>
+#include <android-base/parsedouble.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <android/hardware/automotive/vehicle/TestVendorProperty.h>
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+#include <utils/Trace.h>
+
+#include <dirent.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <regex>
+#include <unordered_set>
+#include <vector>
+
+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<std::string> 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<int32_t, std::vector<int32_t>> 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<int32_t> 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<int32_t>& 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<VehiclePropValuePool>()),
+ 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<int32_t, ConfigDeclaration> FakeVehicleHardware::loadConfigDeclarations() {
+ std::unordered_map<int32_t, ConfigDeclaration> 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<VehiclePropValue> values) {
+ return onValuesChangeCallback(std::move(values));
+ });
+}
+
+std::vector<VehiclePropConfig> FakeVehicleHardware::getAllPropertyConfigs() const {
+ std::vector<VehiclePropConfig> 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<void> 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<void> 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<float>(increment));
+ return numIncrements;
+}
+
+void FakeVehicleHardware::updateHvacTemperatureValueSuggestionInput(
+ const std::vector<int>& hvacTemperatureSetConfigArray,
+ std::vector<float>* 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<int>((*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<float>(suggestedTempInCelsius) / 10.0f;
+ (*hvacTemperatureValueSuggestionInput)[3] =
+ static_cast<float>(suggestedTempInFahrenheit) / 10.0f;
+}
+
+VhalResult<void> 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<void> 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<void> 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<void> FakeVehicleHardware::synchronizeHvacTemp(int32_t hvacDualOnAreaId,
+ std::optional<float> 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<float> 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<int32_t> 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<bool> 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<void> 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<uint8_t> 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<void> 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<void> isAdasPropertyAvailableResult;
+ VhalResult<bool> 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<const SetValuesCallback> callback,
+ const std::vector<SetValueRequest>& 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<void> 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<const GetValuesCallback> callback,
+ const std::vector<GetValueRequest>& 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<std::string>& 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<VehiclePropConfig>& 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<std::string>& 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<LinearFakeValueGenerator>(
+ 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<JsonFakeValueGenerator> generator;
+ if (options[2] == "--path") {
+ const std::string& fileName = options[3];
+ generator = std::make_unique<JsonFakeValueGenerator>(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<JsonFakeValueGenerator>(/*unused=*/true, content, repetition);
+ if (!generator->hasNext()) {
+ return "invalid JSON content, no events";
+ }
+ }
+ int32_t cookie = std::hash<std::string>()(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<int> 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<float> 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<std::mutex> 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_1> [PROP_ID_2] [PROP_ID_N]: dumps the value of specific properties. \n"
+ "--getWithArg <PROP_ID> [ValueArguments]: gets the value for a specific property. "
+ "The value arguments constructs a VehiclePropValue used in the getValue request. \n"
+ "--set <PROP_ID> [ValueArguments]: sets the value of property PROP_ID, the value "
+ "arguments constructs a VehiclePropValue used in the setValue request. \n"
+ "--save-prop <PROP_ID> [-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 <PROP_ID> [-a AREA_ID]: restores a previously saved property value. \n"
+ "--inject-event <PROP_ID> [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<int32_t> 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<void> FakeVehicleHardware::checkArgumentsSize(const std::vector<std::string>& 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<int32_t> FakeVehicleHardware::parsePropId(const std::vector<std::string>& options,
+ size_t index) {
+ const std::string& propIdStr = options[index];
+ auto result = stringToPropId(propIdStr);
+ if (result.ok()) {
+ return result;
+ }
+ return safelyParseInt<int32_t>(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<int32_t> FakeVehicleHardware::parseAreaId(const std::vector<std::string>& options,
+ size_t index, int32_t propId) {
+ const std::string& areaIdStr = options[index];
+ auto result = safelyParseInt<int32_t>(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<std::string>& 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<std::string> FakeVehicleHardware::getOptionValues(
+ const std::vector<std::string>& options, size_t* index) {
+ std::vector<std::string> 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<VehiclePropValue> FakeVehicleHardware::parsePropOptions(
+ const std::vector<std::string>& 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<std::string> parsedOptions;
+ int32_t areaIdIndex = -1;
+
+ while (optionIndex < options.size()) {
+ std::string argType = options[optionIndex];
+ optionIndex++;
+
+ size_t currentIndex = optionIndex;
+ std::vector<std::string> 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<int32_t>(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<int64_t>(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<int64_t>(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<std::string>& 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<std::string>& 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<std::string>& 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<std::mutex> 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<std::string>& 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<std::mutex> 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<std::string>& 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<const PropertyChangeCallback> callback) {
+ if (mOnPropertyChangeCallback != nullptr) {
+ ALOGE("registerOnPropertyChangeEvent must only be called once");
+ return;
+ }
+ mOnPropertyChangeCallback = std::move(callback);
+}
+
+void FakeVehicleHardware::registerOnPropertySetErrorEvent(
+ std::unique_ptr<const PropertySetErrorCallback> 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<std::mutex> 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<PropIdAreaId, VehiclePropertyStore::EventMode, PropIdAreaIdHash>
+ eventModeByPropIdAreaId;
+
+ {
+ std::scoped_lock<std::mutex> 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<int64_t>(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<RecurrentTimer::Callback>(
+ [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<std::mutex> 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<VehiclePropValue> values) {
+ ATRACE_CALL();
+ std::vector<VehiclePropValue> subscribedUpdatedValues;
+
+ {
+ std::scoped_lock<std::mutex> 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<int32_t, ConfigDeclaration>* 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<float> 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<std::vector<uint8_t>> FakeVehicleHardware::parseHexString(const std::string& s) {
+ std::vector<uint8_t> 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 <class CallbackType, class RequestType>
+FakeVehicleHardware::PendingRequestHandler<CallbackType, RequestType>::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 <class CallbackType, class RequestType>
+void FakeVehicleHardware::PendingRequestHandler<CallbackType, RequestType>::addRequest(
+ RequestType request, std::shared_ptr<const CallbackType> callback) {
+ mRequests.push({
+ request,
+ callback,
+ });
+}
+
+template <class CallbackType, class RequestType>
+void FakeVehicleHardware::PendingRequestHandler<CallbackType, RequestType>::stop() {
+ mRequests.deactivate();
+ if (mThread.joinable()) {
+ mThread.join();
+ }
+}
+
+template <>
+void FakeVehicleHardware::PendingRequestHandler<FakeVehicleHardware::GetValuesCallback,
+ GetValueRequest>::handleRequestsOnce() {
+ std::unordered_map<std::shared_ptr<const GetValuesCallback>, std::vector<GetValueResult>>
+ 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<FakeVehicleHardware::SetValuesCallback,
+ SetValueRequest>::handleRequestsOnce() {
+ std::unordered_map<std::shared_ptr<const SetValuesCallback>, std::vector<SetValueResult>>
+ 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 0000000..e7e5ba7
--- /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/fake_impl/hardware/test/fakedata/prop.json b/automotive/vehicle/aidl/impl/3/fake_impl/hardware/test/fakedata/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/hardware/test/fakedata/prop.json
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 0000000..1e71661
--- /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 0000000..8b30477
--- /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 0000000..2adf7c4
--- /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 0000000..55178dc
--- /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 0000000..6fa2bfa
--- /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/3/grpc/GRPCVehicleHardware.h b/automotive/vehicle/aidl/impl/3/grpc/GRPCVehicleHardware.h
new file mode 100644
index 0000000..ad2f512
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/3/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 <IVehicleHardware.h>
+#include <VehicleHalTypes.h>
+#include <VehicleUtils.h>
+#include <android-base/result.h>
+#include <android-base/thread_annotations.h>
+
+#include "VehicleServer.grpc.pb.h"
+#include "VehicleServer.pb.h"
+
+#include <grpc++/grpc++.h>
+
+#include <atomic>
+#include <chrono>
+#include <condition_variable>
+#include <memory>
+#include <shared_mutex>
+#include <string>
+#include <thread>
+#include <unordered_map>
+#include <vector>
+
+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<aidlvhal::VehiclePropConfig> getAllPropertyConfigs() const override;
+
+ // Get the config for the specified propId.
+ std::optional<aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
+ 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<const SetValuesCallback> callback,
+ const std::vector<aidlvhal::SetValueRequest>& 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<const GetValuesCallback> callback,
+ const std::vector<aidlvhal::GetValueRequest>& requests) const override;
+
+ // Dump debug information in the server.
+ DumpResult dump(const std::vector<std::string>& 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<const PropertyChangeCallback> callback) override;
+
+ // Register a callback that would be called when there is a property set error event from
+ // vehicle.
+ void registerOnPropertySetErrorEvent(
+ std::unique_ptr<const PropertySetErrorCallback> 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<const PropertyChangeCallback> mOnPropChange;
+
+ private:
+ friend class GRPCVehicleHardwareUnitTest;
+
+ std::string mServiceAddr;
+ std::shared_ptr<::grpc::Channel> mGrpcChannel;
+ std::unique_ptr<proto::VehicleServer::StubInterface> mGrpcStub;
+ std::thread mValuePollingThread;
+
+ std::unique_ptr<const PropertySetErrorCallback> mOnSetErr;
+
+ std::mutex mShutdownMutex;
+ std::condition_variable mShutdownCV;
+ std::atomic<bool> 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<PropIdAreaId, std::pair<int64_t, int64_t>, PropIdAreaIdHash>
+ mLatestUpdateTimestamps GUARDED_BY(mLatestUpdateTimestampsMutex);
+
+ // Only used for unit testing.
+ GRPCVehicleHardware(std::unique_ptr<proto::VehicleServer::StubInterface> stub,
+ bool startValuePollingLoop);
+
+ void ValuePollingLoop();
+ void pollValue();
+
+ aidlvhal::StatusCode getValuesWithRetry(const std::vector<aidlvhal::GetValueRequest>& requests,
+ std::vector<aidlvhal::GetValueResult>* 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/3/grpc/GRPCVehicleProxyServer.cpp b/automotive/vehicle/aidl/impl/3/grpc/GRPCVehicleProxyServer.cpp
new file mode 100644
index 0000000..927a595
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/3/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 <grpc++/grpc++.h>
+
+#include <android-base/logging.h>
+
+#include <algorithm>
+#include <condition_variable>
+#include <mutex>
+#include <unordered_set>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::automotive::vehicle::virtualization {
+
+std::atomic<uint64_t> 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<IVehicleHardware>&& hardware)
+ : GrpcVehicleProxyServer(std::vector<std::string>({serverAddr}), std::move(hardware)) {};
+
+GrpcVehicleProxyServer::GrpcVehicleProxyServer(std::vector<std::string> serverAddrs,
+ std::unique_ptr<IVehicleHardware>&& hardware)
+ : mServiceAddrs(std::move(serverAddrs)), mHardware(std::move(hardware)) {
+ mHardware->registerOnPropertyChangeEvent(
+ std::make_unique<const IVehicleHardware::PropertyChangeCallback>(
+ [this](std::vector<aidlvhal::VehiclePropValue> values) {
+ OnVehiclePropChange(values);
+ }));
+}
+
+::grpc::Status GrpcVehicleProxyServer::GetAllPropertyConfig(
+ ::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
+ ::grpc::ServerWriter<proto::VehiclePropConfig>* 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<aidlvhal::SetValueRequest> aidlRequests;
+ std::unordered_set<int64_t> 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<std::mutex>();
+ auto waitCV = std::make_shared<std::condition_variable>();
+ auto complete = std::make_shared<bool>(false);
+ auto tmpResults = std::make_shared<proto::SetValueResults>();
+ auto aidlStatus = mHardware->setValues(
+ std::make_shared<const IVehicleHardware::SetValuesCallback>(
+ [waitMtx, waitCV, complete, tmpResults,
+ &requestIds](std::vector<aidlvhal::SetValueResult> 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<proto::StatusCode>(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<aidlvhal::GetValueRequest> aidlRequests;
+ std::unordered_set<int64_t> 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<std::mutex>();
+ auto waitCV = std::make_shared<std::condition_variable>();
+ auto complete = std::make_shared<bool>(false);
+ auto tmpResults = std::make_shared<proto::GetValueResults>();
+ auto aidlStatus = mHardware->getValues(
+ std::make_shared<const IVehicleHardware::GetValuesCallback>(
+ [waitMtx, waitCV, complete, tmpResults,
+ &requestIds](std::vector<aidlvhal::GetValueResult> 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<proto::StatusCode>(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<proto::StatusCode>(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<proto::StatusCode>(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<proto::StatusCode>(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<proto::StatusCode>(mHardware->checkHealth()));
+ return ::grpc::Status::OK;
+}
+
+::grpc::Status GrpcVehicleProxyServer::Dump(::grpc::ServerContext* context,
+ const proto::DumpOptions* options,
+ proto::DumpResult* result) {
+ std::vector<std::string> 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<proto::VehiclePropValues>* stream) {
+ auto conn = std::make_shared<ConnectionDescriptor>(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<aidlvhal::VehiclePropValue>& values) {
+ std::unordered_set<uint64_t> 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/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 0000000..1ab946b
--- /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 0000000..5ae94b5
--- /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 0000000..953760f
--- /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 0000000..9840e63
--- /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 0000000..f653d90
--- /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/3/utils/common/include/VehicleObjectPool.h b/automotive/vehicle/aidl/impl/3/utils/common/include/VehicleObjectPool.h
new file mode 100644
index 0000000..e18413b
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/3/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 <deque>
+#include <map>
+#include <memory>
+#include <mutex>
+
+#include <VehicleHalTypes.h>
+
+#include <android-base/thread_annotations.h>
+
+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<uint32_t> Obtained{0};
+ std::atomic<uint32_t> Created{0};
+ std::atomic<uint32_t> Recycled{0};
+ std::atomic<uint32_t> Deleted{0};
+
+ static PoolStats* instance() {
+ static PoolStats inst;
+ return &inst;
+ }
+};
+
+template <typename T>
+struct Deleter {
+ using OnDeleteFunc = std::function<void(T*)>;
+
+ 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 <typename T>
+using recyclable_ptr = typename std::unique_ptr<T, Deleter<T>>;
+
+// 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 <typename T>
+class ObjectPool {
+ public:
+ using GetSizeFunc = std::function<size_t(const T&)>;
+
+ ObjectPool(size_t maxPoolObjectsSize, GetSizeFunc getSizeFunc)
+ : mMaxPoolObjectsSize(maxPoolObjectsSize), mGetSizeFunc(getSizeFunc) {};
+ virtual ~ObjectPool() = default;
+
+ virtual recyclable_ptr<T> obtain() {
+ std::scoped_lock<std::mutex> 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<std::mutex> 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<T>{o});
+ mPoolObjectsSize += objectSize;
+ }
+
+ const size_t mMaxPoolObjectsSize;
+
+ private:
+ const Deleter<T>& getDeleter() {
+ if (!mDeleter.get()) {
+ Deleter<T>* d =
+ new Deleter<T>(std::bind(&ObjectPool::recycle, this, std::placeholders::_1));
+ mDeleter.reset(d);
+ }
+ return *mDeleter.get();
+ }
+
+ recyclable_ptr<T> wrap(T* raw) { return recyclable_ptr<T>{raw, getDeleter()}; }
+
+ mutable std::mutex mLock;
+ std::deque<std::unique_ptr<T>> mObjects GUARDED_BY(mLock);
+ std::unique_ptr<Deleter<T>> 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<aidl::android::hardware::automotive::vehicle::VehiclePropValue>;
+
+ // 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<aidl::android::hardware::automotive::vehicle::VehiclePropValue> {
+ 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 <typename VecType>
+ bool check(std::vector<VecType>* vec, bool isVectorType) {
+ return vec->size() == (isVectorType ? mVectorSize : 0);
+ }
+
+ private:
+ aidl::android::hardware::automotive::vehicle::VehiclePropertyType mPropType;
+ size_t mVectorSize;
+ };
+ const Deleter<aidl::android::hardware::automotive::vehicle::VehiclePropValue>
+ 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<int32_t, std::unique_ptr<InternalPool>> 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/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 0000000..0450e99
--- /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 0000000..42e2317
--- /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 0000000..a648fd4
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/3/vhal/Android.bp
@@ -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.
+ */
+
+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,
+ 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/3/vhal/src/DefaultVehicleHal.cpp b/automotive/vehicle/aidl/impl/3/vhal/src/DefaultVehicleHal.cpp
new file mode 100644
index 0000000..aa9ef53
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/3/vhal/src/DefaultVehicleHal.cpp
@@ -0,0 +1,1090 @@
+/*
+ * 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 <DefaultVehicleHal.h>
+
+#include <LargeParcelableBase.h>
+#include <VehicleHalTypes.h>
+#include <VehicleUtils.h>
+#include <VersionForVehicleProperty.h>
+
+#include <android-base/logging.h>
+#include <android-base/result.h>
+#include <android-base/stringprintf.h>
+#include <android/binder_ibinder.h>
+#include <private/android_filesystem_config.h>
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+#include <utils/Trace.h>
+
+#include <inttypes.h>
+#include <chrono>
+#include <set>
+#include <unordered_set>
+
+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::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::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<int64_t>& 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<IVehicleHardware> vehicleHardware)
+ : DefaultVehicleHal(std::move(vehicleHardware), /* testInterfaceVersion= */ 0) {};
+
+DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware,
+ int32_t testInterfaceVersion)
+ : mVehicleHardware(std::move(vehicleHardware)),
+ mPendingRequestPool(std::make_shared<PendingRequestPool>(TIMEOUT_IN_NANO)),
+ mTestInterfaceVersion(testInterfaceVersion) {
+ ALOGD("DefaultVehicleHal init");
+ IVehicleHardware* vehicleHardwarePtr = mVehicleHardware.get();
+ mSubscriptionManager = std::make_shared<SubscriptionManager>(vehicleHardwarePtr);
+ mEventBatchingWindow = mVehicleHardware->getPropertyOnChangeEventBatchingWindow();
+ if (mEventBatchingWindow != std::chrono::nanoseconds(0)) {
+ mBatchedEventQueue = std::make_shared<ConcurrentQueue<VehiclePropValue>>();
+ mPropertyChangeEventsBatchingConsumer =
+ std::make_shared<BatchingConsumer<VehiclePropValue>>();
+ mPropertyChangeEventsBatchingConsumer->run(
+ mBatchedEventQueue.get(), mEventBatchingWindow,
+ [this](std::vector<VehiclePropValue> batchedEvents) {
+ handleBatchedPropertyEvents(std::move(batchedEvents));
+ });
+ }
+
+ std::weak_ptr<ConcurrentQueue<VehiclePropValue>> batchedEventQueueCopy = mBatchedEventQueue;
+ std::chrono::nanoseconds eventBatchingWindow = mEventBatchingWindow;
+ std::weak_ptr<SubscriptionManager> subscriptionManagerCopy = mSubscriptionManager;
+ mVehicleHardware->registerOnPropertyChangeEvent(
+ std::make_unique<IVehicleHardware::PropertyChangeCallback>(
+ [subscriptionManagerCopy, batchedEventQueueCopy,
+ eventBatchingWindow](std::vector<VehiclePropValue> updatedValues) {
+ if (eventBatchingWindow != std::chrono::nanoseconds(0)) {
+ batchPropertyChangeEvent(batchedEventQueueCopy,
+ std::move(updatedValues));
+ } else {
+ onPropertyChangeEvent(subscriptionManagerCopy,
+ std::move(updatedValues));
+ }
+ }));
+ mVehicleHardware->registerOnPropertySetErrorEvent(
+ std::make_unique<IVehicleHardware::PropertySetErrorCallback>(
+ [subscriptionManagerCopy](std::vector<SetValueErrorEvent> errorEvents) {
+ onPropertySetErrorEvent(subscriptionManagerCopy, errorEvents);
+ }));
+
+ // Register heartbeat event.
+ mRecurrentAction = std::make_shared<std::function<void()>>(
+ [vehicleHardwarePtr, subscriptionManagerCopy]() {
+ checkHealth(vehicleHardwarePtr, subscriptionManagerCopy);
+ });
+ mRecurrentTimer.registerTimerCallback(HEART_BEAT_INTERVAL_IN_NANO, mRecurrentAction);
+
+ mBinderLifecycleHandler = std::make_unique<BinderLifecycleHandler>();
+ 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<ConcurrentQueue<VehiclePropValue>>& batchedEventQueue,
+ std::vector<VehiclePropValue>&& 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<VehiclePropValue>&& batchedEvents) {
+ onPropertyChangeEvent(mSubscriptionManager, std::move(batchedEvents));
+}
+
+void DefaultVehicleHal::onPropertyChangeEvent(
+ const std::weak_ptr<SubscriptionManager>& subscriptionManager,
+ std::vector<VehiclePropValue>&& 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>& subscriptionManager,
+ const std::vector<SetValueErrorEvent>& 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 <class T>
+std::shared_ptr<T> DefaultVehicleHal::getOrCreateClient(
+ std::unordered_map<const AIBinder*, std::shared_ptr<T>>* clients,
+ const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool) {
+ const AIBinder* clientId = callback->asBinder().get();
+ if (clients->find(clientId) == clients->end()) {
+ (*clients)[clientId] = std::make_shared<T>(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<OnBinderDiedContext> context = std::make_unique<OnBinderDiedContext>(
+ 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<AIBinder*>(clientId), mDeathRecipient.get(), static_cast<void*>(contextPtr));
+ if (status == STATUS_OK) {
+ return true;
+ }
+ ALOGE("failed to call linkToDeath on client binder, client may already died, status: %d",
+ static_cast<int>(status));
+ return false;
+}
+
+void DefaultVehicleHal::onBinderDied(void* cookie) {
+ OnBinderDiedContext* context = reinterpret_cast<OnBinderDiedContext*>(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<std::mutex> 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<OnBinderDiedContext*>(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<std::mutex> 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::GetValuesClient>
+DefaultVehicleHal::getOrCreateClient<DefaultVehicleHal::GetValuesClient>(
+ std::unordered_map<const AIBinder*, std::shared_ptr<GetValuesClient>>* clients,
+ const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool);
+template std::shared_ptr<DefaultVehicleHal::SetValuesClient>
+DefaultVehicleHal::getOrCreateClient<DefaultVehicleHal::SetValuesClient>(
+ std::unordered_map<const AIBinder*, std::shared_ptr<SetValuesClient>>* clients,
+ const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool);
+
+void DefaultVehicleHal::setTimeout(int64_t timeoutInNano) {
+ mPendingRequestPool = std::make_unique<PendingRequestPool>(timeoutInNano);
+}
+
+int32_t DefaultVehicleHal::getVhalInterfaceVersion() const {
+ if (mTestInterfaceVersion != 0) {
+ return mTestInterfaceVersion;
+ }
+ int32_t myVersion = 0;
+ // getInterfaceVersion is in-reality a const method.
+ const_cast<DefaultVehicleHal*>(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<VehicleProperty>(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<VehiclePropConfig> filteredConfigs;
+ for (const auto& config : configs) {
+ if (isConfigSupportedForCurrentVhalVersion(config)) {
+ filteredConfigs.push_back(std::move(config));
+ }
+ }
+
+ {
+ std::unique_lock<std::shared_timed_mutex> 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<int>(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<void(const std::unordered_map<int32_t, VehiclePropConfig>&)> callback) const {
+ if (!mConfigInit) {
+ CHECK(getAllPropConfigsFromHardwareLocked())
+ << "Failed to get property configs from hardware";
+ }
+
+ std::shared_lock<std::shared_timed_mutex> 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<std::shared_timed_mutex> 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<VehiclePropConfig> DefaultVehicleHal::getConfig(int32_t propId) const {
+ Result<VehiclePropConfig> result;
+
+ if (!mConfigInit) {
+ std::optional<VehiclePropConfig> 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<void> 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<LargeParcelableBase::BorrowedOwnedObject<GetValueRequests>, ScopedAStatus>
+ deserializedResults = fromStableLargeParcelable(requests);
+ if (!deserializedResults.ok()) {
+ ALOGE("getValues: failed to parse getValues requests");
+ return std::move(deserializedResults.error());
+ }
+ const std::vector<GetValueRequest>& 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<GetValueResult> failedResults;
+ // The list of requests that we would send to hardware.
+ std::vector<GetValueRequest> 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<int64_t> hardwareRequestIds;
+ for (const auto& request : hardwareRequests) {
+ hardwareRequestIds.insert(request.requestId);
+ }
+
+ std::shared_ptr<GetValuesClient> 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<LargeParcelableBase::BorrowedOwnedObject<SetValueRequests>, ScopedAStatus>
+ deserializedResults = fromStableLargeParcelable(requests);
+ if (!deserializedResults.ok()) {
+ ALOGE("setValues: failed to parse setValues requests");
+ return std::move(deserializedResults.error());
+ }
+ const std::vector<SetValueRequest>& setValueRequests =
+ deserializedResults.value().getObject()->payloads;
+
+ // A list of failed result we already know before sending to hardware.
+ std::vector<SetValueResult> failedResults;
+ // The list of requests that we would send to hardware.
+ std::vector<SetValueRequest> 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<int64_t> hardwareRequestIds;
+ for (const auto& request : hardwareRequests) {
+ hardwareRequestIds.insert(request.requestId);
+ }
+
+ std::shared_ptr<SetValuesClient> 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<int64_t> 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<std::vector<int64_t>> DefaultVehicleHal::checkDuplicateRequests(
+ const std::vector<GetValueRequest>& requests) {
+ CHECK_DUPLICATE_REQUESTS(prop);
+}
+
+::android::base::Result<std::vector<int64_t>> DefaultVehicleHal::checkDuplicateRequests(
+ const std::vector<SetValueRequest>& requests) {
+ CHECK_DUPLICATE_REQUESTS(value);
+}
+
+#undef CHECK_DUPLICATE_REQUESTS
+
+ScopedAStatus DefaultVehicleHal::getPropConfigs(const std::vector<int32_t>& props,
+ VehiclePropConfigs* output) {
+ std::vector<VehiclePropConfig> 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<VehicleAreaConfig>& areaConfigs,
+ VehiclePropertyAccess requiredAccess) {
+ if (areaConfigs.empty()) {
+ return false;
+ }
+ for (VehicleAreaConfig areaConfig : areaConfigs) {
+ if (!hasRequiredAccess(areaConfig.access, requiredAccess)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+VhalResult<void> DefaultVehicleHal::checkSubscribeOptions(
+ const std::vector<SubscribeOptions>& options,
+ const std::unordered_map<int32_t, VehiclePropConfig>& 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<VehicleAreaConfig> areaConfigs;
+ if (option.areaIds.empty()) {
+ areaConfigs = config.areaConfigs;
+ } else {
+ std::unordered_map<int, VehicleAreaConfig> 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<SubscribeOptions>& options,
+ const std::unordered_map<int32_t, VehiclePropConfig>& configsByPropId,
+ std::vector<SubscribeOptions>& onChangeSubscriptions,
+ std::vector<SubscribeOptions>& 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<int32_t> areasVurEnabled;
+ std::vector<int32_t> 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<SubscribeOptions>& 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<SubscribeOptions> onChangeSubscriptions;
+ std::vector<SubscribeOptions> 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<int32_t>& 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();
+}
+
+IVehicleHardware* DefaultVehicleHal::getHardware() {
+ return mVehicleHardware.get();
+}
+
+VhalResult<void> DefaultVehicleHal::checkPermissionHelper(
+ const VehiclePropValue& value, VehiclePropertyAccess accessToTest) const {
+ static const std::unordered_set<VehiclePropertyAccess> 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<int32_t>(accessToTest));
+ }
+ return {};
+}
+
+VhalResult<void> DefaultVehicleHal::checkWritePermission(const VehiclePropValue& value) const {
+ return checkPermissionHelper(value, VehiclePropertyAccess::WRITE);
+}
+
+VhalResult<void> DefaultVehicleHal::checkReadPermission(const VehiclePropValue& value) const {
+ return checkPermissionHelper(value, VehiclePropertyAccess::READ);
+}
+
+void DefaultVehicleHal::checkHealth(IVehicleHardware* vehicleHardware,
+ std::weak_ptr<SubscriptionManager> subscriptionManager) {
+ StatusCode status = vehicleHardware->checkHealth();
+ if (status != StatusCode::OK) {
+ ALOGE("VHAL check health returns non-okay status");
+ return;
+ }
+ std::vector<VehiclePropValue> 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<BinderLifecycleInterface> 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<std::string> 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<int32_t, VehiclePropConfig> configsByPropIdCopy;
+ getConfigsByPropId([this, &configsByPropIdCopy](const auto& configsByPropId) {
+ SharedScopedLockAssertion lockAssertion(mConfigLock);
+
+ configsByPropIdCopy = configsByPropId;
+ });
+ {
+ std::scoped_lock<std::mutex> 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/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/3/vhal/src/fuzzer.cpp b/automotive/vehicle/aidl/impl/3/vhal/src/fuzzer.cpp
new file mode 100644
index 0000000..ac1e3b1
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/3/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 <DefaultVehicleHal.h>
+#include <FakeVehicleHardware.h>
+#include <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+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<FakeVehicleHardware> hardware = std::make_unique<FakeVehicleHardware>();
+ std::shared_ptr<DefaultVehicleHal> vhal =
+ ::ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
+
+ fuzzService(vhal->asBinder().get(), FuzzedDataProvider(data, size));
+
+ return 0;
+}
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 0000000..e86bc81
--- /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/3/vhal/test/DefaultVehicleHalTest.cpp b/automotive/vehicle/aidl/impl/3/vhal/test/DefaultVehicleHalTest.cpp
new file mode 100644
index 0000000..ad34a4c
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/3/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 <IVehicleHardware.h>
+#include <LargeParcelableBase.h>
+#include <aidl/android/hardware/automotive/vehicle/IVehicle.h>
+#include <aidl/android/hardware/automotive/vehicle/IVehicleCallback.h>
+
+#include <android-base/thread_annotations.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <sys/mman.h>
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+
+#include <chrono>
+#include <list>
+#include <memory>
+#include <mutex>
+#include <optional>
+#include <thread>
+#include <unordered_map>
+#include <vector>
+
+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<int32_t>(i) + 0x20000000 + 0x01000000 + 0x00410000;
+}
+
+std::string toString(const std::vector<SubscribeOptions>& 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<SetValuesInvalidRequestTestCase> 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<SubscribeInvalidOptionsTestCase> 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<MockVehicleHardware>()); }
+
+ void init(std::unique_ptr<MockVehicleHardware> hardware) {
+ std::vector<VehiclePropConfig> 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<DefaultVehicleHal>(std::move(hardware));
+ mVhalClient = IVehicle::fromBinder(mVhal->asBinder());
+ mCallback = ndk::SharedRefBase::make<MockVehicleCallback>();
+ // 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<TestBinderLifecycleHandler>();
+ mBinderLifecycleHandler = handler.get();
+ mVhal->setBinderLifecycleHandler(std::move(handler));
+ }
+
+ void TearDown() override {
+ ASSERT_EQ(countPendingRequests(), static_cast<size_t>(0))
+ << "must have no pending requests when test finishes";
+ }
+
+ MockVehicleHardware* getHardware() { return mHardwarePtr; }
+
+ std::shared_ptr<IVehicle> getClient() { return mVhal; }
+
+ std::shared_ptr<IVehicleCallback> 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<std::mutex> lockGuard(mVhal->mLock);
+ return mVhal->mGetValuesClients.size() + mVhal->mSetValuesClients.size() +
+ mVhal->countSubscribeClients();
+ }
+
+ std::shared_ptr<PendingRequestPool> 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<std::mutex> lockGuard(mVhal->mLock);
+ return mVhal->mOnBinderDiedContexts[clientId].get();
+ }
+
+ size_t countOnBinderDiedContexts() {
+ std::scoped_lock<std::mutex> lockGuard(mVhal->mLock);
+ return mVhal->mOnBinderDiedContexts.size();
+ }
+
+ bool hasNoSubscriptions() { return mVhal->mSubscriptionManager->isEmpty(); }
+
+ void setBinderAlive(bool isAlive) { mBinderLifecycleHandler->setAlive(isAlive); };
+
+ static Result<void> getValuesTestCases(size_t size, GetValueRequests& requests,
+ std::vector<GetValueResult>& expectedResults,
+ std::vector<GetValueRequest>& expectedHardwareRequests) {
+ expectedHardwareRequests.clear();
+ for (size_t i = 0; i < size; i++) {
+ int64_t requestId = static_cast<int64_t>(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<void> setValuesTestCases(size_t size, SetValueRequests& requests,
+ std::vector<SetValueResult>& expectedResults,
+ std::vector<SetValueRequest>& expectedHardwareRequests) {
+ expectedHardwareRequests.clear();
+ for (size_t i = 0; i < size; i++) {
+ int64_t requestId = static_cast<int64_t>(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<DefaultVehicleHal> mVhal;
+ std::shared_ptr<IVehicle> mVhalClient;
+ MockVehicleHardware* mHardwarePtr;
+ std::shared_ptr<MockVehicleCallback> mCallback;
+ std::shared_ptr<IVehicleCallback> mCallbackClient;
+ SpAIBinder mBinder;
+ TestBinderLifecycleHandler* mBinderLifecycleHandler;
+};
+
+TEST_F(DefaultVehicleHalTest, testGetAllPropConfigsSmall) {
+ auto testConfigs = std::vector<VehiclePropConfig>({
+ VehiclePropConfig{
+ .prop = testInt32VecProp(1),
+ },
+ VehiclePropConfig{
+ .prop = testInt32VecProp(2),
+ },
+ });
+
+ auto hardware = std::make_unique<MockVehicleHardware>();
+ hardware->setPropertyConfigs(testConfigs);
+ auto vhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
+ std::shared_ptr<IVehicle> 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<VehiclePropConfig> 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<MockVehicleHardware>();
+ hardware->setPropertyConfigs(testConfigs);
+ auto vhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
+ std::shared_ptr<IVehicle> 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<VehiclePropConfig>({
+ // 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<MockVehicleHardware>();
+ hardware->setPropertyConfigs(testConfigs);
+ auto vhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware),
+ /* testInterfaceVersion= */ 2);
+ std::shared_ptr<IVehicle> 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>({
+ VehiclePropConfig{
+ .prop = propId1,
+ },
+ VehiclePropConfig{
+ .prop = propId2,
+ },
+ });
+
+ auto hardware = std::make_unique<MockVehicleHardware>();
+ hardware->setPropertyConfigs(testConfigs);
+ // Store the pointer for testing. We are sure it is valid.
+ MockVehicleHardware* hardwarePtr = hardware.get();
+ auto vhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
+ std::shared_ptr<IVehicle> client = IVehicle::fromBinder(vhal->asBinder());
+
+ VehiclePropConfigs output;
+ auto status = client->getPropConfigs(std::vector<int32_t>({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>({
+ VehiclePropConfig{
+ .prop = testInt32VecProp(1),
+ },
+ VehiclePropConfig{
+ .prop = testInt32VecProp(2),
+ },
+ });
+
+ auto hardware = std::make_unique<MockVehicleHardware>();
+ hardware->setPropertyConfigs(testConfigs);
+ auto vhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
+ std::shared_ptr<IVehicle> client = IVehicle::fromBinder(vhal->asBinder());
+
+ VehiclePropConfigs output;
+ auto status = client->getPropConfigs(
+ std::vector<int32_t>({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<GetValueResult> expectedResults;
+ std::vector<GetValueRequest> 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<size_t>(1));
+ ASSERT_FALSE(getHardware()->getAllPropertyConfigsCalled());
+}
+
+TEST_F(DefaultVehicleHalTest, testGetValuesSmall_AfterGetAllPropConfigs) {
+ GetValueRequests requests;
+ std::vector<GetValueResult> expectedResults;
+ std::vector<GetValueRequest> 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<size_t>(1));
+ ASSERT_TRUE(getHardware()->getAllPropertyConfigsCalled());
+}
+
+TEST_F(DefaultVehicleHalTest, testGetValuesLarge) {
+ GetValueRequests requests;
+ std::vector<GetValueResult> expectedResults;
+ std::vector<GetValueRequest> 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<size_t>(1));
+}
+
+TEST_F(DefaultVehicleHalTest, testGetValuesErrorFromHardware) {
+ GetValueRequests requests;
+ std::vector<GetValueResult> expectedResults;
+ std::vector<GetValueRequest> 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<GetValueResult>({
+ {
+ .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<GetValueResult> expectedResults;
+ std::vector<GetValueRequest> 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<GetValueResult> expectedResults;
+ std::vector<GetValueRequest> 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<GetValueResult> expectedResults;
+ std::vector<GetValueRequest> 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<GetValueResult> expectedResults;
+ std::vector<GetValueRequest> 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<size_t>(0))
+ << "No client should be created if the client binder died";
+}
+
+TEST_F(DefaultVehicleHalTest, testGetValuesExistingClientDied) {
+ GetValueRequests requests;
+ std::vector<GetValueResult> expectedResults;
+ std::vector<GetValueRequest> 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<size_t>(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<size_t>(1));
+}
+
+TEST_F(DefaultVehicleHalTest, testSetValuesSmall) {
+ SetValueRequests requests;
+ std::vector<SetValueResult> expectedResults;
+ std::vector<SetValueRequest> 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<size_t>(1));
+ ASSERT_FALSE(getHardware()->getAllPropertyConfigsCalled());
+}
+
+TEST_F(DefaultVehicleHalTest, testSetValuesSmall_AfterGetAllPropConfigs) {
+ SetValueRequests requests;
+ std::vector<SetValueResult> expectedResults;
+ std::vector<SetValueRequest> 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<size_t>(1));
+ ASSERT_TRUE(getHardware()->getAllPropertyConfigsCalled());
+}
+
+TEST_F(DefaultVehicleHalTest, testSetValuesLarge) {
+ SetValueRequests requests;
+ std::vector<SetValueResult> expectedResults;
+ std::vector<SetValueRequest> 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<size_t>(1));
+}
+
+class SetValuesInvalidRequestTest
+ : public DefaultVehicleHalTest,
+ public testing::WithParamInterface<SetValuesInvalidRequestTestCase> {};
+
+INSTANTIATE_TEST_SUITE_P(
+ SetValuesInvalidRequestTests, SetValuesInvalidRequestTest,
+ testing::ValuesIn(getSetValuesInvalidRequestTestCases()),
+ [](const testing::TestParamInfo<SetValuesInvalidRequestTest::ParamType>& info) {
+ return info.param.name;
+ });
+
+TEST_P(SetValuesInvalidRequestTest, testSetValuesInvalidRequest) {
+ SetValuesInvalidRequestTestCase tc = GetParam();
+ std::vector<SetValueResult> 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<SetValueRequest>({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<SetValueResult>({
+ {
+ .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<SetValueResult> expectedResults;
+ std::vector<SetValueRequest> 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<SetValueResult> expectedResults;
+ std::vector<SetValueRequest> 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<SetValueResult> expectedResults;
+ std::vector<SetValueRequest> 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<SubscribeOptions> 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<int32_t>({GLOBAL_ON_CHANGE_PROP}));
+
+ ASSERT_TRUE(status.isOk()) << "unsubscribe failed: " << status.getMessage();
+}
+
+TEST_F(DefaultVehicleHalTest, testSubscribeGlobalOnChangeNormal) {
+ std::vector<SubscribeOptions> 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<SetValueResult> 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<size_t>(2))
+ << "expect 2 clients, 1 subscribe client and 1 setvalue client";
+}
+
+TEST_F(DefaultVehicleHalTest, testSubscribeGlobalOnchangeUnrelatedEventIgnored) {
+ std::vector<SubscribeOptions> 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<SubscribeOptions> 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<SubscribeOptions> 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<SubscribeOptions> 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<size_t>(1));
+}
+
+TEST_F(DefaultVehicleHalTest, testSubscribeGlobalContinuousRateOutOfRange) {
+ // The maxSampleRate is 100, so the sample rate should be the default max 100.
+ std::vector<SubscribeOptions> 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<size_t>(1));
+}
+
+TEST_F(DefaultVehicleHalTest, testSubscribeContinuous_propNotSupportVur) {
+ std::vector<SubscribeOptions> 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<SubscribeOptions> 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<SubscribeOptions> 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<int32_t>({AREA_CONTINUOUS_PROP}));
+
+ std::vector<VehiclePropValue> 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<size_t>(15));
+ // Should trigger about 10 times, check for at least 5 events to be safe.
+ ASSERT_GE(rightCount, static_cast<size_t>(5));
+}
+
+TEST_F(DefaultVehicleHalTest, testAreaContinuous_areaNotSupportVur) {
+ std::vector<SubscribeOptions> 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<SubscribeOptions> 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<int32_t>({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<SubscribeOptions> 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<int32_t>({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<SubscribeInvalidOptionsTestCase> {};
+
+INSTANTIATE_TEST_SUITE_P(
+ SubscribeInvalidOptionsTests, SubscribeInvalidOptionsTest,
+ testing::ValuesIn(getSubscribeInvalidOptionsTestCases()),
+ [](const testing::TestParamInfo<SubscribeInvalidOptionsTest::ParamType>& info) {
+ return info.param.name;
+ });
+
+TEST_P(SubscribeInvalidOptionsTest, testSubscribeInvalidOptions) {
+ std::vector<SubscribeOptions> 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<SubscribeOptions> 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<SubscribeOptions> 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<SubscribeOptions> 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<int32_t>({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<SubscribeOptions> 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<size_t>(1));
+ VehiclePropValue gotValue = maybeResults.value().payloads[0];
+ ASSERT_EQ(gotValue.prop, toInt(VehicleProperty::VHAL_HEARTBEAT));
+ ASSERT_EQ(gotValue.value.int64Values.size(), static_cast<size_t>(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<const IVehicleHardware::GetValuesCallback> callback,
+ const std::vector<GetValueRequest>& requests) {
+ std::vector<GetValueResult> 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<SubscribeOptions> 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<GetValueResult> expectedResults;
+ std::vector<GetValueRequest> 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<size_t>(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<size_t>(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<size_t>(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<SubscribeOptions> 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<SetValueErrorEvent> 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<VehiclePropError> 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<MockVehicleHardware>();
+ hardware->setPropertyOnChangeEventBatchingWindow(std::chrono::milliseconds(10));
+ init(std::move(hardware));
+
+ std::vector<SubscribeOptions> 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/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/default_config/JsonConfigLoader/include/ConfigDeclaration.h b/automotive/vehicle/aidl/impl/current/default_config/JsonConfigLoader/include/ConfigDeclaration.h
similarity index 100%
copy from automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/include/ConfigDeclaration.h
copy to automotive/vehicle/aidl/impl/current/default_config/JsonConfigLoader/include/ConfigDeclaration.h
diff --git a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/include/JsonConfigLoader.h b/automotive/vehicle/aidl/impl/current/default_config/JsonConfigLoader/include/JsonConfigLoader.h
similarity index 100%
copy from automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/include/JsonConfigLoader.h
copy to automotive/vehicle/aidl/impl/current/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 0000000..f910beb
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/current/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp
@@ -0,0 +1,744 @@
+/*
+ * 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 <JsonConfigLoader.h>
+
+#include <AccessForVehicleProperty.h>
+#include <ChangeModeForVehicleProperty.h>
+#include <PropertyUtils.h>
+
+#ifdef ENABLE_VEHICLE_HAL_TEST_PROPERTIES
+#include <android/hardware/automotive/vehicle/TestVendorProperty.h>
+#endif // ENABLE_VEHICLE_HAL_TEST_PROPERTIES
+
+#include <android-base/strings.h>
+#include <fstream>
+
+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::HasSupportedValueInfo;
+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<std::string, int> 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 T>
+class ConstantParser final : public ConstantParserInterface {
+ public:
+ ConstantParser() {
+ for (const T& v : ndk::enum_range<T>()) {
+ 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<int> 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<std::string, int> 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 T>
+class CppConstantParser final : public ConstantParserInterface {
+ public:
+ CppConstantParser() {
+ for (const T& v : android::enum_range<T>()) {
+ std::string name = android::hardware::automotive::vehicle::toString(v);
+ mValueByName[name] = toInt(v);
+ }
+ }
+
+ ~CppConstantParser() = default;
+
+ Result<int> 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<std::string, int> mValueByName;
+};
+#endif
+
+// A class to parse constant values defined in CONSTANTS_BY_NAME map.
+class LocalVariableParser final : public ConstantParserInterface {
+ public:
+ ~LocalVariableParser() = default;
+
+ Result<int> 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<ConstantParser<VehiclePropertyAccess>>();
+ mConstantParsersByType["VehiclePropertyChangeMode"] =
+ std::make_unique<ConstantParser<VehiclePropertyChangeMode>>();
+ mConstantParsersByType["LocationCharacterization"] =
+ std::make_unique<ConstantParser<LocationCharacterization>>();
+ mConstantParsersByType["VehicleGear"] = std::make_unique<ConstantParser<VehicleGear>>();
+ mConstantParsersByType["VehicleAreaWindow"] =
+ std::make_unique<ConstantParser<VehicleAreaWindow>>();
+ mConstantParsersByType["VehicleAreaMirror"] =
+ std::make_unique<ConstantParser<VehicleAreaMirror>>();
+ mConstantParsersByType["VehicleOilLevel"] = std::make_unique<ConstantParser<VehicleOilLevel>>();
+ mConstantParsersByType["VehicleUnit"] = std::make_unique<ConstantParser<VehicleUnit>>();
+ mConstantParsersByType["VehicleSeatOccupancyState"] =
+ std::make_unique<ConstantParser<VehicleSeatOccupancyState>>();
+ mConstantParsersByType["VehicleHvacFanDirection"] =
+ std::make_unique<ConstantParser<VehicleHvacFanDirection>>();
+ mConstantParsersByType["VehicleApPowerStateReport"] =
+ std::make_unique<ConstantParser<VehicleApPowerStateReport>>();
+ mConstantParsersByType["VehicleTurnSignal"] =
+ std::make_unique<ConstantParser<VehicleTurnSignal>>();
+ mConstantParsersByType["VehicleVendorPermission"] =
+ std::make_unique<ConstantParser<VehicleVendorPermission>>();
+ mConstantParsersByType["EvsServiceType"] = std::make_unique<ConstantParser<EvsServiceType>>();
+ mConstantParsersByType["EvsServiceState"] = std::make_unique<ConstantParser<EvsServiceState>>();
+ mConstantParsersByType["EvConnectorType"] = std::make_unique<ConstantParser<EvConnectorType>>();
+ mConstantParsersByType["VehicleProperty"] = std::make_unique<ConstantParser<VehicleProperty>>();
+ mConstantParsersByType["GsrComplianceRequirementType"] =
+ std::make_unique<ConstantParser<GsrComplianceRequirementType>>();
+ mConstantParsersByType["VehicleIgnitionState"] =
+ std::make_unique<ConstantParser<VehicleIgnitionState>>();
+ mConstantParsersByType["FuelType"] = std::make_unique<ConstantParser<FuelType>>();
+ mConstantParsersByType["WindshieldWipersState"] =
+ std::make_unique<ConstantParser<WindshieldWipersState>>();
+ mConstantParsersByType["WindshieldWipersSwitch"] =
+ std::make_unique<ConstantParser<WindshieldWipersSwitch>>();
+ mConstantParsersByType["VehicleAutonomousState"] =
+ std::make_unique<ConstantParser<VehicleAutonomousState>>();
+ mConstantParsersByType["VehicleAirbagLocation"] =
+ std::make_unique<ConstantParser<VehicleAirbagLocation>>();
+ mConstantParsersByType["ImpactSensorLocation"] =
+ std::make_unique<ConstantParser<ImpactSensorLocation>>();
+ mConstantParsersByType["VehicleSizeClass"] =
+ std::make_unique<ConstantParser<VehicleSizeClass>>();
+ mConstantParsersByType["EmergencyLaneKeepAssistState"] =
+ std::make_unique<ConstantParser<EmergencyLaneKeepAssistState>>();
+ mConstantParsersByType["CameraServiceState"] =
+ std::make_unique<ConstantParser<CameraServiceState>>();
+ mConstantParsersByType["CruiseControlType"] =
+ std::make_unique<ConstantParser<CruiseControlType>>();
+ mConstantParsersByType["CruiseControlState"] =
+ std::make_unique<ConstantParser<CruiseControlState>>();
+ mConstantParsersByType["CruiseControlCommand"] =
+ std::make_unique<ConstantParser<CruiseControlCommand>>();
+ mConstantParsersByType["HandsOnDetectionDriverState"] =
+ std::make_unique<ConstantParser<HandsOnDetectionDriverState>>();
+ mConstantParsersByType["HandsOnDetectionWarning"] =
+ std::make_unique<ConstantParser<HandsOnDetectionWarning>>();
+ mConstantParsersByType["DriverDrowsinessAttentionState"] =
+ std::make_unique<ConstantParser<DriverDrowsinessAttentionState>>();
+ mConstantParsersByType["DriverDrowsinessAttentionWarning"] =
+ std::make_unique<ConstantParser<DriverDrowsinessAttentionWarning>>();
+ mConstantParsersByType["DriverDistractionState"] =
+ std::make_unique<ConstantParser<DriverDistractionState>>();
+ mConstantParsersByType["DriverDistractionWarning"] =
+ std::make_unique<ConstantParser<DriverDistractionWarning>>();
+ mConstantParsersByType["ErrorState"] = std::make_unique<ConstantParser<ErrorState>>();
+ mConstantParsersByType["AutomaticEmergencyBrakingState"] =
+ std::make_unique<ConstantParser<AutomaticEmergencyBrakingState>>();
+ mConstantParsersByType["ForwardCollisionWarningState"] =
+ std::make_unique<ConstantParser<ForwardCollisionWarningState>>();
+ mConstantParsersByType["BlindSpotWarningState"] =
+ std::make_unique<ConstantParser<BlindSpotWarningState>>();
+ mConstantParsersByType["LaneDepartureWarningState"] =
+ std::make_unique<ConstantParser<LaneDepartureWarningState>>();
+ mConstantParsersByType["LaneKeepAssistState"] =
+ std::make_unique<ConstantParser<LaneKeepAssistState>>();
+ mConstantParsersByType["LaneCenteringAssistCommand"] =
+ std::make_unique<ConstantParser<LaneCenteringAssistCommand>>();
+ mConstantParsersByType["LaneCenteringAssistState"] =
+ std::make_unique<ConstantParser<LaneCenteringAssistState>>();
+ mConstantParsersByType["LowSpeedCollisionWarningState"] =
+ std::make_unique<ConstantParser<LowSpeedCollisionWarningState>>();
+ mConstantParsersByType["ElectronicStabilityControlState"] =
+ std::make_unique<ConstantParser<ElectronicStabilityControlState>>();
+ mConstantParsersByType["CrossTrafficMonitoringWarningState"] =
+ std::make_unique<ConstantParser<CrossTrafficMonitoringWarningState>>();
+ mConstantParsersByType["LowSpeedAutomaticEmergencyBrakingState"] =
+ std::make_unique<ConstantParser<LowSpeedAutomaticEmergencyBrakingState>>();
+ mConstantParsersByType["VehicleApPowerBootupReason"] =
+ std::make_unique<ConstantParser<VehicleApPowerBootupReason>>();
+ mConstantParsersByType["Constants"] = std::make_unique<LocalVariableParser>();
+#ifdef ENABLE_VEHICLE_HAL_TEST_PROPERTIES
+ mConstantParsersByType["TestVendorProperty"] =
+ std::make_unique<CppConstantParser<TestVendorProperty>>();
+#endif // ENABLE_VEHICLE_HAL_TEST_PROPERTIES
+}
+
+template <>
+Result<bool> JsonValueParser::convertValueToType<bool>(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<int32_t> JsonValueParser::convertValueToType<int32_t>(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<int32_t>(value.asInt());
+}
+
+template <>
+Result<float> JsonValueParser::convertValueToType<float>(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<int64_t> JsonValueParser::convertValueToType<int64_t>(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<int64_t>(value.asInt64());
+}
+
+template <>
+Result<std::string> JsonValueParser::convertValueToType<std::string>(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<std::string> JsonValueParser::parseStringValue(const std::string& fieldName,
+ const Json::Value& value) const {
+ return convertValueToType<std::string>(fieldName, value);
+}
+
+template <class T>
+Result<T> JsonValueParser::parseValue(const std::string& fieldName,
+ const Json::Value& value) const {
+ if (!value.isString()) {
+ return convertValueToType<T>(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<T>(constantValue);
+}
+
+template <>
+Result<std::string> JsonValueParser::parseValue<std::string>(const std::string& fieldName,
+ const Json::Value& value) const {
+ return parseStringValue(fieldName, value);
+}
+
+template <class T>
+Result<std::vector<T>> 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<T> parsedValues;
+ for (unsigned int i = 0; i < value.size(); i++) {
+ auto result = parseValue<T>(fieldName, value[i]);
+ if (!result.ok()) {
+ return result.error();
+ }
+ parsedValues.push_back(result.value());
+ }
+ return std::move(parsedValues);
+}
+
+std::optional<std::pair<std::string, std::string>> 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<int> JsonValueParser::parseConstantValue(
+ const std::pair<std::string, std::string>& 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 <class T>
+bool JsonConfigParser::tryParseJsonValueToVariable(const Json::Value& parentJsonNode,
+ const std::string& fieldName,
+ bool fieldIsOptional, T* outPtr,
+ std::vector<std::string>* 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<T>(fieldName, parentJsonNode[fieldName]);
+ if (!result.ok()) {
+ errors->push_back(result.error().message());
+ return false;
+ }
+ *outPtr = std::move(result.value());
+ return true;
+}
+
+template <class T>
+bool JsonConfigParser::tryParseJsonArrayToVariable(const Json::Value& parentJsonNode,
+ const std::string& fieldName,
+ bool fieldIsOptional, std::vector<T>* outPtr,
+ std::vector<std::string>* 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<T>(fieldName, parentJsonNode[fieldName]);
+ if (!result.ok()) {
+ errors->push_back(result.error().message());
+ return false;
+ }
+ *outPtr = std::move(result.value());
+ return true;
+}
+
+template <class T>
+void JsonConfigParser::parseAccessChangeMode(const Json::Value& parentJsonNode,
+ const std::string& fieldName,
+ const std::string& propStr,
+ const T* defaultAccessChangeModeValuePtr, T* outPtr,
+ std::vector<std::string>* errors) {
+ if (!parentJsonNode.isObject()) {
+ errors->push_back("Node: " + parentJsonNode.toStyledString() + " is not an object");
+ return;
+ }
+ if (parentJsonNode.isMember(fieldName)) {
+ auto result = mValueParser.parseValue<int32_t>(fieldName, parentJsonNode[fieldName]);
+ if (!result.ok()) {
+ errors->push_back(result.error().message());
+ return;
+ }
+ *outPtr = static_cast<T>(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<std::string>* 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<std::string>* 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<int64_t> supportedEnumValues;
+ tryParseJsonArrayToVariable(jsonAreaConfig, "supportedEnumValues", /*optional=*/true,
+ &supportedEnumValues, errors);
+ if (!supportedEnumValues.empty()) {
+ areaConfig.supportedEnumValues = std::move(supportedEnumValues);
+ }
+
+ if (jsonAreaConfig.isMember("hasSupportedValueInfo")) {
+ HasSupportedValueInfo hasSupportedValueInfo = HasSupportedValueInfo{};
+ const Json::Value& jsonHasSupportedValueInfo = jsonAreaConfig["hasSupportedValueInfo"];
+ tryParseJsonValueToVariable(jsonHasSupportedValueInfo, "hasMinSupportedValue",
+ /*optional=*/true,
+ &hasSupportedValueInfo.hasMinSupportedValue, errors);
+ tryParseJsonValueToVariable(jsonHasSupportedValueInfo, "hasMaxSupportedValue",
+ /*optional=*/true,
+ &hasSupportedValueInfo.hasMaxSupportedValue, errors);
+ tryParseJsonValueToVariable(jsonHasSupportedValueInfo, "hasSupportedValuesList",
+ /*optional=*/true,
+ &hasSupportedValueInfo.hasSupportedValuesList, errors);
+ areaConfig.hasSupportedValueInfo = std::move(hasSupportedValueInfo);
+ }
+
+ config->config.areaConfigs.push_back(std::move(areaConfig));
+
+ RawPropValues areaValue = {};
+ if (parsePropValues(jsonAreaConfig, "defaultValue", &areaValue, errors)) {
+ config->initialAreaValues[areaId] = std::move(areaValue);
+ }
+ }
+}
+
+std::optional<ConfigDeclaration> JsonConfigParser::parseEachProperty(
+ const Json::Value& propJsonValue, std::vector<std::string>* 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<VehicleProperty>(propId));
+ if (itAccess != AccessForVehicleProperty.end()) {
+ defaultAccessMode = &itAccess->second;
+ }
+ VehiclePropertyChangeMode* defaultChangeMode = NULL;
+ auto itChangeMode = ChangeModeForVehicleProperty.find(static_cast<VehicleProperty>(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<std::unordered_map<int32_t, ConfigDeclaration>> JsonConfigParser::parseJsonConfig(
+ std::istream& is) {
+ Json::CharReaderBuilder builder;
+ Json::Value root;
+ std::unordered_map<int32_t, ConfigDeclaration> 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<std::string> 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<jsonconfigloader_impl::JsonConfigParser>();
+}
+
+android::base::Result<std::unordered_map<int32_t, ConfigDeclaration>>
+JsonConfigLoader::loadPropConfig(std::istream& is) {
+ return mParser->parseJsonConfig(is);
+}
+
+android::base::Result<std::unordered_map<int32_t, ConfigDeclaration>>
+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 0000000..595c2ed
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/current/default_config/JsonConfigLoader/test/JsonConfigLoaderUnitTest.cpp
@@ -0,0 +1,912 @@
+/*
+ * 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 <JsonConfigLoader.h>
+
+#include <PropertyUtils.h>
+
+#include <gtest/gtest.h>
+#include <sstream>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+using ::aidl::android::hardware::automotive::vehicle::HasSupportedValueInfo;
+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<int>({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<int>({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<int32_t>({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<int32_t>({1, FUEL_DOOR_REAR_LEFT}));
+ ASSERT_EQ(initialValue.int64Values,
+ std::vector<int64_t>({2, static_cast<int64_t>(FUEL_DOOR_REAR_LEFT)}));
+ ASSERT_EQ(initialValue.floatValues,
+ std::vector<float>({3.0, static_cast<float>(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<int64_t>({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);
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testHasSupportedValueInfo_allTrue) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::CABIN_LIGHTS_SWITCH",
+ "areas": [{
+ "access": "VehiclePropertyAccess::WRITE",
+ "areaId": 0,
+ "hasSupportedValueInfo": {
+ "hasMinSupportedValue": true,
+ "hasMaxSupportedValue": true,
+ "hasSupportedValuesList": true
+ }
+ }],
+ "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.hasSupportedValueInfo, HasSupportedValueInfo({
+ .hasMinSupportedValue = true,
+ .hasMaxSupportedValue = true,
+ .hasSupportedValuesList = true,
+ }));
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testHasSupportedValueInfo_allFalse) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::CABIN_LIGHTS_SWITCH",
+ "areas": [{
+ "access": "VehiclePropertyAccess::WRITE",
+ "areaId": 0,
+ "hasSupportedValueInfo": {
+ "hasMinSupportedValue": false,
+ "hasMaxSupportedValue": false,
+ "hasSupportedValuesList": false
+ }
+ }],
+ "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.hasSupportedValueInfo, HasSupportedValueInfo({
+ .hasMinSupportedValue = false,
+ .hasMaxSupportedValue = false,
+ .hasSupportedValuesList = false,
+ }));
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testHasSupportedValueInfo_unspecified) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::CABIN_LIGHTS_SWITCH",
+ "areas": [{
+ "access": "VehiclePropertyAccess::WRITE",
+ "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.hasSupportedValueInfo, std::nullopt);
+}
+
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/vehicle/aidl/impl/default_config/TEST_MAPPING b/automotive/vehicle/aidl/impl/current/default_config/TEST_MAPPING
similarity index 100%
copy from automotive/vehicle/aidl/impl/default_config/TEST_MAPPING
copy to automotive/vehicle/aidl/impl/current/default_config/TEST_MAPPING
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 0000000..86ac92e
--- /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/default_config/config/README.md b/automotive/vehicle/aidl/impl/current/default_config/config/README.md
similarity index 100%
copy from automotive/vehicle/aidl/impl/default_config/config/README.md
copy to automotive/vehicle/aidl/impl/current/default_config/config/README.md
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 0000000..83debf7
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/current/default_config/config/TestProperties.json
@@ -0,0 +1,212 @@
+{
+ "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": [
+ 2
+ ]
+ },
+ "areaId": "VehicleAreaWindow::FRONT_WINDSHIELD",
+ "hasSupportedValueInfo": {
+ "hasMinSupportedValue": true,
+ "hasMaxSupportedValue": true,
+ "hasSupportedValuesList": true
+ }
+ },
+ {
+ "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/default_config/config/VendorClusterTestProperties.json b/automotive/vehicle/aidl/impl/current/default_config/config/VendorClusterTestProperties.json
similarity index 100%
copy from automotive/vehicle/aidl/impl/default_config/config/VendorClusterTestProperties.json
copy to automotive/vehicle/aidl/impl/current/default_config/config/VendorClusterTestProperties.json
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/default_config/test/DefaultConfigTest.cpp b/automotive/vehicle/aidl/impl/current/default_config/test/DefaultConfigTest.cpp
similarity index 100%
copy from automotive/vehicle/aidl/impl/default_config/test/DefaultConfigTest.cpp
copy to automotive/vehicle/aidl/impl/current/default_config/test/DefaultConfigTest.cpp
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/fake_impl/GeneratorHub/include/FakeValueGenerator.h b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/include/FakeValueGenerator.h
similarity index 100%
copy from automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/FakeValueGenerator.h
copy to automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/include/FakeValueGenerator.h
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/GeneratorHub.h b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/include/GeneratorHub.h
similarity index 100%
copy from automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/GeneratorHub.h
copy to automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/include/GeneratorHub.h
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/JsonFakeValueGenerator.h b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/include/JsonFakeValueGenerator.h
similarity index 100%
copy from automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/JsonFakeValueGenerator.h
copy to automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/include/JsonFakeValueGenerator.h
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/LinearFakeValueGenerator.h b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/include/LinearFakeValueGenerator.h
similarity index 100%
copy from automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/LinearFakeValueGenerator.h
copy to automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/include/LinearFakeValueGenerator.h
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/GeneratorHub.cpp b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/src/GeneratorHub.cpp
similarity index 100%
copy from automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/GeneratorHub.cpp
copy to automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/src/GeneratorHub.cpp
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/JsonFakeValueGenerator.cpp b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/src/JsonFakeValueGenerator.cpp
similarity index 100%
copy from automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/JsonFakeValueGenerator.cpp
copy to automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/src/JsonFakeValueGenerator.cpp
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/LinearFakeValueGenerator.cpp b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/src/LinearFakeValueGenerator.cpp
similarity index 100%
copy from automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/LinearFakeValueGenerator.cpp
copy to automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/src/LinearFakeValueGenerator.cpp
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/fake_impl/GeneratorHub/test/FakeVehicleHalValueGeneratorsTest.cpp b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/test/FakeVehicleHalValueGeneratorsTest.cpp
similarity index 100%
copy from automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/FakeVehicleHalValueGeneratorsTest.cpp
copy to automotive/vehicle/aidl/impl/current/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/current/fake_impl/GeneratorHub/test/prop.json
similarity index 100%
copy from automotive/vehicle/aidl/impl/fake_impl/hardware/test/fakedata/prop.json
copy to automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/test/prop.json
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 0000000..38cd86b
--- /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/fake_impl/GeneratorHub/test/prop_invalid.json b/automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/test/prop_invalid.json
similarity index 100%
copy from automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/prop_invalid.json
copy to automotive/vehicle/aidl/impl/current/fake_impl/GeneratorHub/test/prop_invalid.json
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 0000000..b7ada62
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/current/fake_impl/hardware/include/FakeVehicleHardware.h
@@ -0,0 +1,353 @@
+/*
+ * 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 <ConcurrentQueue.h>
+#include <ConfigDeclaration.h>
+#include <FakeObd2Frame.h>
+#include <FakeUserHal.h>
+#include <GeneratorHub.h>
+#include <IVehicleHardware.h>
+#include <JsonConfigLoader.h>
+#include <RecurrentTimer.h>
+#include <VehicleHalTypes.h>
+#include <VehiclePropertyStore.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleHwKeyInputAction.h>
+#include <android-base/parseint.h>
+#include <android-base/result.h>
+#include <android-base/stringprintf.h>
+#include <android-base/thread_annotations.h>
+#include <grpc++/grpc++.h>
+#include <wakeup_client.grpc.pb.h>
+
+#include <memory>
+#include <mutex>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+
+class FakeVehicleHardware : public IVehicleHardware {
+ public:
+ using ValueResultType = VhalResult<VehiclePropValuePool::RecyclableType>;
+
+ 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<aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
+ 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<const SetValuesCallback> callback,
+ const std::vector<aidl::android::hardware::automotive::vehicle::SetValueRequest>&
+ 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<const GetValuesCallback> callback,
+ const std::vector<aidl::android::hardware::automotive::vehicle::GetValueRequest>&
+ requests) const override;
+
+ // Dump debug information in the server.
+ DumpResult dump(const std::vector<std::string>& 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<const PropertyChangeCallback> callback) override;
+
+ // Register a callback that would be called when there is a property set error event from
+ // vehicle.
+ void registerOnPropertySetErrorEvent(
+ std::unique_ptr<const PropertySetErrorCallback> 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;
+
+ std::vector<aidlvhal::MinMaxSupportedValueResult> getMinMaxSupportedValues(
+ const std::vector<PropIdAreaId>& propIdAreaIds) override;
+
+ std::vector<aidlvhal::SupportedValuesListResult> getSupportedValuesLists(
+ const std::vector<PropIdAreaId>& propIdAreaIds) override;
+
+ protected:
+ // mValuePool is also used in mServerSidePropStore.
+ const std::shared_ptr<VehiclePropValuePool> mValuePool;
+ const std::shared_ptr<VehiclePropertyStore> mServerSidePropStore;
+
+ const std::string mDefaultConfigDir;
+ const std::string mOverrideConfigDir;
+
+ ValueResultType getValue(
+ const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const;
+
+ VhalResult<void> setValue(
+ const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
+
+ bool UseOverrideConfigDir();
+
+ private:
+ // Expose private methods to unit test.
+ friend class FakeVehicleHardwareTestHelper;
+
+ template <class CallbackType, class RequestType>
+ struct RequestWithCallback {
+ RequestType request;
+ std::shared_ptr<const CallbackType> callback;
+ };
+
+ template <class CallbackType, class RequestType>
+ class PendingRequestHandler {
+ public:
+ PendingRequestHandler(FakeVehicleHardware* hardware);
+
+ void addRequest(RequestType request, std::shared_ptr<const CallbackType> callback);
+
+ void stop();
+
+ private:
+ FakeVehicleHardware* mHardware;
+ std::thread mThread;
+ ConcurrentQueue<RequestWithCallback<CallbackType, RequestType>> mRequests;
+
+ void handleRequestsOnce();
+ };
+
+ struct RefreshInfo {
+ VehiclePropertyStore::EventMode eventMode;
+ int64_t intervalInNanos;
+ };
+
+ struct ActionForInterval {
+ std::unordered_set<PropIdAreaId, PropIdAreaIdHash> propIdAreaIdsToRefresh;
+ std::shared_ptr<RecurrentTimer::Callback> recurrentAction;
+ };
+
+ const std::unique_ptr<obd2frame::FakeObd2Frame> mFakeObd2Frame;
+ const std::unique_ptr<FakeUserHal> mFakeUserHal;
+ // RecurrentTimer is thread-safe.
+ std::unique_ptr<RecurrentTimer> mRecurrentTimer;
+ // GeneratorHub is thread-safe.
+ std::unique_ptr<GeneratorHub> mGeneratorHub;
+
+ // Only allowed to set once.
+ std::unique_ptr<const PropertyChangeCallback> mOnPropertyChangeCallback;
+ std::unique_ptr<const PropertySetErrorCallback> mOnPropertySetErrorCallback;
+
+ std::mutex mLock;
+ std::unordered_map<PropIdAreaId, RefreshInfo, PropIdAreaIdHash> mRefreshInfoByPropIdAreaId
+ GUARDED_BY(mLock);
+ std::unordered_map<int64_t, ActionForInterval> mActionByIntervalInNanos GUARDED_BY(mLock);
+ std::unordered_map<PropIdAreaId, VehiclePropValuePool::RecyclableType, PropIdAreaIdHash>
+ mSavedProps GUARDED_BY(mLock);
+ std::unordered_set<PropIdAreaId, PropIdAreaIdHash> mSubOnChangePropIdAreaIds GUARDED_BY(mLock);
+ // PendingRequestHandler is thread-safe.
+ mutable PendingRequestHandler<GetValuesCallback,
+ aidl::android::hardware::automotive::vehicle::GetValueRequest>
+ mPendingGetValueRequests;
+ mutable PendingRequestHandler<SetValuesCallback,
+ aidl::android::hardware::automotive::vehicle::SetValueRequest>
+ mPendingSetValueRequests;
+
+ // Set of HVAC properties dependent on HVAC_POWER_ON
+ std::unordered_set<int32_t> 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<aidl::android::hardware::automotive::vehicle::VehiclePropValue> 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<int32_t, ConfigDeclaration>* 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<int>& hvacTemperatureSetConfigArray,
+ std::vector<float>* hvacTemperatureValueSuggestionInput);
+ VhalResult<void> setHvacTemperatureValueSuggestion(
+ const aidl::android::hardware::automotive::vehicle::VehiclePropValue&
+ hvacTemperatureValueSuggestion);
+ VhalResult<void> maybeSetSpecialValue(
+ const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value,
+ bool* isSpecialValue);
+ VhalResult<bool> isCruiseControlTypeStandard() const;
+ ValueResultType maybeGetSpecialValue(
+ const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value,
+ bool* isSpecialValue) const;
+ VhalResult<void> setApPowerStateReport(
+ const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
+ VhalResult<void> 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<void> 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<void> isAdasPropertyAvailable(int32_t adasStatePropertyId) const;
+ VhalResult<void> synchronizeHvacTemp(int32_t hvacDualOnAreaId,
+ std::optional<float> newTempC) const;
+ std::optional<int32_t> 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<int32_t, ConfigDeclaration> 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<std::string>& options);
+ std::string dumpSetProperties(const std::vector<std::string>& options);
+ std::string dumpGetPropertyWithArg(const std::vector<std::string>& options);
+ std::string dumpSaveProperty(const std::vector<std::string>& options);
+ std::string dumpRestoreProperty(const std::vector<std::string>& options);
+ std::string dumpInjectEvent(const std::vector<std::string>& options);
+ std::string dumpSubscriptions();
+
+ std::vector<std::string> getOptionValues(const std::vector<std::string>& options,
+ size_t* index);
+ android::base::Result<aidl::android::hardware::automotive::vehicle::VehiclePropValue>
+ parsePropOptions(const std::vector<std::string>& options);
+ android::base::Result<std::vector<uint8_t>> parseHexString(const std::string& s);
+
+ android::base::Result<void> checkArgumentsSize(const std::vector<std::string>& 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<std::string>& options);
+ void sendHvacPropertiesCurrentValues(int32_t areaId, int32_t hvacPowerOnVal);
+ void sendAdasPropertiesState(int32_t propertyId, int32_t state);
+ void generateVendorConfigs(
+ std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropConfig>&) 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 <typename T>
+ static android::base::Result<T> 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<float> safelyParseFloat(int index, const std::string& s);
+ static android::base::Result<int32_t> parsePropId(const std::vector<std::string>& options,
+ size_t index);
+ static android::base::Result<int32_t> parseAreaId(const std::vector<std::string>& 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/current/fake_impl/hardware/src/FakeVehicleHardware.cpp b/automotive/vehicle/aidl/impl/current/fake_impl/hardware/src/FakeVehicleHardware.cpp
new file mode 100644
index 0000000..f1aaefc
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/current/fake_impl/hardware/src/FakeVehicleHardware.cpp
@@ -0,0 +1,2675 @@
+/*
+ * 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 <FakeObd2Frame.h>
+#include <JsonFakeValueGenerator.h>
+#include <LinearFakeValueGenerator.h>
+#include <PropertyUtils.h>
+#include <VehicleHalTypes.h>
+#include <VehicleUtils.h>
+
+#include <android-base/file.h>
+#include <android-base/parsedouble.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <android/hardware/automotive/vehicle/TestVendorProperty.h>
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+#include <utils/Trace.h>
+
+#include <dirent.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <regex>
+#include <unordered_set>
+#include <vector>
+
+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::MinMaxSupportedValueResult;
+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::SupportedValuesListResult;
+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/";
+// 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<std::string> 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<int32_t, std::vector<int32_t>> 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<int32_t> 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<int32_t>& 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<VehiclePropValuePool>()),
+ 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<int32_t, ConfigDeclaration> FakeVehicleHardware::loadConfigDeclarations() {
+ std::unordered_map<int32_t, ConfigDeclaration> 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<VehiclePropValue> values) {
+ return onValuesChangeCallback(std::move(values));
+ });
+}
+
+std::vector<VehiclePropConfig> FakeVehicleHardware::getAllPropertyConfigs() const {
+ std::vector<VehiclePropConfig> 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<void> 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<void> 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<float>(increment));
+ return numIncrements;
+}
+
+void FakeVehicleHardware::updateHvacTemperatureValueSuggestionInput(
+ const std::vector<int>& hvacTemperatureSetConfigArray,
+ std::vector<float>* 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<int>((*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<float>(suggestedTempInCelsius) / 10.0f;
+ (*hvacTemperatureValueSuggestionInput)[3] =
+ static_cast<float>(suggestedTempInFahrenheit) / 10.0f;
+}
+
+VhalResult<void> 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<void> 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<void> 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<void> FakeVehicleHardware::synchronizeHvacTemp(int32_t hvacDualOnAreaId,
+ std::optional<float> 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<float> 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<int32_t> 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<bool> 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<void> 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<uint8_t> 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<void> 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<void> isAdasPropertyAvailableResult;
+ VhalResult<bool> 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<const SetValuesCallback> callback,
+ const std::vector<SetValueRequest>& 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<void> 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<const GetValuesCallback> callback,
+ const std::vector<GetValueRequest>& 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<std::string>& 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<VehiclePropConfig>& 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<std::string>& 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<LinearFakeValueGenerator>(
+ 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<JsonFakeValueGenerator> generator;
+ if (options[2] == "--path") {
+ const std::string& fileName = options[3];
+ generator = std::make_unique<JsonFakeValueGenerator>(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<JsonFakeValueGenerator>(/*unused=*/true, content, repetition);
+ if (!generator->hasNext()) {
+ return "invalid JSON content, no events";
+ }
+ }
+ int32_t cookie = std::hash<std::string>()(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<int> 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<float> 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<std::mutex> 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_1> [PROP_ID_2] [PROP_ID_N]: dumps the value of specific properties. \n"
+ "--getWithArg <PROP_ID> [ValueArguments]: gets the value for a specific property. "
+ "The value arguments constructs a VehiclePropValue used in the getValue request. \n"
+ "--set <PROP_ID> [ValueArguments]: sets the value of property PROP_ID, the value "
+ "arguments constructs a VehiclePropValue used in the setValue request. \n"
+ "--save-prop <PROP_ID> [-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 <PROP_ID> [-a AREA_ID]: restores a previously saved property value. \n"
+ "--inject-event <PROP_ID> [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<int32_t> 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<void> FakeVehicleHardware::checkArgumentsSize(const std::vector<std::string>& 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<int32_t> FakeVehicleHardware::parsePropId(const std::vector<std::string>& options,
+ size_t index) {
+ const std::string& propIdStr = options[index];
+ auto result = stringToPropId(propIdStr);
+ if (result.ok()) {
+ return result;
+ }
+ return safelyParseInt<int32_t>(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<int32_t> FakeVehicleHardware::parseAreaId(const std::vector<std::string>& options,
+ size_t index, int32_t propId) {
+ const std::string& areaIdStr = options[index];
+ auto result = safelyParseInt<int32_t>(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<std::string>& 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<std::string> FakeVehicleHardware::getOptionValues(
+ const std::vector<std::string>& options, size_t* index) {
+ std::vector<std::string> 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<VehiclePropValue> FakeVehicleHardware::parsePropOptions(
+ const std::vector<std::string>& 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<std::string> parsedOptions;
+ int32_t areaIdIndex = -1;
+
+ while (optionIndex < options.size()) {
+ std::string argType = options[optionIndex];
+ optionIndex++;
+
+ size_t currentIndex = optionIndex;
+ std::vector<std::string> 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<int32_t>(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<int64_t>(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<int64_t>(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<std::string>& 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<std::string>& 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<std::string>& 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<std::mutex> 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<std::string>& 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<std::mutex> 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<std::string>& 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<const PropertyChangeCallback> callback) {
+ if (mOnPropertyChangeCallback != nullptr) {
+ ALOGE("registerOnPropertyChangeEvent must only be called once");
+ return;
+ }
+ mOnPropertyChangeCallback = std::move(callback);
+}
+
+void FakeVehicleHardware::registerOnPropertySetErrorEvent(
+ std::unique_ptr<const PropertySetErrorCallback> 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<std::mutex> 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;
+}
+
+std::vector<MinMaxSupportedValueResult> FakeVehicleHardware::getMinMaxSupportedValues(
+ const std::vector<PropIdAreaId>& propIdAreaIds) {
+ std::vector<MinMaxSupportedValueResult> results;
+ // We only support VENDOR_EXTENSION_INT_PROPERTY
+ for (const auto& propIdAreaId : propIdAreaIds) {
+ int propId = propIdAreaId.propId;
+ int areaId = propIdAreaId.areaId;
+ if (propId != toInt(TestVendorProperty::VENDOR_EXTENSION_INT_PROPERTY)) {
+ results.push_back(MinMaxSupportedValueResult{
+ .status = StatusCode::INVALID_ARG,
+ });
+ continue;
+ }
+ results.push_back(MinMaxSupportedValueResult{
+ .status = StatusCode::OK,
+ .minSupportedValue =
+ RawPropValues{
+ .int32Values = {0},
+ },
+ .maxSupportedValue =
+ RawPropValues{
+ .int32Values = {10},
+ },
+ });
+ }
+ return results;
+}
+
+std::vector<SupportedValuesListResult> FakeVehicleHardware::getSupportedValuesLists(
+ const std::vector<PropIdAreaId>& propIdAreaIds) {
+ std::vector<SupportedValuesListResult> results;
+ // We only support VENDOR_EXTENSION_INT_PROPERTY
+ for (const auto& propIdAreaId : propIdAreaIds) {
+ int propId = propIdAreaId.propId;
+ int areaId = propIdAreaId.areaId;
+ if (propId != toInt(TestVendorProperty::VENDOR_EXTENSION_INT_PROPERTY)) {
+ results.push_back(SupportedValuesListResult{
+ .status = StatusCode::INVALID_ARG,
+ });
+ continue;
+ }
+ results.push_back(SupportedValuesListResult{
+ .status = StatusCode::OK,
+ .supportedValuesList = std::vector<std::optional<RawPropValues>>({
+ RawPropValues{.int32Values = {0}},
+ RawPropValues{.int32Values = {2}},
+ RawPropValues{.int32Values = {4}},
+ RawPropValues{.int32Values = {6}},
+ RawPropValues{.int32Values = {8}},
+ RawPropValues{.int32Values = {10}},
+ }),
+ });
+ }
+ return results;
+}
+
+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<PropIdAreaId, VehiclePropertyStore::EventMode, PropIdAreaIdHash>
+ eventModeByPropIdAreaId;
+
+ {
+ std::scoped_lock<std::mutex> 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<int64_t>(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<RecurrentTimer::Callback>(
+ [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<std::mutex> 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<VehiclePropValue> values) {
+ ATRACE_CALL();
+ std::vector<VehiclePropValue> subscribedUpdatedValues;
+
+ {
+ std::scoped_lock<std::mutex> 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<int32_t, ConfigDeclaration>* 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<float> 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<std::vector<uint8_t>> FakeVehicleHardware::parseHexString(const std::string& s) {
+ std::vector<uint8_t> 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 <class CallbackType, class RequestType>
+FakeVehicleHardware::PendingRequestHandler<CallbackType, RequestType>::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 <class CallbackType, class RequestType>
+void FakeVehicleHardware::PendingRequestHandler<CallbackType, RequestType>::addRequest(
+ RequestType request, std::shared_ptr<const CallbackType> callback) {
+ mRequests.push({
+ request,
+ callback,
+ });
+}
+
+template <class CallbackType, class RequestType>
+void FakeVehicleHardware::PendingRequestHandler<CallbackType, RequestType>::stop() {
+ mRequests.deactivate();
+ if (mThread.joinable()) {
+ mThread.join();
+ }
+}
+
+template <>
+void FakeVehicleHardware::PendingRequestHandler<FakeVehicleHardware::GetValuesCallback,
+ GetValueRequest>::handleRequestsOnce() {
+ std::unordered_map<std::shared_ptr<const GetValuesCallback>, std::vector<GetValueResult>>
+ 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<FakeVehicleHardware::SetValuesCallback,
+ SetValueRequest>::handleRequestsOnce() {
+ std::unordered_map<std::shared_ptr<const SetValuesCallback>, std::vector<SetValueResult>>
+ 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/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 0000000..29a690b
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/current/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
@@ -0,0 +1,3929 @@
+/*
+ * 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 <FakeVehicleHardware.h>
+
+#include <FakeObd2Frame.h>
+#include <FakeUserHal.h>
+#include <PropertyUtils.h>
+
+#include <aidl/android/hardware/automotive/vehicle/VehicleApPowerStateConfigFlag.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleApPowerStateShutdownParam.h>
+#include <android/hardware/automotive/vehicle/TestVendorProperty.h>
+
+#include <android-base/expected.h>
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
+#include <android-base/thread_annotations.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+
+#include <inttypes.h>
+#include <chrono>
+#include <condition_variable>
+#include <memory>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+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<int32_t, ConfigDeclaration> loadConfigDeclarations() {
+ return mHardware->loadConfigDeclarations();
+ }
+
+ std::unordered_set<int32_t> getHvacPowerDependentProps() {
+ return mHardware->hvacPowerDependentProps;
+ }
+
+ private:
+ FakeVehicleHardware* mHardware;
+};
+
+class FakeVehicleHardwareTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ mHardware = std::make_unique<FakeVehicleHardware>(android::base::GetExecutableDirectory(),
+ /*overrideConfigDir=*/"",
+ /*forceOverride=*/false);
+ auto callback = std::make_unique<IVehicleHardware::PropertyChangeCallback>(
+ [this](const std::vector<VehiclePropValue>& values) {
+ onPropertyChangeEvent(values);
+ });
+ getHardware()->registerOnPropertyChangeEvent(std::move(callback));
+ mSetValuesCallback = std::make_shared<IVehicleHardware::SetValuesCallback>(
+ [this](std::vector<SetValueResult> results) { onSetValues(results); });
+ mGetValuesCallback = std::make_shared<IVehicleHardware::GetValuesCallback>(
+ [this](std::vector<GetValueResult> 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<FakeVehicleHardware> 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<SetValueRequest>& requests) {
+ {
+ std::scoped_lock<std::mutex> 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<std::mutex> 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<GetValueRequest>& requests) {
+ {
+ std::scoped_lock<std::mutex> 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<std::mutex> 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<SetValueRequest> requests = {
+ SetValueRequest{
+ .requestId = 0,
+ .value = value,
+ },
+ };
+
+ if (StatusCode status = setValues(requests); status != StatusCode::OK) {
+ return status;
+ }
+
+ const SetValueResult& result = getSetValueResults().back();
+
+ if (result.requestId != 0) {
+ ALOGE("request ID mismatch, got %" PRId64 ", expect 0", result.requestId);
+ return StatusCode::INTERNAL_ERROR;
+ }
+
+ return result.status;
+ }
+
+ expected<VehiclePropValue, StatusCode> getValue(const VehiclePropValue& value) {
+ std::vector<GetValueRequest> requests = {
+ GetValueRequest{
+ .requestId = 0,
+ .prop = value,
+ },
+ };
+
+ if (StatusCode status = getValues(requests); status != StatusCode::OK) {
+ return unexpected(status);
+ }
+
+ const GetValueResult& result = getGetValueResults().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 <class T>
+ int getStatus(expected<T, StatusCode> result) {
+ return toInt(result.error());
+ }
+
+ void onSetValues(std::vector<SetValueResult> results) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ for (auto& result : results) {
+ mSetValueResults.push_back(result);
+ mPendingSetValueRequests.erase(result.requestId);
+ }
+ mCv.notify_all();
+ }
+
+ const std::vector<SetValueResult>& getSetValueResults() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ return mSetValueResults;
+ }
+
+ void onGetValues(std::vector<GetValueResult> results) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ for (auto& result : results) {
+ mGetValueResults.push_back(result);
+ mPendingGetValueRequests.erase(result.requestId);
+ }
+ mCv.notify_all();
+ }
+
+ const std::vector<GetValueResult>& getGetValueResults() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ return mGetValueResults;
+ }
+
+ void onPropertyChangeEvent(std::vector<VehiclePropValue> values) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ for (auto& value : values) {
+ mChangedProperties.push_back(value);
+ PropIdAreaId propIdAreaId{
+ .propId = value.prop,
+ .areaId = value.areaId,
+ };
+ mEventCount[propIdAreaId]++;
+ }
+ mCv.notify_all();
+ }
+
+ const std::vector<VehiclePropValue>& getChangedProperties() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ return mChangedProperties;
+ }
+
+ bool waitForChangedProperties(size_t count, milliseconds timeout) {
+ std::unique_lock<std::mutex> 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<std::mutex> lk(mLock);
+ return mCv.wait_for(lk, timeout, [this, propIdAreaId, count] {
+ ScopedLockAssertion lockAssertion(mLock);
+ return mEventCount[propIdAreaId] >= count;
+ });
+ }
+
+ void clearChangedProperties() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ mEventCount.clear();
+ mChangedProperties.clear();
+ }
+
+ size_t getEventCount(int32_t propId, int32_t areaId) {
+ PropIdAreaId propIdAreaId{
+ .propId = propId,
+ .areaId = areaId,
+ };
+ std::scoped_lock<std::mutex> 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<SetValueRequest>& requests,
+ std::vector<SetValueResult>& 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<GetValueRequest>& requests,
+ std::vector<GetValueResult>& 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<VehiclePropValue> 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<VehiclePropConfig> getVehiclePropConfig(int32_t propertyId) {
+ auto configs = mHardware->getAllPropertyConfigs();
+ for (auto& config : configs) {
+ if (config.prop == propertyId) {
+ auto ptr = std::make_unique<VehiclePropConfig>();
+ 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<VehiclePropConfig>(nullptr);
+ }
+
+ private:
+ std::unique_ptr<FakeVehicleHardware> mHardware;
+ std::shared_ptr<IVehicleHardware::SetValuesCallback> mSetValuesCallback;
+ std::shared_ptr<IVehicleHardware::GetValuesCallback> mGetValuesCallback;
+ std::condition_variable mCv;
+ std::mutex mLock;
+ std::unordered_map<PropIdAreaId, size_t, PropIdAreaIdHash> mEventCount GUARDED_BY(mLock);
+ std::vector<SetValueResult> mSetValueResults GUARDED_BY(mLock);
+ std::vector<GetValueResult> mGetValueResults GUARDED_BY(mLock);
+ std::vector<VehiclePropValue> mChangedProperties GUARDED_BY(mLock);
+ std::unordered_set<int64_t> mPendingSetValueRequests GUARDED_BY(mLock);
+ std::unordered_set<int64_t> mPendingGetValueRequests GUARDED_BY(mLock);
+};
+
+TEST_F(FakeVehicleHardwareTest, testGetAllPropertyConfigs) {
+ std::vector<VehiclePropConfig> configs = getHardware()->getAllPropertyConfigs();
+
+ FakeVehicleHardwareTestHelper helper(getHardware());
+ ASSERT_EQ(configs.size(), helper.loadConfigDeclarations().size());
+}
+
+TEST_F(FakeVehicleHardwareTest, testGetAllPropertyConfigs_defaultSupportVUR) {
+ std::vector<VehiclePropConfig> 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<GetValueRequest> getValueRequests;
+ std::vector<GetValueResult> 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<GetValueResult> 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<SetValueRequest> requests;
+ std::vector<SetValueResult> 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<SetValueRequest> requests;
+ std::vector<SetValueResult> 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<SetValueRequest> requests;
+ std::vector<SetValueResult> 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<VehiclePropValue> 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<SetValueRequest> setValueRequests;
+ std::vector<SetValueResult> 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<GetValueRequest> getValueRequests;
+ std::vector<GetValueResult> 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<GetValueResult> 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<SetValueRequest> setValueRequests;
+ std::vector<SetValueResult> 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<GetValueRequest> getValueRequests;
+ std::vector<GetValueResult> 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<GetValueRequest> getValueRequests;
+ std::vector<GetValueResult> 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<SetValueRequest> setValueRequests;
+ std::vector<SetValueResult> 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<GetValueRequest> 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<size_t>(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<size_t>(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<FakeVehicleHardware> hardware =
+ std::make_unique<FakeVehicleHardware>(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<size_t>(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<size_t>(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<FakeVehicleHardware> hardware =
+ std::make_unique<FakeVehicleHardware>(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<size_t>(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<FakeVehicleHardware> hardware =
+ std::make_unique<FakeVehicleHardware>(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<size_t>(1), result.value().value.int32Values.size());
+ ASSERT_EQ(4, result.value().value.int32Values[0]);
+}
+
+struct SetSpecialValueTestCase {
+ std::string name;
+ std::vector<VehiclePropValue> valuesToSet;
+ std::vector<VehiclePropValue> expectedValuesToGet;
+};
+
+std::vector<SetSpecialValueTestCase> 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<SetSpecialValueTestCase> {};
+
+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<VehiclePropValue> 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<FakeVehicleHardwareSpecialValuesTest::ParamType>& 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<VehiclePropValue> 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<size_t>(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<size_t>(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<size_t>(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<float> 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<int32_t, std::vector<int32_t>> 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<int32_t, std::vector<int32_t>> 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<int32_t> 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<VehiclePropValue> 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<int32_t, std::vector<int32_t>> 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<int32_t> 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<int32_t> expectedChangedPropIds(enabledToErrorStateProps.second.begin(),
+ enabledToErrorStateProps.second.end());
+ expectedChangedPropIds.insert(adasEnabledPropertyId);
+
+ std::unordered_set<int32_t> 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>({
+ 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<size_t>(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<size_t>(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<size_t>(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<size_t>(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<size_t>(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<size_t>(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<std::string> 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<std::string> 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<std::string> 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<std::string> 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<std::string> 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<std::string> 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<std::string> 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<size_t>(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<float>{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<int32_t>({1234}));
+}
+
+TEST_F(FakeVehicleHardwareTest, testDumpInvalidOptions) {
+ std::vector<std::string> 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<std::string> 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<std::string> options;
+ bool success;
+ std::string errorMsg = "";
+};
+
+class FakeVehicleHardwareSetPropTest : public FakeVehicleHardwareTest,
+ public testing::WithParamInterface<SetPropTestCase> {};
+
+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<SetPropTestCase> 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<FakeVehicleHardwareSetPropTest::ParamType>& 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<std::string> options;
+ std::string expectMsg;
+};
+
+class FakeVehicleHardwareOptionsTest : public FakeVehicleHardwareTest,
+ public testing::WithParamInterface<OptionsTestCase> {};
+
+std::vector<OptionsTestCase> 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<FakeVehicleHardwareOptionsTest::ParamType>& 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<std::string> 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<std::string> 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<std::string> 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<std::string> 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<std::string> 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<std::string> 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<std::string> 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<std::string> 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<std::string> 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<std::string> 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<uint8_t>({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<float> 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<float>(toInt(VehicleUnit::CELSIUS));
+ float FAHRENHEIT = static_cast<float>(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<size_t>(1));
+ events[0].timestamp = 0;
+
+ EXPECT_EQ(events[0], tc.expectedValuesToGet[0]);
+ clearChangedProperties();
+ }
+}
+
+TEST_F(FakeVehicleHardwareTest, testOverrideApPowerStateReqConfig) {
+ auto hardware = std::make_unique<FakeVehicleHardware>(
+ android::base::GetExecutableDirectory(),
+ /*overrideConfigDir=*/"",
+ /*forceOverride=*/false,
+ toInt(VehicleApPowerStateConfigFlag::ENABLE_DEEP_SLEEP_FLAG) |
+ toInt(VehicleApPowerStateConfigFlag::ENABLE_HIBERNATION_FLAG));
+
+ std::vector<VehiclePropConfig> 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;
+ }
+}
+
+TEST_F(FakeVehicleHardwareTest, testGetMinMaxSupportedValues) {
+ auto results = getHardware()->getMinMaxSupportedValues({
+ PropIdAreaId{.propId = toInt(TestVendorProperty::VENDOR_EXTENSION_INT_PROPERTY),
+ .areaId = 0},
+ PropIdAreaId{.propId = toInt(VehicleProperty::HVAC_TEMPERATURE_SET), .areaId = 0},
+ });
+
+ ASSERT_EQ(results.size(), 2u);
+ EXPECT_EQ(results[0].status, StatusCode::OK);
+ EXPECT_NE(results[0].minSupportedValue, std::nullopt);
+ EXPECT_EQ(results[0].minSupportedValue.value(), RawPropValues{.int32Values = {0}});
+ EXPECT_NE(results[0].maxSupportedValue, std::nullopt);
+ EXPECT_EQ(results[0].maxSupportedValue.value(), RawPropValues{.int32Values = {10}});
+ EXPECT_EQ(results[1].status, StatusCode::INVALID_ARG);
+}
+
+TEST_F(FakeVehicleHardwareTest, testGetSupportedValuesLists) {
+ auto results = getHardware()->getSupportedValuesLists({
+ PropIdAreaId{.propId = toInt(TestVendorProperty::VENDOR_EXTENSION_INT_PROPERTY),
+ .areaId = 0},
+ PropIdAreaId{.propId = toInt(VehicleProperty::HVAC_TEMPERATURE_SET), .areaId = 0},
+ });
+
+ ASSERT_EQ(results.size(), 2u);
+ EXPECT_EQ(results[0].status, StatusCode::OK);
+ EXPECT_NE(results[0].supportedValuesList, std::nullopt);
+ EXPECT_NE((results[0].supportedValuesList)->size(), 0u);
+ EXPECT_EQ(results[0].supportedValuesList.value(), std::vector<std::optional<RawPropValues>>({
+ RawPropValues{.int32Values = {0}},
+ RawPropValues{.int32Values = {2}},
+ RawPropValues{.int32Values = {4}},
+ RawPropValues{.int32Values = {6}},
+ RawPropValues{.int32Values = {8}},
+ RawPropValues{.int32Values = {10}},
+ }));
+ EXPECT_EQ(results[1].status, StatusCode::INVALID_ARG);
+}
+
+} // namespace fake
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/fakedata/prop.json b/automotive/vehicle/aidl/impl/current/fake_impl/hardware/test/fakedata/prop.json
similarity index 100%
copy from automotive/vehicle/aidl/impl/fake_impl/hardware/test/fakedata/prop.json
copy to automotive/vehicle/aidl/impl/current/fake_impl/hardware/test/fakedata/prop.json
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/override/gear_selection.json b/automotive/vehicle/aidl/impl/current/fake_impl/hardware/test/override/gear_selection.json
similarity index 100%
copy from automotive/vehicle/aidl/impl/fake_impl/hardware/test/override/gear_selection.json
copy to automotive/vehicle/aidl/impl/current/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/current/fake_impl/hardware/test/override/hvac_temperature_set.json
similarity index 100%
copy from automotive/vehicle/aidl/impl/fake_impl/hardware/test/override/hvac_temperature_set.json
copy to automotive/vehicle/aidl/impl/current/fake_impl/hardware/test/override/hvac_temperature_set.json
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/fake_impl/obd2frame/include/FakeObd2Frame.h b/automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/include/FakeObd2Frame.h
similarity index 100%
copy from automotive/vehicle/aidl/impl/fake_impl/obd2frame/include/FakeObd2Frame.h
copy to automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/include/FakeObd2Frame.h
diff --git a/automotive/vehicle/aidl/impl/fake_impl/obd2frame/include/Obd2SensorStore.h b/automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/include/Obd2SensorStore.h
similarity index 100%
copy from automotive/vehicle/aidl/impl/fake_impl/obd2frame/include/Obd2SensorStore.h
copy to automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/include/Obd2SensorStore.h
diff --git a/automotive/vehicle/aidl/impl/fake_impl/obd2frame/src/FakeObd2Frame.cpp b/automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/src/FakeObd2Frame.cpp
similarity index 100%
copy from automotive/vehicle/aidl/impl/fake_impl/obd2frame/src/FakeObd2Frame.cpp
copy to automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/src/FakeObd2Frame.cpp
diff --git a/automotive/vehicle/aidl/impl/fake_impl/obd2frame/src/Obd2SensorStore.cpp b/automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/src/Obd2SensorStore.cpp
similarity index 100%
copy from automotive/vehicle/aidl/impl/fake_impl/obd2frame/src/Obd2SensorStore.cpp
copy to automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/src/Obd2SensorStore.cpp
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/fake_impl/obd2frame/test/FakeObd2FrameTest.cpp b/automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/test/FakeObd2FrameTest.cpp
similarity index 100%
copy from automotive/vehicle/aidl/impl/fake_impl/obd2frame/test/FakeObd2FrameTest.cpp
copy to automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/test/FakeObd2FrameTest.cpp
diff --git a/automotive/vehicle/aidl/impl/fake_impl/obd2frame/test/Obd2SensorStoreTest.cpp b/automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/test/Obd2SensorStoreTest.cpp
similarity index 100%
copy from automotive/vehicle/aidl/impl/fake_impl/obd2frame/test/Obd2SensorStoreTest.cpp
copy to automotive/vehicle/aidl/impl/current/fake_impl/obd2frame/test/Obd2SensorStoreTest.cpp
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/fake_impl/userhal/include/FakeUserHal.h b/automotive/vehicle/aidl/impl/current/fake_impl/userhal/include/FakeUserHal.h
similarity index 100%
copy from automotive/vehicle/aidl/impl/fake_impl/userhal/include/FakeUserHal.h
copy to automotive/vehicle/aidl/impl/current/fake_impl/userhal/include/FakeUserHal.h
diff --git a/automotive/vehicle/aidl/impl/fake_impl/userhal/include/UserHalHelper.h b/automotive/vehicle/aidl/impl/current/fake_impl/userhal/include/UserHalHelper.h
similarity index 100%
copy from automotive/vehicle/aidl/impl/fake_impl/userhal/include/UserHalHelper.h
copy to automotive/vehicle/aidl/impl/current/fake_impl/userhal/include/UserHalHelper.h
diff --git a/automotive/vehicle/aidl/impl/fake_impl/userhal/include/UserHalTypes.h b/automotive/vehicle/aidl/impl/current/fake_impl/userhal/include/UserHalTypes.h
similarity index 100%
copy from automotive/vehicle/aidl/impl/fake_impl/userhal/include/UserHalTypes.h
copy to automotive/vehicle/aidl/impl/current/fake_impl/userhal/include/UserHalTypes.h
diff --git a/automotive/vehicle/aidl/impl/fake_impl/userhal/src/FakeUserHal.cpp b/automotive/vehicle/aidl/impl/current/fake_impl/userhal/src/FakeUserHal.cpp
similarity index 100%
copy from automotive/vehicle/aidl/impl/fake_impl/userhal/src/FakeUserHal.cpp
copy to automotive/vehicle/aidl/impl/current/fake_impl/userhal/src/FakeUserHal.cpp
diff --git a/automotive/vehicle/aidl/impl/fake_impl/userhal/src/UserHalHelper.cpp b/automotive/vehicle/aidl/impl/current/fake_impl/userhal/src/UserHalHelper.cpp
similarity index 100%
copy from automotive/vehicle/aidl/impl/fake_impl/userhal/src/UserHalHelper.cpp
copy to automotive/vehicle/aidl/impl/current/fake_impl/userhal/src/UserHalHelper.cpp
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/fake_impl/userhal/test/UserHalHelper_test.cpp b/automotive/vehicle/aidl/impl/current/fake_impl/userhal/test/UserHalHelper_test.cpp
similarity index 100%
copy from automotive/vehicle/aidl/impl/fake_impl/userhal/test/UserHalHelper_test.cpp
copy to automotive/vehicle/aidl/impl/current/fake_impl/userhal/test/UserHalHelper_test.cpp
diff --git a/automotive/vehicle/aidl/impl/current/grpc/Android.bp b/automotive/vehicle/aidl/impl/current/grpc/Android.bp
new file mode 100644
index 0000000..f798b72
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/current/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",
+ tools: [
+ "aprotoc",
+ "protoc-gen-grpc-cpp-plugin",
+ ],
+ 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",
+ ":VehicleHalProtoFiles",
+ ],
+ out: [
+ "VehicleServer.pb.h",
+ "VehicleServer.grpc.pb.h",
+ "VehicleServer_mock.grpc.pb.h",
+ ],
+ visibility: ["//visibility:private"],
+}
+
+genrule {
+ name: "VehicleServerProtoStub_cc@default-grpc",
+ tools: [
+ "aprotoc",
+ "protoc-gen-grpc-cpp-plugin",
+ ],
+ 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",
+ ":VehicleHalProtoFiles",
+ ],
+ out: [
+ "VehicleServer.pb.cc",
+ "VehicleServer.grpc.pb.cc",
+ ],
+ visibility: ["//visibility:private"],
+}
+
+cc_library_static {
+ name: "android.hardware.automotive.vehicle@default-grpc-libgrpc",
+ vendor: true,
+ host_supported: true,
+ include_dirs: [
+ "external/protobuf/src",
+ ],
+ generated_headers: [
+ "VehicleServerProtoStub_h@default-grpc",
+ ],
+ export_generated_headers: [
+ "VehicleServerProtoStub_h@default-grpc",
+ ],
+ generated_sources: [
+ "VehicleServerProtoStub_cc@default-grpc",
+ ],
+ whole_static_libs: [
+ "VehicleHalProtos",
+ ],
+ shared_libs: [
+ "libgrpc++",
+ ],
+ cflags: [
+ "-Wno-unused-parameter",
+ ],
+}
+
+cc_library_static {
+ name: "android.hardware.automotive.vehicle@default-grpc-hardware-lib",
+ defaults: ["VehicleHalDefaults"],
+ vendor: true,
+ srcs: [
+ "GRPCVehicleHardware.cpp",
+ ],
+ whole_static_libs: [
+ "android.hardware.automotive.vehicle@default-grpc-libgrpc",
+ "VehicleHalProtoMessageConverter",
+ ],
+ header_libs: [
+ "IVehicleHardware",
+ ],
+ 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",
+ defaults: ["VehicleHalDefaults"],
+ vendor: true,
+ srcs: [
+ "GRPCVehicleProxyServer.cpp",
+ ],
+ whole_static_libs: [
+ "android.hardware.automotive.vehicle@default-grpc-libgrpc",
+ "VehicleHalProtoMessageConverter",
+ ],
+ header_libs: [
+ "IVehicleHardware",
+ ],
+ 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/current/grpc/GRPCVehicleHardware.cpp
similarity index 100%
copy from automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.cpp
copy to automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleHardware.cpp
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 0000000..ad2f512
--- /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 <IVehicleHardware.h>
+#include <VehicleHalTypes.h>
+#include <VehicleUtils.h>
+#include <android-base/result.h>
+#include <android-base/thread_annotations.h>
+
+#include "VehicleServer.grpc.pb.h"
+#include "VehicleServer.pb.h"
+
+#include <grpc++/grpc++.h>
+
+#include <atomic>
+#include <chrono>
+#include <condition_variable>
+#include <memory>
+#include <shared_mutex>
+#include <string>
+#include <thread>
+#include <unordered_map>
+#include <vector>
+
+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<aidlvhal::VehiclePropConfig> getAllPropertyConfigs() const override;
+
+ // Get the config for the specified propId.
+ std::optional<aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
+ 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<const SetValuesCallback> callback,
+ const std::vector<aidlvhal::SetValueRequest>& 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<const GetValuesCallback> callback,
+ const std::vector<aidlvhal::GetValueRequest>& requests) const override;
+
+ // Dump debug information in the server.
+ DumpResult dump(const std::vector<std::string>& 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<const PropertyChangeCallback> callback) override;
+
+ // Register a callback that would be called when there is a property set error event from
+ // vehicle.
+ void registerOnPropertySetErrorEvent(
+ std::unique_ptr<const PropertySetErrorCallback> 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<const PropertyChangeCallback> mOnPropChange;
+
+ private:
+ friend class GRPCVehicleHardwareUnitTest;
+
+ std::string mServiceAddr;
+ std::shared_ptr<::grpc::Channel> mGrpcChannel;
+ std::unique_ptr<proto::VehicleServer::StubInterface> mGrpcStub;
+ std::thread mValuePollingThread;
+
+ std::unique_ptr<const PropertySetErrorCallback> mOnSetErr;
+
+ std::mutex mShutdownMutex;
+ std::condition_variable mShutdownCV;
+ std::atomic<bool> 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<PropIdAreaId, std::pair<int64_t, int64_t>, PropIdAreaIdHash>
+ mLatestUpdateTimestamps GUARDED_BY(mLatestUpdateTimestampsMutex);
+
+ // Only used for unit testing.
+ GRPCVehicleHardware(std::unique_ptr<proto::VehicleServer::StubInterface> stub,
+ bool startValuePollingLoop);
+
+ void ValuePollingLoop();
+ void pollValue();
+
+ aidlvhal::StatusCode getValuesWithRetry(const std::vector<aidlvhal::GetValueRequest>& requests,
+ std::vector<aidlvhal::GetValueResult>* 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 0000000..927a595
--- /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 <grpc++/grpc++.h>
+
+#include <android-base/logging.h>
+
+#include <algorithm>
+#include <condition_variable>
+#include <mutex>
+#include <unordered_set>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::automotive::vehicle::virtualization {
+
+std::atomic<uint64_t> 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<IVehicleHardware>&& hardware)
+ : GrpcVehicleProxyServer(std::vector<std::string>({serverAddr}), std::move(hardware)) {};
+
+GrpcVehicleProxyServer::GrpcVehicleProxyServer(std::vector<std::string> serverAddrs,
+ std::unique_ptr<IVehicleHardware>&& hardware)
+ : mServiceAddrs(std::move(serverAddrs)), mHardware(std::move(hardware)) {
+ mHardware->registerOnPropertyChangeEvent(
+ std::make_unique<const IVehicleHardware::PropertyChangeCallback>(
+ [this](std::vector<aidlvhal::VehiclePropValue> values) {
+ OnVehiclePropChange(values);
+ }));
+}
+
+::grpc::Status GrpcVehicleProxyServer::GetAllPropertyConfig(
+ ::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
+ ::grpc::ServerWriter<proto::VehiclePropConfig>* 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<aidlvhal::SetValueRequest> aidlRequests;
+ std::unordered_set<int64_t> 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<std::mutex>();
+ auto waitCV = std::make_shared<std::condition_variable>();
+ auto complete = std::make_shared<bool>(false);
+ auto tmpResults = std::make_shared<proto::SetValueResults>();
+ auto aidlStatus = mHardware->setValues(
+ std::make_shared<const IVehicleHardware::SetValuesCallback>(
+ [waitMtx, waitCV, complete, tmpResults,
+ &requestIds](std::vector<aidlvhal::SetValueResult> 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<proto::StatusCode>(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<aidlvhal::GetValueRequest> aidlRequests;
+ std::unordered_set<int64_t> 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<std::mutex>();
+ auto waitCV = std::make_shared<std::condition_variable>();
+ auto complete = std::make_shared<bool>(false);
+ auto tmpResults = std::make_shared<proto::GetValueResults>();
+ auto aidlStatus = mHardware->getValues(
+ std::make_shared<const IVehicleHardware::GetValuesCallback>(
+ [waitMtx, waitCV, complete, tmpResults,
+ &requestIds](std::vector<aidlvhal::GetValueResult> 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<proto::StatusCode>(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<proto::StatusCode>(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<proto::StatusCode>(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<proto::StatusCode>(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<proto::StatusCode>(mHardware->checkHealth()));
+ return ::grpc::Status::OK;
+}
+
+::grpc::Status GrpcVehicleProxyServer::Dump(::grpc::ServerContext* context,
+ const proto::DumpOptions* options,
+ proto::DumpResult* result) {
+ std::vector<std::string> 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<proto::VehiclePropValues>* stream) {
+ auto conn = std::make_shared<ConnectionDescriptor>(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<aidlvhal::VehiclePropValue>& values) {
+ std::unordered_set<uint64_t> 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/grpc/GRPCVehicleProxyServer.h b/automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleProxyServer.h
similarity index 100%
copy from automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.h
copy to automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleProxyServer.h
diff --git a/automotive/vehicle/aidl/impl/grpc/proto/VehicleServer.proto b/automotive/vehicle/aidl/impl/current/grpc/proto/VehicleServer.proto
similarity index 100%
copy from automotive/vehicle/aidl/impl/grpc/proto/VehicleServer.proto
copy to automotive/vehicle/aidl/impl/current/grpc/proto/VehicleServer.proto
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/grpc/test/GRPCVehicleHardwareUnitTest.cpp b/automotive/vehicle/aidl/impl/current/grpc/test/GRPCVehicleHardwareUnitTest.cpp
similarity index 100%
copy from automotive/vehicle/aidl/impl/grpc/test/GRPCVehicleHardwareUnitTest.cpp
copy to automotive/vehicle/aidl/impl/current/grpc/test/GRPCVehicleHardwareUnitTest.cpp
diff --git a/automotive/vehicle/aidl/impl/grpc/test/GRPCVehicleProxyServerUnitTest.cpp b/automotive/vehicle/aidl/impl/current/grpc/test/GRPCVehicleProxyServerUnitTest.cpp
similarity index 100%
copy from automotive/vehicle/aidl/impl/grpc/test/GRPCVehicleProxyServerUnitTest.cpp
copy to automotive/vehicle/aidl/impl/current/grpc/test/GRPCVehicleProxyServerUnitTest.cpp
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/grpc/utils/proto_message_converter/include/ProtoMessageConverter.h b/automotive/vehicle/aidl/impl/current/grpc/utils/proto_message_converter/include/ProtoMessageConverter.h
similarity index 100%
copy from automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/include/ProtoMessageConverter.h
copy to automotive/vehicle/aidl/impl/current/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/current/grpc/utils/proto_message_converter/src/ProtoMessageConverter.cpp
similarity index 100%
copy from automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/src/ProtoMessageConverter.cpp
copy to automotive/vehicle/aidl/impl/current/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/current/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp
similarity index 100%
copy from automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp
copy to automotive/vehicle/aidl/impl/current/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp
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 0000000..9122955
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/current/hardware/include/IVehicleHardware.h
@@ -0,0 +1,337 @@
+/*
+ * 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 <VehicleHalTypes.h>
+#include <VehicleUtils.h>
+
+#include <memory>
+#include <optional>
+#include <unordered_set>
+#include <vector>
+
+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<void(std::vector<aidlvhal::SetValueResult>)>;
+ using GetValuesCallback = std::function<void(std::vector<aidlvhal::GetValueResult>)>;
+ using PropertyChangeCallback = std::function<void(std::vector<aidlvhal::VehiclePropValue>)>;
+ using PropertySetErrorCallback = std::function<void(std::vector<SetValueErrorEvent>)>;
+ using SupportedValueChangeCallback = std::function<void(std::vector<PropIdAreaId>)>;
+
+ virtual ~IVehicleHardware() = default;
+
+ // Get all the property configs.
+ //
+ // Note that {@code VehicleAreaConfig.HasSupportedValueInfo} field is newly introduced in VHAL
+ // V4 to specify whether the [propertyId, areaId] has specified min/max supported value or
+ // supported values list.
+ //
+ // Since IVehicleHardware is designed to be backward compatible, this field can be set to null.
+ // If this field is set to null, VHAL client should fallback to use min/max supported value
+ // information in {@code VehicleAreaConfig} and {@code supportedEnumVaules} for enum properties.
+ //
+ // It is highly recommended to specify {@code VehicleAreaConfig.HasSupportedValueInfo} for new
+ // property implementations, even if the property does not specify supported values or the
+ // supported values are static.
+ virtual std::vector<aidlvhal::VehiclePropConfig> 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<aidlvhal::VehiclePropConfig> 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<const SetValuesCallback> callback,
+ const std::vector<aidlvhal::SetValueRequest>& 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<const GetValuesCallback> callback,
+ const std::vector<aidl::android::hardware::automotive::vehicle::GetValueRequest>&
+ requests) const = 0;
+
+ // Dump debug information in the server.
+ virtual DumpResult dump(const std::vector<std::string>& 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<const PropertyChangeCallback> 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<const PropertySetErrorCallback> 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;
+ }
+
+ // Gets the min/max supported values for each of the specified [propId, areaId]s.
+ //
+ // The returned result may change dynamically.
+ //
+ // This is only called for [propId, areaId] that has
+ // {@code HasSupportedValueInfo.hasMinSupportedValue} or
+ // {@code HasSupportedValueInfo.hasMinSupportedValue} set to true.
+ //
+ // Client must implement (override) this function if at least one [propId, areaId]'s
+ // {@code HasSupportedValueInfo} is not null.
+ virtual std::vector<aidlvhal::MinMaxSupportedValueResult> getMinMaxSupportedValues(
+ [[maybe_unused]] const std::vector<PropIdAreaId>& propIdAreaIds) {
+ return {};
+ }
+
+ // Gets the supported values list for each of the specified [propId, areaId]s.
+ //
+ // The returned result may change dynamically.
+ //
+ // This is only called for [propId, areaId] that has
+ // {@code HasSupportedValueInfo.hasSupportedValuesList} set to true.
+ //
+ // Client must implement (override) this function if at least one [propId, areaId]'s
+ // {@code HasSupportedValueInfo} is not null.
+ virtual std::vector<aidlvhal::SupportedValuesListResult> getSupportedValuesLists(
+ [[maybe_unused]] const std::vector<PropIdAreaId>& propIdAreaIds) {
+ return {};
+ }
+
+ // Register a callback that would be called when the min/max supported value or supported
+ // values list change dynamically for propertyID returned from
+ // getPropertyIdsThatImplementGetSupportedValue
+ //
+ // This function must only be called once during initialization.
+ //
+ // Client must implement (override) this function if at least one [propId, areaId]'s
+ // {@code HasSupportedValueInfo} is not null.
+ virtual void registerSupportedValueChangeCallback(
+ [[maybe_unused]] std::unique_ptr<const SupportedValueChangeCallback> callback) {
+ // Do nothing.
+ }
+
+ // Subscribes to the min/max supported value or supported values list change for the specified
+ // [propId, areaId]s.
+ //
+ // If the propertyId's supported values are static, then must do nothing.
+ //
+ // If some of the [propId, areaId]s are already subscribed, then do nothing.
+ //
+ // This is only called for [propId, areaId] that has non-null {@code HasSupportedValueInfo}.
+ //
+ // Client must implement (override) this function if at least one [propId, areaId]'s
+ // {@code HasSupportedValueInfo} is not null.
+ virtual aidlvhal::StatusCode subscribeSupportedValueChange(
+ [[maybe_unused]] const std::vector<PropIdAreaId>& propIdAreaIds) {
+ return aidlvhal::StatusCode::OK;
+ }
+
+ // Unsubscrbies to the min/max supported value or supported values list change.
+ //
+ // Must do nothing if the [propId, areaId] was not previously subscribed to for supported
+ // values change.
+ //
+ // This is only called for [propId, areaId] that has non-null {@code HasSupportedValueInfo}.
+ //
+ // Client must implement (override) this function if at least one [propId, areaId]'s
+ // {@code HasSupportedValueInfo} is not null.
+ virtual aidlvhal::StatusCode unsubscribeSupportedValueChange(
+ [[maybe_unused]] const std::vector<PropIdAreaId>& propIdAreaIds) {
+ 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/current/proto/Android.bp b/automotive/vehicle/aidl/impl/current/proto/Android.bp
new file mode 100644
index 0000000..2b5cdf4
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/current/proto/Android.bp
@@ -0,0 +1,127 @@
+/*
+ * 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",
+ srcs: ["**/*.proto"],
+ visibility: ["//hardware/interfaces/automotive/vehicle:__subpackages__"],
+}
+
+genrule {
+ name: "VehicleProtoStub_h",
+ tools: [
+ "aprotoc",
+ "protoc-gen-grpc-cpp-plugin",
+ ],
+ 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",
+ ],
+ 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",
+ tools: [
+ "aprotoc",
+ "protoc-gen-grpc-cpp-plugin",
+ ],
+ 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",
+ ],
+ 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",
+ vendor: true,
+ host_supported: true,
+ include_dirs: [
+ "external/protobuf/src",
+ ],
+ generated_headers: [
+ "VehicleProtoStub_h",
+ ],
+ export_generated_headers: [
+ "VehicleProtoStub_h",
+ ],
+ generated_sources: [
+ "VehicleProtoStub_cc",
+ ],
+ shared_libs: [
+ "libgrpc++_unsecure",
+ ],
+ cflags: [
+ "-Wno-unused-parameter",
+ ],
+}
+
+rust_protobuf {
+ name: "libvehicle_hal_property_protos",
+ crate_name: "vehicle_hal_property_protos",
+ protos: [":VehicleHalProtoFiles"],
+ 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",
+ ],
+ min_sdk_version: "35",
+}
diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/DumpOptions.proto b/automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/DumpOptions.proto
similarity index 100%
copy from automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/DumpOptions.proto
copy to automotive/vehicle/aidl/impl/current/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/current/proto/android/hardware/automotive/vehicle/DumpResult.proto
similarity index 100%
copy from automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/DumpResult.proto
copy to automotive/vehicle/aidl/impl/current/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/current/proto/android/hardware/automotive/vehicle/StatusCode.proto
similarity index 100%
copy from automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/StatusCode.proto
copy to automotive/vehicle/aidl/impl/current/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/current/proto/android/hardware/automotive/vehicle/SubscribeOptions.proto
similarity index 100%
copy from automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/SubscribeOptions.proto
copy to automotive/vehicle/aidl/impl/current/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/current/proto/android/hardware/automotive/vehicle/SubscribeRequest.proto
similarity index 100%
copy from automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/SubscribeRequest.proto
copy to automotive/vehicle/aidl/impl/current/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/current/proto/android/hardware/automotive/vehicle/UnsubscribeRequest.proto
similarity index 100%
copy from automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/UnsubscribeRequest.proto
copy to automotive/vehicle/aidl/impl/current/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/current/proto/android/hardware/automotive/vehicle/VehicleAreaConfig.proto
similarity index 100%
copy from automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehicleAreaConfig.proto
copy to automotive/vehicle/aidl/impl/current/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/current/proto/android/hardware/automotive/vehicle/VehiclePropConfig.proto
similarity index 100%
copy from automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropConfig.proto
copy to automotive/vehicle/aidl/impl/current/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/current/proto/android/hardware/automotive/vehicle/VehiclePropValue.proto
similarity index 100%
copy from automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropValue.proto
copy to automotive/vehicle/aidl/impl/current/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/current/proto/android/hardware/automotive/vehicle/VehiclePropValueRequest.proto
similarity index 100%
copy from automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropValueRequest.proto
copy to automotive/vehicle/aidl/impl/current/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/current/proto/android/hardware/automotive/vehicle/VehiclePropertyAccess.proto
similarity index 100%
copy from automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropertyAccess.proto
copy to automotive/vehicle/aidl/impl/current/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/current/proto/android/hardware/automotive/vehicle/VehiclePropertyChangeMode.proto
similarity index 100%
copy from automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropertyChangeMode.proto
copy to automotive/vehicle/aidl/impl/current/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/current/proto/android/hardware/automotive/vehicle/VehiclePropertyStatus.proto
similarity index 100%
copy from automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropertyStatus.proto
copy to automotive/vehicle/aidl/impl/current/proto/android/hardware/automotive/vehicle/VehiclePropertyStatus.proto
diff --git a/automotive/vehicle/aidl/impl/utils/README.md b/automotive/vehicle/aidl/impl/current/utils/README.md
similarity index 100%
copy from automotive/vehicle/aidl/impl/utils/README.md
copy to automotive/vehicle/aidl/impl/current/utils/README.md
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/utils/common/include/ConcurrentQueue.h b/automotive/vehicle/aidl/impl/current/utils/common/include/ConcurrentQueue.h
similarity index 100%
copy from automotive/vehicle/aidl/impl/utils/common/include/ConcurrentQueue.h
copy to automotive/vehicle/aidl/impl/current/utils/common/include/ConcurrentQueue.h
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/ParcelableUtils.h b/automotive/vehicle/aidl/impl/current/utils/common/include/ParcelableUtils.h
similarity index 100%
copy from automotive/vehicle/aidl/impl/utils/common/include/ParcelableUtils.h
copy to automotive/vehicle/aidl/impl/current/utils/common/include/ParcelableUtils.h
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/PendingRequestPool.h b/automotive/vehicle/aidl/impl/current/utils/common/include/PendingRequestPool.h
similarity index 100%
copy from automotive/vehicle/aidl/impl/utils/common/include/PendingRequestPool.h
copy to automotive/vehicle/aidl/impl/current/utils/common/include/PendingRequestPool.h
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h b/automotive/vehicle/aidl/impl/current/utils/common/include/PropertyUtils.h
similarity index 100%
copy from automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h
copy to automotive/vehicle/aidl/impl/current/utils/common/include/PropertyUtils.h
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/RecurrentTimer.h b/automotive/vehicle/aidl/impl/current/utils/common/include/RecurrentTimer.h
similarity index 100%
copy from automotive/vehicle/aidl/impl/utils/common/include/RecurrentTimer.h
copy to automotive/vehicle/aidl/impl/current/utils/common/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 0000000..fcc006b
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/current/utils/common/include/VehicleHalTypes.h
@@ -0,0 +1,107 @@
+/*
+ * 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 <aidl/android/hardware/automotive/vehicle/AutomaticEmergencyBrakingState.h>
+#include <aidl/android/hardware/automotive/vehicle/BlindSpotWarningState.h>
+#include <aidl/android/hardware/automotive/vehicle/CameraServiceState.h>
+#include <aidl/android/hardware/automotive/vehicle/CrossTrafficMonitoringWarningState.h>
+#include <aidl/android/hardware/automotive/vehicle/CruiseControlCommand.h>
+#include <aidl/android/hardware/automotive/vehicle/CruiseControlState.h>
+#include <aidl/android/hardware/automotive/vehicle/CruiseControlType.h>
+#include <aidl/android/hardware/automotive/vehicle/DiagnosticFloatSensorIndex.h>
+#include <aidl/android/hardware/automotive/vehicle/DiagnosticIntegerSensorIndex.h>
+#include <aidl/android/hardware/automotive/vehicle/DriverDistractionState.h>
+#include <aidl/android/hardware/automotive/vehicle/DriverDistractionWarning.h>
+#include <aidl/android/hardware/automotive/vehicle/DriverDrowsinessAttentionState.h>
+#include <aidl/android/hardware/automotive/vehicle/DriverDrowsinessAttentionWarning.h>
+#include <aidl/android/hardware/automotive/vehicle/ElectronicStabilityControlState.h>
+#include <aidl/android/hardware/automotive/vehicle/EmergencyLaneKeepAssistState.h>
+#include <aidl/android/hardware/automotive/vehicle/ErrorState.h>
+#include <aidl/android/hardware/automotive/vehicle/EvConnectorType.h>
+#include <aidl/android/hardware/automotive/vehicle/EvStoppingMode.h>
+#include <aidl/android/hardware/automotive/vehicle/EvsServiceState.h>
+#include <aidl/android/hardware/automotive/vehicle/EvsServiceType.h>
+#include <aidl/android/hardware/automotive/vehicle/ForwardCollisionWarningState.h>
+#include <aidl/android/hardware/automotive/vehicle/FuelType.h>
+#include <aidl/android/hardware/automotive/vehicle/GetValueRequest.h>
+#include <aidl/android/hardware/automotive/vehicle/GetValueResult.h>
+#include <aidl/android/hardware/automotive/vehicle/GetValueResults.h>
+#include <aidl/android/hardware/automotive/vehicle/GsrComplianceRequirementType.h>
+#include <aidl/android/hardware/automotive/vehicle/HandsOnDetectionDriverState.h>
+#include <aidl/android/hardware/automotive/vehicle/HandsOnDetectionWarning.h>
+#include <aidl/android/hardware/automotive/vehicle/ImpactSensorLocation.h>
+#include <aidl/android/hardware/automotive/vehicle/LaneCenteringAssistCommand.h>
+#include <aidl/android/hardware/automotive/vehicle/LaneCenteringAssistState.h>
+#include <aidl/android/hardware/automotive/vehicle/LaneDepartureWarningState.h>
+#include <aidl/android/hardware/automotive/vehicle/LaneKeepAssistState.h>
+#include <aidl/android/hardware/automotive/vehicle/LocationCharacterization.h>
+#include <aidl/android/hardware/automotive/vehicle/LowSpeedAutomaticEmergencyBrakingState.h>
+#include <aidl/android/hardware/automotive/vehicle/LowSpeedCollisionWarningState.h>
+#include <aidl/android/hardware/automotive/vehicle/MinMaxSupportedValueResult.h>
+#include <aidl/android/hardware/automotive/vehicle/MinMaxSupportedValueResults.h>
+#include <aidl/android/hardware/automotive/vehicle/Obd2CommonIgnitionMonitors.h>
+#include <aidl/android/hardware/automotive/vehicle/Obd2FuelSystemStatus.h>
+#include <aidl/android/hardware/automotive/vehicle/Obd2FuelType.h>
+#include <aidl/android/hardware/automotive/vehicle/Obd2IgnitionMonitorKind.h>
+#include <aidl/android/hardware/automotive/vehicle/Obd2SecondaryAirStatus.h>
+#include <aidl/android/hardware/automotive/vehicle/Obd2SparkIgnitionMonitors.h>
+#include <aidl/android/hardware/automotive/vehicle/PortLocationType.h>
+#include <aidl/android/hardware/automotive/vehicle/SetValueRequest.h>
+#include <aidl/android/hardware/automotive/vehicle/SetValueResult.h>
+#include <aidl/android/hardware/automotive/vehicle/SetValueResults.h>
+#include <aidl/android/hardware/automotive/vehicle/StatusCode.h>
+#include <aidl/android/hardware/automotive/vehicle/SubscribeOptions.h>
+#include <aidl/android/hardware/automotive/vehicle/SupportedValuesListResult.h>
+#include <aidl/android/hardware/automotive/vehicle/SupportedValuesListResults.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleAirbagLocation.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleApPowerBootupReason.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReport.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReq.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleArea.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleAreaDoor.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleAreaMirror.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleAreaSeat.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleAreaWheel.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleAreaWindow.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleAutonomousState.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleGear.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleHvacFanDirection.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleIgnitionState.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleLightState.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleLightSwitch.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleOilLevel.h>
+#include <aidl/android/hardware/automotive/vehicle/VehiclePropConfig.h>
+#include <aidl/android/hardware/automotive/vehicle/VehiclePropConfigs.h>
+#include <aidl/android/hardware/automotive/vehicle/VehiclePropError.h>
+#include <aidl/android/hardware/automotive/vehicle/VehiclePropValue.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleProperty.h>
+#include <aidl/android/hardware/automotive/vehicle/VehiclePropertyAccess.h>
+#include <aidl/android/hardware/automotive/vehicle/VehiclePropertyChangeMode.h>
+#include <aidl/android/hardware/automotive/vehicle/VehiclePropertyGroup.h>
+#include <aidl/android/hardware/automotive/vehicle/VehiclePropertyStatus.h>
+#include <aidl/android/hardware/automotive/vehicle/VehiclePropertyType.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleSeatOccupancyState.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleSizeClass.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleTurnSignal.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleUnit.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleVendorPermission.h>
+#include <aidl/android/hardware/automotive/vehicle/WindshieldWipersState.h>
+#include <aidl/android/hardware/automotive/vehicle/WindshieldWipersSwitch.h>
+
+#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 0000000..e18413b
--- /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 <deque>
+#include <map>
+#include <memory>
+#include <mutex>
+
+#include <VehicleHalTypes.h>
+
+#include <android-base/thread_annotations.h>
+
+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<uint32_t> Obtained{0};
+ std::atomic<uint32_t> Created{0};
+ std::atomic<uint32_t> Recycled{0};
+ std::atomic<uint32_t> Deleted{0};
+
+ static PoolStats* instance() {
+ static PoolStats inst;
+ return &inst;
+ }
+};
+
+template <typename T>
+struct Deleter {
+ using OnDeleteFunc = std::function<void(T*)>;
+
+ 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 <typename T>
+using recyclable_ptr = typename std::unique_ptr<T, Deleter<T>>;
+
+// 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 <typename T>
+class ObjectPool {
+ public:
+ using GetSizeFunc = std::function<size_t(const T&)>;
+
+ ObjectPool(size_t maxPoolObjectsSize, GetSizeFunc getSizeFunc)
+ : mMaxPoolObjectsSize(maxPoolObjectsSize), mGetSizeFunc(getSizeFunc) {};
+ virtual ~ObjectPool() = default;
+
+ virtual recyclable_ptr<T> obtain() {
+ std::scoped_lock<std::mutex> 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<std::mutex> 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<T>{o});
+ mPoolObjectsSize += objectSize;
+ }
+
+ const size_t mMaxPoolObjectsSize;
+
+ private:
+ const Deleter<T>& getDeleter() {
+ if (!mDeleter.get()) {
+ Deleter<T>* d =
+ new Deleter<T>(std::bind(&ObjectPool::recycle, this, std::placeholders::_1));
+ mDeleter.reset(d);
+ }
+ return *mDeleter.get();
+ }
+
+ recyclable_ptr<T> wrap(T* raw) { return recyclable_ptr<T>{raw, getDeleter()}; }
+
+ mutable std::mutex mLock;
+ std::deque<std::unique_ptr<T>> mObjects GUARDED_BY(mLock);
+ std::unique_ptr<Deleter<T>> 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<aidl::android::hardware::automotive::vehicle::VehiclePropValue>;
+
+ // 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<aidl::android::hardware::automotive::vehicle::VehiclePropValue> {
+ 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 <typename VecType>
+ bool check(std::vector<VecType>* vec, bool isVectorType) {
+ return vec->size() == (isVectorType ? mVectorSize : 0);
+ }
+
+ private:
+ aidl::android::hardware::automotive::vehicle::VehiclePropertyType mPropType;
+ size_t mVectorSize;
+ };
+ const Deleter<aidl::android::hardware::automotive::vehicle::VehiclePropValue>
+ 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<int32_t, std::unique_ptr<InternalPool>> 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/utils/common/include/VehiclePropertyStore.h b/automotive/vehicle/aidl/impl/current/utils/common/include/VehiclePropertyStore.h
similarity index 100%
copy from automotive/vehicle/aidl/impl/utils/common/include/VehiclePropertyStore.h
copy to automotive/vehicle/aidl/impl/current/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 0000000..5b19100
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/current/utils/common/include/VehicleUtils.h
@@ -0,0 +1,387 @@
+/*
+ * 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 <VehicleHalTypes.h>
+
+#include <android-base/format.h>
+#include <android-base/result.h>
+#include <math/HashCombine.h>
+#include <utils/Log.h>
+
+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 <typename ENUM, typename U = typename std::underlying_type<ENUM>::type>
+inline constexpr U toInt(ENUM const value) {
+ return static_cast<U>(value);
+}
+
+inline constexpr aidl::android::hardware::automotive::vehicle::VehiclePropertyType getPropType(
+ int32_t prop) {
+ return static_cast<aidl::android::hardware::automotive::vehicle::VehiclePropertyType>(
+ prop & toInt(aidl::android::hardware::automotive::vehicle::VehiclePropertyType::MASK));
+}
+
+inline constexpr aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup getPropGroup(
+ int32_t prop) {
+ return static_cast<aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup>(
+ prop & toInt(aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup::MASK));
+}
+
+inline constexpr aidl::android::hardware::automotive::vehicle::VehicleArea getPropArea(
+ int32_t prop) {
+ return static_cast<aidl::android::hardware::automotive::vehicle::VehicleArea>(
+ 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<aidl::android::hardware::automotive::vehicle::VehiclePropValue>
+createVehiclePropValueVec(aidl::android::hardware::automotive::vehicle::VehiclePropertyType type,
+ size_t vecSize) {
+ auto val = std::unique_ptr<aidl::android::hardware::automotive::vehicle::VehiclePropValue>(
+ 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<aidl::android::hardware::automotive::vehicle::VehiclePropValue>
+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<size_t>(1));
+ case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::FLOAT:
+ return std::min(value.floatValues.size(), static_cast<size_t>(1));
+ case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT64:
+ return std::min(value.int64Values.size(), static_cast<size_t>(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<void> 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<void> 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<void> 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<T,E>}.
+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 <class T>
+using VhalResult = android::base::Result<T, VhalError>;
+
+// 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<VhalError>;
+
+template <class T>
+aidl::android::hardware::automotive::vehicle::StatusCode getErrorCode(const VhalResult<T>& result) {
+ if (result.ok()) {
+ return aidl::android::hardware::automotive::vehicle::StatusCode::OK;
+ }
+ return result.error().code();
+}
+
+template <class T>
+int getIntErrorCode(const VhalResult<T>& result) {
+ return toInt(getErrorCode(result));
+}
+
+template <class T, class E>
+std::string getErrorMsg(const android::base::Result<T, E>& result) {
+ if (result.ok()) {
+ return "";
+ }
+ return result.error().message();
+}
+
+template <class T, class E>
+ndk::ScopedAStatus toScopedAStatus(const android::base::Result<T, E>& 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 <class T, class E>
+ndk::ScopedAStatus toScopedAStatus(
+ const android::base::Result<T, E>& result,
+ aidl::android::hardware::automotive::vehicle::StatusCode status) {
+ return toScopedAStatus(result, status, "");
+}
+
+template <class T>
+ndk::ScopedAStatus toScopedAStatus(const VhalResult<T>& result) {
+ return toScopedAStatus(result, getErrorCode(result));
+}
+
+template <class T>
+ndk::ScopedAStatus toScopedAStatus(const VhalResult<T>& result,
+ const std::string& additionalErrorMsg) {
+ return toScopedAStatus(result, getErrorCode(result), additionalErrorMsg);
+}
+
+// This is for debug purpose only.
+inline std::string propIdToString(int32_t propId) {
+ return toString(
+ static_cast<aidl::android::hardware::automotive::vehicle::VehicleProperty>(propId));
+}
+
+struct PropIdAreaId {
+ int32_t propId;
+ int32_t areaId;
+
+ inline bool operator==(const PropIdAreaId& other) const {
+ return areaId == other.areaId && propId == other.propId;
+ }
+
+ // This is for debug purpose only.
+ inline std::string toString() const {
+ return fmt::format("{{propId: {}, areaId: {}}}", propIdToString(propId), areaId);
+ }
+};
+
+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.
+android::base::Result<int32_t> stringToPropId(const std::string& propName);
+
+// This is for debug purpose only. Converts an area's name to its enum definition.
+android::base::Result<int32_t> stringToArea(const std::string& areaName, int32_t propId);
+
+template <typename T>
+void roundToNearestResolution(std::vector<T>& 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
+
+// Formatter must not be defined inside our namespace.
+template <>
+struct fmt::formatter<android::hardware::automotive::vehicle::PropIdAreaId> {
+ template <typename ParseContext>
+ constexpr auto parse(ParseContext& ctx) {
+ return ctx.begin();
+ }
+
+ template <typename FormatContext>
+ auto format(const android::hardware::automotive::vehicle::PropIdAreaId& p,
+ FormatContext& ctx) const {
+ return fmt::format_to(ctx.out(), "{{propId: {}, areaId: {}}}",
+ android::hardware::automotive::vehicle::propIdToString(p.propId),
+ p.areaId);
+ }
+};
+
+#endif // android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehicleUtils_H_
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/PendingRequestPool.cpp b/automotive/vehicle/aidl/impl/current/utils/common/src/PendingRequestPool.cpp
similarity index 100%
copy from automotive/vehicle/aidl/impl/utils/common/src/PendingRequestPool.cpp
copy to automotive/vehicle/aidl/impl/current/utils/common/src/PendingRequestPool.cpp
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/RecurrentTimer.cpp b/automotive/vehicle/aidl/impl/current/utils/common/src/RecurrentTimer.cpp
similarity index 100%
copy from automotive/vehicle/aidl/impl/utils/common/src/RecurrentTimer.cpp
copy to automotive/vehicle/aidl/impl/current/utils/common/src/RecurrentTimer.cpp
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/VehicleObjectPool.cpp b/automotive/vehicle/aidl/impl/current/utils/common/src/VehicleObjectPool.cpp
similarity index 100%
copy from automotive/vehicle/aidl/impl/utils/common/src/VehicleObjectPool.cpp
copy to automotive/vehicle/aidl/impl/current/utils/common/src/VehicleObjectPool.cpp
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp b/automotive/vehicle/aidl/impl/current/utils/common/src/VehiclePropertyStore.cpp
similarity index 100%
copy from automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
copy to automotive/vehicle/aidl/impl/current/utils/common/src/VehiclePropertyStore.cpp
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/VehicleUtils.cpp b/automotive/vehicle/aidl/impl/current/utils/common/src/VehicleUtils.cpp
similarity index 100%
copy from automotive/vehicle/aidl/impl/utils/common/src/VehicleUtils.cpp
copy to automotive/vehicle/aidl/impl/current/utils/common/src/VehicleUtils.cpp
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/utils/common/test/PendingRequestPoolTest.cpp b/automotive/vehicle/aidl/impl/current/utils/common/test/PendingRequestPoolTest.cpp
similarity index 100%
copy from automotive/vehicle/aidl/impl/utils/common/test/PendingRequestPoolTest.cpp
copy to automotive/vehicle/aidl/impl/current/utils/common/test/PendingRequestPoolTest.cpp
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp b/automotive/vehicle/aidl/impl/current/utils/common/test/RecurrentTimerTest.cpp
similarity index 100%
copy from automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp
copy to automotive/vehicle/aidl/impl/current/utils/common/test/RecurrentTimerTest.cpp
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/VehicleObjectPoolTest.cpp b/automotive/vehicle/aidl/impl/current/utils/common/test/VehicleObjectPoolTest.cpp
similarity index 100%
copy from automotive/vehicle/aidl/impl/utils/common/test/VehicleObjectPoolTest.cpp
copy to automotive/vehicle/aidl/impl/current/utils/common/test/VehicleObjectPoolTest.cpp
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/VehiclePropertyStoreTest.cpp b/automotive/vehicle/aidl/impl/current/utils/common/test/VehiclePropertyStoreTest.cpp
similarity index 100%
copy from automotive/vehicle/aidl/impl/utils/common/test/VehiclePropertyStoreTest.cpp
copy to automotive/vehicle/aidl/impl/current/utils/common/test/VehiclePropertyStoreTest.cpp
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 0000000..8278376
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/current/utils/common/test/VehicleUtilsTest.cpp
@@ -0,0 +1,850 @@
+/*
+ * 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 <ConcurrentQueue.h>
+#include <PropertyUtils.h>
+#include <VehicleUtils.h>
+
+#include <gtest/gtest.h>
+
+#include <atomic>
+#include <thread>
+#include <vector>
+
+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<InvalidPropValueTestCase> getInvalidPropValuesTestCases() {
+ return std::vector<InvalidPropValueTestCase>(
+ {
+ 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<uint8_t>(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<uint8_t>(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<uint8_t>(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<uint8_t>(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<uint8_t>(0),
+ static_cast<uint8_t>(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<InvalidValueRangeTestCase> getInvalidValueRangeTestCases() {
+ return std::vector<InvalidValueRangeTestCase>({{
+ 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<VehiclePropValue> value = createVehiclePropValue(VehiclePropertyType::INT32);
+
+ ASSERT_NE(value, nullptr);
+ ASSERT_EQ(1u, value->value.int32Values.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueInt32Vec) {
+ std::unique_ptr<VehiclePropValue> value =
+ createVehiclePropValue(VehiclePropertyType::INT32_VEC);
+
+ ASSERT_NE(value, nullptr);
+ ASSERT_EQ(1u, value->value.int32Values.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueInt64) {
+ std::unique_ptr<VehiclePropValue> value = createVehiclePropValue(VehiclePropertyType::INT64);
+
+ ASSERT_NE(value, nullptr);
+ ASSERT_EQ(1u, value->value.int64Values.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueInt64Vec) {
+ std::unique_ptr<VehiclePropValue> value =
+ createVehiclePropValue(VehiclePropertyType::INT64_VEC);
+
+ ASSERT_NE(value, nullptr);
+ ASSERT_EQ(1u, value->value.int64Values.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueFloat) {
+ std::unique_ptr<VehiclePropValue> value = createVehiclePropValue(VehiclePropertyType::FLOAT);
+
+ ASSERT_NE(value, nullptr);
+ ASSERT_EQ(1u, value->value.floatValues.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueFloatVec) {
+ std::unique_ptr<VehiclePropValue> value =
+ createVehiclePropValue(VehiclePropertyType::FLOAT_VEC);
+
+ ASSERT_NE(value, nullptr);
+ ASSERT_EQ(1u, value->value.floatValues.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueBytes) {
+ std::unique_ptr<VehiclePropValue> value = createVehiclePropValue(VehiclePropertyType::BYTES);
+
+ ASSERT_NE(value, nullptr);
+ ASSERT_EQ(1u, value->value.byteValues.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueString) {
+ std::unique_ptr<VehiclePropValue> value = createVehiclePropValue(VehiclePropertyType::STRING);
+
+ ASSERT_NE(value, nullptr);
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueMixed) {
+ std::unique_ptr<VehiclePropValue> value = createVehiclePropValue(VehiclePropertyType::MIXED);
+
+ ASSERT_NE(value, nullptr);
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueVecInt32) {
+ std::unique_ptr<VehiclePropValue> 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<VehiclePropValue> value =
+ createVehiclePropValueVec(VehiclePropertyType::INT32_VEC, /*vecSize=*/2);
+
+ ASSERT_NE(value, nullptr);
+ ASSERT_EQ(2u, value->value.int32Values.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueVecInt64) {
+ std::unique_ptr<VehiclePropValue> 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<VehiclePropValue> value =
+ createVehiclePropValueVec(VehiclePropertyType::INT64_VEC, /*vecSize=*/2);
+
+ ASSERT_NE(value, nullptr);
+ ASSERT_EQ(2u, value->value.int64Values.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueVecFloat) {
+ std::unique_ptr<VehiclePropValue> 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<VehiclePropValue> value =
+ createVehiclePropValueVec(VehiclePropertyType::FLOAT_VEC, /*vecSize=*/2);
+
+ ASSERT_NE(value, nullptr);
+ ASSERT_EQ(2u, value->value.floatValues.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueVecBytes) {
+ std::unique_ptr<VehiclePropValue> value =
+ createVehiclePropValueVec(VehiclePropertyType::BYTES, /*vecSize=*/2);
+
+ ASSERT_NE(value, nullptr);
+ ASSERT_EQ(2u, value->value.byteValues.size());
+}
+
+TEST(VehicleUtilsTest, testConcurrentQueueOneThread) {
+ ConcurrentQueue<int> queue;
+
+ queue.push(1);
+ queue.push(2);
+ auto result = queue.flush();
+
+ ASSERT_EQ(result, std::vector<int>({1, 2}));
+}
+
+TEST(VehicleUtilsTest, testConcurrentQueueMultipleThreads) {
+ ConcurrentQueue<int> queue;
+ std::vector<int> results;
+ std::atomic<bool> 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<size_t>(200));
+ EXPECT_EQ(zeroCount, static_cast<size_t>(100));
+ EXPECT_EQ(oneCount, static_cast<size_t>(100));
+}
+
+TEST(VehicleUtilsTest, testConcurrentQueuePushAfterDeactivate) {
+ ConcurrentQueue<int> queue;
+
+ queue.deactivate();
+ queue.push(1);
+
+ ASSERT_TRUE(queue.flush().empty());
+}
+
+TEST(VehicleUtilsTest, testConcurrentQueueDeactivateNotifyWaitingThread) {
+ ConcurrentQueue<int> queue;
+
+ std::thread t([&queue]() {
+ // This would block until queue is deactivated.
+ queue.waitForItems();
+ });
+
+ queue.deactivate();
+
+ t.join();
+}
+
+TEST(VehicleUtilsTest, testVhalError) {
+ VhalResult<void> result = Error<VhalError>(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());
+}
+
+TEST(VehicleUtilsTest, testPropIdAreaIdToString) {
+ PropIdAreaId propIdAreaId = {
+ .propId = toInt(VehicleProperty::PERF_VEHICLE_SPEED),
+ .areaId = 0,
+ };
+
+ ASSERT_EQ(propIdAreaId.toString(), "{propId: PERF_VEHICLE_SPEED, areaId: 0}");
+}
+
+TEST(VehicleUtilsTest, testPropIdAreaIdFormatter) {
+ PropIdAreaId propIdAreaId1 = {
+ .propId = toInt(VehicleProperty::PERF_VEHICLE_SPEED),
+ .areaId = 0,
+ };
+ PropIdAreaId propIdAreaId2 = {
+ .propId = toInt(VehicleProperty::HVAC_FAN_SPEED),
+ .areaId = 1,
+ };
+
+ ASSERT_EQ(fmt::format("{}", std::vector<PropIdAreaId>{propIdAreaId1, propIdAreaId2}),
+ "[{propId: PERF_VEHICLE_SPEED, areaId: 0}, {propId: HVAC_FAN_SPEED, areaId: 1}]");
+}
+
+class InvalidPropValueTest : public testing::TestWithParam<InvalidPropValueTestCase> {};
+
+INSTANTIATE_TEST_SUITE_P(InvalidPropValueTests, InvalidPropValueTest,
+ testing::ValuesIn(getInvalidPropValuesTestCases()),
+ [](const testing::TestParamInfo<InvalidPropValueTest::ParamType>& 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<InvalidValueRangeTestCase> {};
+
+INSTANTIATE_TEST_SUITE_P(InvalidValueRangeTests, InvalidValueRangeTest,
+ testing::ValuesIn(getInvalidValueRangeTestCases()),
+ [](const testing::TestParamInfo<InvalidValueRangeTest::ParamType>& 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 0000000..217387f
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/current/utils/test_vendor_properties/android/hardware/automotive/vehicle/TestVendorProperty.aidl
@@ -0,0 +1,146 @@
+/*
+ * 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.
+ */
+@JavaDerive(toString=true)
+@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/current/vhal/Android.bp b/automotive/vehicle/aidl/impl/current/vhal/Android.bp
new file mode 100644
index 0000000..8764eff
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/current/vhal/Android.bp
@@ -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.
+ */
+
+package {
+ default_team: "trendy_team_aaos_framework",
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_binary {
+ name: "android.hardware.automotive.vehicle@V4-default-service",
+ vendor: true,
+ defaults: [
+ "FakeVehicleHardwareDefaults",
+ "VehicleHalDefaults",
+ "android-automotive-large-parcelable-defaults",
+ ],
+ vintf_fragments: ["vhal-default-service.xml"],
+ init_rc: ["vhal-default-service.rc"],
+ relative_install_path: "hw",
+ srcs: ["src/VehicleService.cpp"],
+ static_libs: [
+ "DefaultVehicleHal",
+ "FakeVehicleHardware",
+ "VehicleHalUtils",
+ ],
+ header_libs: [
+ "IVehicleHardware",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ ],
+}
+
+cc_library {
+ name: "DefaultVehicleHal",
+ vendor: true,
+ defaults: [
+ "VehicleHalDefaults",
+ ],
+ 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",
+ ],
+ header_libs: [
+ "IVehicleHardware",
+ "IVehicleGeneratedHeaders-V4",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ ],
+}
+
+cc_fuzz {
+ name: "android.hardware.automotive.vehicle-default-service_fuzzer",
+ vendor: true,
+ defaults: [
+ "FakeVehicleHardwareDefaults",
+ "VehicleHalDefaults",
+ "android-automotive-large-parcelable-defaults",
+ "service_fuzzer_defaults",
+ ],
+ static_libs: [
+ "DefaultVehicleHal",
+ "FakeVehicleHardware",
+ "VehicleHalUtils",
+ ],
+ srcs: ["src/fuzzer.cpp"],
+ fuzz_config: {
+ cc: [
+ "keithmok@google.com",
+ ],
+ },
+}
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 0000000..335f5c0
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/current/vhal/include/ConnectedClient.h
@@ -0,0 +1,130 @@
+/*
+ * 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 <IVehicleHardware.h>
+#include <VehicleHalTypes.h>
+#include <VehicleUtils.h>
+
+#include <aidl/android/hardware/automotive/vehicle/IVehicleCallback.h>
+#include <android-base/result.h>
+
+#include <memory>
+#include <unordered_set>
+#include <vector>
+
+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<aidl::android::hardware::automotive::vehicle::IVehicleCallback>;
+
+ ConnectedClient(std::shared_ptr<PendingRequestPool> 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<void> addRequests(const std::unordered_set<int64_t>& 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<int64_t> tryFinishRequests(const std::unordered_set<int64_t>& requestIds);
+
+ protected:
+ // Gets the callback to be called when the request for this client has timeout.
+ virtual std::shared_ptr<const PendingRequestPool::TimeoutCallbackFunc> getTimeoutCallback() = 0;
+
+ const std::shared_ptr<PendingRequestPool> mRequestPool;
+ const CallbackType mCallback;
+};
+
+// A class to represent a client that calls {@code IVehicle.setValues} or {@code
+// IVehicle.getValues}.
+template <class ResultType, class ResultsType>
+class GetSetValuesClient final : public ConnectedClient {
+ public:
+ GetSetValuesClient(std::shared_ptr<PendingRequestPool> requestPool, CallbackType callback);
+
+ // Sends the results to this client.
+ void sendResults(std::vector<ResultType>&& results);
+
+ // Sends each result separately to this client. Each result would be sent through one callback
+ // invocation.
+ void sendResultsSeparately(const std::vector<ResultType>& results);
+
+ // Gets the callback to be called when the request for this client has finished.
+ std::shared_ptr<const std::function<void(std::vector<ResultType>)>> getResultCallback();
+
+ protected:
+ // Gets the callback to be called when the request for this client has timeout.
+ std::shared_ptr<const PendingRequestPool::TimeoutCallbackFunc> getTimeoutCallback() override;
+
+ private:
+ // The following members are only initialized during construction.
+ std::shared_ptr<const PendingRequestPool::TimeoutCallbackFunc> mTimeoutCallback;
+ std::shared_ptr<const std::function<void(std::vector<ResultType>)>> mResultCallback;
+};
+
+class SubscriptionClient {
+ public:
+ using CallbackType =
+ std::shared_ptr<aidl::android::hardware::automotive::vehicle::IVehicleCallback>;
+
+ // Marshals the updated values into largeParcelable and sends it through {@code onPropertyEvent}
+ // callback.
+ static void sendUpdatedValues(
+ CallbackType callback,
+ std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>&&
+ updatedValues);
+ // Marshals the set property error events into largeParcelable and sends it through
+ // {@code onPropertySetError} callback.
+ static void sendPropertySetErrors(
+ CallbackType callback,
+ std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropError>&&
+ vehiclePropErrors);
+
+ // Invokes onSupportedValueChange callback.
+ static void sendSupportedValueChangeEvents(CallbackType callback,
+ std::vector<PropIdAreaId> propIdAreaIds);
+};
+
+} // 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 0000000..d360be0
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/current/vhal/include/DefaultVehicleHal.h
@@ -0,0 +1,288 @@
+/*
+ * 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 <ConnectedClient.h>
+#include <ParcelableUtils.h>
+#include <PendingRequestPool.h>
+#include <RecurrentTimer.h>
+#include <SubscriptionManager.h>
+
+#include <ConcurrentQueue.h>
+#include <IVehicleHardware.h>
+#include <VehicleUtils.h>
+#include <aidl/android/hardware/automotive/vehicle/BnVehicle.h>
+#include <android-base/expected.h>
+#include <android-base/thread_annotations.h>
+#include <android/binder_auto_utils.h>
+
+#include <functional>
+#include <memory>
+#include <mutex>
+#include <shared_mutex>
+#include <unordered_map>
+#include <vector>
+
+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<aidlvhal::IVehicleCallback>;
+
+ explicit DefaultVehicleHal(std::unique_ptr<IVehicleHardware> hardware);
+
+ // Test-only
+ DefaultVehicleHal(std::unique_ptr<IVehicleHardware> 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<int32_t>& props,
+ aidlvhal::VehiclePropConfigs* returnConfigs) override;
+ ndk::ScopedAStatus subscribe(const CallbackType& callback,
+ const std::vector<aidlvhal::SubscribeOptions>& options,
+ int32_t maxSharedMemoryFileCount) override;
+ ndk::ScopedAStatus unsubscribe(const CallbackType& callback,
+ const std::vector<int32_t>& propIds) override;
+ ndk::ScopedAStatus returnSharedMemory(const CallbackType& callback,
+ int64_t sharedMemoryId) override;
+ ndk::ScopedAStatus getSupportedValuesLists(
+ const std::vector<aidlvhal::PropIdAreaId>& propIdAreaIds,
+ aidlvhal::SupportedValuesListResults* supportedValuesListResults) override;
+ ndk::ScopedAStatus getMinMaxSupportedValue(
+ const std::vector<aidlvhal::PropIdAreaId>& propIdAreaIds,
+ aidlvhal::MinMaxSupportedValueResults* minMaxSupportedValueResults) override;
+ ndk::ScopedAStatus registerSupportedValueChangeCallback(
+ const std::shared_ptr<aidlvhal::IVehicleCallback>& callback,
+ const std::vector<aidlvhal::PropIdAreaId>& propIdAreaIds) override;
+ ndk::ScopedAStatus unregisterSupportedValueChangeCallback(
+ const std::shared_ptr<aidlvhal::IVehicleCallback>& callback,
+ const std::vector<aidlvhal::PropIdAreaId>& 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<aidlvhal::GetValueResult, aidlvhal::GetValueResults>;
+ using SetValuesClient = GetSetValuesClient<aidlvhal::SetValueResult, aidlvhal::SetValueResults>;
+
+ // 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<IVehicleHardware> mVehicleHardware;
+
+ // PendingRequestPool is thread-safe.
+ std::shared_ptr<PendingRequestPool> mPendingRequestPool;
+ // SubscriptionManager is thread-safe.
+ std::shared_ptr<SubscriptionManager> mSubscriptionManager;
+ // ConcurrentQueue is thread-safe.
+ std::shared_ptr<ConcurrentQueue<aidlvhal::VehiclePropValue>> mBatchedEventQueue;
+ // BatchingConsumer is thread-safe.
+ std::shared_ptr<BatchingConsumer<aidlvhal::VehiclePropValue>>
+ mPropertyChangeEventsBatchingConsumer;
+ // Only set once during initialization.
+ std::chrono::nanoseconds mEventBatchingWindow;
+ // Only used for testing.
+ int32_t mTestInterfaceVersion = 0;
+
+ mutable std::atomic<bool> mConfigInit = false;
+ mutable std::shared_timed_mutex mConfigLock;
+ mutable std::unordered_map<int32_t, aidlvhal::VehiclePropConfig> mConfigsByPropId
+ GUARDED_BY(mConfigLock);
+ mutable std::unique_ptr<ndk::ScopedFileDescriptor> mConfigFile GUARDED_BY(mConfigLock);
+
+ std::mutex mLock;
+ std::unordered_map<const AIBinder*, std::unique_ptr<OnBinderDiedContext>> mOnBinderDiedContexts
+ GUARDED_BY(mLock);
+ std::unordered_map<const AIBinder*, std::shared_ptr<GetValuesClient>> mGetValuesClients
+ GUARDED_BY(mLock);
+ std::unordered_map<const AIBinder*, std::shared_ptr<SetValuesClient>> mSetValuesClients
+ GUARDED_BY(mLock);
+ // mBinderLifecycleHandler is only going to be changed in test.
+ std::unique_ptr<BinderLifecycleInterface> mBinderLifecycleHandler;
+
+ // Only initialized once.
+ std::shared_ptr<std::function<void()>> mRecurrentAction;
+ // RecurrentTimer is thread-safe.
+ RecurrentTimer mRecurrentTimer;
+
+ ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
+
+ // ConcurrentQueue is thread-safe.
+ ConcurrentQueue<BinderDiedUnlinkedEvent> mBinderEvents;
+
+ // A thread to handle onBinderDied or onBinderUnlinked event.
+ std::thread mOnBinderDiedUnlinkedHandlerThread;
+
+ android::base::Result<void> checkProperty(const aidlvhal::VehiclePropValue& propValue);
+
+ android::base::Result<std::vector<int64_t>> checkDuplicateRequests(
+ const std::vector<aidlvhal::GetValueRequest>& requests);
+
+ android::base::Result<std::vector<int64_t>> checkDuplicateRequests(
+ const std::vector<aidlvhal::SetValueRequest>& requests);
+ VhalResult<void> checkSubscribeOptions(
+ const std::vector<aidlvhal::SubscribeOptions>& options,
+ const std::unordered_map<int32_t, aidlvhal::VehiclePropConfig>& configsByPropId)
+ REQUIRES_SHARED(mConfigLock);
+
+ VhalResult<void> checkPermissionHelper(const aidlvhal::VehiclePropValue& value,
+ aidlvhal::VehiclePropertyAccess accessToTest) const;
+
+ VhalResult<void> checkReadPermission(const aidlvhal::VehiclePropValue& value) const;
+
+ VhalResult<void> checkWritePermission(const aidlvhal::VehiclePropValue& value) const;
+
+ android::base::Result<aidlvhal::VehiclePropConfig> 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 countClients();
+
+ // Handles the property change events in batch.
+ void handleBatchedPropertyEvents(std::vector<aidlvhal::VehiclePropValue>&& 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<void(const std::unordered_map<int32_t, aidlvhal::VehiclePropConfig>&)>
+ callback) const EXCLUDES(mConfigLock);
+
+ android::base::Result<aidlvhal::VehicleAreaConfig> getAreaConfigForPropIdAreaId(
+ int32_t propId, int32_t areaId) const;
+ android::base::Result<aidlvhal::HasSupportedValueInfo> getHasSupportedValueInfo(
+ int32_t propId, int32_t areaId) const;
+ // Puts the property change events into a queue so that they can handled in batch.
+ static void batchPropertyChangeEvent(
+ const std::weak_ptr<ConcurrentQueue<aidlvhal::VehiclePropValue>>& batchedEventQueue,
+ std::vector<aidlvhal::VehiclePropValue>&& updatedValues);
+
+ // Gets or creates a {@code T} object for the client to or from {@code clients}.
+ template <class T>
+ static std::shared_ptr<T> getOrCreateClient(
+ std::unordered_map<const AIBinder*, std::shared_ptr<T>>* clients,
+ const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool);
+
+ static void onPropertyChangeEvent(const std::weak_ptr<SubscriptionManager>& subscriptionManager,
+ std::vector<aidlvhal::VehiclePropValue>&& updatedValues);
+
+ static void onPropertySetErrorEvent(
+ const std::weak_ptr<SubscriptionManager>& subscriptionManager,
+ const std::vector<SetValueErrorEvent>& errorEvents);
+
+ static void onSupportedValueChange(
+ const std::weak_ptr<SubscriptionManager>& subscriptionManager,
+ const std::vector<PropIdAreaId>& updatedPropIdAreaIds);
+
+ static void checkHealth(IVehicleHardware* hardware,
+ std::weak_ptr<SubscriptionManager> subscriptionManager);
+
+ static void onBinderDied(void* cookie);
+
+ static void onBinderUnlinked(void* cookie);
+
+ static void parseSubscribeOptions(
+ const std::vector<aidlvhal::SubscribeOptions>& options,
+ const std::unordered_map<int32_t, aidlvhal::VehiclePropConfig>& configsByPropId,
+ std::vector<aidlvhal::SubscribeOptions>& onChangeSubscriptions,
+ std::vector<aidlvhal::SubscribeOptions>& continuousSubscriptions);
+
+ // Test-only
+ // Set the default timeout for pending requests.
+ void setTimeout(int64_t timeoutInNano);
+
+ // Test-only
+ void setBinderLifecycleHandler(std::unique_ptr<BinderLifecycleInterface> 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 0000000..f4e6ced
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/current/vhal/include/SubscriptionManager.h
@@ -0,0 +1,224 @@
+/*
+ * 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 <IVehicleHardware.h>
+#include <VehicleHalTypes.h>
+#include <VehicleUtils.h>
+
+#include <aidl/android/hardware/automotive/vehicle/IVehicleCallback.h>
+#include <android-base/result.h>
+#include <android-base/thread_annotations.h>
+
+#include <cmath>
+#include <limits>
+#include <mutex>
+#include <optional>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+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<float>::max();
+ bool mEnableVur;
+ std::unordered_map<ClientIdType, SubConfig> 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<aidl::android::hardware::automotive::vehicle::IVehicleCallback>;
+ 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<void> subscribe(
+ const CallbackType& callback,
+ const std::vector<aidl::android::hardware::automotive::vehicle::SubscribeOptions>&
+ options,
+ bool isContinuousProperty);
+
+ // Unsubscribes from the properties for the client.
+ // Returns error if 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<void> unsubscribe(ClientIdType client, const std::vector<int32_t>& propIds);
+
+ // Unsubscribes from all the properties for the client.
+ // Returns error 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<void> 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<CallbackType, std::vector<VehiclePropValue>> getSubscribedClients(
+ std::vector<VehiclePropValue>&& 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<CallbackType,
+ std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropError>>
+ getSubscribedClientsForErrorEvents(const std::vector<SetValueErrorEvent>& errorEvents);
+
+ // For a list of [propId, areaId]s that has updated supported value, returns a map that maps
+ // subscribing clients to updated [propId, areaId]s.
+ std::unordered_map<CallbackType, std::vector<PropIdAreaId>>
+ getSubscribedClientsForSupportedValueChange(const std::vector<PropIdAreaId>& propIdAreaIds);
+
+ // Subscribes to supported values change.
+ VhalResult<void> subscribeSupportedValueChange(const CallbackType& callback,
+ const std::vector<PropIdAreaId>& propIdAreaIds);
+
+ // Unsubscribes to supported values change.
+ VhalResult<void> unsubscribeSupportedValueChange(
+ ClientIdType client, const std::vector<PropIdAreaId>& propIdAreaIds);
+
+ // Returns the number of subscribed property change clients.
+ size_t countPropertyChangeClients();
+
+ // Returns the number of subscribed supported value change clients.
+ size_t countSupportedValueChangeClients();
+
+ // 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;
+ friend class SubscriptionManagerTest;
+
+ 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<PropIdAreaId, std::unordered_map<ClientIdType, CallbackType>,
+ PropIdAreaIdHash>
+ mClientsByPropIdAreaId GUARDED_BY(mLock);
+ std::unordered_map<ClientIdType, std::unordered_set<PropIdAreaId, PropIdAreaIdHash>>
+ mSubscribedPropsByClient GUARDED_BY(mLock);
+ std::unordered_map<PropIdAreaId, ContSubConfigs, PropIdAreaIdHash> mContSubConfigsByPropIdArea
+ GUARDED_BY(mLock);
+ std::unordered_map<CallbackType,
+ std::unordered_set<VehiclePropValue, VehiclePropValueHashPropIdAreaId,
+ VehiclePropValueEqualPropIdAreaId>>
+ mContSubValuesByCallback GUARDED_BY(mLock);
+ std::unordered_map<PropIdAreaId, std::unordered_map<ClientIdType, CallbackType>,
+ PropIdAreaIdHash>
+ mSupportedValueChangeClientsByPropIdAreaId GUARDED_BY(mLock);
+ std::unordered_map<ClientIdType, std::unordered_set<PropIdAreaId, PropIdAreaIdHash>>
+ mSupportedValueChangePropIdAreaIdsByClient GUARDED_BY(mLock);
+
+ VhalResult<void> addContinuousSubscriberLocked(const ClientIdType& clientId,
+ const PropIdAreaId& propIdAreaId,
+ float sampleRateHz, float resolution,
+ bool enableVur) REQUIRES(mLock);
+ VhalResult<void> addOnChangeSubscriberLocked(const PropIdAreaId& propIdAreaId) REQUIRES(mLock);
+ // Removes the subscription client for the continuous [propId, areaId].
+ VhalResult<void> removeContinuousSubscriberLocked(const ClientIdType& clientId,
+ const PropIdAreaId& propIdAreaId)
+ REQUIRES(mLock);
+ // Removes one subscription client for the on-change [propId, areaId].
+ VhalResult<void> removeOnChangeSubscriberLocked(const PropIdAreaId& propIdAreaId)
+ REQUIRES(mLock);
+
+ VhalResult<void> updateContSubConfigsLocked(const PropIdAreaId& PropIdAreaId,
+ const ContSubConfigs& newConfig) REQUIRES(mLock);
+
+ VhalResult<void> unsubscribePropIdAreaIdLocked(SubscriptionManager::ClientIdType clientId,
+ const PropIdAreaId& propIdAreaId)
+ REQUIRES(mLock);
+ VhalResult<void> unsubscribeSupportedValueChangeLocked(
+ SubscriptionManager::ClientIdType clientId,
+ const std::vector<PropIdAreaId>& propIdAreaIds) 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<int64_t> 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 0000000..ac2691a
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/current/vhal/src/ConnectedClient.cpp
@@ -0,0 +1,336 @@
+/*
+ * 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 <VehicleHalTypes.h>
+
+#include <utils/Log.h>
+
+#include <inttypes.h>
+#include <unordered_set>
+#include <vector>
+
+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 <class T>
+ScopedAStatus callCallback(std::shared_ptr<IVehicleCallback> callback, const T& results);
+
+template <>
+ScopedAStatus callCallback<GetValueResults>(std::shared_ptr<IVehicleCallback> callback,
+ const GetValueResults& results) {
+ return callback->onGetValues(results);
+}
+
+template <>
+ScopedAStatus callCallback<SetValueResults>(std::shared_ptr<IVehicleCallback> callback,
+ const SetValueResults& results) {
+ return callback->onSetValues(results);
+}
+
+// Send a single GetValue/SetValue result through the callback.
+template <class ResultType, class ResultsType>
+void sendGetOrSetValueResult(std::shared_ptr<IVehicleCallback> 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 <class ResultType, class ResultsType>
+void sendGetOrSetValueResultsSeparately(std::shared_ptr<IVehicleCallback> callback,
+ const std::vector<ResultType>& results) {
+ for (const auto& result : results) {
+ sendGetOrSetValueResult<ResultType, ResultsType>(callback, result);
+ }
+}
+
+// Send all the GetValue/SetValue results through callback in a single callback invocation.
+template <class ResultType, class ResultsType>
+void sendGetOrSetValueResults(std::shared_ptr<IVehicleCallback> callback,
+ std::vector<ResultType>&& 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<ResultType, ResultsType>(callback,
+ parcelableResults.payloads);
+}
+
+// The timeout callback for GetValues/SetValues.
+template <class ResultType, class ResultsType>
+void onTimeout(
+ std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback> callback,
+ const std::unordered_set<int64_t>& timeoutIds) {
+ std::vector<ResultType> timeoutResults;
+ for (int64_t requestId : timeoutIds) {
+ ALOGD("hardware request timeout, request ID: %" PRId64, requestId);
+ timeoutResults.push_back({
+ .requestId = requestId,
+ .status = StatusCode::TRY_AGAIN,
+ });
+ }
+ sendGetOrSetValueResults<ResultType, ResultsType>(callback, std::move(timeoutResults));
+}
+
+// The on-results callback for GetValues/SetValues.
+template <class ResultType, class ResultsType>
+void getOrSetValuesCallback(
+ const void* clientId,
+ std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback> callback,
+ std::vector<ResultType>&& results, std::shared_ptr<PendingRequestPool> requestPool) {
+ std::unordered_set<int64_t> 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<ResultType, ResultsType>(callback, std::move(results));
+ }
+}
+
+// Specify the functions for GetValues and SetValues types.
+template void sendGetOrSetValueResult<GetValueResult, GetValueResults>(
+ std::shared_ptr<IVehicleCallback> callback, const GetValueResult& result);
+template void sendGetOrSetValueResult<SetValueResult, SetValueResults>(
+ std::shared_ptr<IVehicleCallback> callback, const SetValueResult& result);
+
+template void sendGetOrSetValueResults<GetValueResult, GetValueResults>(
+ std::shared_ptr<IVehicleCallback> callback, std::vector<GetValueResult>&& results);
+template void sendGetOrSetValueResults<SetValueResult, SetValueResults>(
+ std::shared_ptr<IVehicleCallback> callback, std::vector<SetValueResult>&& results);
+
+template void sendGetOrSetValueResultsSeparately<GetValueResult, GetValueResults>(
+ std::shared_ptr<IVehicleCallback> callback, const std::vector<GetValueResult>& results);
+template void sendGetOrSetValueResultsSeparately<SetValueResult, SetValueResults>(
+ std::shared_ptr<IVehicleCallback> callback, const std::vector<SetValueResult>& results);
+
+template void onTimeout<GetValueResult, GetValueResults>(
+ std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback> callback,
+ const std::unordered_set<int64_t>& timeoutIds);
+template void onTimeout<SetValueResult, SetValueResults>(
+ std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback> callback,
+ const std::unordered_set<int64_t>& timeoutIds);
+
+template void getOrSetValuesCallback<GetValueResult, GetValueResults>(
+ const void* clientId,
+ std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback> callback,
+ std::vector<GetValueResult>&& results, std::shared_ptr<PendingRequestPool> requestPool);
+template void getOrSetValuesCallback<SetValueResult, SetValueResults>(
+ const void* clientId,
+ std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback> callback,
+ std::vector<SetValueResult>&& results, std::shared_ptr<PendingRequestPool> requestPool);
+
+} // namespace
+
+ConnectedClient::ConnectedClient(std::shared_ptr<PendingRequestPool> requestPool,
+ std::shared_ptr<IVehicleCallback> callback)
+ : mRequestPool(requestPool), mCallback(callback) {}
+
+const void* ConnectedClient::id() {
+ return reinterpret_cast<const void*>(this);
+}
+
+VhalResult<void> ConnectedClient::addRequests(const std::unordered_set<int64_t>& requestIds) {
+ return mRequestPool->addRequests(id(), requestIds, getTimeoutCallback());
+}
+
+std::unordered_set<int64_t> ConnectedClient::tryFinishRequests(
+ const std::unordered_set<int64_t>& requestIds) {
+ return mRequestPool->tryFinishRequests(id(), requestIds);
+}
+
+template <class ResultType, class ResultsType>
+GetSetValuesClient<ResultType, ResultsType>::GetSetValuesClient(
+ std::shared_ptr<PendingRequestPool> requestPool, std::shared_ptr<IVehicleCallback> callback)
+ : ConnectedClient(requestPool, callback) {
+ mTimeoutCallback = std::make_shared<const PendingRequestPool::TimeoutCallbackFunc>(
+ [callback](const std::unordered_set<int64_t>& timeoutIds) {
+ return onTimeout<ResultType, ResultsType>(callback, timeoutIds);
+ });
+ auto requestPoolCopy = mRequestPool;
+ const void* clientId = id();
+ mResultCallback = std::make_shared<const std::function<void(std::vector<ResultType>)>>(
+ [clientId, callback, requestPoolCopy](std::vector<ResultType> results) {
+ return getOrSetValuesCallback<ResultType, ResultsType>(
+ clientId, callback, std::move(results), requestPoolCopy);
+ });
+}
+
+template <class ResultType, class ResultsType>
+std::shared_ptr<const std::function<void(std::vector<ResultType>)>>
+GetSetValuesClient<ResultType, ResultsType>::getResultCallback() {
+ return mResultCallback;
+}
+
+template <class ResultType, class ResultsType>
+std::shared_ptr<const PendingRequestPool::TimeoutCallbackFunc>
+GetSetValuesClient<ResultType, ResultsType>::getTimeoutCallback() {
+ return mTimeoutCallback;
+}
+
+template <class ResultType, class ResultsType>
+void GetSetValuesClient<ResultType, ResultsType>::sendResults(std::vector<ResultType>&& results) {
+ return sendGetOrSetValueResults<ResultType, ResultsType>(mCallback, std::move(results));
+}
+
+template <class ResultType, class ResultsType>
+void GetSetValuesClient<ResultType, ResultsType>::sendResultsSeparately(
+ const std::vector<ResultType>& results) {
+ return sendGetOrSetValueResultsSeparately<ResultType, ResultsType>(mCallback, results);
+}
+
+template class GetSetValuesClient<GetValueResult, GetValueResults>;
+template class GetSetValuesClient<SetValueResult, SetValueResults>;
+
+void SubscriptionClient::sendUpdatedValues(std::shared_ptr<IVehicleCallback> callback,
+ std::vector<VehiclePropValue>&& 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<IVehicleCallback> callback,
+ std::vector<VehiclePropError>&& 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());
+ }
+}
+
+void SubscriptionClient::sendSupportedValueChangeEvents(std::shared_ptr<IVehicleCallback> callback,
+ std::vector<PropIdAreaId> propIdAreaIds) {
+ if (propIdAreaIds.empty()) {
+ return;
+ }
+
+ std::vector<aidl::android::hardware::automotive::vehicle::PropIdAreaId> vhalPropIdAreaIds;
+ for (const auto& propIdAreaId : propIdAreaIds) {
+ vhalPropIdAreaIds.push_back(aidl::android::hardware::automotive::vehicle::PropIdAreaId{
+ .propId = propIdAreaId.propId,
+ .areaId = propIdAreaId.areaId,
+ });
+ }
+
+ if (ScopedAStatus callbackStatus = callback->onSupportedValueChange(vhalPropIdAreaIds);
+ !callbackStatus.isOk()) {
+ ALOGE("subscribe: failed to call onSupportedValueChange 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 0000000..ea0c215
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/current/vhal/src/DefaultVehicleHal.cpp
@@ -0,0 +1,1357 @@
+/*
+ * 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 <DefaultVehicleHal.h>
+
+#include <LargeParcelableBase.h>
+#include <VehicleHalTypes.h>
+#include <VehicleUtils.h>
+#include <VersionForVehicleProperty.h>
+
+#include <android-base/logging.h>
+#include <android-base/result.h>
+#include <android-base/stringprintf.h>
+#include <android/binder_ibinder.h>
+#include <private/android_filesystem_config.h>
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+#include <utils/Trace.h>
+
+#include <inttypes.h>
+#include <chrono>
+#include <set>
+#include <unordered_set>
+
+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::HasSupportedValueInfo;
+using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback;
+using ::aidl::android::hardware::automotive::vehicle::MinMaxSupportedValueResult;
+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::SupportedValuesListResult;
+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;
+
+using VhalPropIdAreaId = ::aidl::android::hardware::automotive::vehicle::PropIdAreaId;
+
+std::string toString(const std::unordered_set<int64_t>& 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<IVehicleHardware> vehicleHardware)
+ : DefaultVehicleHal(std::move(vehicleHardware), /* testInterfaceVersion= */ 0) {};
+
+DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware,
+ int32_t testInterfaceVersion)
+ : mVehicleHardware(std::move(vehicleHardware)),
+ mPendingRequestPool(std::make_shared<PendingRequestPool>(TIMEOUT_IN_NANO)),
+ mTestInterfaceVersion(testInterfaceVersion) {
+ ALOGD("DefaultVehicleHal init");
+ IVehicleHardware* vehicleHardwarePtr = mVehicleHardware.get();
+ mSubscriptionManager = std::make_shared<SubscriptionManager>(vehicleHardwarePtr);
+ mEventBatchingWindow = mVehicleHardware->getPropertyOnChangeEventBatchingWindow();
+ if (mEventBatchingWindow != std::chrono::nanoseconds(0)) {
+ mBatchedEventQueue = std::make_shared<ConcurrentQueue<VehiclePropValue>>();
+ mPropertyChangeEventsBatchingConsumer =
+ std::make_shared<BatchingConsumer<VehiclePropValue>>();
+ mPropertyChangeEventsBatchingConsumer->run(
+ mBatchedEventQueue.get(), mEventBatchingWindow,
+ [this](std::vector<VehiclePropValue> batchedEvents) {
+ handleBatchedPropertyEvents(std::move(batchedEvents));
+ });
+ }
+
+ std::weak_ptr<ConcurrentQueue<VehiclePropValue>> batchedEventQueueCopy = mBatchedEventQueue;
+ std::chrono::nanoseconds eventBatchingWindow = mEventBatchingWindow;
+ std::weak_ptr<SubscriptionManager> subscriptionManagerCopy = mSubscriptionManager;
+ mVehicleHardware->registerOnPropertyChangeEvent(
+ std::make_unique<IVehicleHardware::PropertyChangeCallback>(
+ [subscriptionManagerCopy, batchedEventQueueCopy,
+ eventBatchingWindow](std::vector<VehiclePropValue> updatedValues) {
+ if (eventBatchingWindow != std::chrono::nanoseconds(0)) {
+ batchPropertyChangeEvent(batchedEventQueueCopy,
+ std::move(updatedValues));
+ } else {
+ onPropertyChangeEvent(subscriptionManagerCopy,
+ std::move(updatedValues));
+ }
+ }));
+ mVehicleHardware->registerOnPropertySetErrorEvent(
+ std::make_unique<IVehicleHardware::PropertySetErrorCallback>(
+ [subscriptionManagerCopy](std::vector<SetValueErrorEvent> errorEvents) {
+ onPropertySetErrorEvent(subscriptionManagerCopy, errorEvents);
+ }));
+ mVehicleHardware->registerSupportedValueChangeCallback(
+ std::make_unique<IVehicleHardware::SupportedValueChangeCallback>(
+ [subscriptionManagerCopy](std::vector<PropIdAreaId> propIdAreaIds) {
+ onSupportedValueChange(subscriptionManagerCopy, propIdAreaIds);
+ }));
+
+ // Register heartbeat event.
+ mRecurrentAction = std::make_shared<std::function<void()>>(
+ [vehicleHardwarePtr, subscriptionManagerCopy]() {
+ checkHealth(vehicleHardwarePtr, subscriptionManagerCopy);
+ });
+ mRecurrentTimer.registerTimerCallback(HEART_BEAT_INTERVAL_IN_NANO, mRecurrentAction);
+
+ mBinderLifecycleHandler = std::make_unique<BinderLifecycleHandler>();
+ 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<ConcurrentQueue<VehiclePropValue>>& batchedEventQueue,
+ std::vector<VehiclePropValue>&& updatedValues) {
+ auto batchedEventQueueStrong = batchedEventQueue.lock();
+ if (batchedEventQueueStrong == nullptr) {
+ ALOGW("%s: the batched property events queue is destroyed, DefaultVehicleHal is ending",
+ __func__);
+ return;
+ }
+ batchedEventQueueStrong->push(std::move(updatedValues));
+}
+
+void DefaultVehicleHal::handleBatchedPropertyEvents(std::vector<VehiclePropValue>&& batchedEvents) {
+ onPropertyChangeEvent(mSubscriptionManager, std::move(batchedEvents));
+}
+
+void DefaultVehicleHal::onPropertyChangeEvent(
+ const std::weak_ptr<SubscriptionManager>& subscriptionManager,
+ std::vector<VehiclePropValue>&& updatedValues) {
+ ATRACE_CALL();
+ auto manager = subscriptionManager.lock();
+ if (manager == nullptr) {
+ ALOGW("%s: the SubscriptionManager is destroyed, DefaultVehicleHal is ending", __func__);
+ 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>& subscriptionManager,
+ const std::vector<SetValueErrorEvent>& errorEvents) {
+ auto manager = subscriptionManager.lock();
+ if (manager == nullptr) {
+ ALOGW("%s: the SubscriptionManager is destroyed, DefaultVehicleHal is ending", __func__);
+ return;
+ }
+ auto vehiclePropErrorsByClient = manager->getSubscribedClientsForErrorEvents(errorEvents);
+ for (auto& [callback, vehiclePropErrors] : vehiclePropErrorsByClient) {
+ SubscriptionClient::sendPropertySetErrors(callback, std::move(vehiclePropErrors));
+ }
+}
+
+void DefaultVehicleHal::onSupportedValueChange(
+ const std::weak_ptr<SubscriptionManager>& subscriptionManager,
+ const std::vector<PropIdAreaId>& propIdAreaIds) {
+ auto manager = subscriptionManager.lock();
+ if (manager == nullptr) {
+ ALOGW("%s: the SubscriptionManager is destroyed, DefaultVehicleHal is ending", __func__);
+ return;
+ }
+ auto updatedPropIdAreaIdsByClient =
+ manager->getSubscribedClientsForSupportedValueChange(propIdAreaIds);
+ for (auto& [callback, updatedPropIdAreaIds] : updatedPropIdAreaIdsByClient) {
+ SubscriptionClient::sendSupportedValueChangeEvents(callback,
+ std::move(updatedPropIdAreaIds));
+ }
+}
+
+template <class T>
+std::shared_ptr<T> DefaultVehicleHal::getOrCreateClient(
+ std::unordered_map<const AIBinder*, std::shared_ptr<T>>* clients,
+ const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool) {
+ const AIBinder* clientId = callback->asBinder().get();
+ if (clients->find(clientId) == clients->end()) {
+ (*clients)[clientId] = std::make_shared<T>(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<OnBinderDiedContext> context = std::make_unique<OnBinderDiedContext>(
+ 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<AIBinder*>(clientId), mDeathRecipient.get(), static_cast<void*>(contextPtr));
+ if (status == STATUS_OK) {
+ return true;
+ }
+ ALOGE("failed to call linkToDeath on client binder, client may already died, status: %d",
+ static_cast<int>(status));
+ return false;
+}
+
+void DefaultVehicleHal::onBinderDied(void* cookie) {
+ OnBinderDiedContext* context = reinterpret_cast<OnBinderDiedContext*>(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<std::mutex> 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<OnBinderDiedContext*>(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<std::mutex> 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::GetValuesClient>
+DefaultVehicleHal::getOrCreateClient<DefaultVehicleHal::GetValuesClient>(
+ std::unordered_map<const AIBinder*, std::shared_ptr<GetValuesClient>>* clients,
+ const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool);
+template std::shared_ptr<DefaultVehicleHal::SetValuesClient>
+DefaultVehicleHal::getOrCreateClient<DefaultVehicleHal::SetValuesClient>(
+ std::unordered_map<const AIBinder*, std::shared_ptr<SetValuesClient>>* clients,
+ const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool);
+
+void DefaultVehicleHal::setTimeout(int64_t timeoutInNano) {
+ mPendingRequestPool = std::make_unique<PendingRequestPool>(timeoutInNano);
+}
+
+int32_t DefaultVehicleHal::getVhalInterfaceVersion() const {
+ if (mTestInterfaceVersion != 0) {
+ return mTestInterfaceVersion;
+ }
+ int32_t myVersion = 0;
+ // getInterfaceVersion is in-reality a const method.
+ const_cast<DefaultVehicleHal*>(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<VehicleProperty>(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<VehiclePropConfig> filteredConfigs;
+ for (const auto& config : configs) {
+ if (isConfigSupportedForCurrentVhalVersion(config)) {
+ filteredConfigs.push_back(std::move(config));
+ }
+ }
+
+ {
+ std::unique_lock<std::shared_timed_mutex> 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<int>(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<void(const std::unordered_map<int32_t, VehiclePropConfig>&)> callback) const {
+ if (!mConfigInit) {
+ CHECK(getAllPropConfigsFromHardwareLocked())
+ << "Failed to get property configs from hardware";
+ }
+
+ std::shared_lock<std::shared_timed_mutex> 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<std::shared_timed_mutex> 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<VehiclePropConfig> DefaultVehicleHal::getConfig(int32_t propId) const {
+ Result<VehiclePropConfig> result;
+
+ if (!mConfigInit) {
+ std::optional<VehiclePropConfig> 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<void> 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<LargeParcelableBase::BorrowedOwnedObject<GetValueRequests>, ScopedAStatus>
+ deserializedResults = fromStableLargeParcelable(requests);
+ if (!deserializedResults.ok()) {
+ ALOGE("getValues: failed to parse getValues requests");
+ return std::move(deserializedResults.error());
+ }
+ const std::vector<GetValueRequest>& 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<GetValueResult> failedResults;
+ // The list of requests that we would send to hardware.
+ std::vector<GetValueRequest> 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<int64_t> hardwareRequestIds;
+ for (const auto& request : hardwareRequests) {
+ hardwareRequestIds.insert(request.requestId);
+ }
+
+ std::shared_ptr<GetValuesClient> 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<LargeParcelableBase::BorrowedOwnedObject<SetValueRequests>, ScopedAStatus>
+ deserializedResults = fromStableLargeParcelable(requests);
+ if (!deserializedResults.ok()) {
+ ALOGE("setValues: failed to parse setValues requests");
+ return std::move(deserializedResults.error());
+ }
+ const std::vector<SetValueRequest>& setValueRequests =
+ deserializedResults.value().getObject()->payloads;
+
+ // A list of failed result we already know before sending to hardware.
+ std::vector<SetValueResult> failedResults;
+ // The list of requests that we would send to hardware.
+ std::vector<SetValueRequest> 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<int64_t> hardwareRequestIds;
+ for (const auto& request : hardwareRequests) {
+ hardwareRequestIds.insert(request.requestId);
+ }
+
+ std::shared_ptr<SetValuesClient> 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<int64_t> 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<std::vector<int64_t>> DefaultVehicleHal::checkDuplicateRequests(
+ const std::vector<GetValueRequest>& requests) {
+ CHECK_DUPLICATE_REQUESTS(prop);
+}
+
+::android::base::Result<std::vector<int64_t>> DefaultVehicleHal::checkDuplicateRequests(
+ const std::vector<SetValueRequest>& requests) {
+ CHECK_DUPLICATE_REQUESTS(value);
+}
+
+#undef CHECK_DUPLICATE_REQUESTS
+
+ScopedAStatus DefaultVehicleHal::getPropConfigs(const std::vector<int32_t>& props,
+ VehiclePropConfigs* output) {
+ std::vector<VehiclePropConfig> 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<VehicleAreaConfig>& areaConfigs,
+ VehiclePropertyAccess requiredAccess) {
+ if (areaConfigs.empty()) {
+ return false;
+ }
+ for (VehicleAreaConfig areaConfig : areaConfigs) {
+ if (!hasRequiredAccess(areaConfig.access, requiredAccess)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+VhalResult<void> DefaultVehicleHal::checkSubscribeOptions(
+ const std::vector<SubscribeOptions>& options,
+ const std::unordered_map<int32_t, VehiclePropConfig>& 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<VehicleAreaConfig> areaConfigs;
+ if (option.areaIds.empty()) {
+ areaConfigs = config.areaConfigs;
+ } else {
+ std::unordered_map<int, VehicleAreaConfig> 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<SubscribeOptions>& options,
+ const std::unordered_map<int32_t, VehiclePropConfig>& configsByPropId,
+ std::vector<SubscribeOptions>& onChangeSubscriptions,
+ std::vector<SubscribeOptions>& 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<int32_t> areasVurEnabled;
+ std::vector<int32_t> 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<SubscribeOptions>& 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<SubscribeOptions> onChangeSubscriptions;
+ std::vector<SubscribeOptions> 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
+ // (before subscribe). Without this, we may create a new subscription for an already dead
+ // client which will never be unsubscribed.
+ 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<int32_t>& 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();
+}
+
+Result<VehicleAreaConfig> DefaultVehicleHal::getAreaConfigForPropIdAreaId(int32_t propId,
+ int32_t areaId) const {
+ auto result = getConfig(propId);
+ if (!result.ok()) {
+ return Error() << "Failed to get property config for propertyId: " << propIdToString(propId)
+ << ", error: " << result.error();
+ }
+ const VehiclePropConfig& config = result.value();
+ const VehicleAreaConfig* areaConfig = getAreaConfig(propId, areaId, config);
+ if (areaConfig == nullptr) {
+ return Error() << "AreaId config not found for propertyId: " << propIdToString(propId)
+ << ", areaId: " << areaId;
+ }
+ return *areaConfig;
+}
+
+Result<HasSupportedValueInfo> DefaultVehicleHal::getHasSupportedValueInfo(int32_t propId,
+ int32_t areaId) const {
+ Result<VehicleAreaConfig> propIdAreaIdConfigResult =
+ getAreaConfigForPropIdAreaId(propId, areaId);
+ if (!isGlobalProp(propId) && !propIdAreaIdConfigResult.ok()) {
+ // For global property, it is possible that no config exists.
+ return Error() << propIdAreaIdConfigResult.error();
+ }
+ if (propIdAreaIdConfigResult.has_value()) {
+ auto areaConfig = propIdAreaIdConfigResult.value();
+ if (areaConfig.hasSupportedValueInfo.has_value()) {
+ return areaConfig.hasSupportedValueInfo.value();
+ }
+ }
+ return Error() << "property: " << propIdToString(propId) << ", areaId: " << areaId
+ << " does not support this operation because hasSupportedValueInfo is null";
+}
+
+ScopedAStatus DefaultVehicleHal::getSupportedValuesLists(
+ const std::vector<VhalPropIdAreaId>& vhalPropIdAreaIds,
+ SupportedValuesListResults* supportedValuesListResults) {
+ std::vector<size_t> toHardwareRequestCounters;
+ std::vector<PropIdAreaId> toHardwarePropIdAreaIds;
+ std::vector<SupportedValuesListResult> results;
+ results.resize(vhalPropIdAreaIds.size());
+ for (size_t requestCounter = 0; requestCounter < vhalPropIdAreaIds.size(); requestCounter++) {
+ const auto& vhalPropIdAreaId = vhalPropIdAreaIds.at(requestCounter);
+ int32_t propId = vhalPropIdAreaId.propId;
+ int32_t areaId = vhalPropIdAreaId.areaId;
+ auto hasSupportedValueInfoResult = getHasSupportedValueInfo(propId, areaId);
+ if (!hasSupportedValueInfoResult.ok()) {
+ ALOGE("getSupportedValuesLists: %s",
+ hasSupportedValueInfoResult.error().message().c_str());
+ results[requestCounter] = SupportedValuesListResult{
+ .status = StatusCode::INVALID_ARG, .supportedValuesList = std::nullopt};
+ continue;
+ }
+
+ const auto& hasSupportedValueInfo = hasSupportedValueInfoResult.value();
+ if (hasSupportedValueInfo.hasSupportedValuesList) {
+ toHardwarePropIdAreaIds.push_back(PropIdAreaId{.propId = propId, .areaId = areaId});
+ toHardwareRequestCounters.push_back(requestCounter);
+ } else {
+ results[requestCounter] = SupportedValuesListResult{
+ .status = StatusCode::OK, .supportedValuesList = std::nullopt};
+ continue;
+ }
+ }
+ if (toHardwarePropIdAreaIds.size() != 0) {
+ std::vector<SupportedValuesListResult> resultsFromHardware =
+ mVehicleHardware->getSupportedValuesLists(toHardwarePropIdAreaIds);
+ // It is guaranteed that toHardwarePropIdAreaIds, toHardwareRequestCounters,
+ // resultsFromHardware have the same size.
+ if (resultsFromHardware.size() != toHardwareRequestCounters.size()) {
+ return ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ toInt(StatusCode::INTERNAL_ERROR),
+ fmt::format(
+ "getSupportedValuesLists: Unexpected results size from IVehicleHardware"
+ ", got: {}, expect: {}",
+ resultsFromHardware.size(), toHardwareRequestCounters.size())
+ .c_str());
+ }
+ for (size_t i = 0; i < toHardwareRequestCounters.size(); i++) {
+ results[toHardwareRequestCounters[i]] = resultsFromHardware[i];
+ }
+ }
+ ScopedAStatus status =
+ vectorToStableLargeParcelable(std::move(results), supportedValuesListResults);
+ if (!status.isOk()) {
+ int statusCode = status.getServiceSpecificError();
+ ALOGE("getSupportedValuesLists: failed to marshal result into large parcelable, error: "
+ "%s, code: %d",
+ status.getMessage(), statusCode);
+ return status;
+ }
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultVehicleHal::getMinMaxSupportedValue(
+ const std::vector<VhalPropIdAreaId>& vhalPropIdAreaIds,
+ MinMaxSupportedValueResults* minMaxSupportedValueResults) {
+ std::vector<size_t> toHardwareRequestCounters;
+ std::vector<PropIdAreaId> toHardwarePropIdAreaIds;
+ std::vector<MinMaxSupportedValueResult> results;
+ results.resize(vhalPropIdAreaIds.size());
+ for (size_t requestCounter = 0; requestCounter < vhalPropIdAreaIds.size(); requestCounter++) {
+ const auto& vhalPropIdAreaId = vhalPropIdAreaIds.at(requestCounter);
+ int32_t propId = vhalPropIdAreaId.propId;
+ int32_t areaId = vhalPropIdAreaId.areaId;
+ auto hasSupportedValueInfoResult = getHasSupportedValueInfo(propId, areaId);
+ if (!hasSupportedValueInfoResult.ok()) {
+ ALOGE("getMinMaxSupportedValue: %s",
+ hasSupportedValueInfoResult.error().message().c_str());
+ results[requestCounter] = MinMaxSupportedValueResult{.status = StatusCode::INVALID_ARG,
+ .minSupportedValue = std::nullopt,
+ .maxSupportedValue = std::nullopt};
+ continue;
+ }
+
+ const auto& hasSupportedValueInfo = hasSupportedValueInfoResult.value();
+ if (hasSupportedValueInfo.hasMinSupportedValue ||
+ hasSupportedValueInfo.hasMaxSupportedValue) {
+ toHardwarePropIdAreaIds.push_back(PropIdAreaId{.propId = propId, .areaId = areaId});
+ toHardwareRequestCounters.push_back(requestCounter);
+ } else {
+ results[requestCounter] = MinMaxSupportedValueResult{.status = StatusCode::OK,
+ .minSupportedValue = std::nullopt,
+ .maxSupportedValue = std::nullopt};
+ continue;
+ }
+ }
+ if (toHardwarePropIdAreaIds.size() != 0) {
+ std::vector<MinMaxSupportedValueResult> resultsFromHardware =
+ mVehicleHardware->getMinMaxSupportedValues(toHardwarePropIdAreaIds);
+ // It is guaranteed that toHardwarePropIdAreaIds, toHardwareRequestCounters,
+ // resultsFromHardware have the same size.
+ if (resultsFromHardware.size() != toHardwareRequestCounters.size()) {
+ return ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ toInt(StatusCode::INTERNAL_ERROR),
+ fmt::format(
+ "getMinMaxSupportedValue: Unexpected results size from IVehicleHardware"
+ ", got: {}, expect: {}",
+ resultsFromHardware.size(), toHardwareRequestCounters.size())
+ .c_str());
+ }
+ for (size_t i = 0; i < toHardwareRequestCounters.size(); i++) {
+ results[toHardwareRequestCounters[i]] = resultsFromHardware[i];
+ }
+ }
+ ScopedAStatus status =
+ vectorToStableLargeParcelable(std::move(results), minMaxSupportedValueResults);
+ if (!status.isOk()) {
+ int statusCode = status.getServiceSpecificError();
+ ALOGE("getMinMaxSupportedValue: failed to marshal result into large parcelable, error: "
+ "%s, code: %d",
+ status.getMessage(), statusCode);
+ return status;
+ }
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultVehicleHal::registerSupportedValueChangeCallback(
+ const std::shared_ptr<IVehicleCallback>& callback,
+ const std::vector<VhalPropIdAreaId>& vhalPropIdAreaIds) {
+ std::vector<PropIdAreaId> propIdAreaIdsToSubscribe;
+ for (size_t i = 0; i < vhalPropIdAreaIds.size(); i++) {
+ const auto& vhalPropIdAreaId = vhalPropIdAreaIds.at(i);
+ int32_t propId = vhalPropIdAreaId.propId;
+ int32_t areaId = vhalPropIdAreaId.areaId;
+ auto hasSupportedValueInfoResult = getHasSupportedValueInfo(propId, areaId);
+ if (!hasSupportedValueInfoResult.ok()) {
+ ALOGE("registerSupportedValueChangeCallback not supported: %s",
+ hasSupportedValueInfoResult.error().message().c_str());
+ return toScopedAStatus(hasSupportedValueInfoResult, StatusCode::INVALID_ARG);
+ }
+ const auto& hasSupportedValueInfo = hasSupportedValueInfoResult.value();
+ if (!hasSupportedValueInfo.hasMinSupportedValue &&
+ !hasSupportedValueInfo.hasMaxSupportedValue &&
+ !hasSupportedValueInfo.hasSupportedValuesList) {
+ ALOGW("registerSupportedValueChangeCallback: do nothing for property: %s, "
+ "areaId: %" PRId32
+ ", no min/max supported values or supported values list"
+ " specified",
+ propIdToString(propId).c_str(), areaId);
+ continue;
+ }
+ propIdAreaIdsToSubscribe.push_back(PropIdAreaId{.propId = propId, .areaId = areaId});
+ }
+ if (propIdAreaIdsToSubscribe.empty()) {
+ return ScopedAStatus::ok();
+ }
+ {
+ // Lock to make sure onBinderDied would not be called concurrently
+ // (before subscribeSupportedValueChange). Without this, we may create a new subscription
+ // for an already dead client which will never be unsubscribed.
+ std::scoped_lock lockGuard(mLock);
+ if (!monitorBinderLifeCycleLocked(callback->asBinder().get())) {
+ return ScopedAStatus::fromExceptionCodeWithMessage(EX_TRANSACTION_FAILED,
+ "client died");
+ }
+ auto result = mSubscriptionManager->subscribeSupportedValueChange(callback,
+ propIdAreaIdsToSubscribe);
+ if (!result.ok()) {
+ ALOGW("registerSupportedValueChangeCallback: failed to subscribe supported value change"
+ " for %s, error: %s",
+ fmt::format("{}", propIdAreaIdsToSubscribe).c_str(),
+ result.error().message().c_str());
+ return toScopedAStatus(result);
+ }
+ }
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultVehicleHal::unregisterSupportedValueChangeCallback(
+ const std::shared_ptr<IVehicleCallback>& callback,
+ const std::vector<VhalPropIdAreaId>& vhalPropIdAreaIds) {
+ std::vector<PropIdAreaId> propIdAreaIds;
+ for (const auto& vhalPropIdAreaId : vhalPropIdAreaIds) {
+ propIdAreaIds.push_back(
+ PropIdAreaId{.propId = vhalPropIdAreaId.propId, .areaId = vhalPropIdAreaId.areaId});
+ }
+
+ auto result = mSubscriptionManager->unsubscribeSupportedValueChange(callback->asBinder().get(),
+ propIdAreaIds);
+ if (!result.ok()) {
+ ALOGW("unregisterSupportedValueChangeCallback: failed to unsubscribe supported value change"
+ " for %s, error: %s",
+ fmt::format("{}", propIdAreaIds).c_str(), result.error().message().c_str());
+ return toScopedAStatus(result);
+ }
+ return ScopedAStatus::ok();
+}
+
+IVehicleHardware* DefaultVehicleHal::getHardware() {
+ return mVehicleHardware.get();
+}
+
+VhalResult<void> DefaultVehicleHal::checkPermissionHelper(
+ const VehiclePropValue& value, VehiclePropertyAccess accessToTest) const {
+ static const std::unordered_set<VehiclePropertyAccess> 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<int32_t>(accessToTest));
+ }
+ return {};
+}
+
+VhalResult<void> DefaultVehicleHal::checkWritePermission(const VehiclePropValue& value) const {
+ return checkPermissionHelper(value, VehiclePropertyAccess::WRITE);
+}
+
+VhalResult<void> DefaultVehicleHal::checkReadPermission(const VehiclePropValue& value) const {
+ return checkPermissionHelper(value, VehiclePropertyAccess::READ);
+}
+
+void DefaultVehicleHal::checkHealth(IVehicleHardware* vehicleHardware,
+ std::weak_ptr<SubscriptionManager> subscriptionManager) {
+ StatusCode status = vehicleHardware->checkHealth();
+ if (status != StatusCode::OK) {
+ ALOGE("VHAL check health returns non-okay status");
+ return;
+ }
+ std::vector<VehiclePropValue> 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<BinderLifecycleInterface> 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<std::string> 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<int32_t, VehiclePropConfig> configsByPropIdCopy;
+ getConfigsByPropId([this, &configsByPropIdCopy](const auto& configsByPropId) {
+ SharedScopedLockAssertion lockAssertion(mConfigLock);
+
+ configsByPropIdCopy = configsByPropId;
+ });
+ {
+ std::scoped_lock<std::mutex> 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",
+ mSubscriptionManager->countPropertyChangeClients());
+ dprintf(fd, "Currently have %zu supported values change subscribe clients\n",
+ mSubscriptionManager->countSupportedValueChangeClients());
+ }
+ return STATUS_OK;
+}
+
+size_t DefaultVehicleHal::countClients() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ return mGetValuesClients.size() + mSetValuesClients.size() +
+ mSubscriptionManager->countPropertyChangeClients() +
+ mSubscriptionManager->countSupportedValueChangeClients();
+}
+
+} // 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 0000000..64c46c9
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/current/vhal/src/SubscriptionManager.cpp
@@ -0,0 +1,623 @@
+/*
+ * 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 <VehicleUtils.h>
+#include <android-base/format.h>
+#include <android-base/stringprintf.h>
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+
+#include <inttypes.h>
+
+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<std::mutex> lockGuard(mLock);
+
+ mClientsByPropIdAreaId.clear();
+ mSubscribedPropsByClient.clear();
+ mSupportedValueChangeClientsByPropIdAreaId.clear();
+ mSupportedValueChangePropIdAreaIdsByClient.clear();
+}
+
+bool SubscriptionManager::checkSampleRateHz(float sampleRateHz) {
+ return getIntervalNanos(sampleRateHz).ok();
+}
+
+Result<int64_t> 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<float>(INT64_MAX))) {
+ return Error() << "invalid sample rate: " << sampleRateHz << ", too small";
+ }
+ intervalNanos = static_cast<int64_t>(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<float>::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<void> 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)
+ << fmt::format("failed subscribe for propIdAreaId: {}", propIdAreaId);
+ }
+ return {};
+}
+
+VhalResult<void> 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<void> 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<void> 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<void> 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<void> SubscriptionManager::subscribe(const std::shared_ptr<IVehicleCallback>& callback,
+ const std::vector<SubscribeOptions>& options,
+ bool isContinuousProperty) {
+ std::scoped_lock<std::mutex> 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<int32_t>& areaIds = option.areaIds;
+ for (int32_t areaId : areaIds) {
+ PropIdAreaId propIdAreaId = {
+ .propId = propId,
+ .areaId = areaId,
+ };
+ VhalResult<void> 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<void> 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<void> SubscriptionManager::unsubscribe(SubscriptionManager::ClientIdType clientId,
+ const std::vector<int32_t>& propIds) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+
+ if (mSubscribedPropsByClient.find(clientId) == mSubscribedPropsByClient.end()) {
+ ALOGW("No property was subscribed for the callback, unsubscribe does nothing");
+ return {};
+ }
+
+ std::vector<PropIdAreaId> propIdAreaIdsToUnsubscribe;
+ std::unordered_set<int32_t> 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<void> SubscriptionManager::unsubscribe(SubscriptionManager::ClientIdType clientId) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+
+ if (mSubscribedPropsByClient.find(clientId) == mSubscribedPropsByClient.end()) {
+ ALOGW("No property was subscribed for this client, unsubscribe does nothing");
+ } else {
+ auto& propIdAreaIds = mSubscribedPropsByClient[clientId];
+ for (auto const& propIdAreaId : propIdAreaIds) {
+ if (auto result = unsubscribePropIdAreaIdLocked(clientId, propIdAreaId); !result.ok()) {
+ return result;
+ }
+ }
+ mSubscribedPropsByClient.erase(clientId);
+ }
+
+ if (mSupportedValueChangePropIdAreaIdsByClient.find(clientId) ==
+ mSupportedValueChangePropIdAreaIdsByClient.end()) {
+ ALOGW("No supported value change was subscribed for this client, unsubscribe does nothing");
+ } else {
+ const auto& propIdAreaIds = mSupportedValueChangePropIdAreaIdsByClient[clientId];
+ if (auto result = unsubscribeSupportedValueChangeLocked(
+ clientId,
+ std::vector<PropIdAreaId>(propIdAreaIds.begin(), propIdAreaIds.end()));
+ !result.ok()) {
+ return result;
+ }
+ }
+ return {};
+}
+
+VhalResult<void> SubscriptionManager::subscribeSupportedValueChange(
+ const std::shared_ptr<IVehicleCallback>& callback,
+ const std::vector<PropIdAreaId>& propIdAreaIds) {
+ // Need to make sure this whole operation is guarded by a lock so that our internal state is
+ // consistent with IVehicleHardware state.
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+
+ ClientIdType clientId = callback->asBinder().get();
+
+ // It is possible that some of the [propId, areaId]s are already subscribed, IVehicleHardware
+ // will ignore them.
+ if (auto status = mVehicleHardware->subscribeSupportedValueChange(propIdAreaIds);
+ status != StatusCode::OK) {
+ return StatusError(status)
+ << fmt::format("failed to call subscribeSupportedValueChange for propIdAreaIds: {}",
+ propIdAreaIds);
+ }
+ for (const auto& propIdAreaId : propIdAreaIds) {
+ mSupportedValueChangeClientsByPropIdAreaId[propIdAreaId][clientId] = callback;
+ // mSupportedValueChangePropIdAreaIdsByClient[clientId] is a set so this will ignore
+ // duplicate [propId, areaId].
+ mSupportedValueChangePropIdAreaIdsByClient[clientId].insert(propIdAreaId);
+ }
+ return {};
+}
+
+VhalResult<void> SubscriptionManager::unsubscribeSupportedValueChange(
+ SubscriptionManager::ClientIdType clientId,
+ const std::vector<PropIdAreaId>& propIdAreaIds) {
+ // Need to make sure this whole operation is guarded by a lock so that our internal state is
+ // consistent with IVehicleHardware state.
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+
+ return unsubscribeSupportedValueChangeLocked(clientId, propIdAreaIds);
+}
+
+VhalResult<void> SubscriptionManager::unsubscribeSupportedValueChangeLocked(
+ SubscriptionManager::ClientIdType clientId,
+ const std::vector<PropIdAreaId>& propIdAreaIds) {
+ std::vector<PropIdAreaId> propIdAreaIdsToUnsubscribe;
+
+ // Check which [propId, areaId] needs to be unsubscribed from the hardware.
+ for (const auto& propIdAreaId : propIdAreaIds) {
+ auto it = mSupportedValueChangeClientsByPropIdAreaId.find(propIdAreaId);
+ if (it != mSupportedValueChangeClientsByPropIdAreaId.end()) {
+ const auto& clients = it->second;
+ if (clients.size() == 1 && clients.find(clientId) != clients.end()) {
+ // This callback is the only client registered for [propId, areaId].
+ // Unregister it should unregister the [propId, areaId].
+ propIdAreaIdsToUnsubscribe.push_back(propIdAreaId);
+ }
+ }
+ }
+
+ // Send the unsubscribe request.
+ if (!propIdAreaIdsToUnsubscribe.empty()) {
+ if (auto status =
+ mVehicleHardware->unsubscribeSupportedValueChange(propIdAreaIdsToUnsubscribe);
+ status != StatusCode::OK) {
+ return StatusError(status) << fmt::format(
+ "failed to call unsubscribeSupportedValueChange for "
+ "propIdAreaIds: {}",
+ propIdAreaIdsToUnsubscribe);
+ }
+ }
+
+ // Remove internal book-keeping.
+ for (const auto& propIdAreaId : propIdAreaIds) {
+ if (mSupportedValueChangeClientsByPropIdAreaId.find(propIdAreaId) !=
+ mSupportedValueChangeClientsByPropIdAreaId.end()) {
+ mSupportedValueChangeClientsByPropIdAreaId[propIdAreaId].erase(clientId);
+ }
+ if (mSupportedValueChangeClientsByPropIdAreaId[propIdAreaId].empty()) {
+ mSupportedValueChangeClientsByPropIdAreaId.erase(propIdAreaId);
+ }
+ mSupportedValueChangePropIdAreaIdsByClient[clientId].erase(propIdAreaId);
+ if (mSupportedValueChangePropIdAreaIdsByClient[clientId].empty()) {
+ mSupportedValueChangePropIdAreaIdsByClient.erase(clientId);
+ }
+ }
+ return {};
+}
+
+bool SubscriptionManager::isValueUpdatedLocked(const std::shared_ptr<IVehicleCallback>& 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::shared_ptr<IVehicleCallback>, std::vector<VehiclePropValue>>
+SubscriptionManager::getSubscribedClients(std::vector<VehiclePropValue>&& updatedValues) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ std::unordered_map<std::shared_ptr<IVehicleCallback>, std::vector<VehiclePropValue>> 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::shared_ptr<IVehicleCallback>, std::vector<VehiclePropError>>
+SubscriptionManager::getSubscribedClientsForErrorEvents(
+ const std::vector<SetValueErrorEvent>& errorEvents) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ std::unordered_map<std::shared_ptr<IVehicleCallback>, std::vector<VehiclePropError>> 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;
+}
+
+std::unordered_map<std::shared_ptr<IVehicleCallback>, std::vector<PropIdAreaId>>
+SubscriptionManager::getSubscribedClientsForSupportedValueChange(
+ const std::vector<PropIdAreaId>& propIdAreaIds) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ std::unordered_map<std::shared_ptr<IVehicleCallback>, std::vector<PropIdAreaId>>
+ propIdAreaIdsByClient;
+
+ for (const auto& propIdAreaId : propIdAreaIds) {
+ const auto clientIter = mSupportedValueChangeClientsByPropIdAreaId.find(propIdAreaId);
+ if (clientIter == mSupportedValueChangeClientsByPropIdAreaId.end()) {
+ continue;
+ }
+ for (const auto& [_, client] : clientIter->second) {
+ propIdAreaIdsByClient[client].push_back(propIdAreaId);
+ }
+ }
+ return propIdAreaIdsByClient;
+}
+
+bool SubscriptionManager::isEmpty() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ return mSubscribedPropsByClient.empty() && mClientsByPropIdAreaId.empty() &&
+ mSupportedValueChangeClientsByPropIdAreaId.empty() &&
+ mSupportedValueChangePropIdAreaIdsByClient.empty();
+}
+
+size_t SubscriptionManager::countPropertyChangeClients() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ return mSubscribedPropsByClient.size();
+}
+
+size_t SubscriptionManager::countSupportedValueChangeClients() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ return mSupportedValueChangePropIdAreaIdsByClient.size();
+}
+
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/vehicle/aidl/impl/vhal/src/VehicleService.cpp b/automotive/vehicle/aidl/impl/current/vhal/src/VehicleService.cpp
similarity index 100%
copy from automotive/vehicle/aidl/impl/vhal/src/VehicleService.cpp
copy to automotive/vehicle/aidl/impl/current/vhal/src/VehicleService.cpp
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 0000000..ac1e3b1
--- /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 <DefaultVehicleHal.h>
+#include <FakeVehicleHardware.h>
+#include <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+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<FakeVehicleHardware> hardware = std::make_unique<FakeVehicleHardware>();
+ std::shared_ptr<DefaultVehicleHal> vhal =
+ ::ndk::SharedRefBase::make<DefaultVehicleHal>(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/vhal/test/ConnectedClientTest.cpp b/automotive/vehicle/aidl/impl/current/vhal/test/ConnectedClientTest.cpp
similarity index 100%
copy from automotive/vehicle/aidl/impl/vhal/test/ConnectedClientTest.cpp
copy to automotive/vehicle/aidl/impl/current/vhal/test/ConnectedClientTest.cpp
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 0000000..3b89e5f
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/current/vhal/test/DefaultVehicleHalTest.cpp
@@ -0,0 +1,2887 @@
+/*
+ * 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 <IVehicleHardware.h>
+#include <LargeParcelableBase.h>
+#include <aidl/android/hardware/automotive/vehicle/HasSupportedValueInfo.h>
+#include <aidl/android/hardware/automotive/vehicle/IVehicle.h>
+#include <aidl/android/hardware/automotive/vehicle/IVehicleCallback.h>
+
+#include <android-base/thread_annotations.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <sys/mman.h>
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+
+#include <chrono>
+#include <list>
+#include <memory>
+#include <mutex>
+#include <optional>
+#include <thread>
+#include <unordered_map>
+#include <vector>
+
+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::HasSupportedValueInfo;
+using ::aidl::android::hardware::automotive::vehicle::IVehicle;
+using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback;
+using ::aidl::android::hardware::automotive::vehicle::MinMaxSupportedValueResult;
+using ::aidl::android::hardware::automotive::vehicle::MinMaxSupportedValueResults;
+using ::aidl::android::hardware::automotive::vehicle::RawPropValues;
+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::SupportedValuesListResult;
+using ::aidl::android::hardware::automotive::vehicle::SupportedValuesListResults;
+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;
+
+using VhalPropIdAreaId = ::aidl::android::hardware::automotive::vehicle::PropIdAreaId;
+
+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<int32_t>(i) + 0x20000000 + 0x01000000 + 0x00410000;
+}
+
+int32_t testInt32VecWindowProp(size_t i) {
+ // VehiclePropertyGroup:VENDOR,VehicleArea:WINDOW,VehiclePropertyType:INT32_VEC
+ return static_cast<int32_t>(i) + 0x20000000 + 0x03000000 + 0x00410000;
+}
+
+std::string toString(const std::vector<SubscribeOptions>& 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<SetValuesInvalidRequestTestCase> 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<SubscribeInvalidOptionsTestCase> 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<MockVehicleHardware>()); }
+
+ void init(std::unique_ptr<MockVehicleHardware> hardware) {
+ // Default init uses the following static configs to create the mock IVehicleHardware,
+ // individual test case may use setHardware to overwrite the underlying IVehicleHardware
+ // to use a different set of configs.
+
+ std::vector<VehiclePropConfig> 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);
+
+ setHardware(std::move(hardware));
+ }
+
+ void TearDown() override {
+ ASSERT_EQ(countPendingRequests(), static_cast<size_t>(0))
+ << "must have no pending requests when test finishes";
+ }
+
+ MockVehicleHardware* getHardware() { return mHardwarePtr; }
+
+ std::shared_ptr<IVehicle> getClient() { return mVhal; }
+
+ std::shared_ptr<IVehicleCallback> 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() { return mVhal->countClients(); }
+
+ std::shared_ptr<PendingRequestPool> 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<std::mutex> lockGuard(mVhal->mLock);
+ return mVhal->mOnBinderDiedContexts[clientId].get();
+ }
+
+ size_t countOnBinderDiedContexts() {
+ std::scoped_lock<std::mutex> lockGuard(mVhal->mLock);
+ return mVhal->mOnBinderDiedContexts.size();
+ }
+
+ bool hasNoSubscriptions() { return mVhal->mSubscriptionManager->isEmpty(); }
+
+ void setBinderAlive(bool isAlive) { mBinderLifecycleHandler->setAlive(isAlive); };
+
+ static Result<void> getValuesTestCases(size_t size, GetValueRequests& requests,
+ std::vector<GetValueResult>& expectedResults,
+ std::vector<GetValueRequest>& expectedHardwareRequests) {
+ expectedHardwareRequests.clear();
+ for (size_t i = 0; i < size; i++) {
+ int64_t requestId = static_cast<int64_t>(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<void> setValuesTestCases(size_t size, SetValueRequests& requests,
+ std::vector<SetValueResult>& expectedResults,
+ std::vector<SetValueRequest>& expectedHardwareRequests) {
+ expectedHardwareRequests.clear();
+ for (size_t i = 0; i < size; i++) {
+ int64_t requestId = static_cast<int64_t>(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 {};
+ }
+
+ protected:
+ // Sets the underlying IVehicleHardware and recreates the DefaultVehicleHal objects under test.
+ // If used, caller should call this at the beginning of the test case.
+ void setHardware(std::unique_ptr<MockVehicleHardware> hardware) {
+ setHardware(std::move(hardware), 0);
+ }
+
+ void setHardware(std::unique_ptr<MockVehicleHardware> hardware, int32_t testInterfaceVersion) {
+ mHardwarePtr = hardware.get();
+ if (testInterfaceVersion == 0) {
+ mVhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
+ } else {
+ mVhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware),
+ testInterfaceVersion);
+ }
+ // Set the linkToDeath to a fake implementation that always returns OK.
+ auto handler = std::make_unique<TestBinderLifecycleHandler>();
+ mBinderLifecycleHandler = handler.get();
+ mVhal->setBinderLifecycleHandler(std::move(handler));
+
+ mVhalClient = IVehicle::fromBinder(mVhal->asBinder());
+ mCallback = ndk::SharedRefBase::make<MockVehicleCallback>();
+ // Keep the local binder alive.
+ mBinder = mCallback->asBinder();
+ mCallbackClient = IVehicleCallback::fromBinder(mBinder);
+ }
+
+ 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<DefaultVehicleHal> mVhal;
+ std::shared_ptr<IVehicle> mVhalClient;
+ MockVehicleHardware* mHardwarePtr;
+ std::shared_ptr<MockVehicleCallback> mCallback;
+ std::shared_ptr<IVehicleCallback> mCallbackClient;
+ SpAIBinder mBinder;
+ TestBinderLifecycleHandler* mBinderLifecycleHandler;
+};
+
+TEST_F(DefaultVehicleHalTest, testGetAllPropConfigsSmall) {
+ auto testConfigs = std::vector<VehiclePropConfig>({
+ VehiclePropConfig{
+ .prop = testInt32VecProp(1),
+ },
+ VehiclePropConfig{
+ .prop = testInt32VecProp(2),
+ },
+ });
+
+ auto hardware = std::make_unique<MockVehicleHardware>();
+ hardware->setPropertyConfigs(testConfigs);
+ setHardware(std::move(hardware));
+
+ VehiclePropConfigs output;
+ auto status = getClient()->getAllPropConfigs(&output);
+
+ ASSERT_TRUE(status.isOk()) << "getAllPropConfigs failed: " << status.getMessage();
+ ASSERT_THAT(output.payloads, WhenSortedBy(propConfigCmp, Eq(testConfigs)));
+}
+
+TEST_F(DefaultVehicleHalTest, testGetAllPropConfigsLarge) {
+ std::vector<VehiclePropConfig> 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<MockVehicleHardware>();
+ hardware->setPropertyConfigs(testConfigs);
+ setHardware(std::move(hardware));
+
+ VehiclePropConfigs output;
+ auto status = getClient()->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<VehiclePropConfig>({
+ // 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<MockVehicleHardware>();
+ hardware->setPropertyConfigs(testConfigs);
+ setHardware(std::move(hardware), /* testInterfaceVersion= */ 2);
+
+ VehiclePropConfigs output;
+ auto status = getClient()->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>({
+ VehiclePropConfig{
+ .prop = propId1,
+ },
+ VehiclePropConfig{
+ .prop = propId2,
+ },
+ });
+
+ auto hardware = std::make_unique<MockVehicleHardware>();
+ hardware->setPropertyConfigs(testConfigs);
+ // Store the pointer for testing. We are sure it is valid.
+ MockVehicleHardware* hardwarePtr = hardware.get();
+ setHardware(std::move(hardware));
+
+ VehiclePropConfigs output;
+ auto status = getClient()->getPropConfigs(std::vector<int32_t>({propId1, propId2}), &output);
+
+ ASSERT_TRUE(status.isOk()) << "getPropConfigs failed: " << status.getMessage();
+ ASSERT_EQ(output.payloads, testConfigs);
+ ASSERT_FALSE(getHardware()->getAllPropertyConfigsCalled());
+}
+
+TEST_F(DefaultVehicleHalTest, testGetPropConfigsInvalidArg) {
+ auto testConfigs = std::vector<VehiclePropConfig>({
+ VehiclePropConfig{
+ .prop = testInt32VecProp(1),
+ },
+ VehiclePropConfig{
+ .prop = testInt32VecProp(2),
+ },
+ });
+
+ auto hardware = std::make_unique<MockVehicleHardware>();
+ hardware->setPropertyConfigs(testConfigs);
+ setHardware(std::move(hardware));
+
+ VehiclePropConfigs output;
+ auto status = getClient()->getPropConfigs(
+ std::vector<int32_t>({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<GetValueResult> expectedResults;
+ std::vector<GetValueRequest> 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<size_t>(1));
+ ASSERT_FALSE(getHardware()->getAllPropertyConfigsCalled());
+}
+
+TEST_F(DefaultVehicleHalTest, testGetValuesSmall_AfterGetAllPropConfigs) {
+ GetValueRequests requests;
+ std::vector<GetValueResult> expectedResults;
+ std::vector<GetValueRequest> 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<size_t>(1));
+ ASSERT_TRUE(getHardware()->getAllPropertyConfigsCalled());
+}
+
+TEST_F(DefaultVehicleHalTest, testGetValuesLarge) {
+ GetValueRequests requests;
+ std::vector<GetValueResult> expectedResults;
+ std::vector<GetValueRequest> 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<size_t>(1));
+}
+
+TEST_F(DefaultVehicleHalTest, testGetValuesErrorFromHardware) {
+ GetValueRequests requests;
+ std::vector<GetValueResult> expectedResults;
+ std::vector<GetValueRequest> 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<GetValueResult>({
+ {
+ .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<GetValueResult> expectedResults;
+ std::vector<GetValueRequest> 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<GetValueResult> expectedResults;
+ std::vector<GetValueRequest> 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<GetValueResult> expectedResults;
+ std::vector<GetValueRequest> 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<GetValueResult> expectedResults;
+ std::vector<GetValueRequest> 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<size_t>(0))
+ << "No client should be created if the client binder died";
+}
+
+TEST_F(DefaultVehicleHalTest, testGetValuesExistingClientDied) {
+ GetValueRequests requests;
+ std::vector<GetValueResult> expectedResults;
+ std::vector<GetValueRequest> 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<size_t>(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<size_t>(1));
+}
+
+TEST_F(DefaultVehicleHalTest, testSetValuesSmall) {
+ SetValueRequests requests;
+ std::vector<SetValueResult> expectedResults;
+ std::vector<SetValueRequest> 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<size_t>(1));
+ ASSERT_FALSE(getHardware()->getAllPropertyConfigsCalled());
+}
+
+TEST_F(DefaultVehicleHalTest, testSetValuesSmall_AfterGetAllPropConfigs) {
+ SetValueRequests requests;
+ std::vector<SetValueResult> expectedResults;
+ std::vector<SetValueRequest> 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<size_t>(1));
+ ASSERT_TRUE(getHardware()->getAllPropertyConfigsCalled());
+}
+
+TEST_F(DefaultVehicleHalTest, testSetValuesLarge) {
+ SetValueRequests requests;
+ std::vector<SetValueResult> expectedResults;
+ std::vector<SetValueRequest> 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<size_t>(1));
+}
+
+class SetValuesInvalidRequestTest
+ : public DefaultVehicleHalTest,
+ public testing::WithParamInterface<SetValuesInvalidRequestTestCase> {};
+
+INSTANTIATE_TEST_SUITE_P(
+ SetValuesInvalidRequestTests, SetValuesInvalidRequestTest,
+ testing::ValuesIn(getSetValuesInvalidRequestTestCases()),
+ [](const testing::TestParamInfo<SetValuesInvalidRequestTest::ParamType>& info) {
+ return info.param.name;
+ });
+
+TEST_P(SetValuesInvalidRequestTest, testSetValuesInvalidRequest) {
+ SetValuesInvalidRequestTestCase tc = GetParam();
+ std::vector<SetValueResult> 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<SetValueRequest>({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<SetValueResult>({
+ {
+ .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<SetValueResult> expectedResults;
+ std::vector<SetValueRequest> 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<SetValueResult> expectedResults;
+ std::vector<SetValueRequest> 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<SetValueResult> expectedResults;
+ std::vector<SetValueRequest> 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<SubscribeOptions> 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<int32_t>({GLOBAL_ON_CHANGE_PROP}));
+
+ ASSERT_TRUE(status.isOk()) << "unsubscribe failed: " << status.getMessage();
+}
+
+TEST_F(DefaultVehicleHalTest, testSubscribeGlobalOnChangeNormal) {
+ std::vector<SubscribeOptions> 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<SetValueResult> 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<size_t>(2))
+ << "expect 2 clients, 1 subscribe client and 1 setvalue client";
+}
+
+TEST_F(DefaultVehicleHalTest, testSubscribeGlobalOnchangeUnrelatedEventIgnored) {
+ std::vector<SubscribeOptions> 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<SubscribeOptions> 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<SubscribeOptions> 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<SubscribeOptions> 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<size_t>(1));
+}
+
+TEST_F(DefaultVehicleHalTest, testSubscribeGlobalContinuousRateOutOfRange) {
+ // The maxSampleRate is 100, so the sample rate should be the default max 100.
+ std::vector<SubscribeOptions> 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<size_t>(1));
+}
+
+TEST_F(DefaultVehicleHalTest, testSubscribeContinuous_propNotSupportVur) {
+ std::vector<SubscribeOptions> 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<SubscribeOptions> 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<SubscribeOptions> 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<int32_t>({AREA_CONTINUOUS_PROP}));
+
+ std::vector<VehiclePropValue> 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<size_t>(15));
+ // Should trigger about 10 times, check for at least 5 events to be safe.
+ ASSERT_GE(rightCount, static_cast<size_t>(5));
+}
+
+TEST_F(DefaultVehicleHalTest, testAreaContinuous_areaNotSupportVur) {
+ std::vector<SubscribeOptions> 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<SubscribeOptions> 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<int32_t>({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<SubscribeOptions> 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<int32_t>({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<SubscribeInvalidOptionsTestCase> {};
+
+INSTANTIATE_TEST_SUITE_P(
+ SubscribeInvalidOptionsTests, SubscribeInvalidOptionsTest,
+ testing::ValuesIn(getSubscribeInvalidOptionsTestCases()),
+ [](const testing::TestParamInfo<SubscribeInvalidOptionsTest::ParamType>& info) {
+ return info.param.name;
+ });
+
+TEST_P(SubscribeInvalidOptionsTest, testSubscribeInvalidOptions) {
+ std::vector<SubscribeOptions> 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<SubscribeOptions> 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<SubscribeOptions> 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<SubscribeOptions> 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, testUnsubscribeNotSubscribedProperty) {
+ auto status = getClient()->unsubscribe(getCallbackClient(),
+ std::vector<int32_t>({GLOBAL_ON_CHANGE_PROP}));
+
+ ASSERT_TRUE(status.isOk()) << "unsubscribe to a not-subscribed property must do nothing";
+}
+
+TEST_F(DefaultVehicleHalTest, testHeartbeatEvent) {
+ std::vector<SubscribeOptions> 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 10s (100ms * 100) buffer time.
+ while (!maybeResults.has_value() && retryCount < 100) {
+ 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<size_t>(1));
+ VehiclePropValue gotValue = maybeResults.value().payloads[0];
+ ASSERT_EQ(gotValue.prop, toInt(VehicleProperty::VHAL_HEARTBEAT));
+ ASSERT_EQ(gotValue.value.int64Values.size(), static_cast<size_t>(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<const IVehicleHardware::GetValuesCallback> callback,
+ const std::vector<GetValueRequest>& requests) {
+ std::vector<GetValueResult> 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<SubscribeOptions> 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<GetValueResult> expectedResults;
+ std::vector<GetValueRequest> 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<size_t>(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<size_t>(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<size_t>(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<SubscribeOptions> 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<SetValueErrorEvent> 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<VehiclePropError> 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<MockVehicleHardware>();
+ hardware->setPropertyOnChangeEventBatchingWindow(std::chrono::milliseconds(10));
+ init(std::move(hardware));
+
+ std::vector<SubscribeOptions> 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";
+ }
+}
+
+TEST_F(DefaultVehicleHalTest, testGetSupportedValuesLists) {
+ auto testConfigs = std::vector<VehiclePropConfig>(
+ {// This ia valid request, but no supported values are specified.
+ VehiclePropConfig{
+ .prop = testInt32VecProp(1),
+ .areaConfigs =
+ {
+ {.areaId = 0,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasSupportedValuesList = false,
+ }},
+ },
+ },
+ // This is an invalid request since hasSupportedValueInfo is null. This is not
+ // supported.
+ VehiclePropConfig{
+ .prop = testInt32VecWindowProp(2),
+ .areaConfigs =
+ {
+ {
+ .areaId = 2,
+ },
+ },
+ },
+ // This is an invalid request for global property.
+ VehiclePropConfig{
+ .prop = testInt32VecProp(3),
+ },
+ // This is a normal request.
+ VehiclePropConfig{
+ .prop = testInt32VecWindowProp(4),
+ .areaConfigs =
+ {
+ {.areaId = 4,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasSupportedValuesList = true,
+ }},
+ },
+ }});
+
+ auto hardware = std::make_unique<MockVehicleHardware>();
+ MockVehicleHardware* hardwarePtr = hardware.get();
+ hardware->setPropertyConfigs(testConfigs);
+
+ SupportedValuesListResult resultFromHardware = {
+ .status = StatusCode::OK,
+ .supportedValuesList =
+ std::vector<std::optional<RawPropValues>>{RawPropValues{.int32Values = {1}}}};
+ auto response = std::vector<SupportedValuesListResult>({resultFromHardware});
+ hardware->setSupportedValuesListResponse(response);
+
+ setHardware(std::move(hardware));
+
+ SupportedValuesListResults results;
+
+ auto propIdAreaId1 = VhalPropIdAreaId{.propId = testInt32VecProp(1), .areaId = 0};
+ auto propIdAreaId2 = VhalPropIdAreaId{.propId = testInt32VecWindowProp(2), .areaId = 2};
+ auto propIdAreaId3 = VhalPropIdAreaId{.propId = testInt32VecWindowProp(3), .areaId = 0};
+ auto propIdAreaId4 = VhalPropIdAreaId{.propId = testInt32VecWindowProp(4), .areaId = 4};
+ auto status = getClient()->getSupportedValuesLists(
+ std::vector<VhalPropIdAreaId>{propIdAreaId1, propIdAreaId2, propIdAreaId3,
+ propIdAreaId4},
+ &results);
+
+ ASSERT_TRUE(status.isOk()) << "Get non-okay status from getSupportedValuesLists"
+ << status.getMessage();
+ ASSERT_THAT(getHardware()->getSupportedValuesListRequest(),
+ ElementsAre(PropIdAreaId{.propId = testInt32VecWindowProp(4), .areaId = 4}))
+ << "Only valid request 4 should get to hardware";
+
+ ASSERT_EQ(results.payloads.size(), 4u);
+ SupportedValuesListResult result = results.payloads[0];
+ ASSERT_EQ(result.status, StatusCode::OK)
+ << "Must return OK even if the supported values list is not specified";
+ ASSERT_FALSE(result.supportedValuesList.has_value())
+ << "Must return an empty supported values list if not specified";
+
+ result = results.payloads[1];
+ ASSERT_EQ(result.status, StatusCode::INVALID_ARG)
+ << "PropId, areaId that set hasSupportedValueInfo to null must not be supported";
+ ASSERT_FALSE(result.supportedValuesList.has_value());
+
+ result = results.payloads[2];
+ ASSERT_EQ(result.status, StatusCode::INVALID_ARG)
+ << "Must return INVALID_ARG for global property without area config";
+ ASSERT_FALSE(result.supportedValuesList.has_value());
+
+ result = results.payloads[3];
+ ASSERT_EQ(result.status, StatusCode::OK);
+ ASSERT_TRUE(result.supportedValuesList.has_value());
+ ASSERT_EQ(result.supportedValuesList.value().size(), 1u);
+ ASSERT_EQ(result.supportedValuesList.value()[0]->int32Values.size(), 1u);
+ ASSERT_EQ((result.supportedValuesList.value())[0]->int32Values[0], 1);
+}
+
+TEST_F(DefaultVehicleHalTest, testGetSupportedValuesLists_propIdAreaIdNotFound) {
+ auto testConfigs = std::vector<VehiclePropConfig>({
+ VehiclePropConfig{
+ .prop = testInt32VecWindowProp(1),
+ .areaConfigs =
+ {
+ {.areaId = 1,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasSupportedValuesList = true,
+ }},
+ },
+ },
+ });
+
+ auto hardware = std::make_unique<MockVehicleHardware>();
+ hardware->setPropertyConfigs(testConfigs);
+
+ setHardware(std::move(hardware));
+
+ SupportedValuesListResults results;
+
+ // propId not valid.
+ auto propIdAreaId1 = VhalPropIdAreaId{.propId = testInt32VecWindowProp(2), .areaId = 1};
+ // areaId not valid.
+ auto propIdAreaId2 = VhalPropIdAreaId{.propId = testInt32VecWindowProp(1), .areaId = 2};
+
+ auto status = getClient()->getSupportedValuesLists(
+ std::vector<VhalPropIdAreaId>{propIdAreaId1, propIdAreaId2}, &results);
+
+ ASSERT_TRUE(status.isOk()) << "Get non-okay status from getSupportedValuesLists"
+ << status.getMessage();
+ ASSERT_EQ(results.payloads.size(), 2u);
+ SupportedValuesListResult result = results.payloads[0];
+ ASSERT_EQ(result.status, StatusCode::INVALID_ARG);
+ result = results.payloads[1];
+ ASSERT_EQ(result.status, StatusCode::INVALID_ARG);
+}
+
+TEST_F(DefaultVehicleHalTest, testGetMinMaxSupportedValue) {
+ auto testConfigs = std::vector<VehiclePropConfig>(
+ {// This ia valid request, but no supported values are specified.
+ VehiclePropConfig{
+ .prop = testInt32VecProp(1),
+ .areaConfigs =
+ {
+ {.areaId = 0,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasMinSupportedValue = false,
+ .hasMaxSupportedValue = false,
+ }},
+ },
+ },
+ // This is an invalid request since hasSupportedValueInfo is null. This is not
+ // supported.
+ VehiclePropConfig{
+ .prop = testInt32VecWindowProp(2),
+ .areaConfigs =
+ {
+ {
+ .areaId = 2,
+ },
+ },
+ },
+ // This is an invalid request for global property.
+ VehiclePropConfig{
+ .prop = testInt32VecProp(3),
+ },
+ // This is a normal request.
+ VehiclePropConfig{
+ .prop = testInt32VecWindowProp(4),
+ .areaConfigs =
+ {
+ {.areaId = 4,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasMinSupportedValue = true,
+ .hasMaxSupportedValue = false,
+ }},
+ },
+ }});
+
+ auto hardware = std::make_unique<MockVehicleHardware>();
+ MockVehicleHardware* hardwarePtr = hardware.get();
+ hardware->setPropertyConfigs(testConfigs);
+
+ MinMaxSupportedValueResult resultFromHardware = {
+ .status = StatusCode::OK,
+ .minSupportedValue = std::optional<RawPropValues>{RawPropValues{.int32Values = {1}}},
+ .maxSupportedValue = std::nullopt,
+ };
+ auto response = std::vector<MinMaxSupportedValueResult>({resultFromHardware});
+ hardware->setMinMaxSupportedValueResponse(response);
+
+ setHardware(std::move(hardware));
+
+ MinMaxSupportedValueResults results;
+
+ auto propIdAreaId1 = VhalPropIdAreaId{.propId = testInt32VecProp(1), .areaId = 0};
+ auto propIdAreaId2 = VhalPropIdAreaId{.propId = testInt32VecWindowProp(2), .areaId = 2};
+ auto propIdAreaId3 = VhalPropIdAreaId{.propId = testInt32VecWindowProp(3), .areaId = 0};
+ auto propIdAreaId4 = VhalPropIdAreaId{.propId = testInt32VecWindowProp(4), .areaId = 4};
+ auto status = getClient()->getMinMaxSupportedValue(
+ std::vector<VhalPropIdAreaId>{propIdAreaId1, propIdAreaId2, propIdAreaId3,
+ propIdAreaId4},
+ &results);
+
+ ASSERT_TRUE(status.isOk()) << "Get non-okay status from getMinMaxSupportedValue"
+ << status.getMessage();
+ ASSERT_THAT(getHardware()->getMinMaxSupportedValueRequest(),
+ ElementsAre(PropIdAreaId{.propId = testInt32VecWindowProp(4), .areaId = 4}))
+ << "Only valid request 4 should get to hardware";
+
+ ASSERT_EQ(results.payloads.size(), 4u);
+ MinMaxSupportedValueResult result = results.payloads[0];
+ ASSERT_EQ(result.status, StatusCode::OK)
+ << "Must return OK even if the min/max supported values are not specified";
+ ASSERT_FALSE(result.minSupportedValue.has_value())
+ << "Must return null min supported value if not specified";
+ ASSERT_FALSE(result.maxSupportedValue.has_value())
+ << "Must return null max supported value if not specified";
+
+ result = results.payloads[1];
+ ASSERT_EQ(result.status, StatusCode::INVALID_ARG)
+ << "PropId, areaId that set hasSupportedValueInfo to null must not be supported";
+ ASSERT_FALSE(result.minSupportedValue.has_value());
+ ASSERT_FALSE(result.maxSupportedValue.has_value());
+
+ result = results.payloads[2];
+ ASSERT_EQ(result.status, StatusCode::INVALID_ARG)
+ << "Must return INVALID_ARG for global property without area config";
+ ASSERT_FALSE(result.minSupportedValue.has_value());
+ ASSERT_FALSE(result.maxSupportedValue.has_value());
+
+ result = results.payloads[3];
+ ASSERT_EQ(result.status, StatusCode::OK);
+ ASSERT_TRUE(result.minSupportedValue.has_value());
+ ASSERT_EQ(result.minSupportedValue->int32Values.size(), 1u);
+ ASSERT_EQ(result.minSupportedValue->int32Values[0], 1);
+ ASSERT_FALSE(result.maxSupportedValue.has_value());
+}
+
+TEST_F(DefaultVehicleHalTest, testGetMinMaxSupportedValue_propIdAreaIdNotFound) {
+ auto testConfigs = std::vector<VehiclePropConfig>({
+ VehiclePropConfig{
+ .prop = testInt32VecWindowProp(1),
+ .areaConfigs =
+ {
+ {.areaId = 1,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasMinSupportedValue = true,
+ .hasMaxSupportedValue = true,
+ }},
+ },
+ },
+ });
+
+ auto hardware = std::make_unique<MockVehicleHardware>();
+ hardware->setPropertyConfigs(testConfigs);
+
+ setHardware(std::move(hardware));
+
+ MinMaxSupportedValueResults results;
+
+ // propId not valid.
+ auto propIdAreaId1 = VhalPropIdAreaId{.propId = testInt32VecWindowProp(2), .areaId = 1};
+ // areaId not valid.
+ auto propIdAreaId2 = VhalPropIdAreaId{.propId = testInt32VecWindowProp(1), .areaId = 2};
+
+ auto status = getClient()->getMinMaxSupportedValue(
+ std::vector<VhalPropIdAreaId>{propIdAreaId1, propIdAreaId2}, &results);
+
+ ASSERT_TRUE(status.isOk()) << "Get non-okay status from getMinMaxSupportedValue"
+ << status.getMessage();
+ ASSERT_EQ(results.payloads.size(), 2u);
+ MinMaxSupportedValueResult result = results.payloads[0];
+ ASSERT_EQ(result.status, StatusCode::INVALID_ARG);
+ result = results.payloads[1];
+ ASSERT_EQ(result.status, StatusCode::INVALID_ARG);
+}
+
+TEST_F(DefaultVehicleHalTest, testRegisterSupportedValueChangeCallback) {
+ auto testConfigs = std::vector<VehiclePropConfig>(
+ {VehiclePropConfig{
+ .prop = testInt32VecProp(1),
+ .areaConfigs =
+ {
+ {.areaId = 0,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasMinSupportedValue = false,
+ .hasMaxSupportedValue = false,
+ .hasSupportedValuesList = false,
+ }},
+ },
+ },
+ VehiclePropConfig{
+ .prop = testInt32VecWindowProp(2),
+ .areaConfigs =
+ {
+ {.areaId = 2,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasMinSupportedValue = true,
+ .hasMaxSupportedValue = false,
+ .hasSupportedValuesList = false,
+ }},
+ },
+ }});
+
+ auto hardware = std::make_unique<MockVehicleHardware>();
+ hardware->setPropertyConfigs(testConfigs);
+
+ setHardware(std::move(hardware));
+
+ // This request is ignored because it does not have supported value info.
+ auto propIdAreaId1 = VhalPropIdAreaId{.propId = testInt32VecProp(1), .areaId = 0};
+ auto propIdAreaId2 = VhalPropIdAreaId{.propId = testInt32VecWindowProp(2), .areaId = 2};
+ auto status = getClient()->registerSupportedValueChangeCallback(
+ getCallbackClient(), std::vector<VhalPropIdAreaId>{propIdAreaId1, propIdAreaId2});
+
+ ASSERT_TRUE(status.isOk()) << "Get non-okay status from registerSupportedValueChangeCallback"
+ << status.getMessage();
+ ASSERT_THAT(
+ getHardware()->getSubscribedSupportedValueChangePropIdAreaIds(),
+ UnorderedElementsAre(PropIdAreaId{.propId = testInt32VecWindowProp(2), .areaId = 2}));
+}
+
+TEST_F(DefaultVehicleHalTest, testRegisterSupportedValueChangeCallback_invalidRequest) {
+ auto testConfigs = std::vector<VehiclePropConfig>({VehiclePropConfig{
+ .prop = testInt32VecProp(1),
+ .areaConfigs =
+ {
+ {.areaId = 0, .hasSupportedValueInfo = std::nullopt},
+ },
+ }});
+ auto hardware = std::make_unique<MockVehicleHardware>();
+ hardware->setPropertyConfigs(testConfigs);
+
+ setHardware(std::move(hardware));
+
+ auto propIdAreaId1 = VhalPropIdAreaId{.propId = testInt32VecProp(1), .areaId = 0};
+ auto status = getClient()->registerSupportedValueChangeCallback(
+ getCallbackClient(), std::vector<VhalPropIdAreaId>{propIdAreaId1});
+
+ ASSERT_FALSE(status.isOk()) << "registerSupportedValueChangeCallback must return error if one "
+ "of the requested [propId, areaId]"
+ " does not have supportedValueInfo";
+}
+
+TEST_F(DefaultVehicleHalTest, testRegisterSupportedValueChangeCallback_errorStatusFromHardware) {
+ auto testConfigs = std::vector<VehiclePropConfig>({VehiclePropConfig{
+ .prop = testInt32VecWindowProp(2),
+ .areaConfigs =
+ {
+ {.areaId = 2,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasMinSupportedValue = true,
+ .hasMaxSupportedValue = false,
+ .hasSupportedValuesList = false,
+ }},
+ },
+ }});
+
+ auto hardware = std::make_unique<MockVehicleHardware>();
+ hardware->setStatus("subscribeSupportedValueChange", StatusCode::INTERNAL_ERROR);
+ hardware->setPropertyConfigs(testConfigs);
+
+ setHardware(std::move(hardware));
+
+ auto propIdAreaId = VhalPropIdAreaId{.propId = testInt32VecWindowProp(2), .areaId = 2};
+ auto status = getClient()->registerSupportedValueChangeCallback(
+ getCallbackClient(), std::vector<VhalPropIdAreaId>{propIdAreaId});
+
+ ASSERT_FALSE(status.isOk()) << "registerSupportedValueChangeCallback must return error if "
+ "VehicleHardware returns error";
+}
+
+TEST_F(DefaultVehicleHalTest, testUnregisterSupportedValueChangeCallback) {
+ auto testConfigs = std::vector<VehiclePropConfig>(
+ {VehiclePropConfig{
+ .prop = testInt32VecProp(1),
+ .areaConfigs =
+ {
+ {.areaId = 0,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasMinSupportedValue = false,
+ .hasMaxSupportedValue = false,
+ .hasSupportedValuesList = true,
+ }},
+ },
+ },
+ VehiclePropConfig{
+ .prop = testInt32VecWindowProp(2),
+ .areaConfigs =
+ {
+ {.areaId = 2,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasMinSupportedValue = true,
+ .hasMaxSupportedValue = false,
+ .hasSupportedValuesList = false,
+ }},
+ },
+ }});
+
+ auto hardware = std::make_unique<MockVehicleHardware>();
+ hardware->setPropertyConfigs(testConfigs);
+
+ setHardware(std::move(hardware));
+
+ auto propIdAreaId1 = VhalPropIdAreaId{.propId = testInt32VecProp(1), .areaId = 0};
+ auto propIdAreaId2 = VhalPropIdAreaId{.propId = testInt32VecWindowProp(2), .areaId = 2};
+ auto status = getClient()->registerSupportedValueChangeCallback(
+ getCallbackClient(), std::vector<VhalPropIdAreaId>{propIdAreaId1, propIdAreaId2});
+
+ ASSERT_TRUE(status.isOk()) << "Get non-okay status from registerSupportedValueChangeCallback"
+ << status.getMessage();
+
+ status = getClient()->unregisterSupportedValueChangeCallback(
+ getCallbackClient(), std::vector<VhalPropIdAreaId>{propIdAreaId1, propIdAreaId2});
+
+ ASSERT_TRUE(status.isOk()) << "Get non-okay status from unregisterSupportedValueChangeCallback"
+ << status.getMessage();
+
+ EXPECT_TRUE(getHardware()->getSubscribedSupportedValueChangePropIdAreaIds().empty())
+ << "All registered [propId, areaId]s must be unregistered";
+ EXPECT_EQ(countClients(), static_cast<size_t>(0)) << "subscribe clients must be cleared";
+ EXPECT_TRUE(hasNoSubscriptions()) << "subscribe clients must be cleared";
+}
+
+TEST_F(DefaultVehicleHalTest, testUnregisterSupportedValueChangeCallback_errorFromHardware) {
+ auto testConfigs = std::vector<VehiclePropConfig>({VehiclePropConfig{
+ .prop = testInt32VecProp(1),
+ .areaConfigs =
+ {
+ {.areaId = 0,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasMinSupportedValue = false,
+ .hasMaxSupportedValue = false,
+ .hasSupportedValuesList = true,
+ }},
+ },
+ }});
+
+ auto hardware = std::make_unique<MockVehicleHardware>();
+ hardware->setStatus("unsubscribeSupportedValueChange", StatusCode::INTERNAL_ERROR);
+ hardware->setPropertyConfigs(testConfigs);
+
+ setHardware(std::move(hardware));
+
+ auto propIdAreaId = VhalPropIdAreaId{.propId = testInt32VecProp(1), .areaId = 0};
+ auto status = getClient()->registerSupportedValueChangeCallback(
+ getCallbackClient(), std::vector<VhalPropIdAreaId>{propIdAreaId});
+
+ ASSERT_TRUE(status.isOk()) << "Get non-okay status from registerSupportedValueChangeCallback"
+ << status.getMessage();
+
+ status = getClient()->unregisterSupportedValueChangeCallback(
+ getCallbackClient(), std::vector<VhalPropIdAreaId>{propIdAreaId});
+
+ ASSERT_FALSE(status.isOk()) << "unregisterSupportedValueChangeCallback must return error if "
+ "VehicleHardware returns error";
+}
+
+TEST_F(DefaultVehicleHalTest, testUnregisterSupportedValueChangeCallback_ignoreUnregistered) {
+ auto testConfigs = std::vector<VehiclePropConfig>(
+ {VehiclePropConfig{
+ .prop = testInt32VecProp(1),
+ .areaConfigs =
+ {
+ {.areaId = 0,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasMinSupportedValue = false,
+ .hasMaxSupportedValue = false,
+ .hasSupportedValuesList = true,
+ }},
+ },
+ },
+ VehiclePropConfig{
+ .prop = testInt32VecWindowProp(2),
+ .areaConfigs =
+ {
+ {.areaId = 2,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasMinSupportedValue = true,
+ .hasMaxSupportedValue = false,
+ .hasSupportedValuesList = false,
+ }},
+ },
+ }});
+
+ auto hardware = std::make_unique<MockVehicleHardware>();
+ hardware->setPropertyConfigs(testConfigs);
+
+ setHardware(std::move(hardware));
+
+ auto propIdAreaId1 = VhalPropIdAreaId{.propId = testInt32VecProp(1), .areaId = 0};
+ auto propIdAreaId2 = VhalPropIdAreaId{.propId = testInt32VecWindowProp(2), .areaId = 2};
+ auto status = getClient()->unregisterSupportedValueChangeCallback(
+ getCallbackClient(), std::vector<VhalPropIdAreaId>{propIdAreaId1, propIdAreaId2});
+
+ ASSERT_TRUE(status.isOk());
+}
+
+TEST_F(DefaultVehicleHalTest, testSupportedValueChangeCallback) {
+ auto testConfigs = std::vector<VehiclePropConfig>(
+ {VehiclePropConfig{
+ .prop = testInt32VecProp(1),
+ .areaConfigs =
+ {
+ {.areaId = 0,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasMinSupportedValue = false,
+ .hasMaxSupportedValue = false,
+ .hasSupportedValuesList = true,
+ }},
+ },
+ },
+ VehiclePropConfig{
+ .prop = testInt32VecWindowProp(2),
+ .areaConfigs =
+ {
+ {.areaId = 2,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasMinSupportedValue = true,
+ .hasMaxSupportedValue = false,
+ .hasSupportedValuesList = false,
+ }},
+ },
+ }});
+
+ auto hardware = std::make_unique<MockVehicleHardware>();
+ hardware->setPropertyConfigs(testConfigs);
+
+ setHardware(std::move(hardware));
+
+ auto vhalPropIdAreaId1 = VhalPropIdAreaId{.propId = testInt32VecProp(1), .areaId = 0};
+ auto vhalPropIdAreaId2 = VhalPropIdAreaId{.propId = testInt32VecWindowProp(2), .areaId = 2};
+ auto propIdAreaId1 = PropIdAreaId{.propId = testInt32VecProp(1), .areaId = 0};
+ auto propIdAreaId2 = PropIdAreaId{.propId = testInt32VecWindowProp(2), .areaId = 2};
+ auto status = getClient()->registerSupportedValueChangeCallback(
+ getCallbackClient(),
+ std::vector<VhalPropIdAreaId>{vhalPropIdAreaId1, vhalPropIdAreaId2});
+
+ ASSERT_TRUE(status.isOk()) << "Get non-okay status from registerSupportedValueChangeCallback"
+ << status.getMessage();
+
+ getHardware()->sendSupportedValueChangeEvent(
+ std::vector<PropIdAreaId>{propIdAreaId1, propIdAreaId2});
+
+ getCallback()->waitForOnSupportedValueChange(/*size=*/2, /*timeoutInNano=*/1'000'000'000);
+
+ ASSERT_THAT(getCallback()->getOnSupportedValueChangePropIdAreaIds(),
+ ElementsAre(vhalPropIdAreaId1, vhalPropIdAreaId2));
+}
+
+TEST_F(DefaultVehicleHalTest, testSupportedValueChangeCallback_unregister) {
+ auto testConfigs = std::vector<VehiclePropConfig>(
+ {VehiclePropConfig{
+ .prop = testInt32VecProp(1),
+ .areaConfigs =
+ {
+ {.areaId = 0,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasMinSupportedValue = false,
+ .hasMaxSupportedValue = false,
+ .hasSupportedValuesList = true,
+ }},
+ },
+ },
+ VehiclePropConfig{
+ .prop = testInt32VecWindowProp(2),
+ .areaConfigs =
+ {
+ {.areaId = 2,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasMinSupportedValue = true,
+ .hasMaxSupportedValue = false,
+ .hasSupportedValuesList = false,
+ }},
+ },
+ }});
+
+ auto hardware = std::make_unique<MockVehicleHardware>();
+ hardware->setPropertyConfigs(testConfigs);
+
+ setHardware(std::move(hardware));
+
+ auto vhalPropIdAreaId1 = VhalPropIdAreaId{.propId = testInt32VecProp(1), .areaId = 0};
+ auto vhalPropIdAreaId2 = VhalPropIdAreaId{.propId = testInt32VecWindowProp(2), .areaId = 2};
+ auto propIdAreaId1 = PropIdAreaId{.propId = testInt32VecProp(1), .areaId = 0};
+ auto propIdAreaId2 = PropIdAreaId{.propId = testInt32VecWindowProp(2), .areaId = 2};
+ auto status = getClient()->registerSupportedValueChangeCallback(
+ getCallbackClient(),
+ std::vector<VhalPropIdAreaId>{vhalPropIdAreaId1, vhalPropIdAreaId2});
+
+ ASSERT_TRUE(status.isOk()) << "Get non-okay status from registerSupportedValueChangeCallback"
+ << status.getMessage();
+
+ // After unregistering for propIdAreaId1, we should no longer receive events for it.
+ status = getClient()->unregisterSupportedValueChangeCallback(
+ getCallbackClient(), std::vector<VhalPropIdAreaId>{vhalPropIdAreaId1});
+
+ ASSERT_TRUE(status.isOk()) << "Get non-okay status from unregisterSupportedValueChangeCallback"
+ << status.getMessage();
+
+ getHardware()->sendSupportedValueChangeEvent(
+ std::vector<PropIdAreaId>{propIdAreaId1, propIdAreaId2});
+
+ getCallback()->waitForOnSupportedValueChange(/*size=*/1, /*timeoutInNano=*/1'000'000'000);
+
+ ASSERT_THAT(getCallback()->getOnSupportedValueChangePropIdAreaIds(),
+ ElementsAre(vhalPropIdAreaId2));
+}
+
+TEST_F(DefaultVehicleHalTest, testRegisterSupportedValueChangeCallback_twoClients) {
+ auto testConfigs = std::vector<VehiclePropConfig>(
+ {VehiclePropConfig{
+ .prop = testInt32VecProp(1),
+ .areaConfigs =
+ {
+ {.areaId = 0,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasMinSupportedValue = false,
+ .hasMaxSupportedValue = false,
+ .hasSupportedValuesList = true,
+ }},
+ },
+ },
+ VehiclePropConfig{
+ .prop = testInt32VecWindowProp(2),
+ .areaConfigs =
+ {
+ {.areaId = 2,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasMinSupportedValue = true,
+ .hasMaxSupportedValue = false,
+ .hasSupportedValuesList = false,
+ }},
+ },
+ }});
+
+ auto hardware = std::make_unique<MockVehicleHardware>();
+ hardware->setPropertyConfigs(testConfigs);
+
+ setHardware(std::move(hardware));
+
+ auto vhalPropIdAreaId1 = VhalPropIdAreaId{.propId = testInt32VecProp(1), .areaId = 0};
+ auto vhalPropIdAreaId2 = VhalPropIdAreaId{.propId = testInt32VecWindowProp(2), .areaId = 2};
+ auto propIdAreaId1 = PropIdAreaId{.propId = testInt32VecProp(1), .areaId = 0};
+ auto propIdAreaId2 = PropIdAreaId{.propId = testInt32VecWindowProp(2), .areaId = 2};
+ std::shared_ptr<IVehicleCallback> callback1 = ndk::SharedRefBase::make<MockVehicleCallback>();
+ std::shared_ptr<IVehicleCallback> callback2 = ndk::SharedRefBase::make<MockVehicleCallback>();
+ // Keep binder alive to prevent binder reuse.
+ SpAIBinder binder1 = callback1->asBinder();
+ // Keep binder alive to prevent binder reuse.
+ SpAIBinder binder2 = callback2->asBinder();
+
+ auto status = getClient()->registerSupportedValueChangeCallback(
+ callback1, std::vector<VhalPropIdAreaId>{vhalPropIdAreaId1, vhalPropIdAreaId2});
+
+ ASSERT_TRUE(status.isOk()) << "Get non-okay status from registerSupportedValueChangeCallback"
+ << status.getMessage();
+
+ status = getClient()->registerSupportedValueChangeCallback(
+ callback2, std::vector<VhalPropIdAreaId>{vhalPropIdAreaId1, vhalPropIdAreaId2});
+
+ ASSERT_TRUE(status.isOk()) << "Get non-okay status from registerSupportedValueChangeCallback"
+ << status.getMessage();
+
+ ASSERT_THAT(getHardware()->getSubscribedSupportedValueChangePropIdAreaIds(),
+ UnorderedElementsAre(propIdAreaId1, propIdAreaId2));
+
+ status = getClient()->unregisterSupportedValueChangeCallback(
+ callback1, std::vector<VhalPropIdAreaId>{vhalPropIdAreaId1, vhalPropIdAreaId2});
+
+ ASSERT_TRUE(status.isOk()) << "Get non-okay status from unregisterSupportedValueChangeCallback"
+ << status.getMessage();
+
+ ASSERT_THAT(getHardware()->getSubscribedSupportedValueChangePropIdAreaIds(),
+ UnorderedElementsAre(propIdAreaId1, propIdAreaId2))
+ << "[propId, areaId] must still be subscribed if one of the two clients unsubscribe";
+
+ status = getClient()->unregisterSupportedValueChangeCallback(
+ callback2, std::vector<VhalPropIdAreaId>{vhalPropIdAreaId1, vhalPropIdAreaId2});
+
+ ASSERT_TRUE(status.isOk()) << "Get non-okay status from unregisterSupportedValueChangeCallback"
+ << status.getMessage();
+
+ ASSERT_TRUE(getHardware()->getSubscribedSupportedValueChangePropIdAreaIds().empty())
+ << "All registered [propId, areaId]s must be unregistered";
+}
+
+TEST_F(DefaultVehicleHalTest, testRegisterSupportedValueChange_monitorBinderLifecycle) {
+ auto testConfigs = std::vector<VehiclePropConfig>({VehiclePropConfig{
+ .prop = testInt32VecProp(1),
+ .areaConfigs =
+ {
+ {.areaId = 0,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasMinSupportedValue = false,
+ .hasMaxSupportedValue = false,
+ .hasSupportedValuesList = true,
+ }},
+ },
+ }});
+
+ auto hardware = std::make_unique<MockVehicleHardware>();
+ hardware->setPropertyConfigs(testConfigs);
+
+ setHardware(std::move(hardware));
+
+ auto vhalPropIdAreaId = VhalPropIdAreaId{.propId = testInt32VecProp(1), .areaId = 0};
+
+ auto status = getClient()->registerSupportedValueChangeCallback(
+ getCallbackClient(), std::vector<VhalPropIdAreaId>{vhalPropIdAreaId});
+
+ ASSERT_TRUE(status.isOk()) << "Get non-okay status from registerSupportedValueChangeCallback"
+ << status.getMessage();
+
+ ASSERT_EQ(countOnBinderDiedContexts(), static_cast<size_t>(1))
+ << "expect one OnBinderDied context when one client is registered";
+}
+
+} // 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 0000000..a557b05
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleCallback.cpp
@@ -0,0 +1,175 @@
+/*
+ * 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 <android-base/thread_annotations.h>
+#include <chrono>
+
+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 <class T>
+static ScopedAStatus storeResults(const T& results, std::list<T>* 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<std::mutex> lockGuard(mLock);
+ result = storeResults(results, &mGetValueResults);
+ }
+ mCond.notify_all();
+ return result;
+}
+
+ScopedAStatus MockVehicleCallback::onSetValues(const SetValueResults& results) {
+ ScopedAStatus result;
+ {
+ std::scoped_lock<std::mutex> 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<std::mutex> lockGuard(mLock);
+ mSharedMemoryFileCount = sharedMemoryFileCount;
+ result = storeResults(results, &mOnPropertyEventResults);
+ }
+ mCond.notify_all();
+ return result;
+}
+
+ScopedAStatus MockVehicleCallback::onPropertySetError(const VehiclePropErrors& results) {
+ ScopedAStatus result;
+ {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ result = storeResults(results, &mOnPropertySetErrorResults);
+ }
+ mCond.notify_all();
+ return result;
+}
+
+ScopedAStatus MockVehicleCallback::onSupportedValueChange(
+ const std::vector<PropIdAreaId>& propIdAreaIds) {
+ {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ mOnSupportedValueChangePropIdAreaIds = propIdAreaIds;
+ }
+ mCond.notify_all();
+ return ScopedAStatus::ok();
+}
+
+std::optional<GetValueResults> MockVehicleCallback::nextGetValueResults() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ return pop(mGetValueResults);
+}
+
+std::optional<SetValueResults> MockVehicleCallback::nextSetValueResults() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ return pop(mSetValueResults);
+}
+
+std::optional<VehiclePropValues> MockVehicleCallback::nextOnPropertyEventResults() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ return pop(mOnPropertyEventResults);
+}
+
+size_t MockVehicleCallback::countOnPropertyEventResults() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ return mOnPropertyEventResults.size();
+}
+
+std::optional<VehiclePropErrors> MockVehicleCallback::nextOnPropertySetErrorResults() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ return pop(mOnPropertySetErrorResults);
+}
+
+size_t MockVehicleCallback::countOnPropertySetErrorResults() {
+ std::scoped_lock<std::mutex> 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;
+ });
+}
+
+bool MockVehicleCallback::waitForOnSupportedValueChange(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 mOnSupportedValueChangePropIdAreaIds.size() >= size;
+ });
+}
+
+std::vector<PropIdAreaId> MockVehicleCallback::getOnSupportedValueChangePropIdAreaIds() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ return mOnSupportedValueChangePropIdAreaIds;
+}
+
+} // 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 0000000..be181a5
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleCallback.h
@@ -0,0 +1,101 @@
+/*
+ * 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 <VehicleHalTypes.h>
+
+#include <aidl/android/hardware/automotive/vehicle/BnVehicleCallback.h>
+#include <android-base/thread_annotations.h>
+
+#include <condition_variable>
+#include <list>
+#include <mutex>
+#include <optional>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+template <class T>
+std::optional<T> pop(std::list<T>& 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<aidl::android::hardware::automotive::vehicle::PropIdAreaId>&)
+ override;
+
+ // Test functions
+ std::optional<aidl::android::hardware::automotive::vehicle::GetValueResults>
+ nextGetValueResults();
+ std::optional<aidl::android::hardware::automotive::vehicle::SetValueResults>
+ nextSetValueResults();
+ std::optional<aidl::android::hardware::automotive::vehicle::VehiclePropValues>
+ nextOnPropertyEventResults();
+ size_t countOnPropertySetErrorResults();
+ std::optional<aidl::android::hardware::automotive::vehicle::VehiclePropErrors>
+ 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);
+ bool waitForOnSupportedValueChange(size_t size, size_t timeoutInNano);
+ std::vector<aidl::android::hardware::automotive::vehicle::PropIdAreaId>
+ getOnSupportedValueChangePropIdAreaIds();
+
+ private:
+ std::mutex mLock;
+ std::condition_variable mCond;
+ std::list<aidl::android::hardware::automotive::vehicle::GetValueResults> mGetValueResults
+ GUARDED_BY(mLock);
+ std::list<aidl::android::hardware::automotive::vehicle::SetValueResults> mSetValueResults
+ GUARDED_BY(mLock);
+ std::list<aidl::android::hardware::automotive::vehicle::VehiclePropValues>
+ mOnPropertyEventResults GUARDED_BY(mLock);
+ int32_t mSharedMemoryFileCount GUARDED_BY(mLock);
+ std::list<aidl::android::hardware::automotive::vehicle::VehiclePropErrors>
+ mOnPropertySetErrorResults GUARDED_BY(mLock);
+ std::vector<aidl::android::hardware::automotive::vehicle::PropIdAreaId>
+ mOnSupportedValueChangePropIdAreaIds 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 0000000..197e99d
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleHardware.cpp
@@ -0,0 +1,442 @@
+/*
+ * 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 <utils/Log.h>
+
+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::MinMaxSupportedValueResult;
+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::SupportedValuesListResult;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+
+MockVehicleHardware::MockVehicleHardware() {
+ mRecurrentTimer = std::make_unique<RecurrentTimer>();
+}
+
+MockVehicleHardware::~MockVehicleHardware() {
+ std::unique_lock<std::mutex> lk(mLock);
+ mCv.wait(lk, [this] { return mThreadCount == 0; });
+ mRecurrentTimer.reset();
+}
+
+std::vector<VehiclePropConfig> MockVehicleHardware::getAllPropertyConfigs() const {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ mGetAllPropertyConfigsCalled = true;
+ return mPropertyConfigs;
+}
+
+std::optional<VehiclePropConfig> MockVehicleHardware::getPropertyConfig(int32_t propId) const {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ for (const auto& config : mPropertyConfigs) {
+ if (config.prop == propId) {
+ return config;
+ }
+ }
+ return std::nullopt;
+}
+
+StatusCode MockVehicleHardware::setValues(std::shared_ptr<const SetValuesCallback> callback,
+ const std::vector<SetValueRequest>& requests) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ if (StatusCode status = handleRequestsLocked(__func__, callback, requests, &mSetValueRequests,
+ &mSetValueResponses);
+ status != StatusCode::OK) {
+ return status;
+ }
+ if (mPropertyChangeCallback == nullptr) {
+ return StatusCode::OK;
+ }
+ std::vector<VehiclePropValue> values;
+ for (auto& request : requests) {
+ values.push_back(request.value);
+ }
+ (*mPropertyChangeCallback)(values);
+ return StatusCode::OK;
+}
+
+StatusCode MockVehicleHardware::getValues(std::shared_ptr<const GetValuesCallback> callback,
+ const std::vector<GetValueRequest>& requests) const {
+ std::scoped_lock<std::mutex> 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<std::string>&) {
+ return mDumpResult;
+}
+
+StatusCode MockVehicleHardware::checkHealth() {
+ return StatusCode::OK;
+}
+
+StatusCode MockVehicleHardware::subscribe(SubscribeOptions options) {
+ {
+ std::scoped_lock<std::mutex> 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<SubscribeOptions> MockVehicleHardware::getSubscribeOptions() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ return mSubscribeOptions;
+}
+
+void MockVehicleHardware::clearSubscribeOptions() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ mSubscribeOptions.clear();
+}
+
+StatusCode MockVehicleHardware::subscribePropIdAreaId(int32_t propId, int32_t areaId,
+ float sampleRateHz) {
+ if (sampleRateHz == 0) {
+ // on-change property.
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ mSubOnChangePropIdAreaIds.insert(std::pair<int32_t, int32_t>(propId, areaId));
+ return StatusCode::OK;
+ }
+
+ // continuous property.
+ std::shared_ptr<std::function<void()>> action;
+
+ {
+ std::scoped_lock<std::mutex> 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<std::function<void()>>([propertyChangeCallback, propId, areaId] {
+ std::vector<VehiclePropValue> 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<int64_t>(1'000'000'000. / sampleRateHz);
+ mRecurrentTimer->registerTimerCallback(interval, action);
+ return StatusCode::OK;
+}
+
+StatusCode MockVehicleHardware::unsubscribe(int32_t propId, int32_t areaId) {
+ std::scoped_lock<std::mutex> 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<std::pair<int32_t, int32_t>> MockVehicleHardware::getSubscribedOnChangePropIdAreaIds() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ std::set<std::pair<int32_t, int32_t>> propIdAreaIds;
+ propIdAreaIds = mSubOnChangePropIdAreaIds;
+ return propIdAreaIds;
+}
+
+std::set<std::pair<int32_t, int32_t>> MockVehicleHardware::getSubscribedContinuousPropIdAreaIds() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ std::set<std::pair<int32_t, int32_t>> propIdAreaIds;
+ for (const auto& [propId, actionByAreaId] : mRecurrentActions) {
+ for (const auto& [areaId, _] : actionByAreaId) {
+ propIdAreaIds.insert(std::make_pair(propId, areaId));
+ }
+ }
+ return propIdAreaIds;
+}
+
+std::vector<SupportedValuesListResult> MockVehicleHardware::getSupportedValuesLists(
+ const std::vector<PropIdAreaId>& propIdAreaIds) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ mSupportedValuesListRequest = propIdAreaIds;
+ return mSupportedValuesListResponse;
+}
+
+std::vector<MinMaxSupportedValueResult> MockVehicleHardware::getMinMaxSupportedValues(
+ const std::vector<PropIdAreaId>& propIdAreaIds) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ mMinMaxSupportedValueRequest = propIdAreaIds;
+ return mMinMaxSupportedValueResponse;
+}
+
+void MockVehicleHardware::registerOnPropertyChangeEvent(
+ std::unique_ptr<const PropertyChangeCallback> callback) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ mPropertyChangeCallback = std::move(callback);
+}
+
+void MockVehicleHardware::registerOnPropertySetErrorEvent(
+ std::unique_ptr<const PropertySetErrorCallback> callback) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ mPropertySetErrorCallback = std::move(callback);
+}
+
+void MockVehicleHardware::registerSupportedValueChangeCallback(
+ std::unique_ptr<const SupportedValueChangeCallback> callback) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ mSupportedValueChangeCallback = std::move(callback);
+}
+
+void MockVehicleHardware::setPropertyConfigs(const std::vector<VehiclePropConfig>& configs) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ mPropertyConfigs = configs;
+}
+
+void MockVehicleHardware::addGetValueResponses(const std::vector<GetValueResult>& responses) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ mGetValueResponses.push_back(responses);
+}
+
+void MockVehicleHardware::addSetValueResponses(const std::vector<SetValueResult>& responses) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ mSetValueResponses.push_back(responses);
+}
+
+void MockVehicleHardware::setGetValueResponder(
+ std::function<StatusCode(std::shared_ptr<const GetValuesCallback>,
+ const std::vector<GetValueRequest>&)>&& responder) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ mGetValueResponder = responder;
+}
+
+std::vector<GetValueRequest> MockVehicleHardware::nextGetValueRequests() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ std::optional<std::vector<GetValueRequest>> request = pop(mGetValueRequests);
+ if (!request.has_value()) {
+ return std::vector<GetValueRequest>();
+ }
+ return std::move(request.value());
+}
+
+std::vector<SetValueRequest> MockVehicleHardware::nextSetValueRequests() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ std::optional<std::vector<SetValueRequest>> request = pop(mSetValueRequests);
+ if (!request.has_value()) {
+ return std::vector<SetValueRequest>();
+ }
+ return std::move(request.value());
+}
+
+void MockVehicleHardware::setStatus(const char* functionName, StatusCode status) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ mStatusByFunctions[functionName] = status;
+}
+
+void MockVehicleHardware::setSleepTime(int64_t timeInNano) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ mSleepTime = timeInNano;
+}
+
+void MockVehicleHardware::setPropertyOnChangeEventBatchingWindow(std::chrono::nanoseconds window) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ mEventBatchingWindow = window;
+}
+
+void MockVehicleHardware::setSupportedValuesListResponse(
+ const std::vector<SupportedValuesListResult>& response) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ mSupportedValuesListResponse = response;
+}
+
+void MockVehicleHardware::setMinMaxSupportedValueResponse(
+ const std::vector<MinMaxSupportedValueResult>& response) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ mMinMaxSupportedValueResponse = response;
+}
+
+std::vector<PropIdAreaId> MockVehicleHardware::getSupportedValuesListRequest() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ return mSupportedValuesListRequest;
+}
+
+std::vector<PropIdAreaId> MockVehicleHardware::getMinMaxSupportedValueRequest() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ return mMinMaxSupportedValueRequest;
+}
+
+std::chrono::nanoseconds MockVehicleHardware::getPropertyOnChangeEventBatchingWindow() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ return mEventBatchingWindow;
+}
+
+StatusCode MockVehicleHardware::subscribeSupportedValueChange(
+ const std::vector<PropIdAreaId>& propIdAreaIds) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ if (auto it = mStatusByFunctions.find(__func__); it != mStatusByFunctions.end()) {
+ if (StatusCode status = it->second; status != StatusCode::OK) {
+ return status;
+ }
+ }
+ for (const auto& propIdAreaId : propIdAreaIds) {
+ mSubscribedSupportedValueChangePropIdAreaIds.insert(propIdAreaId);
+ }
+ return StatusCode::OK;
+}
+
+StatusCode MockVehicleHardware::unsubscribeSupportedValueChange(
+ const std::vector<PropIdAreaId>& propIdAreaIds) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ if (auto it = mStatusByFunctions.find(__func__); it != mStatusByFunctions.end()) {
+ if (StatusCode status = it->second; status != StatusCode::OK) {
+ return status;
+ }
+ }
+ for (const auto& propIdAreaId : propIdAreaIds) {
+ mSubscribedSupportedValueChangePropIdAreaIds.erase(propIdAreaId);
+ }
+ return StatusCode::OK;
+}
+
+std::unordered_set<PropIdAreaId, PropIdAreaIdHash>
+MockVehicleHardware::getSubscribedSupportedValueChangePropIdAreaIds() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ return mSubscribedSupportedValueChangePropIdAreaIds;
+}
+
+template <class ResultType>
+StatusCode MockVehicleHardware::returnResponse(
+ std::shared_ptr<const std::function<void(std::vector<ResultType>)>> callback,
+ std::list<std::vector<ResultType>>* 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<GetValueResult>(
+ std::shared_ptr<const std::function<void(std::vector<GetValueResult>)>> callback,
+ std::list<std::vector<GetValueResult>>* storedResponses) const;
+
+template StatusCode MockVehicleHardware::returnResponse<SetValueResult>(
+ std::shared_ptr<const std::function<void(std::vector<SetValueResult>)>> callback,
+ std::list<std::vector<SetValueResult>>* storedResponses) const;
+
+template <class RequestType, class ResultType>
+StatusCode MockVehicleHardware::handleRequestsLocked(
+ const char* functionName,
+ std::shared_ptr<const std::function<void(std::vector<ResultType>)>> callback,
+ const std::vector<RequestType>& requests,
+ std::list<std::vector<RequestType>>* storedRequests,
+ std::list<std::vector<ResultType>>* 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<GetValueRequest, GetValueResult>(
+ const char* functionName,
+ std::shared_ptr<const std::function<void(std::vector<GetValueResult>)>> callback,
+ const std::vector<GetValueRequest>& requests,
+ std::list<std::vector<GetValueRequest>>* storedRequests,
+ std::list<std::vector<GetValueResult>>* storedResponses) const;
+
+template StatusCode MockVehicleHardware::handleRequestsLocked<SetValueRequest, SetValueResult>(
+ const char* functionName,
+ std::shared_ptr<const std::function<void(std::vector<SetValueResult>)>> callback,
+ const std::vector<SetValueRequest>& requests,
+ std::list<std::vector<SetValueRequest>>* storedRequests,
+ std::list<std::vector<SetValueResult>>* storedResponses) const;
+
+void MockVehicleHardware::sendOnPropertySetErrorEvent(
+ const std::vector<SetValueErrorEvent>& errorEvents) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ (*mPropertySetErrorCallback)(errorEvents);
+}
+
+void MockVehicleHardware::sendSupportedValueChangeEvent(
+ const std::vector<PropIdAreaId>& propIdAreaIds) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ (*mSupportedValueChangeCallback)(propIdAreaIds);
+}
+
+bool MockVehicleHardware::getAllPropertyConfigsCalled() {
+ std::scoped_lock<std::mutex> 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 0000000..444166b
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleHardware.h
@@ -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.
+ */
+
+#ifndef android_hardware_automotive_vehicle_aidl_impl_vhal_test_MockVehicleHardware_H_
+#define android_hardware_automotive_vehicle_aidl_impl_vhal_test_MockVehicleHardware_H_
+
+#include <IVehicleHardware.h>
+#include <RecurrentTimer.h>
+#include <VehicleHalTypes.h>
+
+#include <android-base/thread_annotations.h>
+
+#include <atomic>
+#include <chrono>
+#include <condition_variable>
+#include <list>
+#include <memory>
+#include <mutex>
+#include <set>
+#include <thread>
+#include <unordered_map>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+class MockVehicleHardware final : public IVehicleHardware {
+ public:
+ MockVehicleHardware();
+
+ ~MockVehicleHardware();
+
+ std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
+ getAllPropertyConfigs() const override;
+ std::optional<aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
+ getPropertyConfig(int32_t propId) const override;
+ aidl::android::hardware::automotive::vehicle::StatusCode setValues(
+ std::shared_ptr<const SetValuesCallback> callback,
+ const std::vector<aidl::android::hardware::automotive::vehicle::SetValueRequest>&
+ requests) override;
+ aidl::android::hardware::automotive::vehicle::StatusCode getValues(
+ std::shared_ptr<const GetValuesCallback> callback,
+ const std::vector<aidl::android::hardware::automotive::vehicle::GetValueRequest>&
+ requests) const override;
+ DumpResult dump(const std::vector<std::string>&) override;
+ aidl::android::hardware::automotive::vehicle::StatusCode checkHealth() override;
+ void registerOnPropertyChangeEvent(
+ std::unique_ptr<const PropertyChangeCallback> callback) override;
+ void registerOnPropertySetErrorEvent(std::unique_ptr<const PropertySetErrorCallback>) override;
+ void registerSupportedValueChangeCallback(
+ std::unique_ptr<const SupportedValueChangeCallback>) 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;
+ std::vector<aidl::android::hardware::automotive::vehicle::SupportedValuesListResult>
+ getSupportedValuesLists(const std::vector<PropIdAreaId>& propIdAreaIds) override;
+ std::vector<aidl::android::hardware::automotive::vehicle::MinMaxSupportedValueResult>
+ getMinMaxSupportedValues(const std::vector<PropIdAreaId>& propIdAreaIds) override;
+ aidl::android::hardware::automotive::vehicle::StatusCode subscribeSupportedValueChange(
+ const std::vector<PropIdAreaId>& propIdAreaIds) override;
+ aidl::android::hardware::automotive::vehicle::StatusCode unsubscribeSupportedValueChange(
+ const std::vector<PropIdAreaId>& propIdAreaIds) override;
+
+ // Test functions.
+ void setPropertyConfigs(
+ const std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropConfig>&
+ configs);
+ void addGetValueResponses(
+ const std::vector<aidl::android::hardware::automotive::vehicle::GetValueResult>&
+ responses);
+ void addSetValueResponses(
+ const std::vector<aidl::android::hardware::automotive::vehicle::SetValueResult>&
+ responses);
+ void setSupportedValuesListResponse(
+ const std::vector<
+ aidl::android::hardware::automotive::vehicle::SupportedValuesListResult>&
+ response);
+ void setMinMaxSupportedValueResponse(
+ const std::vector<
+ aidl::android::hardware::automotive::vehicle::MinMaxSupportedValueResult>&
+ response);
+ void setGetValueResponder(
+ std::function<aidl::android::hardware::automotive::vehicle::StatusCode(
+ std::shared_ptr<const GetValuesCallback>,
+ const std::vector<
+ aidl::android::hardware::automotive::vehicle::GetValueRequest>&)>&&
+ responder);
+ std::vector<aidl::android::hardware::automotive::vehicle::GetValueRequest>
+ nextGetValueRequests();
+ std::vector<aidl::android::hardware::automotive::vehicle::SetValueRequest>
+ nextSetValueRequests();
+ std::vector<PropIdAreaId> getSupportedValuesListRequest();
+ std::vector<PropIdAreaId> getMinMaxSupportedValueRequest();
+ 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<SetValueErrorEvent>& errorEvents);
+ void setPropertyOnChangeEventBatchingWindow(std::chrono::nanoseconds window);
+ void sendSupportedValueChangeEvent(const std::vector<PropIdAreaId>& propIdAreaIds);
+
+ std::set<std::pair<int32_t, int32_t>> getSubscribedOnChangePropIdAreaIds();
+ std::set<std::pair<int32_t, int32_t>> getSubscribedContinuousPropIdAreaIds();
+ std::vector<aidl::android::hardware::automotive::vehicle::SubscribeOptions>
+ getSubscribeOptions();
+ void clearSubscribeOptions();
+ // Whether getAllPropertyConfigs() has been called, which blocks on all property configs
+ // being ready.
+ bool getAllPropertyConfigsCalled();
+
+ std::unordered_set<PropIdAreaId, PropIdAreaIdHash>
+ getSubscribedSupportedValueChangePropIdAreaIds();
+
+ private:
+ mutable std::mutex mLock;
+ mutable std::condition_variable mCv;
+ mutable std::atomic<int> mThreadCount;
+ std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropConfig> mPropertyConfigs
+ GUARDED_BY(mLock);
+ mutable std::list<std::vector<aidl::android::hardware::automotive::vehicle::GetValueRequest>>
+ mGetValueRequests GUARDED_BY(mLock);
+ mutable std::list<std::vector<aidl::android::hardware::automotive::vehicle::GetValueResult>>
+ mGetValueResponses GUARDED_BY(mLock);
+ mutable std::list<std::vector<aidl::android::hardware::automotive::vehicle::SetValueRequest>>
+ mSetValueRequests GUARDED_BY(mLock);
+ mutable std::list<std::vector<aidl::android::hardware::automotive::vehicle::SetValueResult>>
+ mSetValueResponses GUARDED_BY(mLock);
+ mutable std::vector<PropIdAreaId> mSupportedValuesListRequest GUARDED_BY(mLock);
+ mutable std::vector<PropIdAreaId> mMinMaxSupportedValueRequest GUARDED_BY(mLock);
+ mutable std::vector<aidl::android::hardware::automotive::vehicle::SupportedValuesListResult>
+ mSupportedValuesListResponse GUARDED_BY(mLock);
+ mutable std::vector<aidl::android::hardware::automotive::vehicle::MinMaxSupportedValueResult>
+ mMinMaxSupportedValueResponse GUARDED_BY(mLock);
+ std::unordered_map<const char*, aidl::android::hardware::automotive::vehicle::StatusCode>
+ mStatusByFunctions GUARDED_BY(mLock);
+ int64_t mSleepTime GUARDED_BY(mLock) = 0;
+ std::unique_ptr<const PropertyChangeCallback> mPropertyChangeCallback GUARDED_BY(mLock);
+ std::unique_ptr<const PropertySetErrorCallback> mPropertySetErrorCallback GUARDED_BY(mLock);
+ std::unique_ptr<const SupportedValueChangeCallback> mSupportedValueChangeCallback
+ GUARDED_BY(mLock);
+ std::function<aidl::android::hardware::automotive::vehicle::StatusCode(
+ std::shared_ptr<const GetValuesCallback>,
+ const std::vector<aidl::android::hardware::automotive::vehicle::GetValueRequest>&)>
+ mGetValueResponder GUARDED_BY(mLock);
+ std::chrono::nanoseconds mEventBatchingWindow GUARDED_BY(mLock) = std::chrono::nanoseconds(0);
+ std::set<std::pair<int32_t, int32_t>> mSubOnChangePropIdAreaIds GUARDED_BY(mLock);
+ std::vector<aidl::android::hardware::automotive::vehicle::SubscribeOptions> mSubscribeOptions
+ GUARDED_BY(mLock);
+
+ template <class ResultType>
+ aidl::android::hardware::automotive::vehicle::StatusCode returnResponse(
+ std::shared_ptr<const std::function<void(std::vector<ResultType>)>> callback,
+ std::list<std::vector<ResultType>>* storedResponses) const;
+ template <class RequestType, class ResultType>
+ aidl::android::hardware::automotive::vehicle::StatusCode handleRequestsLocked(
+ const char* functionName,
+ std::shared_ptr<const std::function<void(std::vector<ResultType>)>> callback,
+ const std::vector<RequestType>& requests,
+ std::list<std::vector<RequestType>>* storedRequests,
+ std::list<std::vector<ResultType>>* 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<RecurrentTimer> mRecurrentTimer;
+ std::unordered_map<int32_t, std::unordered_map<int32_t, std::shared_ptr<std::function<void()>>>>
+ mRecurrentActions GUARDED_BY(mLock);
+
+ std::unordered_set<PropIdAreaId, PropIdAreaIdHash> mSubscribedSupportedValueChangePropIdAreaIds
+ 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 0000000..d624cce
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/current/vhal/test/SubscriptionManagerTest.cpp
@@ -0,0 +1,969 @@
+/*
+ * 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 <MockVehicleHardware.h>
+#include <VehicleHalTypes.h>
+
+#include <aidl/android/hardware/automotive/vehicle/BnVehicleCallback.h>
+#include <android-base/thread_annotations.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <float.h>
+#include <chrono>
+#include <list>
+#include <memory>
+#include <mutex>
+#include <thread>
+#include <vector>
+
+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<std::mutex> 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<VehiclePropValue> getEvents() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ return mEvents;
+ }
+
+ void clearEvents() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ mEvents.clear();
+ }
+
+ private:
+ std::mutex mLock;
+ std::list<VehiclePropValue> mEvents GUARDED_BY(mLock);
+};
+
+class SubscriptionManagerTest : public testing::Test {
+ public:
+ void SetUp() override {
+ mHardware = std::make_shared<MockVehicleHardware>();
+ mManager = std::make_unique<SubscriptionManager>(mHardware.get());
+ mCallback = ndk::SharedRefBase::make<PropertyCallback>();
+ // Keep the local binder alive.
+ mBinder = mCallback->asBinder();
+ mCallbackClient = IVehicleCallback::fromBinder(mBinder);
+ std::shared_ptr<IVehicleCallback> callbackClient = mCallbackClient;
+ mHardware->registerOnPropertyChangeEvent(
+ std::make_unique<IVehicleHardware::PropertyChangeCallback>(
+ [callbackClient](std::vector<VehiclePropValue> updatedValues) {
+ VehiclePropValues values = {
+ .payloads = std::move(updatedValues),
+ };
+ callbackClient->onPropertyEvent(values, 0);
+ }));
+ }
+
+ SubscriptionManager* getManager() { return mManager.get(); }
+
+ std::shared_ptr<IVehicleCallback> getCallbackClient() { return mCallbackClient; }
+
+ PropertyCallback* getCallback() { return mCallback.get(); }
+
+ std::list<VehiclePropValue> getEvents() { return getCallback()->getEvents(); }
+
+ void clearEvents() { return getCallback()->clearEvents(); }
+
+ std::shared_ptr<MockVehicleHardware> getHardware() { return mHardware; }
+
+ bool isEmpty() { return mManager->isEmpty(); }
+
+ private:
+ std::unique_ptr<SubscriptionManager> mManager;
+ std::shared_ptr<PropertyCallback> mCallback;
+ std::shared_ptr<IVehicleCallback> mCallbackClient;
+ std::shared_ptr<MockVehicleHardware> mHardware;
+ SpAIBinder mBinder;
+};
+
+TEST_F(SubscriptionManagerTest, testSubscribeGlobalContinuous) {
+ std::vector<SubscribeOptions> 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<int32_t, int32_t>(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<size_t>(9));
+ EXPECT_EQ(getEvents().back().prop, 0);
+ EXPECT_EQ(getEvents().back().areaId, 0);
+}
+
+TEST_F(SubscriptionManagerTest, testSubscribeMultiplePropsGlobalContinuous) {
+ std::vector<SubscribeOptions> 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<size_t>(9));
+ // Theoretically trigger 20 times, but check for at least 15 times to be stable.
+ EXPECT_GE(event1Count, static_cast<size_t>(15));
+}
+
+TEST_F(SubscriptionManagerTest, testOverrideSubscriptionContinuous) {
+ std::vector<SubscribeOptions> 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<size_t>(9));
+ EXPECT_LE(getEvents().size(), static_cast<size_t>(15));
+}
+
+TEST_F(SubscriptionManagerTest, testSubscribeMultipleAreasContinuous) {
+ std::vector<SubscribeOptions> 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<size_t>(9));
+ // Theoretically trigger 10 times, but check for at least 9 times to be stable.
+ EXPECT_GE(area1Count, static_cast<size_t>(9));
+}
+
+TEST_F(SubscriptionManagerTest, testUnsubscribeGlobalContinuous) {
+ std::vector<SubscribeOptions> 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<SubscribeOptions> 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<int32_t>({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<size_t>(9));
+
+ for (const auto& event : getEvents()) {
+ EXPECT_EQ(event.prop, 1);
+ }
+}
+
+TEST_F(SubscriptionManagerTest, testUnsubscribeByCallback) {
+ std::vector<SubscribeOptions> 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<SubscribeOptions> 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<int32_t>({0, 1, 2}));
+ ASSERT_TRUE(result.ok()) << "unsubscribe an unsubscribed property must do nothing";
+
+ result = getManager()->unsubscribe(getCallbackClient()->asBinder().get(),
+ std::vector<int32_t>({0, 1, 2}));
+ ASSERT_TRUE(result.ok()) << "retry an unsubscribe operation must not throw error";
+
+ std::vector<VehiclePropValue> updatedValues = {
+ {
+ .prop = 0,
+ .areaId = 0,
+ },
+ {
+ .prop = 1,
+ .areaId = 0,
+ },
+ };
+ auto clients = getManager()->getSubscribedClients(std::vector<VehiclePropValue>(updatedValues));
+
+ ASSERT_EQ(clients.size(), 0u) << "all subscribed properties must be unsubscribed";
+}
+
+TEST_F(SubscriptionManagerTest, testSubscribeOnchange) {
+ std::vector<SubscribeOptions> options1 = {
+ {
+ .propId = 0,
+ .areaIds = {0, 1},
+ },
+ {
+ .propId = 1,
+ .areaIds = {0},
+ },
+ };
+ std::vector<SubscribeOptions> options2 = {
+ {
+ .propId = 0,
+ .areaIds = {0},
+ },
+ };
+
+ SpAIBinder binder1 = ndk::SharedRefBase::make<PropertyCallback>()->asBinder();
+ std::shared_ptr<IVehicleCallback> client1 = IVehicleCallback::fromBinder(binder1);
+ SpAIBinder binder2 = ndk::SharedRefBase::make<PropertyCallback>()->asBinder();
+ std::shared_ptr<IVehicleCallback> 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<int32_t, int32_t>(0, 0),
+ std::pair<int32_t, int32_t>(0, 1),
+ std::pair<int32_t, int32_t>(1, 0)));
+ ASSERT_EQ(getHardware()->getSubscribedContinuousPropIdAreaIds().size(), 0u);
+
+ std::vector<VehiclePropValue> updatedValues = {
+ {
+ .prop = 0,
+ .areaId = 0,
+ },
+ {
+ .prop = 0,
+ .areaId = 1,
+ },
+ {
+ .prop = 1,
+ .areaId = 0,
+ },
+ {
+ .prop = 1,
+ .areaId = 1,
+ },
+ };
+ auto clients = getManager()->getSubscribedClients(std::vector<VehiclePropValue>(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<SubscribeOptions> 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<SubscribeOptions> 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<SubscribeOptions> 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<int32_t>({0}));
+ ASSERT_TRUE(result.ok()) << "failed to unsubscribe: " << result.error().message();
+
+ std::vector<VehiclePropValue> updatedValues = {
+ {
+ .prop = 0,
+ .areaId = 0,
+ },
+ {
+ .prop = 1,
+ .areaId = 0,
+ },
+ };
+ auto clients = getManager()->getSubscribedClients(std::vector<VehiclePropValue>(updatedValues));
+
+ ASSERT_THAT(clients[getCallbackClient()], ElementsAre(updatedValues[1]));
+ ASSERT_THAT(getHardware()->getSubscribedOnChangePropIdAreaIds(),
+ UnorderedElementsAre(std::pair<int32_t, int32_t>(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<SubscribeOptions> 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<SubscribeOptions> 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<SubscribeOptions> 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<PropertyCallback>()->asBinder();
+ std::shared_ptr<IVehicleCallback> client1 = IVehicleCallback::fromBinder(binder1);
+ SpAIBinder binder2 = ndk::SharedRefBase::make<PropertyCallback>()->asBinder();
+ std::shared_ptr<IVehicleCallback> 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<VehiclePropValue> 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<VehiclePropValue>(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<PropertyCallback>()->asBinder();
+ std::shared_ptr<IVehicleCallback> client1 = IVehicleCallback::fromBinder(binder1);
+ SpAIBinder binder2 = ndk::SharedRefBase::make<PropertyCallback>()->asBinder();
+ std::shared_ptr<IVehicleCallback> 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<VehiclePropValue> 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<VehiclePropValue>(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<PropertyCallback>()->asBinder();
+ std::shared_ptr<IVehicleCallback> client1 = IVehicleCallback::fromBinder(binder1);
+ SpAIBinder binder2 = ndk::SharedRefBase::make<PropertyCallback>()->asBinder();
+ std::shared_ptr<IVehicleCallback> 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<VehiclePropValue>({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<PropertyCallback>()->asBinder();
+ std::shared_ptr<IVehicleCallback> client1 = IVehicleCallback::fromBinder(binder1);
+ SpAIBinder binder2 = ndk::SharedRefBase::make<PropertyCallback>()->asBinder();
+ std::shared_ptr<IVehicleCallback> client2 = IVehicleCallback::fromBinder(binder2);
+ std::vector<SubscribeOptions> 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";
+}
+
+TEST_F(SubscriptionManagerTest, testSubscribeSupportedValueChange) {
+ SpAIBinder binder1 = ndk::SharedRefBase::make<PropertyCallback>()->asBinder();
+ std::shared_ptr<IVehicleCallback> client1 = IVehicleCallback::fromBinder(binder1);
+ SpAIBinder binder2 = ndk::SharedRefBase::make<PropertyCallback>()->asBinder();
+ std::shared_ptr<IVehicleCallback> client2 = IVehicleCallback::fromBinder(binder2);
+
+ PropIdAreaId propIdAreaId1 = {.propId = 0, .areaId = 0};
+ PropIdAreaId propIdAreaId2 = {.propId = 1, .areaId = 1};
+
+ auto result = getManager()->subscribeSupportedValueChange(client1, {propIdAreaId1});
+
+ ASSERT_TRUE(result.ok()) << "failed to call subscribeSupportedValueChange"
+ << result.error().message();
+
+ result = getManager()->subscribeSupportedValueChange(client2, {propIdAreaId1, propIdAreaId2});
+
+ ASSERT_TRUE(result.ok()) << "failed to call subscribeSupportedValueChange"
+ << result.error().message();
+
+ auto clients = getManager()->getSubscribedClientsForSupportedValueChange(
+ {propIdAreaId1, propIdAreaId2});
+
+ ASSERT_THAT(clients[client1], UnorderedElementsAre(propIdAreaId1))
+ << "Incorrect supported value change events for client1";
+ ASSERT_THAT(clients[client2], UnorderedElementsAre(propIdAreaId1, propIdAreaId2))
+ << "Incorrect supported value change events for client2";
+}
+
+TEST_F(SubscriptionManagerTest, testUnsubscribeSupportedValueChange) {
+ SpAIBinder binder1 = ndk::SharedRefBase::make<PropertyCallback>()->asBinder();
+ std::shared_ptr<IVehicleCallback> client1 = IVehicleCallback::fromBinder(binder1);
+ SpAIBinder binder2 = ndk::SharedRefBase::make<PropertyCallback>()->asBinder();
+ std::shared_ptr<IVehicleCallback> client2 = IVehicleCallback::fromBinder(binder2);
+
+ PropIdAreaId propIdAreaId1 = {.propId = 0, .areaId = 0};
+ PropIdAreaId propIdAreaId2 = {.propId = 1, .areaId = 1};
+
+ auto result = getManager()->subscribeSupportedValueChange(client1, {propIdAreaId1});
+
+ ASSERT_TRUE(result.ok()) << "failed to call subscribeSupportedValueChange"
+ << result.error().message();
+
+ result = getManager()->subscribeSupportedValueChange(client2, {propIdAreaId1, propIdAreaId2});
+
+ ASSERT_TRUE(result.ok()) << "failed to call subscribeSupportedValueChange"
+ << result.error().message();
+
+ result = getManager()->unsubscribeSupportedValueChange(binder2.get(), {propIdAreaId1});
+
+ ASSERT_TRUE(result.ok()) << "failed to call unsubscribeSupportedValueChange"
+ << result.error().message();
+
+ auto clients = getManager()->getSubscribedClientsForSupportedValueChange(
+ {propIdAreaId1, propIdAreaId2});
+
+ ASSERT_THAT(clients[client1], UnorderedElementsAre(propIdAreaId1))
+ << "Incorrect supported value change events for client1";
+ ASSERT_THAT(clients[client2], UnorderedElementsAre(propIdAreaId2))
+ << "Incorrect supported value change events for client2";
+
+ result = getManager()->unsubscribeSupportedValueChange(binder2.get(), {propIdAreaId2});
+
+ ASSERT_TRUE(result.ok()) << "failed to call unsubscribeSupportedValueChange"
+ << result.error().message();
+
+ result = getManager()->unsubscribeSupportedValueChange(binder1.get(), {propIdAreaId1});
+
+ ASSERT_TRUE(result.ok()) << "failed to call unsubscribeSupportedValueChange"
+ << result.error().message();
+
+ EXPECT_EQ(getManager()->countSupportedValueChangeClients(), 0u) << "All clients cleared";
+ EXPECT_TRUE(isEmpty()) << "All clients cleared";
+}
+
+} // 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 0000000..761053f
--- /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 0000000..4695bf7
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/current/vhal/vhal-default-service.xml
@@ -0,0 +1,7 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.automotive.vehicle</name>
+ <version>4</version>
+ <fqname>IVehicle/default</fqname>
+ </hal>
+</manifest>
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 b881109..0000000
--- 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 0363ebd..0000000
--- 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/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
deleted file mode 100644
index a6247a7..0000000
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
+++ /dev/null
@@ -1,2617 +0,0 @@
-/*
- * 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 <FakeObd2Frame.h>
-#include <JsonFakeValueGenerator.h>
-#include <LinearFakeValueGenerator.h>
-#include <PropertyUtils.h>
-#include <VehicleHalTypes.h>
-#include <VehicleUtils.h>
-
-#include <android-base/file.h>
-#include <android-base/parsedouble.h>
-#include <android-base/properties.h>
-#include <android-base/strings.h>
-#include <android/hardware/automotive/vehicle/TestVendorProperty.h>
-#include <utils/Log.h>
-#include <utils/SystemClock.h>
-#include <utils/Trace.h>
-
-#include <dirent.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <regex>
-#include <unordered_set>
-#include <vector>
-
-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/";
-// 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<std::string> 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<int32_t, std::vector<int32_t>> 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<int32_t> 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<int32_t>& 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<VehiclePropValuePool>()),
- 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<int32_t, ConfigDeclaration> FakeVehicleHardware::loadConfigDeclarations() {
- std::unordered_map<int32_t, ConfigDeclaration> 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<VehiclePropValue> values) {
- return onValuesChangeCallback(std::move(values));
- });
-}
-
-std::vector<VehiclePropConfig> FakeVehicleHardware::getAllPropertyConfigs() const {
- std::vector<VehiclePropConfig> 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<void> 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<void> 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<float>(increment));
- return numIncrements;
-}
-
-void FakeVehicleHardware::updateHvacTemperatureValueSuggestionInput(
- const std::vector<int>& hvacTemperatureSetConfigArray,
- std::vector<float>* 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<int>((*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<float>(suggestedTempInCelsius) / 10.0f;
- (*hvacTemperatureValueSuggestionInput)[3] =
- static_cast<float>(suggestedTempInFahrenheit) / 10.0f;
-}
-
-VhalResult<void> 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<void> 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<void> 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<void> FakeVehicleHardware::synchronizeHvacTemp(int32_t hvacDualOnAreaId,
- std::optional<float> 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<float> 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<int32_t> 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<bool> 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<void> 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<uint8_t> 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<void> 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<void> isAdasPropertyAvailableResult;
- VhalResult<bool> 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<const SetValuesCallback> callback,
- const std::vector<SetValueRequest>& 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<void> 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<const GetValuesCallback> callback,
- const std::vector<GetValueRequest>& 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<std::string>& 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<VehiclePropConfig>& 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<std::string>& 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<LinearFakeValueGenerator>(
- 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<JsonFakeValueGenerator> generator;
- if (options[2] == "--path") {
- const std::string& fileName = options[3];
- generator = std::make_unique<JsonFakeValueGenerator>(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<JsonFakeValueGenerator>(/*unused=*/true, content, repetition);
- if (!generator->hasNext()) {
- return "invalid JSON content, no events";
- }
- }
- int32_t cookie = std::hash<std::string>()(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<int> 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<float> 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<std::mutex> 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_1> [PROP_ID_2] [PROP_ID_N]: dumps the value of specific properties. \n"
- "--getWithArg <PROP_ID> [ValueArguments]: gets the value for a specific property. "
- "The value arguments constructs a VehiclePropValue used in the getValue request. \n"
- "--set <PROP_ID> [ValueArguments]: sets the value of property PROP_ID, the value "
- "arguments constructs a VehiclePropValue used in the setValue request. \n"
- "--save-prop <PROP_ID> [-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 <PROP_ID> [-a AREA_ID]: restores a previously saved property value. \n"
- "--inject-event <PROP_ID> [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<int32_t> 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<void> FakeVehicleHardware::checkArgumentsSize(const std::vector<std::string>& 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<int32_t> FakeVehicleHardware::parsePropId(const std::vector<std::string>& options,
- size_t index) {
- const std::string& propIdStr = options[index];
- auto result = stringToPropId(propIdStr);
- if (result.ok()) {
- return result;
- }
- return safelyParseInt<int32_t>(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<int32_t> FakeVehicleHardware::parseAreaId(const std::vector<std::string>& options,
- size_t index, int32_t propId) {
- const std::string& areaIdStr = options[index];
- auto result = safelyParseInt<int32_t>(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<std::string>& 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<std::string> FakeVehicleHardware::getOptionValues(
- const std::vector<std::string>& options, size_t* index) {
- std::vector<std::string> 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<VehiclePropValue> FakeVehicleHardware::parsePropOptions(
- const std::vector<std::string>& 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<std::string> parsedOptions;
- int32_t areaIdIndex = -1;
-
- while (optionIndex < options.size()) {
- std::string argType = options[optionIndex];
- optionIndex++;
-
- size_t currentIndex = optionIndex;
- std::vector<std::string> 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<int32_t>(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<int64_t>(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<int64_t>(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<std::string>& 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<std::string>& 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<std::string>& 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<std::mutex> 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<std::string>& 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<std::mutex> 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<std::string>& 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<const PropertyChangeCallback> callback) {
- if (mOnPropertyChangeCallback != nullptr) {
- ALOGE("registerOnPropertyChangeEvent must only be called once");
- return;
- }
- mOnPropertyChangeCallback = std::move(callback);
-}
-
-void FakeVehicleHardware::registerOnPropertySetErrorEvent(
- std::unique_ptr<const PropertySetErrorCallback> 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<std::mutex> 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<PropIdAreaId, VehiclePropertyStore::EventMode, PropIdAreaIdHash>
- eventModeByPropIdAreaId;
-
- {
- std::scoped_lock<std::mutex> 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<int64_t>(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<RecurrentTimer::Callback>(
- [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<std::mutex> 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<VehiclePropValue> values) {
- ATRACE_CALL();
- std::vector<VehiclePropValue> subscribedUpdatedValues;
-
- {
- std::scoped_lock<std::mutex> 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<int32_t, ConfigDeclaration>* 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<float> 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<std::vector<uint8_t>> FakeVehicleHardware::parseHexString(const std::string& s) {
- std::vector<uint8_t> 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 <class CallbackType, class RequestType>
-FakeVehicleHardware::PendingRequestHandler<CallbackType, RequestType>::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 <class CallbackType, class RequestType>
-void FakeVehicleHardware::PendingRequestHandler<CallbackType, RequestType>::addRequest(
- RequestType request, std::shared_ptr<const CallbackType> callback) {
- mRequests.push({
- request,
- callback,
- });
-}
-
-template <class CallbackType, class RequestType>
-void FakeVehicleHardware::PendingRequestHandler<CallbackType, RequestType>::stop() {
- mRequests.deactivate();
- if (mThread.joinable()) {
- mThread.join();
- }
-}
-
-template <>
-void FakeVehicleHardware::PendingRequestHandler<FakeVehicleHardware::GetValuesCallback,
- GetValueRequest>::handleRequestsOnce() {
- std::unordered_map<std::shared_ptr<const GetValuesCallback>, std::vector<GetValueResult>>
- 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<FakeVehicleHardware::SetValuesCallback,
- SetValueRequest>::handleRequestsOnce() {
- std::unordered_map<std::shared_ptr<const SetValuesCallback>, std::vector<SetValueResult>>
- 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/grpc/Android.bp b/automotive/vehicle/aidl/impl/grpc/Android.bp
deleted file mode 100644
index 7a8da59..0000000
--- a/automotive/vehicle/aidl/impl/grpc/Android.bp
+++ /dev/null
@@ -1,132 +0,0 @@
-// 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",
- tools: [
- "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)",
- srcs: [
- "proto/VehicleServer.proto",
- ":libprotobuf-internal-protos",
- ":VehicleHalProtoFiles",
- ],
- out: [
- "VehicleServer.pb.h",
- "VehicleServer.grpc.pb.h",
- "VehicleServer_mock.grpc.pb.h",
- ],
- visibility: ["//visibility:private"],
-}
-
-genrule {
- name: "VehicleServerProtoStub_cc@default-grpc",
- tools: [
- "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)",
- srcs: [
- "proto/VehicleServer.proto",
- ":libprotobuf-internal-protos",
- ":VehicleHalProtoFiles",
- ],
- out: [
- "VehicleServer.pb.cc",
- "VehicleServer.grpc.pb.cc",
- ],
- visibility: ["//visibility:private"],
-}
-
-cc_library_static {
- name: "android.hardware.automotive.vehicle@default-grpc-libgrpc",
- vendor: true,
- host_supported: true,
- include_dirs: [
- "external/protobuf/src",
- ],
- generated_headers: [
- "VehicleServerProtoStub_h@default-grpc",
- ],
- export_generated_headers: [
- "VehicleServerProtoStub_h@default-grpc",
- ],
- generated_sources: [
- "VehicleServerProtoStub_cc@default-grpc",
- ],
- whole_static_libs: [
- "VehicleHalProtos",
- ],
- shared_libs: [
- "libgrpc++",
- ],
- cflags: [
- "-Wno-unused-parameter",
- ],
-}
-
-cc_library_static {
- name: "android.hardware.automotive.vehicle@default-grpc-hardware-lib",
- defaults: ["VehicleHalDefaults"],
- vendor: true,
- srcs: [
- "GRPCVehicleHardware.cpp",
- ],
- whole_static_libs: [
- "android.hardware.automotive.vehicle@default-grpc-libgrpc",
- "VehicleHalProtoMessageConverter",
- ],
- header_libs: [
- "IVehicleHardware",
- ],
- 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",
- defaults: ["VehicleHalDefaults"],
- vendor: true,
- srcs: [
- "GRPCVehicleProxyServer.cpp",
- ],
- whole_static_libs: [
- "android.hardware.automotive.vehicle@default-grpc-libgrpc",
- "VehicleHalProtoMessageConverter",
- ],
- header_libs: [
- "IVehicleHardware",
- ],
- 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.h b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h
deleted file mode 100644
index 15f473c..0000000
--- a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * 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 <VehicleHalTypes.h>
-#include <VehicleUtils.h>
-#include <android-base/result.h>
-#include <android-base/thread_annotations.h>
-
-#include "VehicleServer.grpc.pb.h"
-#include "VehicleServer.pb.h"
-
-#include <grpc++/grpc++.h>
-
-#include <atomic>
-#include <chrono>
-#include <condition_variable>
-#include <memory>
-#include <shared_mutex>
-#include <string>
-#include <thread>
-#include <unordered_map>
-#include <vector>
-
-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<aidlvhal::VehiclePropConfig> getAllPropertyConfigs() const override;
-
- // Get the config for the specified propId.
- std::optional<aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
- 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<const SetValuesCallback> callback,
- const std::vector<aidlvhal::SetValueRequest>& 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<const GetValuesCallback> callback,
- const std::vector<aidlvhal::GetValueRequest>& requests) const override;
-
- // Dump debug information in the server.
- DumpResult dump(const std::vector<std::string>& 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<const PropertyChangeCallback> callback) override;
-
- // Register a callback that would be called when there is a property set error event from
- // vehicle.
- void registerOnPropertySetErrorEvent(
- std::unique_ptr<const PropertySetErrorCallback> 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<const PropertyChangeCallback> mOnPropChange;
-
- private:
- friend class GRPCVehicleHardwareUnitTest;
-
- std::string mServiceAddr;
- std::shared_ptr<::grpc::Channel> mGrpcChannel;
- std::unique_ptr<proto::VehicleServer::StubInterface> mGrpcStub;
- std::thread mValuePollingThread;
-
- std::unique_ptr<const PropertySetErrorCallback> mOnSetErr;
-
- std::mutex mShutdownMutex;
- std::condition_variable mShutdownCV;
- std::atomic<bool> 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<PropIdAreaId, std::pair<int64_t, int64_t>,
- PropIdAreaIdHash> mLatestUpdateTimestamps
- GUARDED_BY(mLatestUpdateTimestampsMutex);
-
- // Only used for unit testing.
- GRPCVehicleHardware(std::unique_ptr<proto::VehicleServer::StubInterface> stub,
- bool startValuePollingLoop);
-
- void ValuePollingLoop();
- void pollValue();
-
- aidlvhal::StatusCode getValuesWithRetry(const std::vector<aidlvhal::GetValueRequest>& requests,
- std::vector<aidlvhal::GetValueResult>* 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/grpc/GRPCVehicleProxyServer.cpp b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.cpp
deleted file mode 100644
index 7697c03..0000000
--- a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.cpp
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * 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 <grpc++/grpc++.h>
-
-#include <android-base/logging.h>
-
-#include <algorithm>
-#include <condition_variable>
-#include <mutex>
-#include <unordered_set>
-#include <utility>
-#include <vector>
-
-namespace android::hardware::automotive::vehicle::virtualization {
-
-std::atomic<uint64_t> 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<IVehicleHardware>&& hardware)
- : GrpcVehicleProxyServer(std::vector<std::string>({serverAddr}), std::move(hardware)){};
-
-GrpcVehicleProxyServer::GrpcVehicleProxyServer(std::vector<std::string> serverAddrs,
- std::unique_ptr<IVehicleHardware>&& hardware)
- : mServiceAddrs(std::move(serverAddrs)), mHardware(std::move(hardware)) {
- mHardware->registerOnPropertyChangeEvent(
- std::make_unique<const IVehicleHardware::PropertyChangeCallback>(
- [this](std::vector<aidlvhal::VehiclePropValue> values) {
- OnVehiclePropChange(values);
- }));
-}
-
-::grpc::Status GrpcVehicleProxyServer::GetAllPropertyConfig(
- ::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
- ::grpc::ServerWriter<proto::VehiclePropConfig>* 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<aidlvhal::SetValueRequest> aidlRequests;
- std::unordered_set<int64_t> 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<std::mutex>();
- auto waitCV = std::make_shared<std::condition_variable>();
- auto complete = std::make_shared<bool>(false);
- auto tmpResults = std::make_shared<proto::SetValueResults>();
- auto aidlStatus = mHardware->setValues(
- std::make_shared<const IVehicleHardware::SetValuesCallback>(
- [waitMtx, waitCV, complete, tmpResults,
- &requestIds](std::vector<aidlvhal::SetValueResult> 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<proto::StatusCode>(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<aidlvhal::GetValueRequest> aidlRequests;
- std::unordered_set<int64_t> 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<std::mutex>();
- auto waitCV = std::make_shared<std::condition_variable>();
- auto complete = std::make_shared<bool>(false);
- auto tmpResults = std::make_shared<proto::GetValueResults>();
- auto aidlStatus = mHardware->getValues(
- std::make_shared<const IVehicleHardware::GetValuesCallback>(
- [waitMtx, waitCV, complete, tmpResults,
- &requestIds](std::vector<aidlvhal::GetValueResult> 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<proto::StatusCode>(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<proto::StatusCode>(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<proto::StatusCode>(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<proto::StatusCode>(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<proto::StatusCode>(mHardware->checkHealth()));
- return ::grpc::Status::OK;
-}
-
-::grpc::Status GrpcVehicleProxyServer::Dump(::grpc::ServerContext* context,
- const proto::DumpOptions* options,
- proto::DumpResult* result) {
- std::vector<std::string> 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<proto::VehiclePropValues>* stream) {
- auto conn = std::make_shared<ConnectionDescriptor>(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<aidlvhal::VehiclePropValue>& values) {
- std::unordered_set<uint64_t> 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/proto/Android.bp b/automotive/vehicle/aidl/impl/proto/Android.bp
deleted file mode 100644
index 0d3df49..0000000
--- a/automotive/vehicle/aidl/impl/proto/Android.bp
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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",
- srcs: ["**/*.proto"],
- visibility: ["//hardware/interfaces/automotive/vehicle:__subpackages__"],
-}
-
-genrule {
- name: "VehicleProtoStub_h",
- tools: [
- "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)",
- srcs: [
- ":VehicleHalProtoFiles",
- ],
- 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",
- tools: [
- "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)",
- srcs: [
- ":VehicleHalProtoFiles",
- ],
- 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",
- vendor: true,
- host_supported: true,
- include_dirs: [
- "external/protobuf/src",
- ],
- generated_headers: [
- "VehicleProtoStub_h",
- ],
- export_generated_headers: [
- "VehicleProtoStub_h",
- ],
- generated_sources: [
- "VehicleProtoStub_cc",
- ],
- shared_libs: [
- "libgrpc++_unsecure",
- ],
- cflags: [
- "-Wno-unused-parameter",
- ],
-}
-
-rust_protobuf {
- name: "libvehicle_hal_property_protos",
- crate_name: "vehicle_hal_property_protos",
- protos: [":VehicleHalProtoFiles"],
- 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/utils/common/include/VehicleObjectPool.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleObjectPool.h
deleted file mode 100644
index 501ce40..0000000
--- a/automotive/vehicle/aidl/impl/utils/common/include/VehicleObjectPool.h
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * 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 <deque>
-#include <map>
-#include <memory>
-#include <mutex>
-
-#include <VehicleHalTypes.h>
-
-#include <android-base/thread_annotations.h>
-
-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<uint32_t> Obtained{0};
- std::atomic<uint32_t> Created{0};
- std::atomic<uint32_t> Recycled{0};
- std::atomic<uint32_t> Deleted{0};
-
- static PoolStats* instance() {
- static PoolStats inst;
- return &inst;
- }
-};
-
-template <typename T>
-struct Deleter {
- using OnDeleteFunc = std::function<void(T*)>;
-
- 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 <typename T>
-using recyclable_ptr = typename std::unique_ptr<T, Deleter<T>>;
-
-// 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 <typename T>
-class ObjectPool {
- public:
- using GetSizeFunc = std::function<size_t(const T&)>;
-
- ObjectPool(size_t maxPoolObjectsSize, GetSizeFunc getSizeFunc)
- : mMaxPoolObjectsSize(maxPoolObjectsSize), mGetSizeFunc(getSizeFunc){};
- virtual ~ObjectPool() = default;
-
- virtual recyclable_ptr<T> obtain() {
- std::scoped_lock<std::mutex> 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<std::mutex> 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<T>{o});
- mPoolObjectsSize += objectSize;
- }
-
- const size_t mMaxPoolObjectsSize;
-
- private:
- const Deleter<T>& getDeleter() {
- if (!mDeleter.get()) {
- Deleter<T>* d =
- new Deleter<T>(std::bind(&ObjectPool::recycle, this, std::placeholders::_1));
- mDeleter.reset(d);
- }
- return *mDeleter.get();
- }
-
- recyclable_ptr<T> wrap(T* raw) { return recyclable_ptr<T>{raw, getDeleter()}; }
-
- mutable std::mutex mLock;
- std::deque<std::unique_ptr<T>> mObjects GUARDED_BY(mLock);
- std::unique_ptr<Deleter<T>> 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<aidl::android::hardware::automotive::vehicle::VehiclePropValue>;
-
- // 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<aidl::android::hardware::automotive::vehicle::VehiclePropValue> {
- 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 <typename VecType>
- bool check(std::vector<VecType>* vec, bool isVectorType) {
- return vec->size() == (isVectorType ? mVectorSize : 0);
- }
-
- private:
- aidl::android::hardware::automotive::vehicle::VehiclePropertyType mPropType;
- size_t mVectorSize;
- };
- const Deleter<aidl::android::hardware::automotive::vehicle::VehiclePropValue>
- 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<int32_t, std::unique_ptr<InternalPool>> 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/vhal/Android.bp b/automotive/vehicle/aidl/impl/vhal/Android.bp
deleted file mode 100644
index 54d148e..0000000
--- a/automotive/vehicle/aidl/impl/vhal/Android.bp
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * 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",
- "VehicleHalDefaults",
- "android-automotive-large-parcelable-defaults",
- ],
- vintf_fragments: ["vhal-default-service.xml"],
- init_rc: ["vhal-default-service.rc"],
- relative_install_path: "hw",
- srcs: ["src/VehicleService.cpp"],
- static_libs: [
- "DefaultVehicleHal",
- "FakeVehicleHardware",
- "VehicleHalUtils",
- ],
- header_libs: [
- "IVehicleHardware",
- ],
- shared_libs: [
- "libbinder_ndk",
- ],
-}
-
-cc_library {
- name: "DefaultVehicleHal",
- vendor: true,
- defaults: [
- "VehicleHalDefaults",
- ],
- 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",
- ],
- header_libs: [
- "IVehicleHardware",
- "IVehicleGeneratedHeaders-V4",
- ],
- shared_libs: [
- "libbinder_ndk",
- ],
-}
-
-cc_fuzz {
- name: "android.hardware.automotive.vehicle-default-service_fuzzer",
- vendor: true,
- defaults: [
- "FakeVehicleHardwareDefaults",
- "VehicleHalDefaults",
- "android-automotive-large-parcelable-defaults",
- "service_fuzzer_defaults",
- ],
- static_libs: [
- "DefaultVehicleHal",
- "FakeVehicleHardware",
- "VehicleHalUtils",
- ],
- srcs: ["src/fuzzer.cpp"],
- fuzz_config: {
- cc: [
- "keithmok@google.com",
- ],
- },
-}
diff --git a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
deleted file mode 100644
index 0ead819..0000000
--- a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
+++ /dev/null
@@ -1,1090 +0,0 @@
-/*
- * 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 <DefaultVehicleHal.h>
-
-#include <LargeParcelableBase.h>
-#include <VehicleHalTypes.h>
-#include <VehicleUtils.h>
-#include <VersionForVehicleProperty.h>
-
-#include <android-base/logging.h>
-#include <android-base/result.h>
-#include <android-base/stringprintf.h>
-#include <android/binder_ibinder.h>
-#include <private/android_filesystem_config.h>
-#include <utils/Log.h>
-#include <utils/SystemClock.h>
-#include <utils/Trace.h>
-
-#include <inttypes.h>
-#include <chrono>
-#include <set>
-#include <unordered_set>
-
-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::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::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<int64_t>& 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<IVehicleHardware> vehicleHardware)
- : DefaultVehicleHal(std::move(vehicleHardware), /* testInterfaceVersion= */ 0){};
-
-DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware,
- int32_t testInterfaceVersion)
- : mVehicleHardware(std::move(vehicleHardware)),
- mPendingRequestPool(std::make_shared<PendingRequestPool>(TIMEOUT_IN_NANO)),
- mTestInterfaceVersion(testInterfaceVersion) {
- ALOGD("DefaultVehicleHal init");
- IVehicleHardware* vehicleHardwarePtr = mVehicleHardware.get();
- mSubscriptionManager = std::make_shared<SubscriptionManager>(vehicleHardwarePtr);
- mEventBatchingWindow = mVehicleHardware->getPropertyOnChangeEventBatchingWindow();
- if (mEventBatchingWindow != std::chrono::nanoseconds(0)) {
- mBatchedEventQueue = std::make_shared<ConcurrentQueue<VehiclePropValue>>();
- mPropertyChangeEventsBatchingConsumer =
- std::make_shared<BatchingConsumer<VehiclePropValue>>();
- mPropertyChangeEventsBatchingConsumer->run(
- mBatchedEventQueue.get(), mEventBatchingWindow,
- [this](std::vector<VehiclePropValue> batchedEvents) {
- handleBatchedPropertyEvents(std::move(batchedEvents));
- });
- }
-
- std::weak_ptr<ConcurrentQueue<VehiclePropValue>> batchedEventQueueCopy = mBatchedEventQueue;
- std::chrono::nanoseconds eventBatchingWindow = mEventBatchingWindow;
- std::weak_ptr<SubscriptionManager> subscriptionManagerCopy = mSubscriptionManager;
- mVehicleHardware->registerOnPropertyChangeEvent(
- std::make_unique<IVehicleHardware::PropertyChangeCallback>(
- [subscriptionManagerCopy, batchedEventQueueCopy,
- eventBatchingWindow](std::vector<VehiclePropValue> updatedValues) {
- if (eventBatchingWindow != std::chrono::nanoseconds(0)) {
- batchPropertyChangeEvent(batchedEventQueueCopy,
- std::move(updatedValues));
- } else {
- onPropertyChangeEvent(subscriptionManagerCopy,
- std::move(updatedValues));
- }
- }));
- mVehicleHardware->registerOnPropertySetErrorEvent(
- std::make_unique<IVehicleHardware::PropertySetErrorCallback>(
- [subscriptionManagerCopy](std::vector<SetValueErrorEvent> errorEvents) {
- onPropertySetErrorEvent(subscriptionManagerCopy, errorEvents);
- }));
-
- // Register heartbeat event.
- mRecurrentAction = std::make_shared<std::function<void()>>(
- [vehicleHardwarePtr, subscriptionManagerCopy]() {
- checkHealth(vehicleHardwarePtr, subscriptionManagerCopy);
- });
- mRecurrentTimer.registerTimerCallback(HEART_BEAT_INTERVAL_IN_NANO, mRecurrentAction);
-
- mBinderLifecycleHandler = std::make_unique<BinderLifecycleHandler>();
- 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<ConcurrentQueue<VehiclePropValue>>& batchedEventQueue,
- std::vector<VehiclePropValue>&& 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<VehiclePropValue>&& batchedEvents) {
- onPropertyChangeEvent(mSubscriptionManager, std::move(batchedEvents));
-}
-
-void DefaultVehicleHal::onPropertyChangeEvent(
- const std::weak_ptr<SubscriptionManager>& subscriptionManager,
- std::vector<VehiclePropValue>&& 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>& subscriptionManager,
- const std::vector<SetValueErrorEvent>& 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 <class T>
-std::shared_ptr<T> DefaultVehicleHal::getOrCreateClient(
- std::unordered_map<const AIBinder*, std::shared_ptr<T>>* clients,
- const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool) {
- const AIBinder* clientId = callback->asBinder().get();
- if (clients->find(clientId) == clients->end()) {
- (*clients)[clientId] = std::make_shared<T>(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<OnBinderDiedContext> context = std::make_unique<OnBinderDiedContext>(
- 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<AIBinder*>(clientId), mDeathRecipient.get(), static_cast<void*>(contextPtr));
- if (status == STATUS_OK) {
- return true;
- }
- ALOGE("failed to call linkToDeath on client binder, client may already died, status: %d",
- static_cast<int>(status));
- return false;
-}
-
-void DefaultVehicleHal::onBinderDied(void* cookie) {
- OnBinderDiedContext* context = reinterpret_cast<OnBinderDiedContext*>(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<std::mutex> 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<OnBinderDiedContext*>(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<std::mutex> 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::GetValuesClient>
-DefaultVehicleHal::getOrCreateClient<DefaultVehicleHal::GetValuesClient>(
- std::unordered_map<const AIBinder*, std::shared_ptr<GetValuesClient>>* clients,
- const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool);
-template std::shared_ptr<DefaultVehicleHal::SetValuesClient>
-DefaultVehicleHal::getOrCreateClient<DefaultVehicleHal::SetValuesClient>(
- std::unordered_map<const AIBinder*, std::shared_ptr<SetValuesClient>>* clients,
- const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool);
-
-void DefaultVehicleHal::setTimeout(int64_t timeoutInNano) {
- mPendingRequestPool = std::make_unique<PendingRequestPool>(timeoutInNano);
-}
-
-int32_t DefaultVehicleHal::getVhalInterfaceVersion() const {
- if (mTestInterfaceVersion != 0) {
- return mTestInterfaceVersion;
- }
- int32_t myVersion = 0;
- // getInterfaceVersion is in-reality a const method.
- const_cast<DefaultVehicleHal*>(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<VehicleProperty>(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<VehiclePropConfig> filteredConfigs;
- for (const auto& config : configs) {
- if (isConfigSupportedForCurrentVhalVersion(config)) {
- filteredConfigs.push_back(std::move(config));
- }
- }
-
- {
- std::unique_lock<std::shared_timed_mutex> 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<int>(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<void(const std::unordered_map<int32_t, VehiclePropConfig>&)> callback) const {
- if (!mConfigInit) {
- CHECK(getAllPropConfigsFromHardwareLocked())
- << "Failed to get property configs from hardware";
- }
-
- std::shared_lock<std::shared_timed_mutex> 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<std::shared_timed_mutex> 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<VehiclePropConfig> DefaultVehicleHal::getConfig(int32_t propId) const {
- Result<VehiclePropConfig> result;
-
- if (!mConfigInit) {
- std::optional<VehiclePropConfig> 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<void> 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<LargeParcelableBase::BorrowedOwnedObject<GetValueRequests>, ScopedAStatus>
- deserializedResults = fromStableLargeParcelable(requests);
- if (!deserializedResults.ok()) {
- ALOGE("getValues: failed to parse getValues requests");
- return std::move(deserializedResults.error());
- }
- const std::vector<GetValueRequest>& 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<GetValueResult> failedResults;
- // The list of requests that we would send to hardware.
- std::vector<GetValueRequest> 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<int64_t> hardwareRequestIds;
- for (const auto& request : hardwareRequests) {
- hardwareRequestIds.insert(request.requestId);
- }
-
- std::shared_ptr<GetValuesClient> 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<LargeParcelableBase::BorrowedOwnedObject<SetValueRequests>, ScopedAStatus>
- deserializedResults = fromStableLargeParcelable(requests);
- if (!deserializedResults.ok()) {
- ALOGE("setValues: failed to parse setValues requests");
- return std::move(deserializedResults.error());
- }
- const std::vector<SetValueRequest>& setValueRequests =
- deserializedResults.value().getObject()->payloads;
-
- // A list of failed result we already know before sending to hardware.
- std::vector<SetValueResult> failedResults;
- // The list of requests that we would send to hardware.
- std::vector<SetValueRequest> 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<int64_t> hardwareRequestIds;
- for (const auto& request : hardwareRequests) {
- hardwareRequestIds.insert(request.requestId);
- }
-
- std::shared_ptr<SetValuesClient> 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<int64_t> 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<std::vector<int64_t>> DefaultVehicleHal::checkDuplicateRequests(
- const std::vector<GetValueRequest>& requests) {
- CHECK_DUPLICATE_REQUESTS(prop);
-}
-
-::android::base::Result<std::vector<int64_t>> DefaultVehicleHal::checkDuplicateRequests(
- const std::vector<SetValueRequest>& requests) {
- CHECK_DUPLICATE_REQUESTS(value);
-}
-
-#undef CHECK_DUPLICATE_REQUESTS
-
-ScopedAStatus DefaultVehicleHal::getPropConfigs(const std::vector<int32_t>& props,
- VehiclePropConfigs* output) {
- std::vector<VehiclePropConfig> 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<VehicleAreaConfig>& areaConfigs,
- VehiclePropertyAccess requiredAccess) {
- if (areaConfigs.empty()) {
- return false;
- }
- for (VehicleAreaConfig areaConfig : areaConfigs) {
- if (!hasRequiredAccess(areaConfig.access, requiredAccess)) {
- return false;
- }
- }
- return true;
-}
-
-VhalResult<void> DefaultVehicleHal::checkSubscribeOptions(
- const std::vector<SubscribeOptions>& options,
- const std::unordered_map<int32_t, VehiclePropConfig>& 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<VehicleAreaConfig> areaConfigs;
- if (option.areaIds.empty()) {
- areaConfigs = config.areaConfigs;
- } else {
- std::unordered_map<int, VehicleAreaConfig> 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<SubscribeOptions>& options,
- const std::unordered_map<int32_t, VehiclePropConfig>& configsByPropId,
- std::vector<SubscribeOptions>& onChangeSubscriptions,
- std::vector<SubscribeOptions>& 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<int32_t> areasVurEnabled;
- std::vector<int32_t> 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<SubscribeOptions>& 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<SubscribeOptions> onChangeSubscriptions;
- std::vector<SubscribeOptions> 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<int32_t>& 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();
-}
-
-IVehicleHardware* DefaultVehicleHal::getHardware() {
- return mVehicleHardware.get();
-}
-
-VhalResult<void> DefaultVehicleHal::checkPermissionHelper(
- const VehiclePropValue& value, VehiclePropertyAccess accessToTest) const {
- static const std::unordered_set<VehiclePropertyAccess> 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<int32_t>(accessToTest));
- }
- return {};
-}
-
-VhalResult<void> DefaultVehicleHal::checkWritePermission(const VehiclePropValue& value) const {
- return checkPermissionHelper(value, VehiclePropertyAccess::WRITE);
-}
-
-VhalResult<void> DefaultVehicleHal::checkReadPermission(const VehiclePropValue& value) const {
- return checkPermissionHelper(value, VehiclePropertyAccess::READ);
-}
-
-void DefaultVehicleHal::checkHealth(IVehicleHardware* vehicleHardware,
- std::weak_ptr<SubscriptionManager> subscriptionManager) {
- StatusCode status = vehicleHardware->checkHealth();
- if (status != StatusCode::OK) {
- ALOGE("VHAL check health returns non-okay status");
- return;
- }
- std::vector<VehiclePropValue> 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<BinderLifecycleInterface> 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<std::string> 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<int32_t, VehiclePropConfig> configsByPropIdCopy;
- getConfigsByPropId([this, &configsByPropIdCopy](const auto& configsByPropId) {
- SharedScopedLockAssertion lockAssertion(mConfigLock);
-
- configsByPropIdCopy = configsByPropId;
- });
- {
- std::scoped_lock<std::mutex> 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/vhal/src/fuzzer.cpp b/automotive/vehicle/aidl/impl/vhal/src/fuzzer.cpp
deleted file mode 100644
index 6d994bb..0000000
--- a/automotive/vehicle/aidl/impl/vhal/src/fuzzer.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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 <DefaultVehicleHal.h>
-#include <FakeVehicleHardware.h>
-#include <fuzzbinder/libbinder_ndk_driver.h>
-#include <fuzzer/FuzzedDataProvider.h>
-
-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) {
- // TODO(b/183141167): need to rewrite 'dump' to avoid SIGPIPE.
- signal(SIGPIPE, SIG_IGN);
- std::unique_ptr<FakeVehicleHardware> hardware = std::make_unique<FakeVehicleHardware>();
- std::shared_ptr<DefaultVehicleHal> vhal =
- ::ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
-
- fuzzService(vhal->asBinder().get(), FuzzedDataProvider(data, size));
-
- return 0;
-}
diff --git a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
deleted file mode 100644
index 4891bf5..0000000
--- a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
+++ /dev/null
@@ -1,2121 +0,0 @@
-/*
- * 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 <IVehicleHardware.h>
-#include <LargeParcelableBase.h>
-#include <aidl/android/hardware/automotive/vehicle/IVehicle.h>
-#include <aidl/android/hardware/automotive/vehicle/IVehicleCallback.h>
-
-#include <android-base/thread_annotations.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-#include <sys/mman.h>
-#include <utils/Log.h>
-#include <utils/SystemClock.h>
-
-#include <chrono>
-#include <list>
-#include <memory>
-#include <mutex>
-#include <optional>
-#include <thread>
-#include <unordered_map>
-#include <vector>
-
-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<int32_t>(i) + 0x20000000 + 0x01000000 + 0x00410000;
-}
-
-std::string toString(const std::vector<SubscribeOptions>& 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<SetValuesInvalidRequestTestCase> 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<SubscribeInvalidOptionsTestCase> 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<MockVehicleHardware>()); }
-
- void init(std::unique_ptr<MockVehicleHardware> hardware) {
- std::vector<VehiclePropConfig> 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<DefaultVehicleHal>(std::move(hardware));
- mVhalClient = IVehicle::fromBinder(mVhal->asBinder());
- mCallback = ndk::SharedRefBase::make<MockVehicleCallback>();
- // 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<TestBinderLifecycleHandler>();
- mBinderLifecycleHandler = handler.get();
- mVhal->setBinderLifecycleHandler(std::move(handler));
- }
-
- void TearDown() override {
- ASSERT_EQ(countPendingRequests(), static_cast<size_t>(0))
- << "must have no pending requests when test finishes";
- }
-
- MockVehicleHardware* getHardware() { return mHardwarePtr; }
-
- std::shared_ptr<IVehicle> getClient() { return mVhal; }
-
- std::shared_ptr<IVehicleCallback> 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<std::mutex> lockGuard(mVhal->mLock);
- return mVhal->mGetValuesClients.size() + mVhal->mSetValuesClients.size() +
- mVhal->countSubscribeClients();
- }
-
- std::shared_ptr<PendingRequestPool> 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<std::mutex> lockGuard(mVhal->mLock);
- return mVhal->mOnBinderDiedContexts[clientId].get();
- }
-
- size_t countOnBinderDiedContexts() {
- std::scoped_lock<std::mutex> lockGuard(mVhal->mLock);
- return mVhal->mOnBinderDiedContexts.size();
- }
-
- bool hasNoSubscriptions() { return mVhal->mSubscriptionManager->isEmpty(); }
-
- void setBinderAlive(bool isAlive) { mBinderLifecycleHandler->setAlive(isAlive); };
-
- static Result<void> getValuesTestCases(size_t size, GetValueRequests& requests,
- std::vector<GetValueResult>& expectedResults,
- std::vector<GetValueRequest>& expectedHardwareRequests) {
- expectedHardwareRequests.clear();
- for (size_t i = 0; i < size; i++) {
- int64_t requestId = static_cast<int64_t>(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<void> setValuesTestCases(size_t size, SetValueRequests& requests,
- std::vector<SetValueResult>& expectedResults,
- std::vector<SetValueRequest>& expectedHardwareRequests) {
- expectedHardwareRequests.clear();
- for (size_t i = 0; i < size; i++) {
- int64_t requestId = static_cast<int64_t>(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<DefaultVehicleHal> mVhal;
- std::shared_ptr<IVehicle> mVhalClient;
- MockVehicleHardware* mHardwarePtr;
- std::shared_ptr<MockVehicleCallback> mCallback;
- std::shared_ptr<IVehicleCallback> mCallbackClient;
- SpAIBinder mBinder;
- TestBinderLifecycleHandler* mBinderLifecycleHandler;
-};
-
-TEST_F(DefaultVehicleHalTest, testGetAllPropConfigsSmall) {
- auto testConfigs = std::vector<VehiclePropConfig>({
- VehiclePropConfig{
- .prop = testInt32VecProp(1),
- },
- VehiclePropConfig{
- .prop = testInt32VecProp(2),
- },
- });
-
- auto hardware = std::make_unique<MockVehicleHardware>();
- hardware->setPropertyConfigs(testConfigs);
- auto vhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
- std::shared_ptr<IVehicle> 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<VehiclePropConfig> 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<MockVehicleHardware>();
- hardware->setPropertyConfigs(testConfigs);
- auto vhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
- std::shared_ptr<IVehicle> 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<VehiclePropConfig>({
- // 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<MockVehicleHardware>();
- hardware->setPropertyConfigs(testConfigs);
- auto vhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware),
- /* testInterfaceVersion= */ 2);
- std::shared_ptr<IVehicle> 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>({
- VehiclePropConfig{
- .prop = propId1,
- },
- VehiclePropConfig{
- .prop = propId2,
- },
- });
-
- auto hardware = std::make_unique<MockVehicleHardware>();
- hardware->setPropertyConfigs(testConfigs);
- // Store the pointer for testing. We are sure it is valid.
- MockVehicleHardware* hardwarePtr = hardware.get();
- auto vhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
- std::shared_ptr<IVehicle> client = IVehicle::fromBinder(vhal->asBinder());
-
- VehiclePropConfigs output;
- auto status = client->getPropConfigs(std::vector<int32_t>({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>({
- VehiclePropConfig{
- .prop = testInt32VecProp(1),
- },
- VehiclePropConfig{
- .prop = testInt32VecProp(2),
- },
- });
-
- auto hardware = std::make_unique<MockVehicleHardware>();
- hardware->setPropertyConfigs(testConfigs);
- auto vhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
- std::shared_ptr<IVehicle> client = IVehicle::fromBinder(vhal->asBinder());
-
- VehiclePropConfigs output;
- auto status = client->getPropConfigs(
- std::vector<int32_t>({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<GetValueResult> expectedResults;
- std::vector<GetValueRequest> 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<size_t>(1));
- ASSERT_FALSE(getHardware()->getAllPropertyConfigsCalled());
-}
-
-TEST_F(DefaultVehicleHalTest, testGetValuesSmall_AfterGetAllPropConfigs) {
- GetValueRequests requests;
- std::vector<GetValueResult> expectedResults;
- std::vector<GetValueRequest> 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<size_t>(1));
- ASSERT_TRUE(getHardware()->getAllPropertyConfigsCalled());
-}
-
-TEST_F(DefaultVehicleHalTest, testGetValuesLarge) {
- GetValueRequests requests;
- std::vector<GetValueResult> expectedResults;
- std::vector<GetValueRequest> 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<size_t>(1));
-}
-
-TEST_F(DefaultVehicleHalTest, testGetValuesErrorFromHardware) {
- GetValueRequests requests;
- std::vector<GetValueResult> expectedResults;
- std::vector<GetValueRequest> 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<GetValueResult>({
- {
- .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<GetValueResult> expectedResults;
- std::vector<GetValueRequest> 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<GetValueResult> expectedResults;
- std::vector<GetValueRequest> 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<GetValueResult> expectedResults;
- std::vector<GetValueRequest> 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<GetValueResult> expectedResults;
- std::vector<GetValueRequest> 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<size_t>(0))
- << "No client should be created if the client binder died";
-}
-
-TEST_F(DefaultVehicleHalTest, testGetValuesExistingClientDied) {
- GetValueRequests requests;
- std::vector<GetValueResult> expectedResults;
- std::vector<GetValueRequest> 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<size_t>(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<size_t>(1));
-}
-
-TEST_F(DefaultVehicleHalTest, testSetValuesSmall) {
- SetValueRequests requests;
- std::vector<SetValueResult> expectedResults;
- std::vector<SetValueRequest> 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<size_t>(1));
- ASSERT_FALSE(getHardware()->getAllPropertyConfigsCalled());
-}
-
-TEST_F(DefaultVehicleHalTest, testSetValuesSmall_AfterGetAllPropConfigs) {
- SetValueRequests requests;
- std::vector<SetValueResult> expectedResults;
- std::vector<SetValueRequest> 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<size_t>(1));
- ASSERT_TRUE(getHardware()->getAllPropertyConfigsCalled());
-}
-
-TEST_F(DefaultVehicleHalTest, testSetValuesLarge) {
- SetValueRequests requests;
- std::vector<SetValueResult> expectedResults;
- std::vector<SetValueRequest> 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<size_t>(1));
-}
-
-class SetValuesInvalidRequestTest
- : public DefaultVehicleHalTest,
- public testing::WithParamInterface<SetValuesInvalidRequestTestCase> {};
-
-INSTANTIATE_TEST_SUITE_P(
- SetValuesInvalidRequestTests, SetValuesInvalidRequestTest,
- testing::ValuesIn(getSetValuesInvalidRequestTestCases()),
- [](const testing::TestParamInfo<SetValuesInvalidRequestTest::ParamType>& info) {
- return info.param.name;
- });
-
-TEST_P(SetValuesInvalidRequestTest, testSetValuesInvalidRequest) {
- SetValuesInvalidRequestTestCase tc = GetParam();
- std::vector<SetValueResult> 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<SetValueRequest>({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<SetValueResult>({
- {
- .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<SetValueResult> expectedResults;
- std::vector<SetValueRequest> 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<SetValueResult> expectedResults;
- std::vector<SetValueRequest> 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<SetValueResult> expectedResults;
- std::vector<SetValueRequest> 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<SubscribeOptions> 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<int32_t>({GLOBAL_ON_CHANGE_PROP}));
-
- ASSERT_TRUE(status.isOk()) << "unsubscribe failed: " << status.getMessage();
-}
-
-TEST_F(DefaultVehicleHalTest, testSubscribeGlobalOnChangeNormal) {
- std::vector<SubscribeOptions> 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<SetValueResult> 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<size_t>(2))
- << "expect 2 clients, 1 subscribe client and 1 setvalue client";
-}
-
-TEST_F(DefaultVehicleHalTest, testSubscribeGlobalOnchangeUnrelatedEventIgnored) {
- std::vector<SubscribeOptions> 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<SubscribeOptions> 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<SubscribeOptions> 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<SubscribeOptions> 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<size_t>(1));
-}
-
-TEST_F(DefaultVehicleHalTest, testSubscribeGlobalContinuousRateOutOfRange) {
- // The maxSampleRate is 100, so the sample rate should be the default max 100.
- std::vector<SubscribeOptions> 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<size_t>(1));
-}
-
-TEST_F(DefaultVehicleHalTest, testSubscribeContinuous_propNotSupportVur) {
- std::vector<SubscribeOptions> 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<SubscribeOptions> 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<SubscribeOptions> 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<int32_t>({AREA_CONTINUOUS_PROP}));
-
- std::vector<VehiclePropValue> 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<size_t>(15));
- // Should trigger about 10 times, check for at least 5 events to be safe.
- ASSERT_GE(rightCount, static_cast<size_t>(5));
-}
-
-TEST_F(DefaultVehicleHalTest, testAreaContinuous_areaNotSupportVur) {
- std::vector<SubscribeOptions> 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<SubscribeOptions> 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<int32_t>({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<SubscribeOptions> 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<int32_t>({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<SubscribeInvalidOptionsTestCase> {};
-
-INSTANTIATE_TEST_SUITE_P(
- SubscribeInvalidOptionsTests, SubscribeInvalidOptionsTest,
- testing::ValuesIn(getSubscribeInvalidOptionsTestCases()),
- [](const testing::TestParamInfo<SubscribeInvalidOptionsTest::ParamType>& info) {
- return info.param.name;
- });
-
-TEST_P(SubscribeInvalidOptionsTest, testSubscribeInvalidOptions) {
- std::vector<SubscribeOptions> 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<SubscribeOptions> 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<SubscribeOptions> 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<SubscribeOptions> 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<int32_t>({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<SubscribeOptions> 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();
- ASSERT_TRUE(maybeResults.has_value()) << "no results in callback";
- ASSERT_EQ(maybeResults.value().payloads.size(), static_cast<size_t>(1));
- VehiclePropValue gotValue = maybeResults.value().payloads[0];
- ASSERT_EQ(gotValue.prop, toInt(VehicleProperty::VHAL_HEARTBEAT));
- ASSERT_EQ(gotValue.value.int64Values.size(), static_cast<size_t>(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<const IVehicleHardware::GetValuesCallback> callback,
- const std::vector<GetValueRequest>& requests) {
- std::vector<GetValueResult> 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<SubscribeOptions> 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<GetValueResult> expectedResults;
- std::vector<GetValueRequest> 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<size_t>(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<size_t>(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<size_t>(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<SubscribeOptions> 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<SetValueErrorEvent> 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<VehiclePropError> 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<MockVehicleHardware>();
- hardware->setPropertyOnChangeEventBatchingWindow(std::chrono::milliseconds(10));
- init(std::move(hardware));
-
- std::vector<SubscribeOptions> 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_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 b469578..768e97e 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 @@
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 4c5dad2..5abf667 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
@@ -32,7 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.automotive.vehicle;
-@Backing(type="int") @VintfStability
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
enum VehicleProperty {
INVALID = 0x00000000,
INFO_VIN = (((0x0100 + 0x10000000) + 0x01000000) + 0x00100000) /* 286261504 */,
@@ -48,11 +48,15 @@
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 @@
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 @@
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 @@
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 0000000..6817124
--- /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 <name>-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 7891dd9..5738d21 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 @@
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)
@@ -89,6 +92,32 @@
/** 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
* extended with an appropriate value.
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 e5c09b0..856d38c 100644
--- a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl
+++ b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl
@@ -39,6 +39,7 @@
* in response to such ill formed requests.
*/
@VintfStability
+@JavaDerive(toString=true)
@Backing(type="int")
enum VehicleProperty {
/**
@@ -232,6 +233,45 @@
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
*
* @change_mode VehiclePropertyChangeMode.CONTINUOUS
@@ -303,6 +343,38 @@
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
*
* @change_mode VehiclePropertyChangeMode.CONTINUOUS
@@ -525,26 +597,45 @@
/**
* 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.
+ * Each tire is identified by its areaConfig.areaId config and its 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.
+ * of the left_front tire is from 200.0 KILOPASCAL to 240.0 KILOPASCAL.
* .areaConfigs = {
* VehicleAreaConfig {
* .areaId = VehicleAreaWheel::LEFT_FRONT,
* .minFloatValue = 200.0,
* .maxFloatValue = 240.0,
* }
- * },
+ * }
+ *
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minFloatValue.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxFloatValue.
+ * 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.
+ * At boot, minFloatValue is equal to minSupportedValue, maxFloatValue is equal to
+ * maxSupportedValue.
*
* @change_mode VehiclePropertyChangeMode.CONTINUOUS
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @unit VehicleUnit.KILOPASCAL
* @version 2
*/
@@ -567,6 +658,100 @@
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.
*
* If true, the vehicle may automatically shut off the engine when it is not needed and then
@@ -592,6 +777,11 @@
* For the global area ID (0), the VehicleAreaConfig#supportedEnumValues array must be defined
* unless all bit flags of ImpactSensorLocation are supported.
*
+ * If {@code HasSupportedValueInfo} is not {@code null} 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.
+ * At boot, supportedEnumValues is equal to the supported values list.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum ImpactSensorLocation
@@ -600,22 +790,51 @@
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,...}
+ * Values in the config array must represent the list of supported gears for this vehicle at
+ * boot time. For example, config array 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 contain {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.
*
+ * If {@code HasSupportedValueInfo} is not {@code null} for the global area ID (0):
+ * {@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"), the GEAR_SELECTION property value must be set to the
+ * specific gear selected by the driver instead of simply GEAR_DRIVE.
+ * At boot, the config array's values are equal to the supported values list.
+ *
* @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 +845,31 @@
* 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
+ * Values in the config array must represent the list of supported gears
+ * for this vehicle at boot time. For example, config array for an automatic transmission
* must contain {GEAR_NEUTRAL, GEAR_REVERSE, GEAR_PARK, GEAR_1, GEAR_2,...}
- * and for manual transmission the list must be
+ * and for manual transmission the list must contain
* {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.
*
+ * If {@code HasSupportedValueInfo} is not {@code null} for the global area ID (0):
+ * {@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.
+ * At boot, the config array's values are equal to the supported values list.
+ *
* @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 +907,23 @@
/**
* 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.
+ * The minInt32Value and maxInt32Value in VehicleAreaConfig must be defined. All values between
+ * minInt32Value and maxInt32Value must be supported.
+ *
+ * The minInt32Value indicates the setting for no regenerative braking, must be 0.
*
* The maxInt32Value indicates the setting for the maximum amount of energy regenerated from
- * braking. The minInt32Value indicates the setting for no regenerative braking.
+ * braking.
+ *
+ * All values between min and max supported value must be supported.
+ *
+ * If {@code HasSupportedValueInfo} is not {@code null} for the global area ID (0):
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for global area ID(0)
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
*
* 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 +935,7 @@
* @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 +973,12 @@
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
@@ -777,6 +1029,12 @@
* For the global area ID (0), the VehicleAreaConfig#supportedEnumValues must be defined unless
* all enum values of EvStoppingMode are supported.
*
+ * If {@code HasSupportedValueInfo} is not {@code null} for the global area ID (0):
+ * 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.
+ * At boot, supportedEnumValues is equal to the supported values list.
+ *
* The EvStoppingMode enum may be extended to include more states in the future.
*
* This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
@@ -823,6 +1081,13 @@
* unless all states of both ElectronicStabilityControlState (including OTHER, which is not
* recommended) and ErrorState are supported.
*
+ * If {@code HasSupportedValueInfo} is not {@code null} for the global area ID (0):
+ * 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.
+ * At boot, supportedEnumValues is equal to the supported values list.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum ElectronicStabilityControlState
@@ -832,6 +1097,60 @@
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
*
* Additional rules for mapping non-GLOBAL VehicleArea type HVAC properties
@@ -884,8 +1203,19 @@
* All integers between minInt32Value and maxInt32Value must be supported.
*
* The minInt32Value indicates the lowest fan speed.
+ *
* The maxInt32Value indicates the highest fan speed.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the specific
+ * area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative speeds.
*
* This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
@@ -894,6 +1224,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
HVAC_FAN_SPEED = 0x0500 + 0x10000000 + 0x05000000
@@ -904,6 +1235,10 @@
* 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
@@ -928,6 +1263,7 @@
* The minFloatValue and maxFloatValue in VehicleAreaConfig must be defined.
*
* The minFloatValue indicates the minimum temperature setting in Celsius.
+ *
* The maxFloatValue indicates the maximum temperature setting in Celsius.
*
* If all the values between minFloatValue and maxFloatValue are not supported, the configArray
@@ -967,6 +1303,19 @@
*
* Any value set in between a valid value should be rounded to the closest valid value.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the specific
+ * area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minFloatValue.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxFloatValue.
+ * If not all the values between minSupportedValue and maxSupportedValue are supported,
+ * {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} for the
+ * specified area ID. At boot, supportedValuesList must be equal to what is described in
+ * config array.
+ * At boot, minFloatValue is equal to minSupportedValue, maxFloatValue is equal to
+ * maxSupportedValue.
+ *
* It is highly recommended that the OEM also implement the HVAC_TEMPERATURE_VALUE_SUGGESTION
* vehicle property because it provides applications a simple method for determining temperature
* values that can be set for this vehicle and for converting values between Celsius and
@@ -979,6 +1328,7 @@
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit.CELSIUS
+ * @require_min_max_supported_value
* @version 2
*/
HVAC_TEMPERATURE_SET = 0x0503 + 0x10000000 + 0x05000000
@@ -1139,10 +1489,21 @@
* The maxInt32Value and minInt32Value in VehicleAreaConfig must be defined.
* All integers between minInt32Value and maxInt32Value must be supported.
*
- * The maxInt32Value indicates the maximum seat temperature heating setting.
* The minInt32Value must be 0, unless the vehicle supports seat cooling as well. In this case,
* minInt32Value indicates the maximum seat temperature cooling setting.
*
+ * The maxInt32Value indicates the maximum seat temperature heating setting.
+ *
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the specified
+ * area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit, but in a specified range of relative temperature
* settings.
*
@@ -1152,6 +1513,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
HVAC_SEAT_TEMPERATURE = 0x050B + 0x10000000 + 0x05000000
@@ -1164,9 +1526,20 @@
* The maxInt32Value and minInt32Value in VehicleAreaConfig must be defined.
* All integers between minInt32Value and maxInt32Value must be supported.
*
- * The maxInt32Value in the config data represents the maximum heating level.
* The minInt32Value in the config data MUST be zero and indicates no heating.
*
+ * The maxInt32Value in the config data represents the maximum heating level.
+ *
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the specified
+ * area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative heating
* settings.
*
@@ -1176,6 +1549,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
HVAC_SIDE_MIRROR_HEAT = 0x050C + 0x10000000 + 0x04000000
@@ -1188,10 +1562,20 @@
* The maxInt32Value and minInt32Value in VehicleAreaConfig must be defined.
* All integers between minInt32Value and maxInt32Value must be supported.
*
- * The maxInt32Value indicates the maximum steering wheel heating setting.
* The minInt32Value should be 0, unless the vehicle supports steering wheel cooling as well. In
* such a case, the minInt32Value indicates the maximum steering wheel cooling setting.
*
+ * The maxInt32Value indicates the maximum steering wheel heating setting.
+ *
+ * If {@code HasSupportedValueInfo} is not null for the global area ID (0):
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true}.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of heating settings.
*
* This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
@@ -1200,6 +1584,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
HVAC_STEERING_WHEEL_HEAT = 0x050D + 0x10000000 + 0x01000000
@@ -1207,12 +1592,21 @@
/**
* Temperature units for display
*
- * Indicates whether the vehicle is displaying temperature to the user as
- * Celsius or Fahrenheit.
+ * Indicates whether the vehicle is displaying temperature to the user as Celsius or Fahrenheit.
+ *
* VehiclePropConfig.configArray is used to indicate the supported temperature display units.
+ *
* For example: configArray[0] = CELSIUS
* configArray[1] = FAHRENHEIT
*
+ * If {@code HasSupportedValueInfo} is not {@code null} for the global area ID (0):
+ * {@code VehicleAreaConfig.HasSupportedValueInfo.hasSupportedValuesList} for the global area ID
+ * (0) must be {@code true}.
+ * {@code getSupportedValuesLists} for [HVAC_TEMPERATURE_DISPLAY_UNITS, areaId=0] must return a
+ * {@code SupportedValuesListResult} that contains non-null {@code supportedValuesList},
+ * e.g. [CELSIUS, FAHRENHEIT].
+ * At boot, the values in the config array are equal to the supported values list.
+ *
* This parameter MAY be used for displaying any HVAC temperature in the system.
* Values must be one of VehicleUnit.CELSIUS or VehicleUnit.FAHRENHEIT
* Note that internally, all temperatures are represented in floating point Celsius.
@@ -1227,6 +1621,8 @@
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleUnit
+ * @require_supported_values_list
+ * @legacy_supported_values_in_config
* @version 2
*/
HVAC_TEMPERATURE_DISPLAY_UNITS = 0x050E + 0x10000000 + 0x01000000
@@ -1327,12 +1723,24 @@
/**
* Seat ventilation
*
- * The maxInt32Value and minInt32Value in VehicleAreaConfig must be defined.
+ * The minInt32Value and maxInt32Value in VehicleAreaConfig must be defined.
+ *
* All integers between minInt32Value and maxInt32Value must be supported.
*
* The minInt32Value must be 0.
+ *
* The maxInt32Value indicates the maximum ventilation setting available for the seat.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the specified
+ * area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in the specified range of ventilation
* settings.
*
@@ -1346,6 +1754,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
HVAC_SEAT_VENTILATION = 0x0513 + 0x10000000 + 0x05000000
@@ -1431,6 +1840,14 @@
* configArray[1] = KILOMETER
* configArray[2] = MILE
*
+ * If {@code HasSupportedValueInfo} is not {@code null} for the global area ID (0):
+ * {@code VehicleAreaConfig.HasSupportedValueInfo.hasSupportedValuesList} for the global area ID
+ * (0) must be {@code true}.
+ * {@code getSupportedValuesLists} for [DISTANCE_DISPLAY_UNITS, areaId=0] must returns a
+ * {@code SupportedValuesListResult} that contains non-null {@code supportedValuesList},
+ * e.g. [METER, KILOMETER, MILE].
+ * At boot, the values in the config array are equal to the supported values list.
+ *
* If updating DISTANCE_DISPLAY_UNITS affects the values of other *_DISPLAY_UNITS properties,
* then their values must be updated and communicated to the AAOS framework as well.
*
@@ -1441,6 +1858,8 @@
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleUnit
+ * @require_supported_values_list
+ * @legacy_supported_values_in_config
* @version 2
*/
DISTANCE_DISPLAY_UNITS = 0x0600 + 0x10000000 + 0x01000000
@@ -1456,6 +1875,14 @@
* For example: configArray[0] = LITER
* configArray[1] = GALLON
*
+ * If {@code HasSupportedValueInfo} is not {@code null} for the global area ID (0):
+ * {@code VehicleAreaConfig.HasSupportedValueInfo.hasSupportedValuesList} for the global area ID
+ * (0) must be {@code true}.
+ * {@code getSupportedValuesLists} for [FUEL_VOLUME_DISPLAY_UNITS, areaId=0] must return a
+ * {@code SupportedValuesListResult} that contains non-null {@code supportedValuesList},
+ * e.g. [LITER, GALLON].
+ * At boot, the values in the config array are equal to the supported values list.
+ *
* If updating FUEL_VOLUME_DISPLAY_UNITS affects the values of other *_DISPLAY_UNITS properties,
* then their values must be updated and communicated to the AAOS framework as well.
*
@@ -1466,6 +1893,8 @@
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleUnit
+ * @require_supported_values_list
+ * @legacy_supported_values_in_config
* @version 2
*/
FUEL_VOLUME_DISPLAY_UNITS = 0x0601 + 0x10000000 + 0x01000000
@@ -1482,6 +1911,14 @@
* configArray[1] = PSI
* configArray[2] = BAR
*
+ * If {@code HasSupportedValueInfo} is not {@code null} for the global area ID (0):
+ * {@code VehicleAreaConfig.HasSupportedValueInfo.hasSupportedValuesList} for the global area ID
+ * (0) must be {@code true}.
+ * {@code getSupportedValuesLists} for [TIRE_PRESSURE_DISPLAY_UNITS, areaId=0] must return a
+ * {@code SupportedValuesListResult} that contains non-null {@code supportedValuesList},
+ * e.g. [KILOPASCAL, PSI, BAR].
+ * At boot, the values in the config array are equal to the supported values list.
+ *
* If updating TIRE_PRESSURE_DISPLAY_UNITS affects the values of other *_DISPLAY_UNITS
* properties, then their values must be updated and communicated to the AAOS framework as well.
*
@@ -1492,6 +1929,8 @@
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleUnit
+ * @require_supported_values_list
+ * @legacy_supported_values_in_config
* @version 2
*/
TIRE_PRESSURE_DISPLAY_UNITS = 0x0602 + 0x10000000 + 0x01000000
@@ -1508,6 +1947,14 @@
* configArray[1] = AMPERE_HOURS
* configArray[2] = KILOWATT_HOUR
*
+ * If {@code HasSupportedValueInfo} is not {@code null} for the global area ID (0):
+ * {@code VehicleAreaConfig.HasSupportedValueInfo.hasSupportedValuesList} for the global area ID
+ * (0) must be {@code true}.
+ * {@code getSupportedValuesLists} for [EV_BATTERY_DISPLAY_UNITS, areaId=0] must return a
+ * {@code SupportedValuesListResult} that contains non-null {@code supportedValuesList},
+ * e.g. [WATT_HOUR, AMPERE_HOURS, KILOWATT_HOUR].
+ * At boot, the values in the config array are equal to the supported values list.
+ *
* If updating EV_BATTERY_DISPLAY_UNITS affects the values of other *_DISPLAY_UNITS properties,
* then their values must be updated and communicated to the AAOS framework as well.
*
@@ -1518,6 +1965,8 @@
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleUnit
+ * @require_supported_values_list
+ * @legacy_supported_values_in_config
* @version 2
*/
EV_BATTERY_DISPLAY_UNITS = 0x0603 + 0x10000000 + 0x01000000
@@ -1550,6 +1999,14 @@
* configArray[1] = MILES_PER_HOUR
* configArray[2] = KILOMETERS_PER_HOUR
*
+ * If {@code HasSupportedValueInfo} is not {@code null} for the global area ID (0):
+ * {@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].
+ * At boot, the values in the config array are equal to the supported values list.
+ *
* If 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.
*
@@ -1559,6 +2016,9 @@
* @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
@@ -1973,11 +2433,21 @@
* All integers between minInt32Value and maxInt32Value must be supported.
*
* The minInt32Value indicates the door is closed. The minInt32Value must be 0.
+ *
* The maxInt32Value indicates the door is fully open.
*
* Values in between minInt32Value and maxInt32Value indicate a transition state between the
* closed and fully open positions.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative positions.
*
* Some vehicles (minivans) can open the door electronically. Hence, the
@@ -1989,6 +2459,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
DOOR_POS = 0x0B00 + 0x10000000 + 0x06000000
@@ -1999,13 +2470,23 @@
* The maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers
* between minInt32Value and maxInt32Value must be supported.
*
- * The maxInt32Value represents the maximum movement speed of the door while opening.
* The minInt32Value represents the maximum movement speed of the door while closing.
*
+ * The maxInt32Value represents the maximum movement speed of the door while opening.
+ *
* Larger absolute values, either positive or negative, indicate a faster movement speed. Once
* the door reaches the positional limit, the value must reset to 0. If DOOR_MOVE's value is
* currently 0, then that means there is no movement currently occurring.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative movement
* speeds.
*
@@ -2015,6 +2496,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
DOOR_MOVE = 0x0B01 + 0x10000000 + 0x06000000
@@ -2059,13 +2541,26 @@
*
* The minInt32Value indicates the mirror is tilted completely downwards. This must be a
* non-positive value.
+ *
* The maxInt32Value indicates the mirror is tilted completely upwards. This must be a
* non-negative value.
+ *
* 0 indicates the mirror is not tilted in either direction.
*
* Values in between minInt32Value and maxInt32Value indicate a transition state between the
* fully downward and fully upwards positions.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * Values in between minSupportedValue and maxSupportedValue indicate a transition state between
+ * the fully downward and fully upwards positions.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative positions.
*
* This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
@@ -2074,6 +2569,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
MIRROR_Z_POS = 0x0B40 + 0x10000000 + 0x04000000
@@ -2084,14 +2580,24 @@
* The maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers
* between minInt32Value and maxInt32Value must be supported.
*
- * The maxInt32Value represents the maximum movement speed of the mirror while tilting upwards.
* The minInt32Value represents the maximum movement speed of the mirror while tilting
* downwards.
*
+ * The maxInt32Value represents the maximum movement speed of the mirror while tilting upwards.
+ *
* Larger absolute values, either positive or negative, indicate a faster movement speed. Once
* the mirror reaches the positional limit, the value must reset to 0. If MIRROR_Z_MOVE's value
* is currently 0, then that means there is no movement currently occurring.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative movement
* speeds.
*
@@ -2101,6 +2607,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
MIRROR_Z_MOVE = 0x0B41 + 0x10000000 + 0x04000000
@@ -2113,13 +2620,26 @@
*
* The minInt32Value indicates the mirror is tilted completely to the left. This must be a
* non-positive value.
+ *
* The maxInt32Value indicates the mirror is tilted completely to the right. This must be a
* non-negative value.
+ *
* 0 indicates the mirror is not tilted in either direction.
*
* Values in between minInt32Value and maxInt32Value indicate a transition state between the
* left extreme and right extreme positions.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * Values in between minSupportedValue and maxSupportedValue indicate a transition state between
+ * the fully downward and fully upwards positions.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative positions.
*
* This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
@@ -2128,6 +2648,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
MIRROR_Y_POS = 0x0B42 + 0x10000000 + 0x04000000
@@ -2138,13 +2659,23 @@
* The maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers
* between minInt32Value and maxInt32Value must be supported.
*
- * The maxInt32Value represents the maximum movement speed of the mirror while tilting right.
* The minInt32Value represents the maximum movement speed of the mirror while tilting left.
*
+ * The maxInt32Value represents the maximum movement speed of the mirror while tilting right.
+ *
* Larger absolute values, either positive or negative, indicate a faster movement speed. Once
* the mirror reaches the positional limit, the value must reset to 0. If MIRROR_Y_MOVE's value
* is currently 0, then that means there is no movement currently occurring.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative movement
* speeds.
*
@@ -2154,6 +2685,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
MIRROR_Y_MOVE = 0x0B43 + 0x10000000 + 0x04000000
@@ -2230,17 +2762,30 @@
/**
* Seat memory select
*
- * This parameter selects the memory preset to use to select the seat position. The
- * maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers between
- * minInt32Value and maxInt32Value must be supported. The minInt32Value is always 0, and the
- * maxInt32Value determines the number of seat preset memory slots available (i.e.
- * numSeatPresets - 1).
+ * This parameter selects the memory preset to use to select the seat position.
+ *
+ * The maxInt32Value and minInt32Value in VehicleAreaConfig must be defined.
+ *
+ * All integers between minInt32Value and maxInt32Value must be supported.
+ *
+ * The minInt32Value is always 0, and the maxInt32Value determines the number of seat preset
+ * memory slots available (i.e. numSeatPresets - 1).
*
* For instance, if the driver's seat has 3 memory presets, the maxInt32Value will be 2. When
* the user wants to select a preset, the desired preset number (0, 1, or 2) is set.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.WRITE
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_MEMORY_SELECT = 0x0B80 + 0x10000000 + 0x05000000
@@ -2249,12 +2794,24 @@
* Seat memory set
*
* This setting allows the user to save the current seat position settings into the selected
- * preset slot. The maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. The
- * minInt32Value must be 0, and the maxInt32Value for each seat position must match the
+ * preset slot.
+ *
+ * The maxInt32Value and minInt32Value in VehicleAreaConfig must be defined.
+ *
+ * The minInt32Value must be 0, and the maxInt32Value for each seat position must match the
* maxInt32Value for SEAT_MEMORY_SELECT.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.WRITE
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_MEMORY_SET = 0x0B81 + 0x10000000 + 0x05000000
@@ -2286,11 +2843,22 @@
* All integers between minInt32Value and maxInt32Value must be supported.
*
* The minInt32Value indicates the seat belt's shoulder anchor is at its lowest position.
+ *
* The maxInt32Value indicates the seat belt's shoulder anchor is at its highest position.
*
* Values in between minInt32Value and maxInt32Value indicate a transition state between the
* lowest and highest positions.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * Values in between minSupportedValue and maxSupportedValue indicate a transition state between
+ * the lowest and highest positions. All integers between minSupportedValue and
+ * maxSupportedValue must be supported. At boot, minInt32Value is equal to minSupportedValue,
+ * maxInt32Value is equal to maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative positions.
*
* This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
@@ -2299,6 +2867,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_BELT_HEIGHT_POS = 0x0B83 + 0x10000000 + 0x05000000
@@ -2309,16 +2878,26 @@
* The maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers
* between minInt32Value and maxInt32Value must be supported.
*
- * The maxInt32Value represents the maximum movement speed of the seat belt's shoulder anchor
- * while moving upwards.
* The minInt32Value represents the maximum movement speed of the seat belt's shoulder anchor
* while moving downwards.
*
+ * The maxInt32Value represents the maximum movement speed of the seat belt's shoulder anchor
+ * while moving upwards.
+ *
* Larger absolute values, either positive or negative, indicate a faster movement speed. Once
* the seat belt reaches the positional limit, the value must reset to 0. If
* SEAT_BELT_HEIGHT_MOVE's value is currently 0, then that means there is no movement currently
* occurring.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative movement
* speeds.
*
@@ -2328,6 +2907,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_BELT_HEIGHT_MOVE = 0x0B84 + 0x10000000 + 0x05000000
@@ -2341,11 +2921,21 @@
* All integers between minInt32Value and maxInt32Value must be supported.
*
* The minInt32Value indicates the seat is at its rearward-most linear position.
+ *
* The maxInt32Value indicates the seat is at its forward-most linear position.
*
* Values in between minInt32Value and maxInt32Value indicate a transition state between the
* closest and farthest positions.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative positions.
*
* This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
@@ -2354,6 +2944,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_FORE_AFT_POS = 0x0B85 + 0x10000000 + 0x05000000
@@ -2366,13 +2957,23 @@
* The maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers
* between minInt32Value and maxInt32Value must be supported.
*
- * The maxInt32Value represents the maximum movement speed of the seat while moving forward.
* The minInt32Value represents the maximum movement speed of the seat while moving backward.
*
+ * The maxInt32Value represents the maximum movement speed of the seat while moving forward.
+ *
* Larger absolute values, either positive or negative, indicate a faster movement speed. Once
* the seat reaches the positional limit, the value must reset to 0. If SEAT_FORE_AFT_MOVE's
* value is currently 0, then that means there is no movement currently occurring.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative movement
* speeds.
*
@@ -2382,6 +2983,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_FORE_AFT_MOVE = 0x0B86 + 0x10000000 + 0x05000000
@@ -2396,12 +2998,24 @@
*
* The minInt32Value indicates the seat backrest's full recline position w.r.t the
* actuator at the bottom of the seat.
+ *
* The maxInt32Value indicates the seat backrest's most upright/forward position w.r.t the
* actuator at the bottom of the seat.
*
* Values in between minInt32Value and maxInt32Value indicate a transition state between the
* full recline and upright/forward positions.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * Values in between minSupportedValue and maxSupportedValue indicate a transition state between
+ * the full recline and upright/forward positions.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative positions.
*
* This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
@@ -2410,6 +3024,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_BACKREST_ANGLE_1_POS = 0x0B87 + 0x10000000 + 0x05000000
@@ -2420,15 +3035,25 @@
* The maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers
* between minInt32Value and maxInt32Value must be supported.
*
+ * The minInt32Value represents the maximum movement speed of the seat backrest while reclining.
+ *
* The maxInt32Value represents the maximum movement speed of the seat backrest while angling
* forward.
- * The minInt32Value represents the maximum movement speed of the seat backrest while reclining.
*
* Larger absolute values, either positive or negative, indicate a faster movement speed. Once
* the seat backrest reaches the positional limit, the value must reset to 0. If
* SEAT_BACKREST_ANGLE_1_MOVE's value is currently 0, then that means there is no movement
* currently occurring.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative movement
* speeds.
*
@@ -2438,6 +3063,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_BACKREST_ANGLE_1_MOVE = 0x0B88 + 0x10000000 + 0x05000000
@@ -2453,6 +3079,7 @@
* The minInt32Value indicates the seat backrest's full recline position w.r.t the next
* actuator in the backrest from the one at the bottom of the seat (see
* SEAT_BACKREST_ANGLE_1_POS for additional details).
+ *
* The maxInt32Value indicates the seat backrest's most upright/forward position w.r.t the
* next actuator in the backrest from the one at the bottom of the seat(see
* SEAT_BACKREST_ANGLE_1_POS for additional details).
@@ -2460,6 +3087,17 @@
* Values in between minInt32Value and maxInt32Value indicate a transition state between the
* full recline and upright/forward positions.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} ihas the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * Values in between minSupportedValue and maxSupportedValue indicate a transition state between
+ * the full recline and upright/forward positions.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative positions.
*
* This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
@@ -2468,6 +3106,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_BACKREST_ANGLE_2_POS = 0x0B89 + 0x10000000 + 0x05000000
@@ -2478,15 +3117,25 @@
* The maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers
* between minInt32Value and maxInt32Value must be supported.
*
+ * The minInt32Value represents the maximum movement speed of the seat backrest while reclining.
+ *
* The maxInt32Value represents the maximum movement speed of the seat backrest while angling
* forward.
- * The minInt32Value represents the maximum movement speed of the seat backrest while reclining.
*
* Larger absolute values, either positive or negative, indicate a faster movement speed. Once
* the seat backrest reaches the positional limit, the value must reset to 0. If
* SEAT_BACKREST_ANGLE_2_MOVE's value is currently 0, then that means there is no movement
* currently occurring.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative movement
* speeds.
*
@@ -2496,6 +3145,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_BACKREST_ANGLE_2_MOVE = 0x0B8A + 0x10000000 + 0x05000000
@@ -2507,11 +3157,22 @@
* All integers between minInt32Value and maxInt32Value must be supported.
*
* The minInt32Value indicates the seat is in its lowest position.
+ *
* The maxInt32Value indicates the seat is in its highest position.
*
* Values in between minInt32Value and maxInt32Value indicate a transition state between the
* lowest and highest positions.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * position.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative positions.
*
* This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
@@ -2520,6 +3181,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_HEIGHT_POS = 0x0B8B + 0x10000000 + 0x05000000
@@ -2530,13 +3192,23 @@
* The maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers
* between minInt32Value and maxInt32Value must be supported.
*
- * The maxInt32Value represents the maximum movement speed of the seat while moving upward.
* The minInt32Value represents the maximum movement speed of the seat while moving downward.
*
+ * The maxInt32Value represents the maximum movement speed of the seat while moving upward.
+ *
* Larger absolute values, either positive or negative, indicate a faster movement speed. Once
* the seat reaches the positional limit, the value must reset to 0. If SEAT_HEIGHT_MOVE's value
* is currently 0, then that means there is no movement currently occurring.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative movement
* speeds.
*
@@ -2546,6 +3218,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_HEIGHT_MOVE = 0x0B8C + 0x10000000 + 0x05000000
@@ -2561,12 +3234,22 @@
* The minInt32Value indicates the seat is in its shallowest position (i.e. the position with
* the smallest distance between the front edge of the seat cushion and the rear end of the
* seat).
+ *
* The maxInt32Value indicates the seat is in its deepest position (i.e. the position with the
* largest distance between the front edge of the seat cushion and the rear end of the seat).
*
* Values in between minInt32Value and maxInt32Value indicate a transition state between the
* shallowest and deepest positions.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative positions.
*
* This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
@@ -2575,6 +3258,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_DEPTH_POS = 0x0B8D + 0x10000000 + 0x05000000
@@ -2585,14 +3269,24 @@
* The maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers
* between minInt32Value and maxInt32Value must be supported.
*
- * The maxInt32Value represents the maximum movement speed of the seat while getting deeper
* The minInt32Value represents the maximum movement speed of the seat while getting shallower.
*
+ * The maxInt32Value represents the maximum movement speed of the seat while getting deeper.
+ *
* Larger absolute values, either positive or negative, indicate a faster movement speed. Once
* the seat backrest reaches the positional limit, the value must reset to 0. If
* SEAT_DEPTH_MOVE's value is currently 0, then that means there is no movement currently
* occurring.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative movement
* speeds.
*
@@ -2602,6 +3296,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_DEPTH_MOVE = 0x0B8E + 0x10000000 + 0x05000000
@@ -2615,6 +3310,7 @@
* The minInt32Value indicates the seat bottom is angled at its lowest angular position. This
* corresponds to the seat's front edge at its lowest possible position relative to the rear
* end of the seat.
+ *
* The maxInt32Value indicates the seat bottom is angled at its highest angular position. This
* corresponds to the seat's front edge at its highest possible position relative to the rear
* end of the seat.
@@ -2622,6 +3318,15 @@
* Values in between minInt32Value and maxInt32Value indicate a transition state between the
* lowest and highest positions.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative positions.
*
* This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
@@ -2630,6 +3335,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_TILT_POS = 0x0B8F + 0x10000000 + 0x05000000
@@ -2640,15 +3346,25 @@
* The maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers
* between minInt32Value and maxInt32Value must be supported.
*
- * The maxInt32Value represents the maximum movement speed of the front edge of the seat while
- * moving upward.
* The minInt32Value represents the maximum movement speed of the front edge of the seat while
* moving downward.
*
+ * The maxInt32Value represents the maximum movement speed of the front edge of the seat while
+ * moving upward.
+ *
* Larger absolute values, either positive or negative, indicate a faster movement speed. Once
* the seat bottom reaches the positional limit, the value must reset to 0. If SEAT_TILT_MOVE's
* value is currently 0, then that means there is no movement currently occurring.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative movement
* speeds.
*
@@ -2658,6 +3374,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_TILT_MOVE = 0x0B90 + 0x10000000 + 0x05000000
@@ -2670,12 +3387,22 @@
*
* The minInt32Value indicates the lumbar support is in its rearward most position (i.e. least
* supportive position).
+ *
* The maxInt32Value indicates the lumbar support is in its forward most position (i.e. most
* supportive position).
*
* Values in between minInt32Value and maxInt32Value indicate a transition state between the
* forward and rearward positions.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative positions.
*
* This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
@@ -2684,6 +3411,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_LUMBAR_FORE_AFT_POS = 0x0B91 + 0x10000000 + 0x05000000
@@ -2694,16 +3422,26 @@
* The maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers
* between minInt32Value and maxInt32Value must be supported.
*
- * The maxInt32Value represents the maximum movement speed of the seat's lumbar support while
- * moving forward.
* The minInt32Value represents the maximum movement speed of the seat's lumbar support while
* moving backward.
*
+ * The maxInt32Value represents the maximum movement speed of the seat's lumbar support while
+ * moving forward.
+ *
* Larger absolute values, either positive or negative, indicate a faster movement speed. Once
* the seat's lumbar support reaches the positional limit, the value must reset to 0. If
* SEAT_LUMBAR_FORE_AFT_MOVE's value is currently 0, then that means there is no movement
* currently occurring.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative movement
* speeds.
*
@@ -2713,6 +3451,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_LUMBAR_FORE_AFT_MOVE = 0x0B92 + 0x10000000 + 0x05000000
@@ -2725,12 +3464,22 @@
*
* The minInt32Value indicates the lumbar side support is in its thinnest position (i.e.
* most support).
+ *
* The maxInt32Value indicates the lumbar side support is in its widest position (i.e.
* least support).
*
* Values in between minInt32Value and maxInt32Value indicate a transition state between the
* thinnest and widest positions.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative positions.
*
* This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
@@ -2739,6 +3488,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_LUMBAR_SIDE_SUPPORT_POS = 0x0B93 + 0x10000000 + 0x05000000
@@ -2749,16 +3499,26 @@
* The maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers
* between minInt32Value and maxInt32Value must be supported.
*
- * The maxInt32Value represents the maximum movement speed of the seat's lumbar side support
- * while getting wider.
* The minInt32Value represents the maximum movement speed of the seat's lumbar side support
* while getting thinner.
*
+ * The maxInt32Value represents the maximum movement speed of the seat's lumbar side support
+ * while getting wider.
+ *
* Larger absolute values, either positive or negative, indicate a faster movement speed. Once
* the seat's lumbar side support reaches the positional limit, the value must reset to 0. If
* SEAT_LUMBAR_SIDE_SUPPORT_MOVE's value is currently 0, then that means there is no movement
* currently occurring.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative movement
* speeds.
*
@@ -2768,6 +3528,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_LUMBAR_SIDE_SUPPORT_MOVE = 0x0B94 + 0x10000000 + 0x05000000
@@ -2804,11 +3565,21 @@
* All integers between minInt32Value and maxInt32Value must be supported.
*
* The minInt32Value indicates the headrest is in its lowest position.
+ *
* The maxInt32Value indicates the headrest is in its highest position.
*
* Values in between minInt32Value and maxInt32Value indicate a transition state between the
* lowest and highest positions.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative positions.
*
* This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
@@ -2817,6 +3588,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_HEADREST_HEIGHT_POS_V2 =
@@ -2828,16 +3600,26 @@
* The maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers
* between minInt32Value and maxInt32Value must be supported.
*
- * The maxInt32Value represents the maximum movement speed of the seat's headrest while moving
- * up.
* The minInt32Value represents the maximum movement speed of the seat's headrest while moving
* down.
*
+ * The maxInt32Value represents the maximum movement speed of the seat's headrest while moving
+ * up.
+ *
* Larger absolute values, either positive or negative, indicate a faster movement speed. Once
* the seat's headrest reaches the positional limit, the value must reset to 0. If
* SEAT_HEADREST_HEIGHT_MOVE's value is currently 0, then that means there is no movement
* currently occurring.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative movement
* speeds.
*
@@ -2847,6 +3629,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_HEADREST_HEIGHT_MOVE = 0x0B96 + 0x10000000 + 0x05000000
@@ -2858,11 +3641,21 @@
* All integers between minInt32Value and maxInt32Value must be supported.
*
* The minInt32Value indicates the headrest is in its full recline position.
+ *
* The maxInt32Value indicates the headrest is in its most upright/forward position.
*
* Values in between minInt32Value and maxInt32Value indicate a transition state between the
* full recline and most upright/forward positions.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative positions.
*
* This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
@@ -2871,6 +3664,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_HEADREST_ANGLE_POS = 0x0B97 + 0x10000000 + 0x05000000
@@ -2881,16 +3675,26 @@
* The maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers
* between minInt32Value and maxInt32Value must be supported.
*
- * The maxInt32Value represents the maximum movement speed of the seat's headrest while moving
- * into an upright/forward position.
* The minInt32Value represents the maximum movement speed of the seat's headrest while moving
* into a shallow position.
*
+ * The maxInt32Value represents the maximum movement speed of the seat's headrest while moving
+ * into an upright/forward position.
+ *
* Larger absolute values, either positive or negative, indicate a faster movement speed. Once
* the seat's headrest reaches the positional limit, the value must reset to 0. If
* SEAT_HEADREST_ANGLE_MOVE's value is currently 0, then that means there is no movement
* currently occurring.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative movement
* speeds.
*
@@ -2900,6 +3704,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_HEADREST_ANGLE_MOVE = 0x0B98 + 0x10000000 + 0x05000000
@@ -2911,11 +3716,21 @@
* All integers between minInt32Value and maxInt32Value must be supported.
*
* The minInt32Value indicates the headrest is in its rearward-most linear position.
+ *
* The maxInt32Value indicates the headrest is in its forward-most linear position.
*
* Values in between minInt32Value and maxInt32Value indicate a transition state between the
* forward and rearward positions.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative positions.
*
* This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
@@ -2924,6 +3739,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_HEADREST_FORE_AFT_POS = 0x0B99 + 0x10000000 + 0x05000000
@@ -2934,16 +3750,26 @@
* The maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers
* between minInt32Value and maxInt32Value must be supported.
*
- * The maxInt32Value represents the maximum movement speed of the seat's headrest while moving
- * forward.
* The minInt32Value represents the maximum movement speed of the seat's headrest while moving
* backward.
*
+ * The maxInt32Value represents the maximum movement speed of the seat's headrest while moving
+ * forward.
+ *
* Larger absolute values, either positive or negative, indicate a faster movement speed. Once
* the seat's headrest reaches the positional limit, the value must reset to 0. If
* SEAT_HEADREST_FORE_AFT_MOVE's value is currently 0, then that means there is no movement
* currently occurring.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative movement
* speeds.
*
@@ -2953,6 +3779,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_HEADREST_FORE_AFT_MOVE = 0x0B9A + 0x10000000 + 0x05000000
@@ -2972,6 +3799,11 @@
* For each supported area ID, the VehicleAreaConfig#supportedEnumValues must be defined unless
* all enum values of VehicleLightState are supported.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} for the area ID
+ * unless all enum values of VehicleLightState are supported.
+ * At boot, the supported values list is the same as supportedEnumValues.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleLightState
@@ -2994,6 +3826,11 @@
* For each supported area ID, the VehicleAreaConfig#supportedEnumValues must be defined unless
* all enum values of VehicleLightSwitch are supported.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} for the area ID
+ * unless all enum values of VehicleLightSwitch are supported.
+ * At boot, the supported values list is the same as supportedEnumValues.
+ *
* This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
* implement it as VehiclePropertyAccess.READ only.
*
@@ -3059,6 +3896,12 @@
* all states of VehicleAirbagLocation are supported (including OTHER, which is not
* recommended).
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} for the area ID
+ * unless all states of VehicleAirbagLocation are supported (including OTHER, which is not
+ * recommended).
+ * At boot, the supported values list is the same as supportedEnumValues.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleAirbagLocation
@@ -3072,14 +3915,24 @@
* The maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers
* between minInt32Value and maxInt32Value must be supported.
*
- * The maxInt32Value indicates the seat cushion side support is in its widest position (i.e.
- * least support).
* The minInt32Value indicates the seat cushion side support is in its thinnest position (i.e.
* most support).
*
+ * The maxInt32Value indicates the seat cushion side support is in its widest position (i.e.
+ * least support).
+ *
* Values in between minInt32Value and maxInt32Value indicate a transition state between the
* thinnest and widest positions.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative positions.
*
* This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
@@ -3088,6 +3941,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_CUSHION_SIDE_SUPPORT_POS =
@@ -3098,16 +3952,26 @@
* The maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers
* between minInt32Value and maxInt32Value must be supported.
*
- * The maxInt32Value represents the maximum movement speed of the seat cushion side support when
- * growing wider (i.e. support is decreasing).
* The minInt32Value represents the maximum movement speed of the seat cushion side support when
* growing thinner (i.e. support is increasing).
*
+ * The maxInt32Value represents the maximum movement speed of the seat cushion side support when
+ * growing wider (i.e. support is decreasing).
+ *
* Larger absolute values, either positive or negative, indicate a faster movement speed. Once
* the seat cushion side support reaches the positional limit, the value must reset to 0. If
* SEAT_CUSHION_SIDE_SUPPORT_MOVE's value is currently 0, then that means there is no movement
* currently occurring.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative movement
* speeds.
*
@@ -3117,6 +3981,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_CUSHION_SIDE_SUPPORT_MOVE =
@@ -3127,12 +3992,22 @@
* The maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers
* between minInt32Value and maxInt32Value must be supported.
*
- * The maxInt32Value indicates the lumbar support's highest position.
* The minInt32Value indicates the lumbar support's lowest position.
*
+ * The maxInt32Value indicates the lumbar support's highest position.
+ *
* Values in between minInt32Value and maxInt32Value indicate a transition state between the
* lowest and highest positions.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative positions.
*
* This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
@@ -3141,6 +4016,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_LUMBAR_VERTICAL_POS =
@@ -3151,14 +4027,24 @@
* The maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers
* between minInt32Value and maxInt32Value must be supported.
*
- * The maxInt32Value indicates the lumbar support is moving at the fastest upward speed.
* The minInt32Value indicates the lumbar support is moving at the fastest downward speed.
*
+ * The maxInt32Value indicates the lumbar support is moving at the fastest upward speed.
+ *
* Larger absolute values, either positive or negative, indicate a faster movement speed. Once
* the seat cushion side support reaches the positional limit, the value must reset to 0. If
* SEAT_LUMBAR_VERTICAL_MOVE's value is currently 0, then that means there is no movement
* currently occurring.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative movement
* speeds.
*
@@ -3168,6 +4054,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_LUMBAR_VERTICAL_MOVE =
@@ -3179,11 +4066,21 @@
* All integers between minInt32Value and maxInt32Value must be supported.
*
* The minInt32Value indicates the normal seat position. The minInt32Value must be 0.
+ *
* The maxInt32Value indicates the seat is in the full walk-in position.
*
* Values in between minInt32Value and maxInt32Value indicate a transition state between the
* normal and walk-in positions.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative positions.
*
* The area ID must match the seat that actually moves when the walk-in feature activates, not
@@ -3195,6 +4092,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
SEAT_WALK_IN_POS =
@@ -3235,6 +4133,7 @@
* Window Position
*
* The maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined.
+ *
* All integers between minInt32Value and maxInt32Value must be supported.
*
* The minInt32Value indicates the window is closed/fully open out of plane. If the window
@@ -3242,6 +4141,7 @@
* and must be 0. If the window can open out of plane, the minInt32Value indicates the window
* is fully open in its position out of plane and will be a negative value. See the example
* below for a more detailed explanation.
+ *
* The maxInt32Value indicates the window is fully open.
*
* Values in between minInt32Value and maxInt32Value indicate a transition state between the
@@ -3258,12 +4158,22 @@
*
* Note that in this mode, 0 indicates the window is closed.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* 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
+ * @require_min_max_supported_value
* @version 2
*/
WINDOW_POS = 0x0BC0 + 0x10000000 + 0x03000000
@@ -3274,11 +4184,12 @@
* The maxInt32Value and minInt32Value in each VehicleAreaConfig must be defined. All integers
* between minInt32Value and maxInt32Value must be supported.
*
- * The maxInt32Value indicates the window is opening in plane/closing in the out of plane
- * direction at the fastest speed.
* The minInt32Value indicates the window is closing in plane/opening in the out of plane
* direction at the fastest speed.
*
+ * The maxInt32Value indicates the window is opening in plane/closing in the out of plane
+ * direction at the fastest speed.
+ *
* Larger absolute values, either positive or negative, indicate a faster movement speed. Once
* the window reaches the positional limit, the value must reset to 0. If WINDOW_MOVE's value is
* currently 0, then that means there is no movement currently occurring.
@@ -3301,12 +4212,22 @@
* Max = open the sunroof, automatically stop when sunroof is fully open.
* Min = open the vent, automatically stop when vent is fully open.
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true} for the area ID.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* 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
+ * @require_min_max_supported_value
* @version 2
*/
WINDOW_MOVE = 0x0BC1 + 0x10000000 + 0x03000000
@@ -3336,13 +4257,25 @@
* When an intermittent wiper setting is selected, this property value must be set to 0 during
* the "pause" period of the intermittent wiping.
*
- * The maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. The maxInt32Value
- * for each area ID must specify the longest wiper period. The minInt32Value must be set to 0
- * for each area ID.
+ * The maxInt32Value and minInt32Value in VehicleAreaConfig must be defined.
+ *
+ * The minInt32Value must be set to 0 for each area ID.
+ *
+ * The maxInt32Value for each area ID must specify the longest wiper period.
+ *
+ * If {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true}.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit.MILLI_SECS
+ * @require_min_max_supported_value
* @version 2
*/
WINDSHIELD_WIPERS_PERIOD =
@@ -3362,6 +4295,12 @@
* unless all states in WindshieldWipersState are supported (including OTHER, which is not
* recommended).
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} for the area ID
+ * unless all states in WindshieldWipersState are supported (including OTHER, which is not
+ * recommended).
+ * At boot, the supported values list is the same as supportedEnumValues.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum WindshieldWipersState
@@ -3381,6 +4320,12 @@
* unless all states in WindshieldWipersSwitch are supported (including OTHER, which is not
* recommended).
*
+ * If {@code HasSupportedValueInfo} for a specific area ID is not {@code null}:
+ * {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true} for the area ID
+ * unless all states in WindshieldWipersSwitch are supported (including OTHER, which is not
+ * recommended).
+ * At boot, the supported values list is the same as supportedEnumValues.
+ *
* This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
* implement it as VehiclePropertyAccess.READ only.
*
@@ -3405,12 +4350,22 @@
* The maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All values between
* minInt32Value and maxInt32Value must be supported.
*
- * The maxInt32Value indicates the steering wheel position furthest from the driver.
* The minInt32Value indicates the steering wheel position closest to the driver.
*
+ * The maxInt32Value indicates the steering wheel position furthest from the driver.
+ *
* Values in between minInt32Value and maxInt32Value indicate a transition state between the
* closest and furthest positions.
*
+ * If {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true}.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative positions.
*
* This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
@@ -3419,6 +4374,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
STEERING_WHEEL_DEPTH_POS =
@@ -3429,14 +4385,24 @@
* The maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All values between
* minInt32Value and maxInt32Value must be supported.
*
- * The maxInt32Value indicates the steering wheel moving away from the driver.
* The minInt32Value indicates the steering wheel moving towards the driver.
*
+ * The maxInt32Value indicates the steering wheel moving away from the driver.
+ *
* Larger integers, either positive or negative, indicate a faster movement speed. Once the
* steering wheel reaches the positional limit, the value must reset to 0. If
* STEERING_WHEEL_DEPTH_MOVE's value is currently 0, then that means there is no movement
* currently occurring.
*
+ * If {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true}.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative movement
* speeds.
*
@@ -3446,6 +4412,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
STEERING_WHEEL_DEPTH_MOVE =
@@ -3456,12 +4423,22 @@
* The maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All values between
* minInt32Value and maxInt32Value must be supported.
*
- * The maxInt32Value indicates the steering wheel being in the highest position.
* The minInt32Value indicates the steering wheel being in the lowest position.
*
+ * The maxInt32Value indicates the steering wheel being in the highest position.
+ *
* Values in between minInt32Value and maxInt32Value indicate a transition state between the
* lowest and highest positions.
*
+ * If {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true}.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative positions.
*
* This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
@@ -3470,6 +4447,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
STEERING_WHEEL_HEIGHT_POS =
@@ -3480,14 +4458,24 @@
* The maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All values between
* minInt32Value and maxInt32Value must be supported.
*
- * The maxInt32Value indicates the steering wheel moving upwards.
* The minInt32Value indicates the steering wheel moving downwards.
*
+ * The maxInt32Value indicates the steering wheel moving upwards.
+ *
* Larger integers, either positive or negative, indicate a faster movement speed. Once the
* steering wheel reaches the positional limit, the value must reset to 0. If
* STEERING_WHEEL_HEIGHT_MOVE's value is currently 0, then that means there is no movement
* currently occurring.
*
+ * If {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true}.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative movement
* speeds.
*
@@ -3497,6 +4485,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
STEERING_WHEEL_HEIGHT_MOVE =
@@ -3555,11 +4544,21 @@
* All integers between minInt32Value and maxInt32Value must be supported.
*
* The minInt32Value indicates that the glove box door is closed. The minInt32Value must be 0.
+ *
* The maxInt32Value indicates that the glove box door is in the fully open position.
*
* Values in between minInt32Value and maxInt32Value indicate a transition state between the
* closed and fully open positions.
*
+ * If {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}:
+ * {@code HasSupportedValueInfo.hasMinSupportedValue} and
+ * {@code HasSupportedValueInfo.hasMaxSupportedValue} must be {@code true}.
+ * {@code MinMaxSupportedValueResult.minSupportedValue} has the same meaning as minInt32Value.
+ * {@code MinMaxSupportedValueResult.maxSupportedValue} has the same meaning as maxInt32Value.
+ * All integers between minSupportedValue and maxSupportedValue must be supported.
+ * At boot, minInt32Value is equal to minSupportedValue, maxInt32Value is equal to
+ * maxSupportedValue.
+ *
* This property is not in any particular unit but in a specified range of relative positions.
*
* The area ID must match the seat by which the glove box is intended to be used (e.g. if the
@@ -3572,6 +4571,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
+ * @require_min_max_supported_value
* @version 2
*/
GLOVE_BOX_DOOR_POS =
@@ -4146,6 +5146,11 @@
* For the global area ID (0), the VehicleAreaConfig#supportedEnumValues must be defined unless
* all enum values of VehicleLightState are supported.
*
+ * If {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}:
+ * {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true}
+ * unless all enum values of VehicleLightState are supported.
+ * At boot, the supported values list is the same as supportedEnumValues.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleLightState
@@ -4168,6 +5173,11 @@
* For the global area ID (0), the VehicleAreaConfig#supportedEnumValues must be defined unless
* all enum values of VehicleLightSwitch are supported.
*
+ * If {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}:
+ * {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true}
+ * unless all enum values of VehicleLightSwitch are supported.
+ * At boot, the supported values list is the same as supportedEnumValues.
+ *
* This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
* implement it as VehiclePropertyAccess.READ only.
*
@@ -5187,13 +6197,16 @@
*
* 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.
*
+ * If {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}:
+ * {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true}
+ * unless all enum values of VehicleAutonomousState are supported.
+ * At boot, the supported values list is the same as supportedEnumValues.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleAutonomousState
@@ -5201,7 +6214,35 @@
*/
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.
*
@@ -5293,6 +6334,12 @@
* unless all states of both AutomaticEmergencyBrakingState (including OTHER, which is not
* recommended) and ErrorState are supported.
*
+ * If {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}:
+ * {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true}
+ * unless all states of both AutomaticEmergencyBrakingState (including OTHER, which is not
+ * recommended) and ErrorState are supported.
+ * At boot, the supported values list is the same as supportedEnumValues.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum AutomaticEmergencyBrakingState
@@ -5335,6 +6382,12 @@
* unless all states of both ForwardCollisionWarningState (including OTHER, which is not
* recommended) and ErrorState are supported.
*
+ * If {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}:
+ * {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true}
+ * unless all states of both ForwardCollisionWarningState (including OTHER, which is not
+ * recommended) and ErrorState are supported.
+ * At boot, the supported values list is the same as supportedEnumValues.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum ForwardCollisionWarningState
@@ -5377,6 +6430,12 @@
* unless all states of both BlindSpotWarningState (including OTHER, which is not
* recommended) and ErrorState are supported.
*
+ * If {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}:
+ * {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true}
+ * unless all states of both BlindSpotWarningState (including OTHER, which is not
+ * recommended) and ErrorState are supported.
+ * At boot, the supported values list is the same as supportedEnumValues.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum BlindSpotWarningState
@@ -5420,6 +6479,12 @@
* unless all states of both LaneDepartureWarningState (including OTHER, which is not
* recommended) and ErrorState are supported.
*
+ * If {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}:
+ * {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true}
+ * unless all states of both LaneDepartureWarningState (including OTHER, which is not
+ * recommended) and ErrorState are supported.
+ * At boot, the supported values list is the same as supportedEnumValues.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum LaneDepartureWarningState
@@ -5470,6 +6535,12 @@
* unless all states of both LaneKeepAssistState (including OTHER, which is not
* recommended) and ErrorState are supported.
*
+ * If {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}:
+ * {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true}
+ * unless all states of both LaneKeepAssistState (including OTHER, which is not
+ * recommended) and ErrorState are supported.
+ * At boot, the supported values list is the same as supportedEnumValues.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum LaneKeepAssistState
@@ -5522,6 +6593,11 @@
* For the global area ID (0), the VehicleAreaConfig#supportedEnumValues must be defined unless
* all enum values of LaneCenteringAssistCommand are supported.
*
+ * If {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}:
+ * {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true}
+ * unless all enum values of LaneCenteringAssistCommand are supported.
+ * At boot, the supported values list is the same as supportedEnumValues.
+ *
* When this property is not available because LCA is disabled (i.e.
* LANE_CENTERING_ASSIST_ENABLED is false), this property must return
* StatusCode#NOT_AVAILABLE_DISABLED. If LANE_CENTERING_ASSIST_STATE is implemented and the
@@ -5552,6 +6628,12 @@
* unless all states of both LaneCenteringAssistState (including OTHER, which is not
* recommended) and ErrorState are supported.
*
+ * If {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}:
+ * {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true}
+ * unless all states of both LaneCenteringAssistState (including OTHER, which is not
+ * recommended) and ErrorState are supported.
+ * At boot, the supported values list is the same as supportedEnumValues.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum LaneCenteringAssistState
@@ -5597,6 +6679,12 @@
* unless all states of EmergencyLaneKeepAssistState (including OTHER, which is not recommended)
* and ErrorState are supported.
*
+ * If {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}:
+ * {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true}
+ * unless all states of EmergencyLaneKeepAssistState (including OTHER, which is not recommended)
+ * and ErrorState are supported.
+ * At boot, the supported values list is the same as supportedEnumValues.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum EmergencyLaneKeepAssistState
@@ -5644,6 +6732,12 @@
* unless all states of CruiseControlType (including OTHER, which is not recommended) and
* ErrorState are supported.
*
+ * If {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}:
+ * {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true}
+ * unless all states of CruiseControlType (including OTHER, which is not recommended) and
+ * ErrorState are supported.
+ * At boot, the supported values list is the same as supportedEnumValues.
+ *
* Trying to write CruiseControlType#OTHER or an ErrorState to this property will throw an
* IllegalArgumentException.
*
@@ -5672,6 +6766,12 @@
* unless all states of CruiseControlState (including OTHER, which is not recommended) and
* ErrorState are supported.
*
+ * If {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}:
+ * {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true}
+ * unless all states of CruiseControlState (including OTHER, which is not recommended) and
+ * ErrorState are supported.
+ * At boot, the supported values list is the same as supportedEnumValues.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum CruiseControlState
@@ -5690,6 +6790,11 @@
* unless all states of CruiseControlState are supported. Any unsupported commands sent through
* this property must return StatusCode#INVALID_ARG.
*
+ * If {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}:
+ * {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true}
+ * unless all states of CruiseControlState are supported.
+ * At boot, the supported values list is the same as supportedEnumValues.
+ *
* When this property is not available because CC is disabled (i.e. CRUISE_CONTROL_ENABLED is
* false), this property must return StatusCode#NOT_AVAILABLE_DISABLED. If CRUISE_CONTROL_STATE
* is implemented and the state is set to an ErrorState value, then this property must return a
@@ -5830,6 +6935,12 @@
* unless all states of both HandsOnDetectionDriverState (including OTHER, which is not
* recommended) and ErrorState are supported.
*
+ * If {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}:
+ * {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true}
+ * unless all states of both HandsOnDetectionDriverState (including OTHER, which is not
+ * recommended) and ErrorState are supported.
+ * At boot, the supported values list is the same as supportedEnumValues.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum HandsOnDetectionDriverState
@@ -5853,6 +6964,12 @@
* unless all states of both HandsOnDetectionWarning (including OTHER, which is not recommended)
* and ErrorState are supported.
*
+ * If {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}:
+ * {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true}
+ * unless all states of both HandsOnDetectionWarning (including OTHER, which is not recommended)
+ * and ErrorState are supported.
+ * At boot, the supported values list is the same as supportedEnumValues.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum HandsOnDetectionWarning
@@ -5903,6 +7020,12 @@
* unless all states of both DriverDrowsinessAttentionState (including OTHER, which is not
* recommended) and ErrorState are supported.
*
+ * If {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}:
+ * {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true}
+ * unless all states of both DriverDrowsinessAttentionState (including OTHER, which is not
+ * recommended) and ErrorState are supported.
+ * At boot, the supported values list is the same as supportedEnumValues.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum DriverDrowsinessAttentionState
@@ -5950,6 +7073,12 @@
* unless all states of both DriverDrowsinessAttentionWarning (including OTHER, which is not
* recommended) and ErrorState are supported.
*
+ * If {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}:
+ * {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true}
+ * unless all states of both DriverDrowsinessAttentionWarning (including OTHER, which is not
+ * recommended) and ErrorState are supported.
+ * At boot, the supported values list is the same as supportedEnumValues.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum DriverDrowsinessAttentionWarning
@@ -5998,6 +7127,12 @@
* unless all states of both DriverDistractionState (including OTHER, which is not
* recommended) and ErrorState are supported.
*
+ * If {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}:
+ * {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true}
+ * unless all states of both DriverDistractionState (including OTHER, which is not
+ * recommended) and ErrorState are supported.
+ * At boot, the supported values list is the same as supportedEnumValues.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum DriverDistractionState
@@ -6044,6 +7179,12 @@
* unless all states of both DriverDistractionWarning (including OTHER, which is not
* recommended) and ErrorState are supported.
*
+ * If {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}:
+ * {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true}
+ * unless all states of both DriverDistractionWarning (including OTHER, which is not
+ * recommended) and ErrorState are supported.
+ * At boot, the supported values list is the same as supportedEnumValues.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum DriverDistractionWarning
@@ -6093,6 +7234,12 @@
* unless all states of both LowSpeedCollisionWarningState (including OTHER, which is not
* recommended) and ErrorState are supported.
*
+ * If {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}:
+ * {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true}
+ * unless all states of both LowSpeedCollisionWarningState (including OTHER, which is not
+ * recommended) and ErrorState are supported.
+ * At boot, the supported values list is the same as supportedEnumValues.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum LowSpeedCollisionWarningState
@@ -6136,6 +7283,12 @@
* unless all states of both CrossTrafficMonitoringWarningState (including OTHER, which is not
* recommended) and ErrorState are supported.
*
+ * If {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}:
+ * {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true}
+ * unless all states of both CrossTrafficMonitoringWarningState (including OTHER, which is not
+ * recommended) and ErrorState are supported.
+ * At boot, the supported values list is the same as supportedEnumValues.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum CrossTrafficMonitoringWarningState
@@ -6190,6 +7343,12 @@
* unless all states of both LowSpeedAutomaticEmergencyBrakingState (including OTHER, which is
* not recommended) and ErrorState are supported.
*
+ * If {@code HasSupportedValueInfo} for the global area ID (0) is not {@code null}:
+ * {@code HasSupportedValueInfo.hasSupportedValuesList} must be {@code true}
+ * unless all states of both LowSpeedAutomaticEmergencyBrakingState (including OTHER, which is
+ * not recommended) and ErrorState are supported.
+ * At boot, the supported values list is the same as supportedEnumValues.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum LowSpeedAutomaticEmergencyBrakingState
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 0000000..1915c4a
--- /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 a7c1808..53afef3 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 @@
"""
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 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
- msg = line
+ 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 + '\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 @@
@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 @@
@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 @@
@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<Integer> {3}s =
VehiclePropertyUtils.getIntegersFromDataEnums({0}.class);
@@ -194,11 +256,11 @@
}}
}}
}}
-""".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 @@
+ "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 9371453..7ab34f4 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 fb3c8cd..02a9830 100644
--- a/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp
+++ b/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp
@@ -1376,6 +1376,84 @@
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/biometrics/fingerprint/aidl/default/Fingerprint.cpp b/biometrics/fingerprint/aidl/default/Fingerprint.cpp
index 3055da1..143e231 100644
--- a/biometrics/fingerprint/aidl/default/Fingerprint.cpp
+++ b/biometrics/fingerprint/aidl/default/Fingerprint.cpp
@@ -50,6 +50,9 @@
} else if (sensorTypeProp == "udfps") {
mSensorType = FingerprintSensorType::UNDER_DISPLAY_OPTICAL;
mEngine = std::make_unique<FakeFingerprintEngineUdfps>();
+ } else if (sensorTypeProp == "udfps-us") {
+ mSensorType = FingerprintSensorType::UNDER_DISPLAY_ULTRASONIC;
+ mEngine = std::make_unique<FakeFingerprintEngineUdfps>();
} else if (sensorTypeProp == "side") {
mSensorType = FingerprintSensorType::POWER_BUTTON;
mEngine = std::make_unique<FakeFingerprintEngineSide>();
@@ -220,7 +223,7 @@
case FingerprintSensorType::UNDER_DISPLAY_OPTICAL:
return "udfps";
case FingerprintSensorType::UNDER_DISPLAY_ULTRASONIC:
- return "udfps";
+ return "udfps-us";
default:
return "unknown";
}
diff --git a/biometrics/fingerprint/aidl/default/api/android.hardware.biometrics.fingerprint.VirtualProps-current.txt b/biometrics/fingerprint/aidl/default/api/android.hardware.biometrics.fingerprint.VirtualProps-current.txt
index 8c02a68..ad6f9e0 100644
--- a/biometrics/fingerprint/aidl/default/api/android.hardware.biometrics.fingerprint.VirtualProps-current.txt
+++ b/biometrics/fingerprint/aidl/default/api/android.hardware.biometrics.fingerprint.VirtualProps-current.txt
@@ -173,6 +173,6 @@
type: String
access: ReadWrite
prop_name: "persist.vendor.fingerprint.virtual.type"
- enum_values: "default|rear|udfps|side"
+ enum_values: "default|rear|udfps|udfps-us|side"
}
}
diff --git a/biometrics/fingerprint/aidl/default/fingerprint.sysprop b/biometrics/fingerprint/aidl/default/fingerprint.sysprop
index eb33432..1d64c48 100644
--- a/biometrics/fingerprint/aidl/default/fingerprint.sysprop
+++ b/biometrics/fingerprint/aidl/default/fingerprint.sysprop
@@ -9,7 +9,7 @@
type: String
scope: Public
access: ReadWrite
- enum_values: "default|rear|udfps|side"
+ enum_values: "default|rear|udfps|udfps-us|side"
api_name: "type"
}
diff --git a/biometrics/fingerprint/aidl/default/tests/VirtualHalTest.cpp b/biometrics/fingerprint/aidl/default/tests/VirtualHalTest.cpp
index 8ffc96b..25abffe 100644
--- a/biometrics/fingerprint/aidl/default/tests/VirtualHalTest.cpp
+++ b/biometrics/fingerprint/aidl/default/tests/VirtualHalTest.cpp
@@ -152,7 +152,7 @@
} typeMap[] = {{FingerprintSensorType::REAR, "rear"},
{FingerprintSensorType::POWER_BUTTON, "side"},
{FingerprintSensorType::UNDER_DISPLAY_OPTICAL, "udfps"},
- {FingerprintSensorType::UNDER_DISPLAY_ULTRASONIC, "udfps"},
+ {FingerprintSensorType::UNDER_DISPLAY_ULTRASONIC, "udfps-us"},
{FingerprintSensorType::UNKNOWN, "unknown"}};
for (auto const& x : typeMap) {
mVhal->setType(x.type);
diff --git a/broadcastradio/aidl/Android.bp b/broadcastradio/aidl/Android.bp
index 82ee949..081bae3 100644
--- a/broadcastradio/aidl/Android.bp
+++ b/broadcastradio/aidl/Android.bp
@@ -51,12 +51,12 @@
},
],
- 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 0000000..7e02f70
--- /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 <name>-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 0000000..aa828d0
--- /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 <name>-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 0000000..f493e75
--- /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 <name>-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 0000000..dcf283a
--- /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 <name>-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 0000000..da08c9a
--- /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 <name>-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 0000000..2b89c92
--- /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 <name>-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 0000000..5c91abd
--- /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 <name>-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 0000000..8ce69b5
--- /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 <name>-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 0000000..fd0491d
--- /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 <name>-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 0000000..b303986
--- /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 <name>-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 0000000..a07e1c0
--- /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 <name>-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 0000000..4d4d78d
--- /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 <name>-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 997cdd7..dd57901 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 @@
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 0000000..a307ccc
--- /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.
+ *
+ * <p>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 0000000..b3f07b3
--- /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
+ *
+ * <p>(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 0000000..a24361a
--- /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.
+ *
+ * <p>(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 0000000..11f069e
--- /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
+ *
+ * <p>(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 0000000..ab2e6f7
--- /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.
+ *
+ * <p>(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.
+ *
+ * <p>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.
+ *
+ * <p>Urgency represents the time available to prepare for the alert.
+ */
+ AlertUrgency urgency;
+
+ /**
+ * The severity of the subject event of the alert info.
+ *
+ * <p>Severity represents the intensity of impact.
+ */
+ AlertSeverity severity;
+
+ /**
+ * The certainty of the subject event of the alert info.
+ *
+ * <p>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.
+ *
+ * <p>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 0000000..1dd4e2b
--- /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
+ *
+ * <p>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 0000000..acc11c4
--- /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
+ *
+ * <p>(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 0000000..8b0c917
--- /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
+ *
+ * <p>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 0000000..c7bfdbc
--- /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.
+ *
+ * <p>(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 0000000..9c9680b
--- /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
+ *
+ * <p>(see ITU-T X.1303 bis for more info).
+ */
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable Coordinate {
+ /**
+ * Latitude of the cooridinate.
+ *
+ * <p>Latitude is in the range of -90 to 90.
+ */
+ double latitude;
+
+ /**
+ * Longitude of the cooridinate.
+ *
+ * <p>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 0000000..ca98154
--- /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.
+ *
+ * <p>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.
+ *
+ * <p>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 0000000..12bd2cd
--- /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
+ *
+ * <p>(see ITU-T X.1303 bis for more info).
+ */
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable Polygon {
+ /**
+ * Cooridinates of points defining a polygon.
+ *
+ * <p>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 d4ccd01..0b5abe2 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 @@
* for example: paid-service=true; bitrate=320kbps.
*/
VendorKeyValue[] vendorInfo;
+
+ /**
+ * Emergency alert message.
+ *
+ * <p>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 4d6d81d..f19a4e5 100644
--- a/broadcastradio/aidl/default/BroadcastRadio.cpp
+++ b/broadcastradio/aidl/default/BroadcastRadio.cpp
@@ -17,11 +17,9 @@
#include "BroadcastRadio.h"
#include <broadcastradio-utils-aidl/Utils.h>
#include <broadcastradio-utils-aidl/UtilsV2.h>
+#include <broadcastradio-utils-aidl/UtilsV3.h>
#include "resources.h"
-#include <aidl/android/hardware/broadcastradio/IdentifierType.h>
-#include <aidl/android/hardware/broadcastradio/Result.h>
-
#include <android-base/logging.h>
#include <android-base/strings.h>
@@ -47,6 +45,8 @@
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 @@
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 @@
return false;
}
+static bool parseGeocode(int fd, const string& geocodeString, Geocode& parsedGeocode) {
+ vector<string> 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<Coordinate> coordinates;
+ vector<string> 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<string> areaEntryStrings = ::android::base::Split(areaString, "_");
+ for (const auto& areaEntryString : areaEntryStrings) {
+ vector<string> areaTypeValuePair = ::android::base::Split(areaEntryString, ":");
+ if (areaTypeValuePair.size() != 2) {
+ dprintf(fd, "Area is not of \"<TYPE>:<VALUE>\" 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 <TYPE> other than \"polygon\" and \"geocode\": %s\n",
+ areaTypeValuePair[0].c_str());
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool parseAreaListString(int fd, const string& areaListString,
+ vector<AlertArea>& parsedAlertAreas) {
+ if (EqualsIgnoreCase(areaListString, kAlertAreaDelimiter)) {
+ return true;
+ }
+ vector<string> 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 @@
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 @@
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 @@
void BroadcastRadio::handleProgramInfoUpdateRadioCallback(
ProgramInfo programInfo, const std::shared_ptr<ITunerCallback>& callback) {
callback->onCurrentProgramInfoChanged(programInfo);
+ {
+ lock_guard<mutex> lk(mMutex);
+ mCurrentProgramInfo = programInfo;
+ }
if (programInfo.selector.primaryId.type != IdentifierType::HD_STATION_ID_EXT) {
return;
}
@@ -285,12 +394,14 @@
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<mutex> lk(mMutex);
mIsTuneCompleted = true;
+ mCurrentProgramInfo = hdProgramInfoWithAudio;
};
lock_guard<mutex> lk(mMutex);
mTuningThread->schedule(audioAcquiredTask, cancelTask, kTuneDelayTimeMs);
@@ -481,7 +592,8 @@
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 @@
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 @@
LOG(DEBUG) << __func__ << ": cancelling current tuning operations...";
mTuningThread->cancelAll();
- if (mCurrentProgram.primaryId.type != IdentifierType::INVALID) {
+ if (mCurrentProgramSelector.primaryId.type != IdentifierType::INVALID) {
mIsTuneCompleted = true;
}
}
@@ -678,27 +790,25 @@
ScopedAStatus BroadcastRadio::setParameters(
[[maybe_unused]] const vector<VendorKeyValue>& parameters,
vector<VendorKeyValue>* returnParameters) {
- // TODO(b/243682330) Support vendor parameter functionality
*returnParameters = {};
return ScopedAStatus::ok();
}
ScopedAStatus BroadcastRadio::getParameters([[maybe_unused]] const vector<string>& keys,
vector<VendorKeyValue>* returnParameters) {
- // TODO(b/243682330) Support vendor parameter functionality
*returnParameters = {};
return ScopedAStatus::ok();
}
bool BroadcastRadio::adjustAmFmRangeLocked() {
bool hasBandBefore = mCurrentAmFmBandRange.has_value();
- if (!utils::hasAmFmFrequency(mCurrentProgram)) {
+ if (!utils::hasAmFmFrequency(mCurrentProgramSelector)) {
LOG(WARNING) << __func__ << ": current program does not has AMFM_FREQUENCY_KHZ identifier";
mCurrentAmFmBandRange.reset();
return hasBandBefore;
}
- int32_t freq = static_cast<int32_t>(utils::getAmFmFrequency(mCurrentProgram));
+ int32_t freq = static_cast<int32_t>(utils::getAmFmFrequency(mCurrentProgramSelector));
for (const auto& range : mAmFmConfig.ranges) {
if (range.lowerBound <= freq && range.upperBound >= freq) {
bool isBandChanged = hasBandBefore ? *mCurrentAmFmBandRange != range : true;
@@ -711,6 +821,24 @@
return !hasBandBefore;
}
+void BroadcastRadio::updateCurrentProgramInfoWithAlert(std::optional<Alert>& alert) {
+ std::shared_ptr<ITunerCallback> callback;
+ ProgramInfo currentProgramInfo;
+ {
+ lock_guard<mutex> 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<IAnnouncementListener>& listener,
const vector<AnnouncementType>& enabled, std::shared_ptr<ICloseHandle>* returnCloseHandle) {
@@ -745,6 +873,8 @@
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 +897,7 @@
} 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 +928,41 @@
"excludeModifications (string, should be either \"true\" or \"false\")\n");
dprintf(fd, "--stopProgramListUpdates: stop current pending program list updates\n");
dprintf(fd,
- "Note on <TYPE> for --startProgramList command: it is int for identifier type. "
+ "\t<TYPE>: it is int for identifier type. "
"Please see broadcastradio/aidl/android/hardware/broadcastradio/IdentifierType.aidl "
"for its definition.\n");
dprintf(fd,
- "Note on <VALUE> for --startProgramList command: it is long type for identifier value. "
+ "\t<VALUE>: it is long type for identifier value. "
"Please see broadcastradio/aidl/android/hardware/broadcastradio/IdentifierType.aidl "
"for its value.\n");
+ dprintf(fd,
+ "--simulateAlert <STATUS> <MESSAGE_TYPE> <CATEGORIES> <URGENCY> <SEVERITY> "
+ "<CERTAINTY> <DESCRIPTION> <LANGUAGE> <AREAS>: simulate emergency alert on current "
+ "program; if no arguments following \"--simulateAlert\", the default alert message"
+ "is applied.\n");
+ dprintf(fd, "\t<STATUS>: string representation of alert scope.\n");
+ dprintf(fd, "\t<MESSAGE_TYPE>: string representation of alert message type.\n");
+ dprintf(fd,
+ "\t<CATEGORIES>: string representation of alert categories separated by "
+ "\",\".\n");
+ dprintf(fd, "\t<URGENCY>: string representation of alert urgency type.\n");
+ dprintf(fd, "\t<SEVERITY>: string representation of alert severity type.\n");
+ dprintf(fd, "\t<CERTAINTY>: string representation of alert certainty type.\n");
+ dprintf(fd, "\t<DESCRIPTION>: description of alert message within quotation mark(\"\").\n");
+ dprintf(fd, "\t<LANGUAGE>: language code of alert message, \"null\" if unspecified.\n");
+ dprintf(fd,
+ "\t<AREAS>: <TYPE>:<VALUE>_<TYPE>:<VALUE>_...+<TYPE>:<VALUE>_<TYPE>:<VALUE>_... "
+ "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 "
+ "<TYPE> can be either \"polygon\" or \"geocode\". If <TYPE> is polygon, <VALUE> is a "
+ "series of coordinates of \"LATITUDE,LONGITUDE\" format separated by \",\"; if "
+ "<TYPE> is geocode, <VALUE> 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 +1196,71 @@
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<Alert> alertOpt;
+ if (numArgs == 1) {
+ alertOpt.emplace(createSampleAlert());
+ updateCurrentProgramInfoWithAlert(alertOpt);
+ return STATUS_OK;
+ }
+ if (numArgs != 10) {
+ dprintf(fd,
+ "Invalid number of arguments: please provide --simulateAlert "
+ "<STATUS> <MESSAGE_TYPE> <CATEGORIES> <URGENCY> "
+ "<SEVERITY> <CERTAINTY> <DESCRIPTION> <LANGUAGE> <AREAS>, 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<string> 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<AlertArea> 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 60ea907..a4cba3b 100644
--- a/broadcastradio/aidl/default/BroadcastRadio.h
+++ b/broadcastradio/aidl/default/BroadcastRadio.h
@@ -78,7 +78,8 @@
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<VirtualProgram> mProgramList GUARDED_BY(mMutex) = {};
std::optional<AmFmBandRange> mCurrentAmFmBandRange GUARDED_BY(mMutex);
std::shared_ptr<ITunerCallback> mCallback GUARDED_BY(mMutex);
@@ -99,6 +100,7 @@
void jumpToFirstSubChannelLocked(std::vector<VirtualProgram>::const_iterator& it) const
REQUIRES(mMutex);
bool isConfigFlagSetLocked(ConfigFlag flag) const REQUIRES(mMutex);
+ void updateCurrentProgramInfoWithAlert(std::optional<Alert>& alert);
binder_status_t cmdHelp(int fd) const;
binder_status_t cmdTune(int fd, const char** args, uint32_t numArgs);
@@ -107,6 +109,7 @@
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 4627ec9..508d8f1 100644
--- a/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp
+++ b/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp
@@ -16,6 +16,7 @@
#define EGMOCK_VERBOSE 1
+#include <aidl/android/hardware/broadcastradio/Alert.h>
#include <aidl/android/hardware/broadcastradio/BnAnnouncementListener.h>
#include <aidl/android/hardware/broadcastradio/BnTunerCallback.h>
#include <aidl/android/hardware/broadcastradio/ConfigFlag.h>
@@ -76,12 +77,13 @@
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 @@
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 @@
}
}
- 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<std::mutex> lk(mLock);
@@ -349,7 +380,7 @@
// 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<TunerCallbackImpl>(mAidlVersion);
@@ -1124,12 +1155,22 @@
* 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<bcutils::ProgramInfoSet> 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 d88081f..2245492 100644
--- a/broadcastradio/common/utilsaidl/Android.bp
+++ b/broadcastradio/common/utilsaidl/Android.bp
@@ -24,7 +24,7 @@
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 {
name: "android.hardware.broadcastradio@common-utils-aidl-lib-V2",
defaults: [
"BroadcastRadioUtilsDefaults",
@@ -47,7 +47,21 @@
],
}
-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 @@
],
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 a34ee10..f5b71b2 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 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 0000000..250e217
--- /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 <aidl/android/hardware/broadcastradio/ProgramInfo.h>
+
+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 3de1866..bfa93a5 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 <android-base/logging.h>
+#include <android-base/parsedouble.h>
#include <android-base/parseint.h>
#include <android-base/strings.h>
@@ -631,6 +632,10 @@
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 0000000..bf694da
--- /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 <android-base/strings.h>
+
+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 a9c1a1a..d7303fc 100644
--- a/camera/metadata/aidl/Android.bp
+++ b/camera/metadata/aidl/Android.bp
@@ -13,7 +13,7 @@
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 138101b..49243dd 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 @@
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 85eee08..588179f 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 @@
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 9321ec0..c3cb3f7 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 @@
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 @@
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 @@
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 2381605..69f0f5f 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 @@
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 0000000..eac2147
--- /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 <name>-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 0000000..36da888
--- /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 <name>-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 0000000..d16ef99
--- /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 <name>-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 0000000..8004b91
--- /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 <name>-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 0000000..abd06a7
--- /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 <name>-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 0000000..6cfdc02
--- /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 <name>-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 0000000..339d2fa
--- /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 <name>-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 0000000..7755069
--- /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 <name>-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 35dc1a9..11be18e 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 73bcc12..b7edaf2 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 @@
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 75e7915..b36a433 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 @@
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 236bcaf..8b2ac72 100644
--- a/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl
+++ b/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl
@@ -70,6 +70,38 @@
*/
ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
/**
+ * android.colorCorrection.colorTemperature [dynamic, int32, public]
+ *
+ * <p>Specifies the color temperature for CCT mode in Kelvin
+ * to adjust the white balance of the image.</p>
+ */
+ ANDROID_COLOR_CORRECTION_COLOR_TEMPERATURE,
+ /**
+ * android.colorCorrection.colorTint [dynamic, int32, public]
+ *
+ * <p>Specifies the color tint for CCT mode to adjust the white
+ * balance of the image.</p>
+ */
+ ANDROID_COLOR_CORRECTION_COLOR_TINT,
+ /**
+ * android.colorCorrection.colorTemperatureRange [static, int32[], public]
+ *
+ * <p>The range of supported color temperature values for
+ * ANDROID_COLOR_CORRECTION_COLOR_TEMPERATURE.</p>
+ *
+ * @see ANDROID_COLOR_CORRECTION_COLOR_TEMPERATURE
+ */
+ ANDROID_COLOR_CORRECTION_COLOR_TEMPERATURE_RANGE,
+ /**
+ * android.colorCorrection.availableModes [static, byte[], public]
+ *
+ * <p>List of color correction modes for ANDROID_COLOR_CORRECTION_MODE that are
+ * supported by this camera device.</p>
+ *
+ * @see ANDROID_COLOR_CORRECTION_MODE
+ */
+ ANDROID_COLOR_CORRECTION_AVAILABLE_MODES,
+ /**
* android.control.aeAntibandingMode [dynamic, enum, public]
*
* <p>The desired setting for the camera device's auto-exposure
@@ -502,6 +534,21 @@
*/
ANDROID_CONTROL_LOW_LIGHT_BOOST_STATE,
/**
+ * android.control.aePriorityMode [dynamic, enum, public]
+ *
+ * <p>Turn on AE priority mode.</p>
+ */
+ ANDROID_CONTROL_AE_PRIORITY_MODE = 65597,
+ /**
+ * android.control.aeAvailablePriorityModes [static, byte[], public]
+ *
+ * <p>List of auto-exposure priority modes for ANDROID_CONTROL_AE_PRIORITY_MODE
+ * that are supported by this camera device.</p>
+ *
+ * @see ANDROID_CONTROL_AE_PRIORITY_MODE
+ */
+ ANDROID_CONTROL_AE_AVAILABLE_PRIORITY_MODES,
+ /**
* android.demosaic.mode [controls, enum, system]
*
* <p>Controls the quality of the demosaicing
@@ -2346,6 +2393,62 @@
*/
ANDROID_HEIC_AVAILABLE_HEIC_STALL_DURATIONS_MAXIMUM_RESOLUTION,
/**
+ * android.heic.availableHeicUltraHdrStreamConfigurations [static, enum[], ndk_public]
+ *
+ * <p>The available HEIC (ISO/IEC 23008-12/24) UltraHDR stream
+ * configurations that this camera device supports
+ * (i.e. format, width, height, output/input stream).</p>
+ */
+ ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_STREAM_CONFIGURATIONS,
+ /**
+ * android.heic.availableHeicUltraHdrMinFrameDurations [static, int64[], ndk_public]
+ *
+ * <p>This lists the minimum frame duration for each
+ * format/size combination for HEIC UltraHDR output formats.</p>
+ */
+ ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_MIN_FRAME_DURATIONS,
+ /**
+ * android.heic.availableHeicUltraHdrStallDurations [static, int64[], ndk_public]
+ *
+ * <p>This lists the maximum stall duration for each
+ * output format/size combination for HEIC UltraHDR streams.</p>
+ */
+ ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_STALL_DURATIONS,
+ /**
+ * android.heic.availableHeicUltraHdrStreamConfigurationsMaximumResolution [static, enum[], ndk_public]
+ *
+ * <p>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
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+ *
+ * @see ANDROID_SENSOR_PIXEL_MODE
+ */
+ ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION,
+ /**
+ * android.heic.availableHeicUltraHdrMinFrameDurationsMaximumResolution [static, int64[], ndk_public]
+ *
+ * <p>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
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+ *
+ * @see ANDROID_SENSOR_PIXEL_MODE
+ */
+ ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION,
+ /**
+ * android.heic.availableHeicUltraHdrStallDurationsMaximumResolution [static, int64[], ndk_public]
+ *
+ * <p>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
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+ *
+ * @see ANDROID_SENSOR_PIXEL_MODE
+ */
+ ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_STALL_DURATIONS_MAXIMUM_RESOLUTION,
+ /**
* android.heic.info.supported [static, enum, system]
*
* <p>Whether this camera device can support identical set of stream combinations
@@ -2375,6 +2478,13 @@
*/
ANDROID_AUTOMOTIVE_LENS_FACING = CameraMetadataSectionStart.ANDROID_AUTOMOTIVE_LENS_START,
/**
+ * android.extension.nightModeIndicator [dynamic, enum, public]
+ *
+ * <p>Indicates when to activate Night Mode Camera Extension for high-quality
+ * still captures in low-light conditions.</p>
+ */
+ ANDROID_EXTENSION_NIGHT_MODE_INDICATOR = 2097154,
+ /**
* android.jpegr.availableJpegRStreamConfigurations [static, enum[], ndk_public]
*
* <p>The available Jpeg/R stream
@@ -2426,4 +2536,50 @@
* @see ANDROID_SENSOR_PIXEL_MODE
*/
ANDROID_JPEGR_AVAILABLE_JPEG_R_STALL_DURATIONS_MAXIMUM_RESOLUTION,
+ /**
+ * android.desktopEffects.capabilities [static, enum[], system]
+ *
+ * <p>List of special effects supported by the camera device.</p>
+ */
+ ANDROID_DESKTOP_EFFECTS_CAPABILITIES = CameraMetadataSectionStart.ANDROID_DESKTOP_EFFECTS_START,
+ /**
+ * android.desktopEffects.backgroundBlurModes [static, byte[], system]
+ *
+ * <p>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.</p>
+ *
+ * @see ANDROID_DESKTOP_EFFECTS_CAPABILITIES
+ */
+ ANDROID_DESKTOP_EFFECTS_BACKGROUND_BLUR_MODES,
+ /**
+ * android.desktopEffects.backgroundBlurMode [controls, enum, system]
+ *
+ * <p>Control how the background should be blurred. Supported modes are listed in
+ * ANDROID_DESKTOP_EFFECTS_BACKGROUND_BLUR_MODES by the camera device.</p>
+ *
+ * @see ANDROID_DESKTOP_EFFECTS_BACKGROUND_BLUR_MODES
+ */
+ ANDROID_DESKTOP_EFFECTS_BACKGROUND_BLUR_MODE,
+ /**
+ * android.desktopEffects.faceRetouchMode [controls, enum, system]
+ *
+ * <p>Whether to enable face retouch effect.</p>
+ */
+ ANDROID_DESKTOP_EFFECTS_FACE_RETOUCH_MODE,
+ /**
+ * android.desktopEffects.faceRetouchStrength [controls, byte, system]
+ *
+ * <p>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.</p>
+ *
+ * @see ANDROID_DESKTOP_EFFECTS_FACE_RETOUCH_MODE
+ */
+ ANDROID_DESKTOP_EFFECTS_FACE_RETOUCH_STRENGTH,
+ /**
+ * android.desktopEffects.portraitRelightMode [controls, enum, system]
+ *
+ * <p>Whether to enable portrait relighting effect.</p>
+ */
+ 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 2a51bfc..f12b6f6 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 @@
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 0000000..fd4f531
--- /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 0000000..e8b2180
--- /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 0000000..45cb78e
--- /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 0000000..d8c8101
--- /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 0000000..4a1d438
--- /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 0000000..3c3bdf5
--- /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 0000000..56761b9
--- /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 0000000..7fb19dc
--- /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 9fa4df2..ec61eec 100644
--- a/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp
+++ b/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp
@@ -118,7 +118,8 @@
ScopedAStatus ret = mProvider->setCallback(cb);
ASSERT_TRUE(ret.isOk());
ret = mProvider->setCallback(nullptr);
- ASSERT_EQ(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT), ret.getServiceSpecificError());
+ ASSERT_TRUE(static_cast<int32_t>(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 6ecd451..44af306 100644
--- a/camera/provider/aidl/vts/camera_aidl_test.cpp
+++ b/camera/provider/aidl/vts/camera_aidl_test.cpp
@@ -2590,8 +2590,7 @@
return ret;
}
- if (flags::session_hal_buf_manager() &&
- (bufferManagerType == BufferManagerType::SESSION && interfaceVersion >= 3)) {
+ if (bufferManagerType == BufferManagerType::SESSION && interfaceVersion >= 3) {
ret = session->configureStreamsV2(config, &aidl_return);
} else {
ret = session->configureStreams(config, halStreams);
@@ -2599,12 +2598,11 @@
if (!ret.isOk()) {
return ret;
}
- if (flags::session_hal_buf_manager() && bufferManagerType == BufferManagerType::SESSION) {
+ if (bufferManagerType == BufferManagerType::SESSION) {
*halStreams = std::move(aidl_return.halStreams);
}
for (const auto& halStream : *halStreams) {
- if ((flags::session_hal_buf_manager() && bufferManagerType == BufferManagerType::SESSION &&
- halStream.enableHalBufferManager) ||
+ if ((bufferManagerType == BufferManagerType::SESSION && halStream.enableHalBufferManager) ||
bufferManagerType == BufferManagerType::HAL) {
halBufManagedStreamIds->insert(halStream.id);
}
diff --git a/camera/provider/aidl/vts/device_cb.cpp b/camera/provider/aidl/vts/device_cb.cpp
index bfd1cd1..940b4af 100644
--- a/camera/provider/aidl/vts/device_cb.cpp
+++ b/camera/provider/aidl/vts/device_cb.cpp
@@ -421,12 +421,19 @@
}
for (const auto& buffer : results.outputBuffers) {
+ std::unique_lock<std::mutex> l(mLock);
CameraAidlTest::InFlightRequest::StreamBufferAndTimestamp streamBufferAndTimestamp;
- auto outstandingBuffers = mUseHalBufManager ? mOutstandingBufferIds :
+ auto& outstandingBuffers = mUseHalBufManager ? mOutstandingBufferIds :
request->mOutstandingBufferIds;
auto bufferId = mUseHalBufManager ? buffer.bufferId : results.frameNumber;
- auto outputBuffer = outstandingBuffers.empty() ? ::android::makeFromAidl(buffer.buffer) :
- outstandingBuffers[buffer.streamId][bufferId];
+ const native_handle_t *outputBuffer = nullptr;
+ if (outstandingBuffers.empty()) {
+ outputBuffer = ::android::makeFromAidl(buffer.buffer);
+ } else if (outstandingBuffers[buffer.streamId].contains(bufferId)) {
+ outputBuffer = outstandingBuffers[buffer.streamId][bufferId];
+ } else {
+ ALOGV("%s: Invalid bufferId: %" PRId64, __FUNCTION__, bufferId);
+ }
streamBufferAndTimestamp.buffer = {buffer.streamId,
bufferId,
outputBuffer,
diff --git a/compatibility_matrices/compatibility_matrix.202504.xml b/compatibility_matrices/compatibility_matrix.202504.xml
index 8338e13..8d5a50a 100644
--- a/compatibility_matrices/compatibility_matrix.202504.xml
+++ b/compatibility_matrices/compatibility_matrix.202504.xml
@@ -171,7 +171,7 @@
</hal>
<hal format="aidl">
<name>android.hardware.broadcastradio</name>
- <version>1-2</version>
+ <version>1-3</version>
<interface>
<name>IBroadcastRadio</name>
<regex-instance>.*</regex-instance>
@@ -233,7 +233,7 @@
</hal>
<hal format="aidl">
<name>android.hardware.gnss</name>
- <version>2-4</version>
+ <version>2-5</version>
<interface>
<name>IGnss</name>
<instance>default</instance>
@@ -257,7 +257,7 @@
</hal>
<hal format="aidl">
<name>android.hardware.health</name>
- <version>3</version>
+ <version>3-4</version>
<interface>
<name>IHealth</name>
<instance>default</instance>
@@ -380,7 +380,7 @@
</hal>
<hal format="aidl">
<name>android.hardware.power</name>
- <version>5</version>
+ <version>5-6</version>
<interface>
<name>IPower</name>
<instance>default</instance>
@@ -543,7 +543,7 @@
</hal>
<hal format="aidl">
<name>android.hardware.sensors</name>
- <version>2</version>
+ <version>2-3</version>
<interface>
<name>ISensors</name>
<instance>default</instance>
@@ -567,7 +567,7 @@
</hal>
<hal format="aidl">
<name>android.hardware.thermal</name>
- <version>2</version>
+ <version>3</version>
<interface>
<name>IThermal</name>
<instance>default</instance>
@@ -607,7 +607,7 @@
</hal>
<hal format="aidl">
<name>android.hardware.tv.tuner</name>
- <version>1-2</version>
+ <version>1-3</version>
<interface>
<name>ITuner</name>
<instance>default</instance>
@@ -615,7 +615,7 @@
</hal>
<hal format="aidl">
<name>android.hardware.tv.input</name>
- <version>1-2</version>
+ <version>1-3</version>
<interface>
<name>ITvInput</name>
<instance>default</instance>
@@ -671,7 +671,7 @@
</hal>
<hal format="aidl" updatable-via-apex="true">
<name>android.hardware.wifi</name>
- <version>1-2</version>
+ <version>2-3</version>
<interface>
<name>IWifi</name>
<instance>default</instance>
@@ -701,6 +701,14 @@
<instance>default</instance>
</interface>
</hal>
+ <hal format="aidl" optional="true">
+ <name>android.hardware.tv.mediaquality</name>
+ <version>1</version>
+ <interface>
+ <name>IMediaQuality</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
<!-- The native mapper HAL must exist on the device -->
<hal format="native">
<name>mapper</name>
diff --git a/compatibility_matrices/exclude/fcm_exclude.cpp b/compatibility_matrices/exclude/fcm_exclude.cpp
index 1d5b2bd..57e039c 100644
--- a/compatibility_matrices/exclude/fcm_exclude.cpp
+++ b/compatibility_matrices/exclude/fcm_exclude.cpp
@@ -140,6 +140,7 @@
"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/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHub.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHub.aidl
index 93b8ff5..2940745 100644
--- a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHub.aidl
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHub.aidl
@@ -51,14 +51,6 @@
void sendMessageDeliveryStatusToHub(in int contextHubId, in android.hardware.contexthub.MessageDeliveryStatus messageDeliveryStatus);
List<android.hardware.contexthub.HubInfo> getHubs();
List<android.hardware.contexthub.EndpointInfo> getEndpoints();
- void registerEndpoint(in android.hardware.contexthub.EndpointInfo endpoint);
- void unregisterEndpoint(in android.hardware.contexthub.EndpointInfo endpoint);
- void registerEndpointCallback(in android.hardware.contexthub.IEndpointCallback callback);
- int[] requestSessionIdRange(int size);
- void openEndpointSession(int sessionId, in android.hardware.contexthub.EndpointId destination, in android.hardware.contexthub.EndpointId initiator, in @nullable String serviceDescriptor);
- void sendMessageToEndpoint(int sessionId, in android.hardware.contexthub.Message msg);
- void sendMessageDeliveryStatusToEndpoint(int sessionId, in android.hardware.contexthub.MessageDeliveryStatus msgStatus);
- void closeEndpointSession(int sessionId, in android.hardware.contexthub.Reason reason);
- void endpointSessionOpenComplete(int sessionId);
+ @PropagateAllowBlocking android.hardware.contexthub.IEndpointCommunication registerEndpointHub(in android.hardware.contexthub.IEndpointCallback callback, in android.hardware.contexthub.HubInfo hubInfo);
const int EX_CONTEXT_HUB_UNSPECIFIED = (-1) /* -1 */;
}
diff --git a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IEndpointCommunication.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IEndpointCommunication.aidl
new file mode 100644
index 0000000..8742415
--- /dev/null
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IEndpointCommunication.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 <name>-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.contexthub;
+@VintfStability
+interface IEndpointCommunication {
+ void registerEndpoint(in android.hardware.contexthub.EndpointInfo endpoint);
+ void unregisterEndpoint(in android.hardware.contexthub.EndpointInfo endpoint);
+ int[2] requestSessionIdRange(int size);
+ void openEndpointSession(int sessionId, in android.hardware.contexthub.EndpointId destination, in android.hardware.contexthub.EndpointId initiator, in @nullable String serviceDescriptor);
+ void sendMessageToEndpoint(int sessionId, in android.hardware.contexthub.Message msg);
+ void sendMessageDeliveryStatusToEndpoint(int sessionId, in android.hardware.contexthub.MessageDeliveryStatus msgStatus);
+ void closeEndpointSession(int sessionId, in android.hardware.contexthub.Reason reason);
+ void endpointSessionOpenComplete(int sessionId);
+ void unregister();
+}
diff --git a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/Reason.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/Reason.aidl
index a315438..b285337 100644
--- a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/Reason.aidl
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/Reason.aidl
@@ -43,4 +43,5 @@
ENDPOINT_GONE,
ENDPOINT_CRASHED,
HUB_RESET,
+ PERMISSION_DENIED,
}
diff --git a/contexthub/aidl/android/hardware/contexthub/IContextHub.aidl b/contexthub/aidl/android/hardware/contexthub/IContextHub.aidl
index 24192a1..3fb452c 100644
--- a/contexthub/aidl/android/hardware/contexthub/IContextHub.aidl
+++ b/contexthub/aidl/android/hardware/contexthub/IContextHub.aidl
@@ -18,19 +18,16 @@
import android.hardware.contexthub.ContextHubInfo;
import android.hardware.contexthub.ContextHubMessage;
-import android.hardware.contexthub.EndpointId;
import android.hardware.contexthub.EndpointInfo;
import android.hardware.contexthub.HostEndpointInfo;
import android.hardware.contexthub.HubInfo;
import android.hardware.contexthub.IContextHubCallback;
import android.hardware.contexthub.IEndpointCallback;
-import android.hardware.contexthub.Message;
+import android.hardware.contexthub.IEndpointCommunication;
import android.hardware.contexthub.MessageDeliveryStatus;
import android.hardware.contexthub.NanSessionStateUpdate;
import android.hardware.contexthub.NanoappBinary;
import android.hardware.contexthub.NanoappInfo;
-import android.hardware.contexthub.Reason;
-import android.hardware.contexthub.Service;
import android.hardware.contexthub.Setting;
@VintfStability
@@ -271,128 +268,22 @@
List<EndpointInfo> getEndpoints();
/**
- * Publishes an endpoint from the calling side (e.g. Android). Endpoints must be registered
- * prior to starting a session.
+ * Registers a new hub for endpoint communication which will receive events for its endpoints
+ * over the given callback. Returns an interface for the hub to register endpoints, start
+ * sessions, and send messages.
+ *
+ * It is valid for the same callback to be registered for multiple hubs, as the
+ * IEndpointCallback events provide sufficient information to determine which hub the event is
+ * intended for:
+ * * session ids are allocated to a specific hub and are unique
+ * * endpoints are identified by hub and endpoint id
+ *
+ * @param callback Interface to send endpoint events targeting the caller
+ * @param hubInfo Details of the hub being registered
+ * @return Interface for the hub to interact with other endpoint hubs
+ *
+ * @throws EX_ILLEGAL_STATE if hubInfo.hubId has already been registered
*/
- void registerEndpoint(in EndpointInfo endpoint);
-
- /**
- * Teardown an endpoint from the calling side (e.g. Android). This endpoint must have already
- * been published via registerEndpoint().
- */
- void unregisterEndpoint(in EndpointInfo endpoint);
-
- /**
- * Attaches a callback interface to receive events targeted at endpoints registered by the
- * caller.
- */
- void registerEndpointCallback(in IEndpointCallback callback);
-
- /**
- * Request a range of session IDs for the caller to use when initiating sessions. This may be
- * called more than once, but typical usage is to request a large enough range to accommodate
- * the maximum expected number of concurrent sessions, but not overly large as to limit other
- * clients.
- *
- * @param size The number of sessionId reserved for host-initiated sessions. This number should
- * be less than or equal to 1024.
- *
- * @return An array with two elements representing the smallest and largest possible session id
- * available for host.
- *
- * @throws EX_ILLEGAL_ARGUMENT if the size is invalid.
- * @throws EX_SERVICE_SPECIFIC if the id range requested cannot be allocated.
- */
- int[] requestSessionIdRange(int size);
-
- /**
- * Request to open a session for communication between an endpoint previously registered by the
- * caller and a target endpoint found in getEndpoints(), optionally scoped to a service
- * published by the target endpoint.
- *
- * Upon returning from this function, the session is in pending state, and the final result will
- * be given by an asynchronous call to onEndpointSessionOpenComplete() on success, or
- * onCloseEndpointSession() on failure.
- *
- * @param sessionId Caller-allocated session identifier, which must be unique across all active
- * sessions, and must fall in a range allocated via requestSessionIdRange().
- * @param destination The EndpointId representing the destination side of the session.
- * @param initiator The EndpointId representing the initiating side of the session, which
- * must've already been published through registerEndpoint().
- * @param serviceDescriptor Descriptor for the service specification for scoping this session
- * (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
- * - EX_CONTEXT_HUB_UNSPECIFIED if the request failed for other reasons.
- */
- void openEndpointSession(int sessionId, in EndpointId destination, in EndpointId initiator,
- in @nullable String serviceDescriptor);
-
- /**
- * Send a message from one endpoint to another on the (currently open) session.
- *
- * @param sessionId The integer representing the communication session, previously set in
- * openEndpointSession() or onEndpointSessionOpenRequest().
- * @param msg The Message object representing a message to endpoint from the endpoint on host.
- *
- * @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
- * - EX_CONTEXT_HUB_UNSPECIFIED if the request failed for other reasons.
- */
- void sendMessageToEndpoint(int sessionId, in Message msg);
-
- /**
- * Sends a message delivery status to the endpoint in response to receiving a Message with flag
- * FLAG_REQUIRES_DELIVERY_STATUS. Each message with the flag should have a MessageDeliveryStatus
- * response. This method sends the message delivery status back to the remote endpoint for a
- * session.
- *
- * @param sessionId The integer representing the communication session, previously set in
- * openEndpointSession() or onEndpointSessionOpenRequest().
- * @param msgStatus The MessageDeliveryStatus object representing the delivery status for a
- * specific message (identified by the sequenceNumber) within the session.
- *
- * @throws EX_UNSUPPORTED_OPERATION if ContextHubInfo.supportsReliableMessages is false for
- * the hub involved in this session.
- */
- void sendMessageDeliveryStatusToEndpoint(int sessionId, in MessageDeliveryStatus msgStatus);
-
- /**
- * Closes a session previously opened by openEndpointSession() or requested via
- * onEndpointSessionOpenRequest(). Processing of session closure must be ordered/synchronized
- * with message delivery, such that if this session was open, any messages previously passed to
- * sendMessageToEndpoint() that are still in-flight must still be delivered before the session
- * is closed. Any in-flight messages to the endpoint that requested to close the session will
- * not be delivered.
- *
- * @param sessionId The integer representing the communication session, previously set in
- * openEndpointSession() or onEndpointSessionOpenRequest().
- * @param reason The reason for this close endpoint session request.
- *
- * @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
- * - EX_CONTEXT_HUB_UNSPECIFIED if the request failed for other reasons.
- */
- void closeEndpointSession(int sessionId, in Reason reason);
-
- /**
- * Notifies the HAL that the session requested by onEndpointSessionOpenRequest is ready to use.
- *
- * @param sessionId The integer representing the communication session, previously set in
- * onEndpointSessionOpenRequest(). This id is assigned by the HAL.
- *
- * @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
- * - EX_CONTEXT_HUB_UNSPECIFIED if the request failed for other reasons.
- */
- void endpointSessionOpenComplete(int sessionId);
+ @PropagateAllowBlocking
+ IEndpointCommunication registerEndpointHub(in IEndpointCallback callback, in HubInfo hubInfo);
}
diff --git a/contexthub/aidl/android/hardware/contexthub/IEndpointCommunication.aidl b/contexthub/aidl/android/hardware/contexthub/IEndpointCommunication.aidl
new file mode 100644
index 0000000..e5045ba
--- /dev/null
+++ b/contexthub/aidl/android/hardware/contexthub/IEndpointCommunication.aidl
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.contexthub;
+
+import android.hardware.contexthub.EndpointId;
+import android.hardware.contexthub.EndpointInfo;
+import android.hardware.contexthub.IEndpointCallback;
+import android.hardware.contexthub.Message;
+import android.hardware.contexthub.MessageDeliveryStatus;
+import android.hardware.contexthub.Reason;
+import android.hardware.contexthub.Service;
+
+@VintfStability
+interface IEndpointCommunication {
+ /**
+ * Publishes an endpoint from the calling side (e.g. Android). Endpoints must be registered
+ * prior to starting a session.
+ */
+ void registerEndpoint(in EndpointInfo endpoint);
+
+ /**
+ * Teardown an endpoint from the calling side (e.g. Android). This endpoint must have already
+ * been published via registerEndpoint().
+ */
+ void unregisterEndpoint(in EndpointInfo endpoint);
+
+ /**
+ * Request a range of session IDs for the caller to use when initiating sessions. This may be
+ * called more than once, but typical usage is to request a large enough range to accommodate
+ * the maximum expected number of concurrent sessions, but not overly large as to limit other
+ * clients.
+ *
+ * @param size The number of sessionId reserved for host-initiated sessions. This number should
+ * be less than or equal to 1024.
+ *
+ * @return An array with two elements representing the smallest and largest possible session id
+ * available for host.
+ *
+ * @throws EX_ILLEGAL_ARGUMENT if the size is invalid.
+ * @throws EX_SERVICE_SPECIFIC if the id range requested cannot be allocated.
+ */
+ int[2] requestSessionIdRange(int size);
+
+ /**
+ * Request to open a session for communication between an endpoint previously registered by the
+ * caller and a target endpoint found in getEndpoints(), optionally scoped to a service
+ * published by the target endpoint.
+ *
+ * Upon returning from this function, the session is in pending state, and the final result will
+ * be given by an asynchronous call to onEndpointSessionOpenComplete() on success, or
+ * onCloseEndpointSession() on failure.
+ *
+ * @param sessionId Caller-allocated session identifier, which must be unique across all active
+ * sessions, and must fall in a range allocated via requestSessionIdRange().
+ * @param destination The EndpointId representing the destination side of the session.
+ * @param initiator The EndpointId representing the initiating side of the session, which
+ * must've already been published through registerEndpoint().
+ * @param serviceDescriptor Descriptor for the service specification for scoping this session
+ * (nullable). Null indicates a fully custom marshalling scheme. The value should match
+ * a published descriptor for both destination and initiator.
+ *
+ * @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
+ * - EX_CONTEXT_HUB_UNSPECIFIED if the request failed for other reasons.
+ */
+ void openEndpointSession(int sessionId, in EndpointId destination, in EndpointId initiator,
+ in @nullable String serviceDescriptor);
+
+ /**
+ * Send a message from one endpoint to another on the (currently open) session.
+ *
+ * @param sessionId The integer representing the communication session, previously set in
+ * openEndpointSession() or onEndpointSessionOpenRequest().
+ * @param msg The Message object representing a message to endpoint from the endpoint on host.
+ *
+ * @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
+ * - EX_CONTEXT_HUB_UNSPECIFIED if the request failed for other reasons.
+ */
+ void sendMessageToEndpoint(int sessionId, in Message msg);
+
+ /**
+ * Sends a message delivery status to the endpoint in response to receiving a Message with flag
+ * FLAG_REQUIRES_DELIVERY_STATUS. Each message with the flag should have a MessageDeliveryStatus
+ * response. This method sends the message delivery status back to the remote endpoint for a
+ * session.
+ *
+ * @param sessionId The integer representing the communication session, previously set in
+ * openEndpointSession() or onEndpointSessionOpenRequest().
+ * @param msgStatus The MessageDeliveryStatus object representing the delivery status for a
+ * specific message (identified by the sequenceNumber) within the session.
+ *
+ * @throws EX_UNSUPPORTED_OPERATION if ContextHubInfo.supportsReliableMessages is false for
+ * the hub involved in this session.
+ */
+ void sendMessageDeliveryStatusToEndpoint(int sessionId, in MessageDeliveryStatus msgStatus);
+
+ /**
+ * Closes a session previously opened by openEndpointSession() or requested via
+ * onEndpointSessionOpenRequest(). Processing of session closure must be ordered/synchronized
+ * with message delivery, such that if this session was open, any messages previously passed to
+ * sendMessageToEndpoint() that are still in-flight must still be delivered before the session
+ * is closed. Any in-flight messages to the endpoint that requested to close the session will
+ * not be delivered.
+ *
+ * @param sessionId The integer representing the communication session, previously set in
+ * openEndpointSession() or onEndpointSessionOpenRequest().
+ * @param reason The reason for this close endpoint session request.
+ *
+ * @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
+ * - EX_CONTEXT_HUB_UNSPECIFIED if the request failed for other reasons.
+ */
+ void closeEndpointSession(int sessionId, in Reason reason);
+
+ /**
+ * Notifies the HAL that the session requested by onEndpointSessionOpenRequest is ready to use.
+ *
+ * @param sessionId The integer representing the communication session, previously set in
+ * onEndpointSessionOpenRequest(). This id is assigned by the HAL.
+ *
+ * @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
+ * - EX_CONTEXT_HUB_UNSPECIFIED if the request failed for other reasons.
+ */
+ void endpointSessionOpenComplete(int sessionId);
+
+ /**
+ * Unregisters this hub. Subsequent calls on this interface will fail.
+ *
+ * @throws EX_ILLEGAL_STATE if this interface was already unregistered.
+ */
+ void unregister();
+}
diff --git a/contexthub/aidl/android/hardware/contexthub/Reason.aidl b/contexthub/aidl/android/hardware/contexthub/Reason.aidl
index 65d9f8a..8a86f94 100644
--- a/contexthub/aidl/android/hardware/contexthub/Reason.aidl
+++ b/contexthub/aidl/android/hardware/contexthub/Reason.aidl
@@ -63,4 +63,9 @@
* Hub was reset or is resetting.
*/
HUB_RESET,
+
+ /**
+ * The caller does not have the required permissions.
+ */
+ PERMISSION_DENIED,
}
diff --git a/contexthub/aidl/android/hardware/contexthub/Service.aidl b/contexthub/aidl/android/hardware/contexthub/Service.aidl
index fd748c3..e107193 100644
--- a/contexthub/aidl/android/hardware/contexthub/Service.aidl
+++ b/contexthub/aidl/android/hardware/contexthub/Service.aidl
@@ -16,6 +16,17 @@
package android.hardware.contexthub;
+/**
+ * Services that are provided by an endpoint.
+ *
+ * To support testing, the following service is defined here:
+ * 1. Test echo service:
+ * - This service responds to a received message back to the sender with a
+ * message with identical content as the received message.
+ * - Format: Service::RpcFormat::CUSTOM
+ * - Service descriptor: android.hardware.contexthub.test.EchoService
+ * - Major version: 1
+ */
@VintfStability
parcelable Service {
/**
diff --git a/contexthub/aidl/default/Android.bp b/contexthub/aidl/default/Android.bp
index da173f9..d4d03e4 100644
--- a/contexthub/aidl/default/Android.bp
+++ b/contexthub/aidl/default/Android.bp
@@ -30,6 +30,7 @@
shared_libs: [
"libbase",
"libbinder_ndk",
+ "liblog",
"android.hardware.contexthub-V4-ndk",
],
export_include_dirs: ["include"],
@@ -51,6 +52,7 @@
shared_libs: [
"libbase",
"libbinder_ndk",
+ "liblog",
"android.hardware.contexthub-V4-ndk",
],
static_libs: [
@@ -87,5 +89,6 @@
prebuilts: [
"android.hardware.contexthub-service.example.rc",
"contexthub-default.xml",
+ "android.hardware.context_hub.prebuilt.xml",
],
}
diff --git a/contexthub/aidl/default/ContextHub.cpp b/contexthub/aidl/default/ContextHub.cpp
index 5713a1b..433617e 100644
--- a/contexthub/aidl/default/ContextHub.cpp
+++ b/contexthub/aidl/default/ContextHub.cpp
@@ -15,26 +15,62 @@
*/
#include "contexthub-impl/ContextHub.h"
+#include "aidl/android/hardware/contexthub/IContextHubCallback.h"
-namespace aidl::android::hardware::contexthub {
+#ifndef LOG_TAG
+#define LOG_TAG "CHRE"
+#endif
+
+#include <inttypes.h>
+#include <log/log.h>
+#include <optional>
+#include <thread>
using ::ndk::ScopedAStatus;
-ScopedAStatus ContextHub::getContextHubs(std::vector<ContextHubInfo>* out_contextHubInfos) {
- ContextHubInfo hub = {};
- hub.name = "Mock Context Hub";
- hub.vendor = "AOSP";
- hub.toolchain = "n/a";
- hub.id = kMockHubId;
- hub.peakMips = 1;
- hub.maxSupportedMessageLengthBytes = 4096;
- hub.chrePlatformId = UINT64_C(0x476f6f6754000000);
- hub.chreApiMajorVersion = 1;
- hub.chreApiMinorVersion = 6;
- hub.supportsReliableMessages = false;
+namespace aidl::android::hardware::contexthub {
- out_contextHubInfos->push_back(hub);
+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,
+ },
+};
+
+//! Mutex used to ensure callbacks are called after the initial function returns.
+std::mutex gCallbackMutex;
+
+} // anonymous namespace
+
+ScopedAStatus ContextHub::getContextHubs(std::vector<ContextHubInfo>* /* out_contextHubInfos */) {
return ScopedAStatus::ok();
}
@@ -112,7 +148,14 @@
}
}
-ScopedAStatus ContextHub::setTestMode(bool /* enable */) {
+ScopedAStatus ContextHub::setTestMode(bool enable) {
+ if (enable) {
+ std::lock_guard lock(mHostHubsLock);
+ for (auto& [id, hub] : mIdToHostHub) {
+ hub->mActive = false;
+ }
+ mIdToHostHub.clear();
+ }
return ScopedAStatus::ok();
}
@@ -137,82 +180,288 @@
}
ScopedAStatus ContextHub::getHubs(std::vector<HubInfo>* _aidl_return) {
- ContextHubInfo hub = {};
- hub.name = "Mock Context Hub";
- hub.vendor = "AOSP";
- hub.toolchain = "n/a";
- hub.id = kMockHubId;
- hub.peakMips = 1;
- hub.maxSupportedMessageLengthBytes = 4096;
- hub.chrePlatformId = UINT64_C(0x476f6f6754000000);
- hub.chreApiMajorVersion = 1;
- hub.chreApiMinorVersion = 6;
- hub.supportsReliableMessages = false;
-
- HubInfo hubInfo1 = {};
- hubInfo1.hubId = hub.chrePlatformId;
- hubInfo1.hubDetails = HubInfo::HubDetails::make<HubInfo::HubDetails::Tag::contextHubInfo>(hub);
+ if (_aidl_return == nullptr) {
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
VendorHubInfo vendorHub = {};
vendorHub.name = "Mock Vendor Hub";
vendorHub.version = 42;
- HubInfo hubInfo2 = {};
- hubInfo1.hubId = UINT64_C(0x1234567812345678);
+ HubInfo hubInfo1 = {};
+ hubInfo1.hubId = kMockVendorHubId;
hubInfo1.hubDetails =
HubInfo::HubDetails::make<HubInfo::HubDetails::Tag::vendorHubInfo>(vendorHub);
+ VendorHubInfo vendorHub2 = {};
+ vendorHub2.name = "Mock Vendor Hub 2";
+ vendorHub2.version = 24;
+
+ HubInfo hubInfo2 = {};
+ hubInfo2.hubId = kMockVendorHub2Id;
+ hubInfo2.hubDetails =
+ HubInfo::HubDetails::make<HubInfo::HubDetails::Tag::vendorHubInfo>(vendorHub2);
+
_aidl_return->push_back(hubInfo1);
_aidl_return->push_back(hubInfo2);
return ScopedAStatus::ok();
};
-ScopedAStatus ContextHub::getEndpoints(std::vector<EndpointInfo>* /* _aidl_return */) {
- return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ScopedAStatus ContextHub::getEndpoints(std::vector<EndpointInfo>* _aidl_return) {
+ if (_aidl_return == nullptr) {
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+
+ Service echoService;
+ echoService.format = Service::RpcFormat::CUSTOM;
+ echoService.serviceDescriptor = "android.hardware.contexthub.test.EchoService";
+ 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::registerEndpointHub(
+ const std::shared_ptr<IEndpointCallback>& in_callback, const HubInfo& in_hubInfo,
+ std::shared_ptr<IEndpointCommunication>* _aidl_return) {
+ std::lock_guard lock(mHostHubsLock);
+ if (mIdToHostHub.count(in_hubInfo.hubId)) {
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ auto hub = ndk::SharedRefBase::make<HubInterface>(*this, in_callback, in_hubInfo);
+ mIdToHostHub.insert({in_hubInfo.hubId, hub});
+ *_aidl_return = std::move(hub);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus ContextHub::HubInterface::registerEndpoint(const EndpointInfo& in_endpoint) {
+ if (!mActive) {
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ std::unique_lock<std::mutex> 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::HubInterface::unregisterEndpoint(const EndpointInfo& in_endpoint) {
+ if (!mActive) {
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ std::unique_lock<std::mutex> 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<IEndpointCallback>& /* in_callback */) {
- return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ScopedAStatus ContextHub::HubInterface::requestSessionIdRange(
+ int32_t in_size, std::array<int32_t, 2>* _aidl_return) {
+ if (!mActive) {
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ constexpr int32_t kMaxSize = 1024;
+ if (in_size > kMaxSize || _aidl_return == nullptr) {
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+
+ uint16_t base = 0;
+ {
+ std::lock_guard lock(mHal.mHostHubsLock);
+ if (static_cast<int32_t>(USHRT_MAX) - mHal.mNextSessionIdBase + 1 < in_size) {
+ return ScopedAStatus::fromServiceSpecificError(EX_CONTEXT_HUB_UNSPECIFIED);
+ }
+ base = mHal.mNextSessionIdBase;
+ mHal.mNextSessionIdBase += in_size;
+ }
+
+ {
+ std::lock_guard<std::mutex> lock(mEndpointMutex);
+ (*_aidl_return)[0] = mBaseSessionId = base;
+ (*_aidl_return)[1] = mMaxSessionId = base + (in_size - 1);
+ }
+ return ScopedAStatus::ok();
};
-ScopedAStatus ContextHub::requestSessionIdRange(int32_t /* in_size */,
- std::vector<int32_t>* /* _aidl_return */) {
- return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ScopedAStatus ContextHub::HubInterface::openEndpointSession(
+ int32_t in_sessionId, const EndpointId& in_destination, const EndpointId& in_initiator,
+ const std::optional<std::string>& in_serviceDescriptor) {
+ if (!mActive) {
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ // We are not calling onCloseEndpointSession on failure because the remote endpoints (our
+ // mock endpoints) always accept the session.
+
+ std::weak_ptr<IEndpointCallback> callback;
+ {
+ std::unique_lock<std::mutex> lock(mEndpointMutex);
+ if (in_sessionId < mBaseSessionId || in_sessionId > mMaxSessionId) {
+ 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) {
+ return ScopedAStatus::ok();
+ }
+ callback = mEndpointCallback;
+ }
+
+ std::unique_lock<std::mutex> lock(gCallbackMutex);
+ std::thread{[callback, in_sessionId]() {
+ std::unique_lock<std::mutex> lock(gCallbackMutex);
+ if (auto cb = callback.lock(); cb != nullptr) {
+ cb->onEndpointSessionOpenComplete(in_sessionId);
+ }
+ }}.detach();
+ return ScopedAStatus::ok();
};
-ScopedAStatus ContextHub::openEndpointSession(
- int32_t /* in_sessionId */, const EndpointId& /* in_destination */,
- const EndpointId& /* in_initiator */,
- const std::optional<std::string>& /* in_serviceDescriptor */) {
- return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ScopedAStatus ContextHub::HubInterface::sendMessageToEndpoint(int32_t in_sessionId,
+ const Message& in_msg) {
+ if (!mActive) {
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ std::weak_ptr<IEndpointCallback> callback;
+ {
+ std::unique_lock<std::mutex> lock(mEndpointMutex);
+ bool foundSession = false;
+ for (const EndpointSession& session : mEndpointSessions) {
+ if (session.sessionId == in_sessionId) {
+ foundSession = true;
+ break;
+ }
+ }
+
+ if (!foundSession) {
+ ALOGE("sendMessageToEndpoint: session ID %" PRId32 " is invalid", in_sessionId);
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+
+ if (mEndpointCallback == nullptr) {
+ return ScopedAStatus::ok();
+ }
+ callback = mEndpointCallback;
+ }
+
+ std::unique_lock<std::mutex> lock(gCallbackMutex);
+ if ((in_msg.flags & Message::FLAG_REQUIRES_DELIVERY_STATUS) != 0) {
+ MessageDeliveryStatus msgStatus = {};
+ msgStatus.messageSequenceNumber = in_msg.sequenceNumber;
+ msgStatus.errorCode = ErrorCode::OK;
+
+ std::thread{[callback, in_sessionId, msgStatus]() {
+ std::unique_lock<std::mutex> lock(gCallbackMutex);
+ if (auto cb = callback.lock(); cb != nullptr) {
+ cb->onMessageDeliveryStatusReceived(in_sessionId, msgStatus);
+ }
+ }}.detach();
+ }
+
+ // Echo the message back
+ std::thread{[callback, in_sessionId, in_msg]() {
+ std::unique_lock<std::mutex> lock(gCallbackMutex);
+ if (auto cb = callback.lock(); cb != nullptr) {
+ cb->onMessageReceived(in_sessionId, in_msg);
+ }
+ }}.detach();
+ return ScopedAStatus::ok();
};
-ScopedAStatus ContextHub::sendMessageToEndpoint(int32_t /* in_sessionId */,
- const Message& /* in_msg */) {
- return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
-};
-
-ScopedAStatus ContextHub::sendMessageDeliveryStatusToEndpoint(
+ScopedAStatus ContextHub::HubInterface::sendMessageDeliveryStatusToEndpoint(
int32_t /* in_sessionId */, const MessageDeliveryStatus& /* in_msgStatus */) {
- return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ if (!mActive) {
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ return ScopedAStatus::ok();
};
-ScopedAStatus ContextHub::closeEndpointSession(int32_t /* in_sessionId */, Reason /* in_reason */) {
- return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ScopedAStatus ContextHub::HubInterface::closeEndpointSession(int32_t in_sessionId,
+ Reason /* in_reason */) {
+ if (!mActive) {
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ std::unique_lock<std::mutex> 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);
+ScopedAStatus ContextHub::HubInterface::endpointSessionOpenComplete(int32_t /* in_sessionId */) {
+ if (!mActive) {
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ return ScopedAStatus::ok();
};
+ScopedAStatus ContextHub::HubInterface::unregister() {
+ if (!mActive.exchange(false)) {
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ std::lock_guard lock(mHal.mHostHubsLock);
+ mHal.mIdToHostHub.erase(kInfo.hubId);
+ 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 5680a77..65e84bb 100644
--- a/contexthub/aidl/default/include/contexthub-impl/ContextHub.h
+++ b/contexthub/aidl/default/include/contexthub-impl/ContextHub.h
@@ -17,7 +17,10 @@
#pragma once
#include <aidl/android/hardware/contexthub/BnContextHub.h>
+#include <aidl/android/hardware/contexthub/BnEndpointCommunication.h>
+#include <atomic>
+#include <mutex>
#include <unordered_set>
#include <vector>
@@ -55,27 +58,79 @@
::ndk::ScopedAStatus getHubs(std::vector<HubInfo>* _aidl_return) override;
::ndk::ScopedAStatus getEndpoints(std::vector<EndpointInfo>* _aidl_return) override;
- ::ndk::ScopedAStatus registerEndpoint(const EndpointInfo& in_endpoint) override;
- ::ndk::ScopedAStatus unregisterEndpoint(const EndpointInfo& in_endpoint) override;
- ::ndk::ScopedAStatus registerEndpointCallback(
- const std::shared_ptr<IEndpointCallback>& in_callback) override;
- ::ndk::ScopedAStatus requestSessionIdRange(int32_t in_size,
- std::vector<int32_t>* _aidl_return) override;
- ::ndk::ScopedAStatus openEndpointSession(
- int32_t in_sessionId, const EndpointId& in_destination, const EndpointId& in_initiator,
- const std::optional<std::string>& in_serviceDescriptor) override;
- ::ndk::ScopedAStatus sendMessageToEndpoint(int32_t in_sessionId,
- const Message& in_msg) override;
- ::ndk::ScopedAStatus sendMessageDeliveryStatusToEndpoint(
- int32_t in_sessionId, const MessageDeliveryStatus& in_msgStatus) override;
- ::ndk::ScopedAStatus closeEndpointSession(int32_t in_sessionId, Reason in_reason) override;
- ::ndk::ScopedAStatus endpointSessionOpenComplete(int32_t in_sessionId) override;
+ ::ndk::ScopedAStatus registerEndpointHub(
+ const std::shared_ptr<IEndpointCallback>& in_callback, const HubInfo& in_hubInfo,
+ std::shared_ptr<IEndpointCommunication>* _aidl_return) override;
private:
+ class HubInterface : public BnEndpointCommunication {
+ public:
+ HubInterface(ContextHub& hal, const std::shared_ptr<IEndpointCallback>& in_callback,
+ const HubInfo& in_hubInfo)
+ : mHal(hal), mEndpointCallback(in_callback), kInfo(in_hubInfo) {}
+ ~HubInterface() = default;
+
+ ::ndk::ScopedAStatus registerEndpoint(const EndpointInfo& in_endpoint) override;
+ ::ndk::ScopedAStatus unregisterEndpoint(const EndpointInfo& in_endpoint) override;
+ ::ndk::ScopedAStatus requestSessionIdRange(int32_t in_size,
+ std::array<int32_t, 2>* _aidl_return) override;
+ ::ndk::ScopedAStatus openEndpointSession(
+ int32_t in_sessionId, const EndpointId& in_destination,
+ const EndpointId& in_initiator,
+ const std::optional<std::string>& in_serviceDescriptor) override;
+ ::ndk::ScopedAStatus sendMessageToEndpoint(int32_t in_sessionId,
+ const Message& in_msg) override;
+ ::ndk::ScopedAStatus sendMessageDeliveryStatusToEndpoint(
+ int32_t in_sessionId, const MessageDeliveryStatus& in_msgStatus) override;
+ ::ndk::ScopedAStatus closeEndpointSession(int32_t in_sessionId, Reason in_reason) override;
+ ::ndk::ScopedAStatus endpointSessionOpenComplete(int32_t in_sessionId) override;
+ ::ndk::ScopedAStatus unregister() override;
+
+ private:
+ friend class ContextHub;
+
+ struct EndpointSession {
+ int32_t sessionId;
+ EndpointId initiator;
+ EndpointId peer;
+ std::optional<std::string> serviceDescriptor;
+ };
+
+ //! Finds an endpoint in the range defined by the endpoints
+ //! @return whether the endpoint was found
+ template <typename Iter>
+ 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;
+ }
+
+ //! Endpoint storage and information
+ ContextHub& mHal;
+ std::shared_ptr<IEndpointCallback> mEndpointCallback;
+ const HubInfo kInfo;
+
+ std::atomic<bool> mActive = true;
+
+ std::mutex mEndpointMutex;
+ std::vector<EndpointInfo> mEndpoints;
+ std::vector<EndpointSession> mEndpointSessions;
+ uint16_t mBaseSessionId;
+ uint16_t mMaxSessionId;
+ };
+
static constexpr uint32_t kMockHubId = 0;
+
std::shared_ptr<IContextHubCallback> mCallback;
std::unordered_set<char16_t> mConnectedHostEndpoints;
+
+ std::mutex mHostHubsLock;
+ std::unordered_map<int64_t, std::shared_ptr<HubInterface>> mIdToHostHub;
+ int32_t mNextSessionIdBase = 0;
};
} // namespace contexthub
diff --git a/contexthub/aidl/vts/Android.bp b/contexthub/aidl/vts/Android.bp
index 62a319e..a19b6fd 100644
--- a/contexthub/aidl/vts/Android.bp
+++ b/contexthub/aidl/vts/Android.bp
@@ -33,7 +33,7 @@
"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 fa427a5..d7859d9 100644
--- a/contexthub/aidl/vts/VtsAidlHalContextHubTargetTest.cpp
+++ b/contexthub/aidl/vts/VtsAidlHalContextHubTargetTest.cpp
@@ -20,8 +20,11 @@
#include <android/hardware/contexthub/BnContextHub.h>
#include <android/hardware/contexthub/BnContextHubCallback.h>
+#include <android/hardware/contexthub/BnEndpointCallback.h>
#include <android/hardware/contexthub/IContextHub.h>
#include <android/hardware/contexthub/IContextHubCallback.h>
+#include <android/hardware/contexthub/IEndpointCallback.h>
+#include <android/hardware/contexthub/IEndpointCommunication.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <log/log.h>
@@ -34,18 +37,26 @@
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::IEndpointCommunication;
+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;
@@ -53,26 +64,71 @@
// 6612b522-b717-41c8-b48d-c0b1cc64e142
constexpr std::array<uint8_t, 16> kUuid = {0x66, 0x12, 0xb5, 0x22, 0xb7, 0x17, 0x41, 0xc8,
0xb4, 0x8d, 0xc0, 0xb1, 0xcc, 0x64, 0xe1, 0x42};
+
const String16 kName{"VtsAidlHalContextHubTargetTest"};
+const String16 kEchoServiceName{"android.hardware.contexthub.test.EchoService"};
+
+constexpr int64_t kDefaultHubId = 1;
+
+class TestEndpointCallback;
class ContextHubAidl : public testing::TestWithParam<std::tuple<std::string, int32_t>> {
public:
- virtual void SetUp() override {
- contextHub = android::waitForDeclaredService<IContextHub>(
+ void SetUp() override {
+ mContextHub = android::waitForDeclaredService<IContextHub>(
String16(std::get<0>(GetParam()).c_str()));
- ASSERT_NE(contextHub, nullptr);
+ ASSERT_NE(mContextHub, nullptr);
+ mEndpointCb = sp<TestEndpointCallback>::make();
}
uint32_t getHubId() { return std::get<1>(GetParam()); }
+ Status registerHub(int64_t id, sp<IEndpointCommunication>* hubInterface) {
+ HubInfo info;
+ info.hubId = id;
+ return mContextHub->registerEndpointHub(mEndpointCb, info, hubInterface);
+ }
+
+ bool registerDefaultHub() {
+ Status status = registerHub(kDefaultHubId, &mHubInterface);
+ if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
+ status.transactionError() == android::UNKNOWN_TRANSACTION) {
+ return false;
+ }
+ EXPECT_TRUE(status.isOk());
+ EXPECT_NE(mHubInterface, nullptr);
+ if (!mHubInterface) {
+ return false;
+ }
+ return true;
+ }
+
void testSettingChanged(Setting setting);
- sp<IContextHub> contextHub;
+ sp<IContextHub> mContextHub;
+ sp<TestEndpointCallback> mEndpointCb;
+ sp<IEndpointCommunication> mHubInterface;
+};
+
+class ContextHubAidlWithTestMode : public ContextHubAidl {
+ public:
+ void SetUp() override {
+ ContextHubAidl::SetUp();
+
+ // Best effort enable test mode - this may not be supported on older HALS, so we
+ // ignore the return value.
+ mContextHub->setTestMode(/* enable= */ true);
+ }
+
+ void TearDown() override {
+ mContextHub->setTestMode(/* enable= */ false);
+ ContextHubAidl::TearDown();
+ }
};
TEST_P(ContextHubAidl, TestGetHubs) {
std::vector<ContextHubInfo> hubs;
- ASSERT_TRUE(contextHub->getContextHubs(&hubs).isOk());
+ ASSERT_TRUE(mContextHub->getContextHubs(&hubs).isOk());
ALOGD("System reports %zu hubs", hubs.size());
@@ -94,7 +150,7 @@
}
TEST_P(ContextHubAidl, TestEnableTestMode) {
- Status status = contextHub->setTestMode(true);
+ Status status = mContextHub->setTestMode(true);
if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
status.transactionError() == android::UNKNOWN_TRANSACTION) {
GTEST_SKIP() << "Not supported -> old API; or not implemented";
@@ -104,7 +160,7 @@
}
TEST_P(ContextHubAidl, TestDisableTestMode) {
- Status status = contextHub->setTestMode(false);
+ Status status = mContextHub->setTestMode(false);
if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
status.transactionError() == android::UNKNOWN_TRANSACTION) {
GTEST_SKIP() << "Not supported -> old API; or not implemented";
@@ -153,7 +209,7 @@
TEST_P(ContextHubAidl, TestRegisterCallback) {
sp<EmptyContextHubCallback> cb = sp<EmptyContextHubCallback>::make();
- ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb).isOk());
+ ASSERT_TRUE(mContextHub->registerCallback(getHubId(), cb).isOk());
}
// Helper callback that puts the async appInfo callback data into a promise
@@ -202,8 +258,8 @@
// Calls queryApps() and checks the returned metadata
TEST_P(ContextHubAidl, TestQueryApps) {
sp<QueryAppsCallback> cb = sp<QueryAppsCallback>::make();
- ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb).isOk());
- ASSERT_TRUE(contextHub->queryNanoapps(getHubId()).isOk());
+ ASSERT_TRUE(mContextHub->registerCallback(getHubId(), cb).isOk());
+ ASSERT_TRUE(mContextHub->queryNanoapps(getHubId()).isOk());
std::vector<NanoappInfo> appInfoList;
ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &appInfoList));
@@ -224,7 +280,7 @@
// Calls getPreloadedNanoappsIds() and verifies there are preloaded nanoapps
TEST_P(ContextHubAidl, TestGetPreloadedNanoappIds) {
std::vector<int64_t> preloadedNanoappIds;
- Status status = contextHub->getPreloadedNanoappIds(getHubId(), &preloadedNanoappIds);
+ Status status = mContextHub->getPreloadedNanoappIds(getHubId(), &preloadedNanoappIds);
if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
status.transactionError() == android::UNKNOWN_TRANSACTION) {
GTEST_SKIP() << "Not supported -> old API; or not implemented";
@@ -287,7 +343,7 @@
public:
virtual void SetUp() override {
ContextHubAidl::SetUp();
- ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb).isOk());
+ ASSERT_TRUE(mContextHub->registerCallback(getHubId(), cb).isOk());
}
sp<TransactionResultCallback> cb = sp<TransactionResultCallback>::make();
@@ -301,7 +357,7 @@
std::fill(message.messageBody.begin(), message.messageBody.end(), 0);
ALOGD("Sending message to non-existent nanoapp");
- ASSERT_TRUE(contextHub->sendMessageToHub(getHubId(), message).isOk());
+ ASSERT_TRUE(mContextHub->sendMessageToHub(getHubId(), message).isOk());
}
TEST_P(ContextHubTransactionTest, TestLoadEmptyNanoapp) {
@@ -315,7 +371,7 @@
emptyApp.targetChreApiMinorVersion = 0;
ALOGD("Loading empty nanoapp");
- bool success = contextHub->loadNanoapp(getHubId(), emptyApp, cb->expectedTransactionId).isOk();
+ bool success = mContextHub->loadNanoapp(getHubId(), emptyApp, cb->expectedTransactionId).isOk();
if (success) {
bool transactionSuccess;
ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
@@ -328,7 +384,7 @@
ALOGD("Unloading nonexistent nanoapp");
bool success =
- contextHub->unloadNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId)
+ mContextHub->unloadNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId)
.isOk();
if (success) {
bool transactionSuccess;
@@ -342,7 +398,7 @@
ALOGD("Enabling nonexistent nanoapp");
bool success =
- contextHub->enableNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId)
+ mContextHub->enableNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId)
.isOk();
if (success) {
bool transactionSuccess;
@@ -356,7 +412,7 @@
ALOGD("Disabling nonexistent nanoapp");
bool success =
- contextHub->disableNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId)
+ mContextHub->disableNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId)
.isOk();
if (success) {
bool transactionSuccess;
@@ -369,10 +425,10 @@
// In VTS, we only test that sending the values doesn't cause things to blow up - GTS tests
// verify the expected E2E behavior in CHRE
sp<EmptyContextHubCallback> cb = sp<EmptyContextHubCallback>::make();
- ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb).isOk());
+ ASSERT_TRUE(mContextHub->registerCallback(getHubId(), cb).isOk());
- ASSERT_TRUE(contextHub->onSettingChanged(setting, true /* enabled */).isOk());
- ASSERT_TRUE(contextHub->onSettingChanged(setting, false /* enabled */).isOk());
+ ASSERT_TRUE(mContextHub->onSettingChanged(setting, true /* enabled */).isOk());
+ ASSERT_TRUE(mContextHub->onSettingChanged(setting, false /* enabled */).isOk());
}
TEST_P(ContextHubAidl, TestOnLocationSettingChanged) {
@@ -427,27 +483,27 @@
hostEndpointInfo.type = HostEndpointInfo::Type::NATIVE;
hostEndpointInfo.hostEndpointId = kHostEndpointId;
- ASSERT_TRUE(contextHub->onHostEndpointConnected(hostEndpointInfo).isOk());
- ASSERT_TRUE(contextHub->onHostEndpointDisconnected(kHostEndpointId).isOk());
+ ASSERT_TRUE(mContextHub->onHostEndpointConnected(hostEndpointInfo).isOk());
+ ASSERT_TRUE(mContextHub->onHostEndpointDisconnected(kHostEndpointId).isOk());
}
TEST_P(ContextHubTransactionTest, TestInvalidHostConnection) {
constexpr char16_t kHostEndpointId = 1;
- ASSERT_TRUE(contextHub->onHostEndpointDisconnected(kHostEndpointId).isOk());
+ ASSERT_TRUE(mContextHub->onHostEndpointDisconnected(kHostEndpointId).isOk());
}
TEST_P(ContextHubTransactionTest, TestNanSessionStateChange) {
NanSessionStateUpdate update;
update.state = true;
- Status status = contextHub->onNanSessionStateChanged(update);
+ Status status = mContextHub->onNanSessionStateChanged(update);
if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
status.transactionError() == android::UNKNOWN_TRANSACTION) {
GTEST_SKIP() << "Not supported -> old API; or not implemented";
} else {
ASSERT_TRUE(status.isOk());
update.state = false;
- ASSERT_TRUE(contextHub->onNanSessionStateChanged(update).isOk());
+ ASSERT_TRUE(mContextHub->onNanSessionStateChanged(update).isOk());
}
}
@@ -456,7 +512,7 @@
messageDeliveryStatus.messageSequenceNumber = 123;
messageDeliveryStatus.errorCode = ErrorCode::OK;
- Status status = contextHub->sendMessageDeliveryStatusToHub(getHubId(), messageDeliveryStatus);
+ Status status = mContextHub->sendMessageDeliveryStatusToHub(getHubId(), messageDeliveryStatus);
if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
status.transactionError() == android::UNKNOWN_TRANSACTION) {
GTEST_SKIP() << "Not supported -> old API; or not implemented";
@@ -465,6 +521,322 @@
}
}
+class TestEndpointCallback : public BnEndpointCallback {
+ public:
+ Status onEndpointStarted(const std::vector<EndpointInfo>& /* endpointInfos */) override {
+ return Status::ok();
+ }
+
+ Status onEndpointStopped(const std::vector<EndpointId>& /* endpointIds */,
+ Reason /* reason */) override {
+ return Status::ok();
+ }
+
+ Status onMessageReceived(int32_t /* sessionId */, const Message& message) override {
+ {
+ std::unique_lock<std::mutex> lock(mMutex);
+ mMessages.push_back(message);
+ }
+ mCondVar.notify_one();
+ 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<String16>& /* serviceDescriptor */) override {
+ return Status::ok();
+ }
+
+ Status onCloseEndpointSession(int32_t /* sessionId */, Reason /* reason */) override {
+ return Status::ok();
+ }
+
+ Status onEndpointSessionOpenComplete(int32_t /* sessionId */) override {
+ {
+ std::unique_lock<std::mutex> lock(mMutex);
+ mWasOnEndpointSessionOpenCompleteCalled = true;
+ }
+ mCondVar.notify_one();
+ return Status::ok();
+ }
+
+ bool wasOnEndpointSessionOpenCompleteCalled() {
+ return mWasOnEndpointSessionOpenCompleteCalled;
+ }
+
+ void resetWasOnEndpointSessionOpenCompleteCalled() {
+ mWasOnEndpointSessionOpenCompleteCalled = false;
+ }
+
+ std::mutex& getMutex() { return mMutex; }
+ std::condition_variable& getCondVar() { return mCondVar; }
+ std::vector<Message> getMessages() { return mMessages; }
+
+ private:
+ std::vector<Message> mMessages;
+ std::mutex mMutex;
+ std::condition_variable mCondVar;
+ bool mWasOnEndpointSessionOpenCompleteCalled = false;
+};
+
+TEST_P(ContextHubAidlWithTestMode, RegisterHub) {
+ if (!registerDefaultHub()) {
+ GTEST_SKIP() << "Not supported -> old API; or not implemented";
+ }
+
+ sp<IEndpointCommunication> hub2;
+ Status status = registerHub(kDefaultHubId + 1, &hub2);
+ EXPECT_TRUE(status.isOk());
+
+ sp<IEndpointCommunication> hub3;
+ status = registerHub(kDefaultHubId + 1, &hub3);
+ ASSERT_FALSE(status.isOk());
+ EXPECT_EQ(status.exceptionCode(), Status::EX_ILLEGAL_STATE);
+
+ hub2->unregister();
+ status = registerHub(kDefaultHubId + 1, &hub3);
+ EXPECT_TRUE(status.isOk());
+}
+
+TEST_P(ContextHubAidlWithTestMode, RegisterEndpoint) {
+ if (!registerDefaultHub()) {
+ GTEST_SKIP() << "Not supported -> old API; or not implemented";
+ }
+
+ 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 = mHubInterface->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(ContextHubAidlWithTestMode, RegisterEndpointSameNameFailure) {
+ if (!registerDefaultHub()) {
+ GTEST_SKIP() << "Not supported -> old API; or not implemented";
+ }
+
+ 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 = mHubInterface->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(mHubInterface->registerEndpoint(endpointInfo2).isOk());
+}
+
+TEST_P(ContextHubAidlWithTestMode, RegisterEndpointSameIdFailure) {
+ if (!registerDefaultHub()) {
+ GTEST_SKIP() << "Not supported -> old API; or not implemented";
+ }
+
+ 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 = mHubInterface->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(mHubInterface->registerEndpoint(endpointInfo2).isOk());
+}
+
+TEST_P(ContextHubAidlWithTestMode, UnregisterEndpoint) {
+ if (!registerDefaultHub()) {
+ GTEST_SKIP() << "Not supported -> old API; or not implemented";
+ }
+
+ 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 = mHubInterface->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(mHubInterface->unregisterEndpoint(endpointInfo).isOk());
+}
+
+TEST_P(ContextHubAidlWithTestMode, UnregisterEndpointNonexistent) {
+ if (!registerDefaultHub()) {
+ GTEST_SKIP() << "Not supported -> old API; or not implemented";
+ }
+
+ 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 = mHubInterface->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(ContextHubAidlWithTestMode, OpenEndpointSessionInvalidRange) {
+ if (!registerDefaultHub()) {
+ GTEST_SKIP() << "Not supported -> old API; or not implemented";
+ }
+
+ // 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(mHubInterface->registerEndpoint(initiatorEndpoint).isOk());
+
+ // Find the destination, if it exists
+ std::vector<EndpointInfo> endpoints;
+ EXPECT_TRUE(mContextHub->getEndpoints(&endpoints).isOk());
+ const EndpointInfo* destinationEndpoint = nullptr;
+ for (const EndpointInfo& endpoint : endpoints) {
+ for (const Service& service : endpoint.services) {
+ if (service.serviceDescriptor == kEchoServiceName) {
+ destinationEndpoint = &endpoint;
+ break;
+ }
+ }
+ }
+ if (destinationEndpoint == nullptr) {
+ return; // no echo service endpoint -> just return
+ }
+
+ // Request the range
+ constexpr int32_t requestedRange = 100;
+ std::array<int32_t, 2> range;
+ ASSERT_TRUE(mHubInterface->requestSessionIdRange(requestedRange, &range).isOk());
+ EXPECT_EQ(range.size(), 2);
+ EXPECT_GE(range[1] - range[0] + 1, requestedRange);
+
+ // Open the session
+ int32_t sessionId = range[1] + 10; // invalid
+ EXPECT_FALSE(mHubInterface
+ ->openEndpointSession(sessionId, destinationEndpoint->id,
+ initiatorEndpoint.id,
+ /* in_serviceDescriptor= */ kEchoServiceName)
+ .isOk());
+}
+
+TEST_P(ContextHubAidlWithTestMode, OpenEndpointSessionAndSendMessageEchoesBack) {
+ if (!registerDefaultHub()) {
+ GTEST_SKIP() << "Not supported -> old API; or not implemented";
+ }
+ std::unique_lock<std::mutex> lock(mEndpointCb->getMutex());
+
+ // 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(mHubInterface->registerEndpoint(initiatorEndpoint).isOk());
+
+ // Find the destination, if it exists
+ std::vector<EndpointInfo> endpoints;
+ EXPECT_TRUE(mContextHub->getEndpoints(&endpoints).isOk());
+ const EndpointInfo* destinationEndpoint = nullptr;
+ for (const EndpointInfo& endpoint : endpoints) {
+ for (const Service& service : endpoint.services) {
+ if (service.serviceDescriptor == kEchoServiceName) {
+ destinationEndpoint = &endpoint;
+ break;
+ }
+ }
+ }
+ if (destinationEndpoint == nullptr) {
+ return; // no echo service endpoint -> just return
+ }
+
+ // Request the range
+ constexpr int32_t requestedRange = 100;
+ std::array<int32_t, 2> range;
+ ASSERT_TRUE(mHubInterface->requestSessionIdRange(requestedRange, &range).isOk());
+ EXPECT_EQ(range.size(), 2);
+ EXPECT_GE(range[1] - range[0] + 1, requestedRange);
+
+ // Open the session
+ mEndpointCb->resetWasOnEndpointSessionOpenCompleteCalled();
+ int32_t sessionId = range[0];
+ ASSERT_TRUE(mHubInterface
+ ->openEndpointSession(sessionId, destinationEndpoint->id,
+ initiatorEndpoint.id,
+ /* in_serviceDescriptor= */ kEchoServiceName)
+ .isOk());
+ mEndpointCb->getCondVar().wait(lock);
+ EXPECT_TRUE(mEndpointCb->wasOnEndpointSessionOpenCompleteCalled());
+
+ // Send the message
+ Message message;
+ message.flags = 0;
+ message.sequenceNumber = 0;
+ message.content.push_back(42);
+ ASSERT_TRUE(mHubInterface->sendMessageToEndpoint(sessionId, message).isOk());
+
+ // Check for echo
+ mEndpointCb->getCondVar().wait(lock);
+ EXPECT_FALSE(mEndpointCb->getMessages().empty());
+ EXPECT_EQ(mEndpointCb->getMessages().back().content.back(), 42);
+}
+
std::string PrintGeneratedTest(const testing::TestParamInfo<ContextHubAidl::ParamType>& info) {
return std::string("CONTEXT_HUB_ID_") + std::to_string(std::get<1>(info.param));
}
@@ -473,13 +845,17 @@
INSTANTIATE_TEST_SUITE_P(ContextHub, ContextHubAidl, testing::ValuesIn(generateContextHubMapping()),
PrintGeneratedTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContextHubAidlWithTestMode);
+INSTANTIATE_TEST_SUITE_P(ContextHub, ContextHubAidlWithTestMode,
+ testing::ValuesIn(generateContextHubMapping()), PrintGeneratedTest);
+
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContextHubTransactionTest);
INSTANTIATE_TEST_SUITE_P(ContextHub, ContextHubTransactionTest,
testing::ValuesIn(generateContextHubMapping()), PrintGeneratedTest);
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
- ProcessState::self()->setThreadPoolMaxThreadCount(1);
+ ProcessState::self()->setThreadPoolMaxThreadCount(2);
ProcessState::self()->startThreadPool();
return RUN_ALL_TESTS();
}
diff --git a/gnss/1.1/default/Android.bp b/gnss/1.1/default/Android.bp
index 697cb91..6c338bd 100644
--- a/gnss/1.1/default/Android.bp
+++ b/gnss/1.1/default/Android.bp
@@ -27,7 +27,7 @@
"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 65c752c..13984629 100644
--- a/gnss/1.1/vts/functional/Android.bp
+++ b/gnss/1.1/vts/functional/Android.bp
@@ -37,7 +37,7 @@
"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 35c2e37..6a4965b 100644
--- a/gnss/2.0/default/Android.bp
+++ b/gnss/2.0/default/Android.bp
@@ -50,7 +50,7 @@
"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 4ca3063..08d4cb3 100644
--- a/gnss/2.0/vts/functional/Android.bp
+++ b/gnss/2.0/vts/functional/Android.bp
@@ -40,7 +40,7 @@
"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 1bb7512..a2e652e 100644
--- a/gnss/2.1/default/Android.bp
+++ b/gnss/2.1/default/Android.bp
@@ -44,7 +44,7 @@
"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 af66037..8a8fa93 100644
--- a/gnss/2.1/vts/functional/Android.bp
+++ b/gnss/2.1/vts/functional/Android.bp
@@ -41,7 +41,7 @@
"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 47fc3af..6e159a1 100644
--- a/gnss/aidl/Android.bp
+++ b/gnss/aidl/Android.bp
@@ -30,6 +30,7 @@
"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 @@
},
],
- 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 d1aaf2c..fc74612 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 @@
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/AuxiliaryInformation.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/AuxiliaryInformation.aidl
new file mode 100644
index 0000000..a0351f8
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/AuxiliaryInformation.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 <name>-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 AuxiliaryInformation {
+ int svid;
+ android.hardware.gnss.GnssSignalType[] availableSignalTypes;
+ int frequencyChannelNumber;
+ android.hardware.gnss.gnss_assistance.AuxiliaryInformation.BeidouB1CSatelliteOrbitType satType;
+ @Backing(type="int") @VintfStability
+ enum BeidouB1CSatelliteOrbitType {
+ UNDEFINED = 0,
+ GEO = 1,
+ IGSO = 2,
+ MEO = 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 0000000..f7b16f9
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/BeidouSatelliteEphemeris.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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 <name>-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 svid;
+ 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 0000000..6d8040b
--- /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 <name>-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 0000000..e5a3630
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/GalileoSatelliteEphemeris.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 <name>-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 svid;
+ 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 {
+ android.hardware.gnss.gnss_assistance.GalileoSatelliteEphemeris.GalileoSvHealth.GalileoHealthDataVaidityType dataValidityStatusE1b;
+ android.hardware.gnss.gnss_assistance.GalileoSatelliteEphemeris.GalileoSvHealth.GalileoHealthStatusType signalHealthStatusE1b;
+ android.hardware.gnss.gnss_assistance.GalileoSatelliteEphemeris.GalileoSvHealth.GalileoHealthDataVaidityType dataValidityStatusE5a;
+ android.hardware.gnss.gnss_assistance.GalileoSatelliteEphemeris.GalileoSvHealth.GalileoHealthStatusType signalHealthStatusE5a;
+ android.hardware.gnss.gnss_assistance.GalileoSatelliteEphemeris.GalileoSvHealth.GalileoHealthDataVaidityType dataValidityStatusE5b;
+ android.hardware.gnss.gnss_assistance.GalileoSatelliteEphemeris.GalileoSvHealth.GalileoHealthStatusType signalHealthStatusE5b;
+ @Backing(type="int") @VintfStability
+ enum GalileoHealthDataVaidityType {
+ DATA_VALID = 0,
+ WORKING_WITHOUT_GUARANTEE = 1,
+ }
+ @Backing(type="int") @VintfStability
+ enum GalileoHealthStatusType {
+ OK = 0,
+ OUT_OF_SERVICE = 1,
+ EXTENDED_OPERATION_MODE = 2,
+ IN_TEST = 3,
+ }
+ }
+}
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 0000000..1d2b30a
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/GlonassAlmanac.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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 <name>-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[] satelliteAlmanacs;
+ @VintfStability
+ parcelable GlonassSatelliteAlmanac {
+ int slotNumber;
+ int svHealth;
+ int frequencyChannelNumber;
+ int calendarDayNumber;
+ boolean isGlonassM;
+ 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 0000000..a08268b
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/GlonassSatelliteEphemeris.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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 <name>-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;
+ int updateIntervalMinutes;
+ boolean isOddUpdateInterval;
+ boolean isGlonassM;
+ android.hardware.gnss.gnss_assistance.GlonassSatelliteEphemeris.GlonassSatelliteClockModel satelliteClockModel;
+ android.hardware.gnss.gnss_assistance.GlonassSatelliteEphemeris.GlonassSatelliteOrbitModel satelliteOrbitModel;
+ const int GLONASS_HEALTH_STATUS_HEALTHY = 0;
+ const int GLONASS_HEALTH_STATUS_UNHEALTHY = 1;
+ @VintfStability
+ parcelable GlonassSatelliteClockModel {
+ long timeOfClockSeconds;
+ double clockBias;
+ double frequencyBias;
+ int frequencyChannelNumber;
+ double groupDelayDiffSeconds;
+ }
+ @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 0000000..a7f3f5c
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/GnssAlmanac.aidl
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <name>-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 ioda;
+ int weekNumber;
+ int toaSeconds;
+ boolean isCompleteAlmanacProvided;
+ android.hardware.gnss.gnss_assistance.GnssAlmanac.GnssSatelliteAlmanac[] satelliteAlmanacs;
+ @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 0000000..5f7b886
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/gnss_assistance/GnssAssistance.aidl
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <name>-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[] ionosphericCorrections;
+ }
+ @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;
+ android.hardware.gnss.gnss_assistance.AuxiliaryInformation auxiliaryInformation;
+ }
+ @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;
+ android.hardware.gnss.gnss_assistance.AuxiliaryInformation auxiliaryInformation;
+ }
+ @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;
+ android.hardware.gnss.gnss_assistance.AuxiliaryInformation auxiliaryInformation;
+ }
+ @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;
+ android.hardware.gnss.gnss_assistance.AuxiliaryInformation auxiliaryInformation;
+ }
+ @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;
+ android.hardware.gnss.gnss_assistance.AuxiliaryInformation auxiliaryInformation;
+ }
+}
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 0000000..2d43bb3
--- /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 <name>-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 0000000..8a2ab77
--- /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 <name>-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 svid;
+ 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 0000000..602a249
--- /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 <name>-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 0000000..4dd5cf6
--- /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 <name>-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 0000000..6e8434a
--- /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 <name>-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 ionosphericCorrectionComponent;
+}
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 0000000..835c6ec
--- /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 <name>-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 0000000..5a0caa5
--- /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 <name>-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 0000000..bc38b9b
--- /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 <name>-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 0000000..5f13167
--- /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 <name>-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 svid;
+ 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 0000000..21ba2ef
--- /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 <name>-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 badSvid;
+ android.hardware.gnss.GnssSignalType[] badSignalTypes;
+ 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 0000000..1e5cd02
--- /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 <name>-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 0000000..e1ce890
--- /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 <name>-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 0000000..df754bc
--- /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 <name>-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 aaafe7f..5fc8a48 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.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 @@
* 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/AuxiliaryInformation.aidl b/gnss/aidl/android/hardware/gnss/gnss_assistance/AuxiliaryInformation.aidl
new file mode 100644
index 0000000..f6c6cb9
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/gnss_assistance/AuxiliaryInformation.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.gnss.gnss_assistance;
+
+import android.hardware.gnss.GnssSignalType;
+
+/**
+ * Contains parameters to provide additional information dependent on the GNSS constellation.
+ *
+ * @hide
+ */
+@VintfStability
+parcelable AuxiliaryInformation {
+ /**
+ * BDS B1C Satellite orbit type.
+ *
+ * This is defined in BDS-SIS-ICD-B1I-3.0, section 3.1.
+ */
+ @VintfStability
+ @Backing(type="int")
+ enum BeidouB1CSatelliteOrbitType {
+ UNDEFINED = 0,
+ GEO = 1,
+ IGSO = 2,
+ MEO = 3
+ }
+
+ /**
+ * 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:
+ *
+ * - GPS: 1-32
+ * - Glonass: 1-25
+ * - QZSS: 183-206
+ * - Galileo: 1-36
+ * - Beidou: 1-63
+ */
+ int svid;
+
+ /** The list of available signal types for the satellite. */
+ GnssSignalType[] availableSignalTypes;
+
+ /**
+ * Glonass carrier frequency number of the satellite. This is required for Glonass.
+ *
+ * This is defined in Glonass ICD v5.1 section 3.3.1.1.
+ */
+ int frequencyChannelNumber;
+
+ /** BDS B1C satellite orbit type. This is required for Beidou. */
+ BeidouB1CSatelliteOrbitType satType;
+}
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 0000000..4c5a05b
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/gnss_assistance/BeidouSatelliteEphemeris.aidl
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+/**
+ * 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;
+ }
+
+ /** PRN or satellite ID number for the Beidou satellite. */
+ int svid;
+
+ /** 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 0000000..ced8917
--- /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 0000000..1af07e5
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/gnss_assistance/GalileoSatelliteEphemeris.aidl
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 {
+ /** Galileo health data validity type. */
+ @VintfStability
+ @Backing(type="int")
+ enum GalileoHealthDataVaidityType {
+ DATA_VALID = 0,
+ WORKING_WITHOUT_GUARANTEE = 1
+ }
+
+ /** Galileo health status type. */
+ @VintfStability
+ @Backing(type="int")
+ enum GalileoHealthStatusType {
+ OK = 0,
+ OUT_OF_SERVICE = 1,
+ EXTENDED_OPERATION_MODE = 2,
+ IN_TEST = 3
+ }
+
+ /** E1-B data validity status. */
+ GalileoHealthDataVaidityType dataValidityStatusE1b;
+
+ /** E1-B/C signal health status. */
+ GalileoHealthStatusType signalHealthStatusE1b;
+
+ /** E5a data validity status. */
+ GalileoHealthDataVaidityType dataValidityStatusE5a;
+
+ /** E5a signal health status. */
+ GalileoHealthStatusType signalHealthStatusE5a;
+
+ /** E5b data validity status. */
+ GalileoHealthDataVaidityType dataValidityStatusE5b;
+
+ /** E5b signal health status. */
+ GalileoHealthStatusType signalHealthStatusE5b;
+ }
+
+ /** PRN or satellite ID number for the Galileo satellite. */
+ int svid;
+
+ /** 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 0000000..ebf6c05
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/gnss_assistance/GlonassAlmanac.aidl
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 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 which is set with the GLONASS_HEALTH_STATUS_*
+ * constants in GlonassSatelliteEphemeris.
+ */
+ int svHealth;
+
+ /**
+ * Frequency channel number.
+ *
+ * This is defined in Glonass ICD v5.1 section 3.3.1.1.
+ */
+ int frequencyChannelNumber;
+
+ /** Calendar day number within the four-year period beginning since the leap year. */
+ int calendarDayNumber;
+
+ /** Flag to indicates if the satellite is a GLONASS-M satellitee. */
+ boolean isGlonassM;
+
+ /** 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 semi-circles. */
+ double omega;
+ }
+
+ /** Almanac issue date in milliseconds (UTC). */
+ long issueDateMs;
+
+ /** Array of GlonassSatelliteAlmanac. */
+ GlonassSatelliteAlmanac[] satelliteAlmanacs;
+}
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 0000000..e17de59
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/gnss_assistance/GlonassSatelliteEphemeris.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.gnss.gnss_assistance;
+
+/**
+ * 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 frequencyBias;
+
+ /**
+ * Frequency channel number.
+ *
+ * This is defined in Glonass ICD v5.1 section 3.3.1.1.
+ */
+ int frequencyChannelNumber;
+
+ /**
+ * L1/L2 group delay difference in seconds (DeltaTau).
+ *
+ * It is set to 0.999999999999E+09 if the value is not available.
+ */
+ double groupDelayDiffSeconds;
+ }
+
+ /** 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;
+ }
+
+ /** Glonass health status healthy. */
+ const int GLONASS_HEALTH_STATUS_HEALTHY = 0;
+
+ /** Glonass health status unhealthy. */
+ const int GLONASS_HEALTH_STATUS_UNHEALTHY = 1;
+
+ /** Slot number. */
+ int slotNumber;
+
+ /** Satellite health which is set with the GLONASS_HEALTH_STATUS_* constants */
+ 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;
+
+ /** Update and validity interval in minutes (P1) **/
+ int updateIntervalMinutes;
+
+ /** Flag to indicate oddness(1) or evenness(0) of update interval (P2). */
+ boolean isOddUpdateInterval;
+
+ /** Flag to indicates if the satellite is a Glonass-M satellitee (M). */
+ boolean isGlonassM;
+
+ /** 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 0000000..f12378b
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/gnss_assistance/GnssAlmanac.aidl
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 ioda;
+
+ /**
+ * 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;
+
+ /**
+ * Flag to indicate if the satelliteAlmanacs contains complete GNSS
+ * constellation indicated by svid.
+ **/
+ boolean isCompleteAlmanacProvided;
+
+ /**
+ * 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 {
+ /** PRN or satellite ID number for the 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[] satelliteAlmanacs;
+}
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 0000000..21555cb
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/gnss_assistance/GnssAssistance.aidl
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.AuxiliaryInformation;
+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:
+ *
+ * - GPS: 1-32
+ * - GLONASS: 1-25
+ * - QZSS: 183-206
+ * - Galileo: 1-36
+ * - Beidou: 1-63
+ */
+ int svid;
+
+ /** Ionospheric corrections */
+ IonosphericCorrection[] ionosphericCorrections;
+ }
+
+ /** 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;
+
+ /** The auxiliary information. */
+ AuxiliaryInformation auxiliaryInformation;
+ }
+
+ /** 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;
+
+ /** The auxiliary information. */
+ AuxiliaryInformation auxiliaryInformation;
+ }
+
+ /** 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;
+
+ /** The auxiliary information. */
+ AuxiliaryInformation auxiliaryInformation;
+ }
+
+ /** 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;
+
+ /** The auxiliary information. */
+ AuxiliaryInformation auxiliaryInformation;
+ }
+
+ /** 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;
+
+ /** The auxiliary information. */
+ AuxiliaryInformation auxiliaryInformation;
+ }
+
+ /** 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 0000000..445727f
--- /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 0000000..4be2fcc
--- /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 {
+ /** PRN or satellite ID number for the GPS satellite. */
+ int svid;
+
+ /* 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 0000000..883189c
--- /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 0000000..2097e1e
--- /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 0000000..fe6b63d
--- /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 component. */
+ GnssCorrectionComponent ionosphericCorrectionComponent;
+}
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 0000000..441b61d
--- /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 0000000..e261e97
--- /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 0000000..0ebd46d
--- /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 0000000..6768daf
--- /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 {
+ /** PRN or satellite ID number for the Qzss satellite. */
+ int svid;
+
+ /** 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 0000000..b05176b
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/gnss_assistance/RealTimeIntegrityModel.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.
+ */
+
+package android.hardware.gnss.gnss_assistance;
+
+import android.hardware.gnss.GnssSignalType;
+
+/**
+ * Contains the real time integrity status of a GNSS satellite based on
+ * notice advisory.
+ *
+ * @hide
+ */
+@VintfStability
+parcelable RealTimeIntegrityModel {
+ /**
+ * The bad signal ID number or OSN number for Glonass.
+ * The distinction is made by looking at the constellation field.
+ * Values must be in the range of:
+ *
+ * - GPS: 1-32
+ * - GLONASS: 1-25
+ * - QZSS: 183-206
+ * - Galileo: 1-36
+ * - Beidou: 1-63
+ */
+ int badSvid;
+
+ /**
+ * The signal type of the badSvid, it's set to null array if
+ * all signals on the specific SV are not healthy.
+ */
+ GnssSignalType[] badSignalTypes;
+
+ /** 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 0000000..8849401
--- /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 0000000..8804f02
--- /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 0000000..c16a711
--- /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 822e8fc..efe2953 100644
--- a/gnss/aidl/default/Android.bp
+++ b/gnss/aidl/default/Android.bp
@@ -45,13 +45,14 @@
"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 94d4d00..41720c0 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 @@
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 @@
this->reportLocation(location);
}
} while (mIsActive && mThreadBlocker.wait_for(std::chrono::milliseconds(mMinIntervalMs)));
+ ALOGD("reportGnssCount: %d", reportGnssCount);
});
return ScopedAStatus::ok();
}
@@ -390,6 +395,14 @@
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus Gnss::getExtensionGnssAssistanceInterface(
+ std::shared_ptr<gnss_assistance::IGnssAssistanceInterface>* iGnssAssistanceInterface) {
+ ALOGD("Gnss::getExtensionGnssAssistanceInterface");
+
+ *iGnssAssistanceInterface = SharedRefBase::make<gnss_assistance::GnssAssistanceInterface>();
+ 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 73085ef..56fe399 100644
--- a/gnss/aidl/default/Gnss.h
+++ b/gnss/aidl/default/Gnss.h
@@ -26,6 +26,7 @@
#include <aidl/android/hardware/gnss/BnGnssMeasurementInterface.h>
#include <aidl/android/hardware/gnss/BnGnssPowerIndication.h>
#include <aidl/android/hardware/gnss/BnGnssPsds.h>
+#include <aidl/android/hardware/gnss/gnss_assistance/BnGnssAssistanceInterface.h>
#include <aidl/android/hardware/gnss/measurement_corrections/BnMeasurementCorrectionsInterface.h>
#include <aidl/android/hardware/gnss/visibility_control/BnGnssVisibilityControl.h>
#include <atomic>
@@ -83,6 +84,9 @@
std::shared_ptr<android::hardware::gnss::measurement_corrections::
IMeasurementCorrectionsInterface>* iMeasurementCorrections)
override;
+ ndk::ScopedAStatus getExtensionGnssAssistanceInterface(
+ std::shared_ptr<android::hardware::gnss::gnss_assistance::IGnssAssistanceInterface>*
+ 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 0000000..2ef334c
--- /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 <aidl/android/hardware/gnss/BnGnss.h>
+#include <log/log.h>
+
+namespace aidl::android::hardware::gnss::gnss_assistance {
+
+std::shared_ptr<IGnssAssistanceCallback> GnssAssistanceInterface::sCallback = nullptr;
+
+ndk::ScopedAStatus GnssAssistanceInterface::setCallback(
+ const std::shared_ptr<IGnssAssistanceCallback>& callback) {
+ ALOGD("setCallback");
+ std::unique_lock<std::mutex> 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 0000000..9d92975
--- /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 <aidl/android/hardware/gnss/gnss_assistance/BnGnssAssistanceInterface.h>
+
+namespace aidl::android::hardware::gnss::gnss_assistance {
+
+struct GnssAssistanceInterface : public BnGnssAssistanceInterface {
+ public:
+ ndk::ScopedAStatus setCallback(
+ const std::shared_ptr<IGnssAssistanceCallback>& callback) override;
+ ndk::ScopedAStatus injectGnssAssistance(const GnssAssistance& gnssAssistance) override;
+
+ private:
+ // Guarded by mMutex
+ static std::shared_ptr<IGnssAssistanceCallback> sCallback;
+
+ // Synchronization lock for sCallback
+ mutable std::mutex mMutex;
+};
+
+} // namespace aidl::android::hardware::gnss::gnss_assistance
diff --git a/gnss/aidl/default/GnssDebug.cpp b/gnss/aidl/default/GnssDebug.cpp
index 5ae6edd..185bfe4 100644
--- a/gnss/aidl/default/GnssDebug.cpp
+++ b/gnss/aidl/default/GnssDebug.cpp
@@ -126,9 +126,46 @@
.ephemerisAgeSeconds = 12,
.serverPredictionIsAvailable = true,
.serverPredictionAgeSeconds = 30};
+ SatelliteData satelliteData10 = {
+ .svid = 2,
+ .constellation = GnssConstellationType::GALILEO,
+ .ephemerisType = SatelliteEphemerisType::EPHEMERIS,
+ .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM,
+ .ephemerisHealth = SatelliteEphemerisHealth::GOOD,
+ .ephemerisAgeSeconds = 12,
+ .serverPredictionIsAvailable = true,
+ .serverPredictionAgeSeconds = 30};
+ SatelliteData satelliteData11 = {
+ .svid = 4,
+ .constellation = GnssConstellationType::GALILEO,
+ .ephemerisType = SatelliteEphemerisType::EPHEMERIS,
+ .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM,
+ .ephemerisHealth = SatelliteEphemerisHealth::GOOD,
+ .ephemerisAgeSeconds = 12,
+ .serverPredictionIsAvailable = true,
+ .serverPredictionAgeSeconds = 30};
+ SatelliteData satelliteData12 = {
+ .svid = 10,
+ .constellation = GnssConstellationType::GALILEO,
+ .ephemerisType = SatelliteEphemerisType::EPHEMERIS,
+ .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM,
+ .ephemerisHealth = SatelliteEphemerisHealth::GOOD,
+ .ephemerisAgeSeconds = 12,
+ .serverPredictionIsAvailable = true,
+ .serverPredictionAgeSeconds = 30};
+ SatelliteData satelliteData13 = {
+ .svid = 29,
+ .constellation = GnssConstellationType::GALILEO,
+ .ephemerisType = SatelliteEphemerisType::EPHEMERIS,
+ .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM,
+ .ephemerisHealth = SatelliteEphemerisHealth::GOOD,
+ .ephemerisAgeSeconds = 12,
+ .serverPredictionIsAvailable = true,
+ .serverPredictionAgeSeconds = 30};
std::vector<SatelliteData> satelliteDataArrayDebug = {
- satelliteData1, satelliteData2, satelliteData3, satelliteData4, satelliteData5,
- satelliteData6, satelliteData7, satelliteData8, satelliteData9};
+ satelliteData1, satelliteData2, satelliteData3, satelliteData4, satelliteData5,
+ satelliteData6, satelliteData7, satelliteData8, satelliteData9, satelliteData10,
+ satelliteData11, satelliteData12, satelliteData13};
debugData->position = positionDebug;
debugData->time = timeDebug;
debugData->satelliteDataArray = satelliteDataArrayDebug;
diff --git a/gnss/aidl/default/gnss-default.xml b/gnss/aidl/default/gnss-default.xml
index c01069e..700e240 100644
--- a/gnss/aidl/default/gnss-default.xml
+++ b/gnss/aidl/default/gnss-default.xml
@@ -1,7 +1,7 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.gnss</name>
- <version>4</version>
+ <version>5</version>
<interface>
<name>IGnss</name>
<instance>default</instance>
diff --git a/gnss/aidl/vts/Android.bp b/gnss/aidl/vts/Android.bp
index 2bd6f07..20cf44f 100644
--- a/gnss/aidl/vts/Android.bp
+++ b/gnss/aidl/vts/Android.bp
@@ -52,7 +52,7 @@
"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.cpp b/gnss/aidl/vts/gnss_hal_test.cpp
index 0dd8b32..f7deb29 100644
--- a/gnss/aidl/vts/gnss_hal_test.cpp
+++ b/gnss/aidl/vts/gnss_hal_test.cpp
@@ -276,35 +276,43 @@
}
/*
- * FindStrongFrequentBlockableSource:
+ * FindStrongFrequentSource:
*
- * Search through a GnssSvStatus list for the strongest blockable satellite observed enough times
+ * Search through a GnssSvStatus list for the strongest satellite observed enough times per
+ * constellation
*
- * returns the strongest source,
- * or a source with constellation == UNKNOWN if none are found sufficient times
+ * returns the strongest sources for each constellation,
+ * or an empty vector if none are found sufficient times
*/
-BlocklistedSource GnssHalTest::FindStrongFrequentBlockableSource(
+std::vector<BlocklistedSource> GnssHalTest::FindStrongFrequentSources(
const std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_list,
const int min_observations) {
- return FindStrongFrequentBlockableSource(convertToAidl(sv_info_list), min_observations);
+ return FindStrongFrequentSources(convertToAidl(sv_info_list), min_observations);
}
-BlocklistedSource GnssHalTest::FindStrongFrequentBlockableSource(
+bool GnssHalTest::isBlockableConstellation(const GnssConstellationType constellation,
+ const bool isCnBuild) {
+ if (constellation == GnssConstellationType::GPS) {
+ return false;
+ }
+ if (isCnBuild && (constellation == GnssConstellationType::BEIDOU)) {
+ // Do not blocklist BDS on CN builds
+ return false;
+ }
+ return true;
+}
+
+std::vector<BlocklistedSource> GnssHalTest::FindStrongFrequentSources(
const std::list<std::vector<IGnssCallback::GnssSvInfo>> sv_info_list,
const int min_observations) {
- std::map<ComparableBlocklistedSource, SignalCounts> mapSignals;
+ ALOGD("Find strongest sv from %d sv_info_list with %d min_observations.",
+ (int)sv_info_list.size(), min_observations);
- bool isCnBuild = Utils::isCnBuild();
- ALOGD("isCnBuild: %s", isCnBuild ? "true" : "false");
+ std::map<ComparableBlocklistedSource, SignalCounts> mapSignals;
for (const auto& sv_info_vec : sv_info_list) {
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
const auto& gnss_sv = sv_info_vec[iSv];
- if ((gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX) &&
- (gnss_sv.constellation != GnssConstellationType::GPS)) {
- if (isCnBuild && (gnss_sv.constellation == GnssConstellationType::BEIDOU)) {
- // Do not blocklist BDS on CN builds
- continue;
- }
+ if (gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX) {
ComparableBlocklistedSource source;
source.id.svid = gnss_sv.svid;
source.id.constellation = gnss_sv.constellation;
@@ -326,27 +334,76 @@
}
}
- float max_cn0_dbhz_with_sufficient_count = 0.;
- int total_observation_count = 0;
- int blocklisted_source_count_observation = 0;
+ // the Cn0 of the strongest SV per constellation
+ std::unordered_map<GnssConstellationType, float> max_cn0_map;
+ // # of total observations of all signals per constellation
+ std::unordered_map<GnssConstellationType, int> total_observation_count_map;
+ // # of observations of the strongest sv per constellation
+ std::unordered_map<GnssConstellationType, int> source_observation_count_map;
+ // the source to blocklist per constellation
+ std::unordered_map<GnssConstellationType, ComparableBlocklistedSource> source_map;
+ // # of signals per constellation
+ std::unordered_map<GnssConstellationType, int> signal_count_map;
- ComparableBlocklistedSource source_to_blocklist; // initializes to zero = UNKNOWN constellation
for (auto const& pairSignal : mapSignals) {
- total_observation_count += pairSignal.second.observations;
- if ((pairSignal.second.observations >= min_observations) &&
- (pairSignal.second.max_cn0_dbhz > max_cn0_dbhz_with_sufficient_count)) {
- source_to_blocklist = pairSignal.first;
- blocklisted_source_count_observation = pairSignal.second.observations;
- max_cn0_dbhz_with_sufficient_count = pairSignal.second.max_cn0_dbhz;
+ ComparableBlocklistedSource source = pairSignal.first;
+ total_observation_count_map[source.id.constellation] += pairSignal.second.observations;
+ signal_count_map[source.id.constellation]++;
+ if (pairSignal.second.observations < min_observations) {
+ continue;
+ }
+ if (pairSignal.second.max_cn0_dbhz > max_cn0_map[source.id.constellation]) {
+ source_map[source.id.constellation] = pairSignal.first;
+ source_observation_count_map[source.id.constellation] = pairSignal.second.observations;
+ max_cn0_map[source.id.constellation] = pairSignal.second.max_cn0_dbhz;
}
}
- ALOGD("Among %d observations, chose svid %d, constellation %d, "
- "with %d observations at %.1f max CNo",
- total_observation_count, source_to_blocklist.id.svid,
- (int)source_to_blocklist.id.constellation, blocklisted_source_count_observation,
- max_cn0_dbhz_with_sufficient_count);
- return source_to_blocklist.id;
+ std::vector<BlocklistedSource> sources;
+ if (aidl_gnss_hal_->getInterfaceVersion() <= 4) {
+ /* For AIDL version <= 4 (launched-in-15 or earlier), only blocklist 1 sv */
+ float max_cn0 = 0;
+ ComparableBlocklistedSource source_to_blocklist;
+ for (auto const& pair : source_map) {
+ GnssConstellationType constellation = pair.first;
+ ComparableBlocklistedSource source = pair.second;
+ if (max_cn0_map[constellation] > max_cn0) {
+ max_cn0 = max_cn0_map[constellation];
+ source_to_blocklist = source;
+ }
+ }
+ if (source_to_blocklist.id.constellation != GnssConstellationType::UNKNOWN) {
+ ALOGD("In constellation %d, among %d observed SVs, svid %d is chosen to blocklist. "
+ "It has %d observations with max Cn0: %.1f among %d total observations of this "
+ "constellation.",
+ (int)source_to_blocklist.id.constellation,
+ signal_count_map[source_to_blocklist.id.constellation],
+ source_to_blocklist.id.svid,
+ source_observation_count_map[source_to_blocklist.id.constellation], max_cn0,
+ total_observation_count_map[source_to_blocklist.id.constellation]);
+ sources.push_back(source_to_blocklist.id);
+ }
+ } else {
+ /* For AIDL version >= 5 (launched-in-16 or later), blocklist 1 sv per constellation */
+ for (auto const& pair : source_map) {
+ ComparableBlocklistedSource source = pair.second;
+ if (signal_count_map[source.id.constellation] < 4) {
+ // Skip the constellation with a small number of signals
+ // 4 is arbitrarily chosen to avoid affecting constellations with a limited coverage
+ continue;
+ }
+ ALOGD("In constellation %d, among %d observed SVs, svid %d is chosen to blocklist. "
+ "It has %d observations with max Cn0: %.1f among %d total observations of this "
+ "constellation.",
+ (int)source.id.constellation, signal_count_map[source.id.constellation],
+ source.id.svid, source_observation_count_map[source.id.constellation],
+ max_cn0_map[source.id.constellation],
+ total_observation_count_map[source.id.constellation]);
+ sources.push_back(source.id);
+ }
+ }
+
+ return sources;
}
GnssConstellationType GnssHalTest::startLocationAndGetBlockableConstellation(
diff --git a/gnss/aidl/vts/gnss_hal_test.h b/gnss/aidl/vts/gnss_hal_test.h
index dec5856..c41620a 100644
--- a/gnss/aidl/vts/gnss_hal_test.h
+++ b/gnss/aidl/vts/gnss_hal_test.h
@@ -81,14 +81,17 @@
std::list<std::vector<android::hardware::gnss::IGnssCallback::GnssSvInfo>> convertToAidl(
const std::list<hidl_vec<android::hardware::gnss::V2_1::IGnssCallback::GnssSvInfo>>&
sv_info_list);
- android::hardware::gnss::BlocklistedSource FindStrongFrequentBlockableSource(
+ std::vector<android::hardware::gnss::BlocklistedSource> FindStrongFrequentSources(
const std::list<hidl_vec<android::hardware::gnss::V2_1::IGnssCallback::GnssSvInfo>>
sv_info_list,
const int min_observations);
- android::hardware::gnss::BlocklistedSource FindStrongFrequentBlockableSource(
+ std::vector<android::hardware::gnss::BlocklistedSource> FindStrongFrequentSources(
const std::list<std::vector<android::hardware::gnss::IGnssCallback::GnssSvInfo>>
sv_info_list,
const int min_observations);
+ bool isBlockableConstellation(
+ const android::hardware::gnss::GnssConstellationType constellation,
+ const bool isCnBuild);
void checkGnssMeasurementClockFields(const android::hardware::gnss::GnssData& measurement);
void checkGnssMeasurementFlags(const android::hardware::gnss::GnssMeasurement& measurement);
diff --git a/gnss/aidl/vts/gnss_hal_test_cases.cpp b/gnss/aidl/vts/gnss_hal_test_cases.cpp
index e4890a7..781476fd 100644
--- a/gnss/aidl/vts/gnss_hal_test_cases.cpp
+++ b/gnss/aidl/vts/gnss_hal_test_cases.cpp
@@ -25,6 +25,7 @@
#include <android/hardware/gnss/IGnssMeasurementInterface.h>
#include <android/hardware/gnss/IGnssPowerIndication.h>
#include <android/hardware/gnss/IGnssPsds.h>
+#include <android/hardware/gnss/gnss_assistance/IGnssAssistanceInterface.h>
#include <android/hardware/gnss/measurement_corrections/IMeasurementCorrectionsInterface.h>
#include <android/hardware/gnss/visibility_control/IGnssVisibilityControl.h>
#include <cutils/properties.h>
@@ -73,6 +74,8 @@
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;
@@ -612,7 +615,7 @@
* BlocklistIndividualSatellites:
*
* 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding
- * GnssStatus for common satellites (strongest and one other.)
+ * GnssStatus for common satellites (strongest one in each constellation.)
* 2a & b) Turns off location, and blocklists common satellites.
* 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
* GnssStatus does not use those satellites.
@@ -630,6 +633,7 @@
return;
}
+ const int kWarmUpLocations = 3;
const int kLocationsToAwait = 3;
const int kRetriesToUnBlocklist = 10;
@@ -638,7 +642,7 @@
} else {
aidl_gnss_cb_->location_cbq_.reset();
}
- StartAndCheckLocations(kLocationsToAwait);
+ StartAndCheckLocations(kLocationsToAwait + kWarmUpLocations);
int location_called_count = (aidl_gnss_hal_->getInterfaceVersion() <= 1)
? gnss_cb_->location_cbq_.calledCount()
: aidl_gnss_cb_->location_cbq_.calledCount();
@@ -647,37 +651,50 @@
int sv_info_list_cbq_size = (aidl_gnss_hal_->getInterfaceVersion() <= 1)
? gnss_cb_->sv_info_list_cbq_.size()
: aidl_gnss_cb_->sv_info_list_cbq_.size();
- EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
+ EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait + kWarmUpLocations);
ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)",
- sv_info_list_cbq_size, kLocationsToAwait, location_called_count);
+ sv_info_list_cbq_size, kLocationsToAwait + kWarmUpLocations, location_called_count);
/*
- * Identify strongest SV seen at least kLocationsToAwait -1 times
- * Why -1? To avoid test flakiness in case of (plausible) slight flakiness in strongest signal
- * observability (one epoch RF null)
+ * Identify strongest SV per constellation seen seen at least kLocationsToAwait -1 times.
+ *
+ * Why not (kLocationsToAwait + kWarmUpLocations)? To avoid test flakiness in case of
+ * (plausible) slight flakiness in strongest signal observability (one epoch RF null)
*/
const int kGnssSvInfoListTimeout = 2;
- BlocklistedSource source_to_blocklist;
+ std::vector<BlocklistedSource> sources_to_blocklist;
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
+ // Discard kWarmUpLocations sv_info_vec
+ std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> tmp;
+ int count =
+ gnss_cb_->sv_info_list_cbq_.retrieve(tmp, kWarmUpLocations, kGnssSvInfoListTimeout);
+ ASSERT_EQ(count, kWarmUpLocations);
+
+ // Retrieve (sv_info_list_cbq_size - kWarmUpLocations) sv_info_vec
std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_vec_list;
- int count = gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec_list, sv_info_list_cbq_size,
- kGnssSvInfoListTimeout);
- ASSERT_EQ(count, sv_info_list_cbq_size);
- source_to_blocklist =
- FindStrongFrequentBlockableSource(sv_info_vec_list, kLocationsToAwait - 1);
+ count = gnss_cb_->sv_info_list_cbq_.retrieve(
+ sv_info_vec_list, sv_info_list_cbq_size - kWarmUpLocations, kGnssSvInfoListTimeout);
+ ASSERT_EQ(count, sv_info_list_cbq_size - kWarmUpLocations);
+ sources_to_blocklist = FindStrongFrequentSources(sv_info_vec_list, kLocationsToAwait - 1);
} else {
+ // Discard kWarmUpLocations sv_info_vec
+ std::list<std::vector<IGnssCallback::GnssSvInfo>> tmp;
+ int count = aidl_gnss_cb_->sv_info_list_cbq_.retrieve(tmp, kWarmUpLocations,
+ kGnssSvInfoListTimeout);
+ ASSERT_EQ(count, kWarmUpLocations);
+
+ // Retrieve (sv_info_list_cbq_size - kWarmUpLocations) sv_info_vec
std::list<std::vector<IGnssCallback::GnssSvInfo>> sv_info_vec_list;
- int count = aidl_gnss_cb_->sv_info_list_cbq_.retrieve(
- sv_info_vec_list, sv_info_list_cbq_size, kGnssSvInfoListTimeout);
- ASSERT_EQ(count, sv_info_list_cbq_size);
- source_to_blocklist =
- FindStrongFrequentBlockableSource(sv_info_vec_list, kLocationsToAwait - 1);
+ count = aidl_gnss_cb_->sv_info_list_cbq_.retrieve(
+ sv_info_vec_list, sv_info_list_cbq_size - kWarmUpLocations, kGnssSvInfoListTimeout);
+ ASSERT_EQ(count, sv_info_list_cbq_size - kWarmUpLocations);
+ sources_to_blocklist = FindStrongFrequentSources(sv_info_vec_list, kLocationsToAwait - 1);
}
- if (source_to_blocklist.constellation == GnssConstellationType::UNKNOWN) {
- // Cannot find a blockable satellite. Let the test pass.
- ALOGD("Cannot find a blockable satellite. Letting the test pass.");
+ if (sources_to_blocklist.empty()) {
+ // Cannot find a satellite to blocklist. Let the test pass.
+ ALOGD("Cannot find a satellite to blocklist. Letting the test pass.");
return;
}
@@ -690,9 +707,7 @@
ASSERT_NE(gnss_configuration_hal, nullptr);
std::vector<BlocklistedSource> sources;
- sources.resize(1);
- sources[0] = source_to_blocklist;
-
+ sources = sources_to_blocklist;
status = gnss_configuration_hal->setBlocklist(sources);
ASSERT_TRUE(status.isOk());
@@ -723,26 +738,47 @@
EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)",
sv_info_list_cbq_size, kLocationsToAwait, location_called_count);
+ bool isCnBuild = Utils::isCnBuild();
for (int i = 0; i < sv_info_list_cbq_size; ++i) {
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
auto& gnss_sv = sv_info_vec[iSv];
- EXPECT_FALSE(
- (gnss_sv.v2_0.v1_0.svid == source_to_blocklist.svid) &&
- (static_cast<GnssConstellationType>(gnss_sv.v2_0.constellation) ==
- source_to_blocklist.constellation) &&
- (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
+ if (!(gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)) {
+ continue;
+ }
+ for (auto const& source : sources_to_blocklist) {
+ if (isBlockableConstellation(source.constellation, isCnBuild)) {
+ EXPECT_FALSE((gnss_sv.v2_0.v1_0.svid == source.svid) &&
+ (static_cast<GnssConstellationType>(
+ gnss_sv.v2_0.constellation) == source.constellation));
+ } else if ((gnss_sv.v2_0.v1_0.svid == source.svid) &&
+ (static_cast<GnssConstellationType>(gnss_sv.v2_0.constellation) ==
+ source.constellation)) {
+ ALOGW("Found constellation %d, svid %d blocklisted but still used-in-fix.",
+ source.constellation, source.svid);
+ }
+ }
}
} else {
std::vector<IGnssCallback::GnssSvInfo> sv_info_vec;
aidl_gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
auto& gnss_sv = sv_info_vec[iSv];
- EXPECT_FALSE((gnss_sv.svid == source_to_blocklist.svid) &&
- (gnss_sv.constellation == source_to_blocklist.constellation) &&
- (gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX));
+ if (!(gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX)) {
+ continue;
+ }
+ for (auto const& source : sources_to_blocklist) {
+ if (isBlockableConstellation(source.constellation, isCnBuild)) {
+ EXPECT_FALSE((gnss_sv.svid == source.svid) &&
+ (gnss_sv.constellation == source.constellation));
+ } else if ((gnss_sv.svid == source.svid) &&
+ (gnss_sv.constellation == source.constellation)) {
+ ALOGW("Found constellation %d, svid %d blocklisted but still used-in-fix.",
+ gnss_sv.constellation, gnss_sv.svid);
+ }
+ }
}
}
}
@@ -792,12 +828,15 @@
gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
auto& gnss_sv = sv_info_vec[iSv];
- if ((gnss_sv.v2_0.v1_0.svid == source_to_blocklist.svid) &&
- (static_cast<GnssConstellationType>(gnss_sv.v2_0.constellation) ==
- source_to_blocklist.constellation) &&
- (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)) {
- strongest_sv_is_reobserved = true;
- break;
+ for (auto const& source : sources_to_blocklist) {
+ if ((gnss_sv.v2_0.v1_0.svid == source.svid) &&
+ (static_cast<GnssConstellationType>(gnss_sv.v2_0.constellation) ==
+ source.constellation) &&
+ (gnss_sv.v2_0.v1_0.svFlag &
+ IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)) {
+ strongest_sv_is_reobserved = true;
+ break;
+ }
}
}
} else {
@@ -805,11 +844,13 @@
aidl_gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
auto& gnss_sv = sv_info_vec[iSv];
- if ((gnss_sv.svid == source_to_blocklist.svid) &&
- (gnss_sv.constellation == source_to_blocklist.constellation) &&
- (gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX)) {
- strongest_sv_is_reobserved = true;
- break;
+ for (auto const& source : sources_to_blocklist) {
+ if ((gnss_sv.svid == source.svid) &&
+ (gnss_sv.constellation == source.constellation) &&
+ (gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX)) {
+ strongest_sv_is_reobserved = true;
+ break;
+ }
}
}
}
@@ -1877,3 +1918,22 @@
}
}
}
+
+/*
+ * 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<IGnssAssistanceInterface> 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 208bc59..e8c370a 100644
--- a/gnss/common/utils/default/Android.bp
+++ b/gnss/common/utils/default/Android.bp
@@ -57,6 +57,6 @@
"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/default/Utils.cpp b/gnss/common/utils/default/Utils.cpp
index 8303d93..740bc59 100644
--- a/gnss/common/utils/default/Utils.cpp
+++ b/gnss/common/utils/default/Utils.cpp
@@ -338,16 +338,25 @@
std::vector<GnssSvInfo> Utils::getMockSvInfoList() {
std::vector<GnssSvInfo> gnssSvInfoList = {
+ // svid in [1, 32] for GPS
getMockSvInfo(3, GnssConstellationType::GPS, 32.5, 27.5, 59.1, 166.5, kGpsL1FreqHz),
getMockSvInfo(5, GnssConstellationType::GPS, 27.0, 22.0, 29.0, 56.5, kGpsL1FreqHz),
getMockSvInfo(17, GnssConstellationType::GPS, 30.5, 25.5, 71.0, 77.0, kGpsL5FreqHz),
getMockSvInfo(26, GnssConstellationType::GPS, 24.1, 19.1, 28.0, 253.0, kGpsL5FreqHz),
+ // svid in [1, 36] for GAL
+ getMockSvInfo(2, GnssConstellationType::GALILEO, 33.5, 27.5, 59.1, 166.5, kGalE1FreqHz),
+ getMockSvInfo(4, GnssConstellationType::GALILEO, 28.0, 22.0, 29.0, 56.5, kGalE1FreqHz),
+ getMockSvInfo(10, GnssConstellationType::GALILEO, 35.5, 25.5, 71.0, 77.0, kGalE1FreqHz),
+ getMockSvInfo(29, GnssConstellationType::GALILEO, 34.1, 19.1, 28.0, 253.0,
+ kGalE1FreqHz),
+ // "1 <= svid <= 25 || 93 <= svid <= 106" for GLO
getMockSvInfo(5, GnssConstellationType::GLONASS, 20.5, 15.5, 11.5, 116.0, kGloG1FreqHz),
getMockSvInfo(17, GnssConstellationType::GLONASS, 21.5, 16.5, 28.5, 186.0,
kGloG1FreqHz),
getMockSvInfo(18, GnssConstellationType::GLONASS, 28.3, 25.3, 38.8, 69.0, kGloG1FreqHz),
getMockSvInfo(10, GnssConstellationType::GLONASS, 25.0, 20.0, 66.0, 247.0,
kGloG1FreqHz),
+ // "1 <= X <= 14" for IRNSS
getMockSvInfo(3, GnssConstellationType::IRNSS, 22.0, 19.7, 35.0, 112.0, kIrnssL5FreqHz),
};
return gnssSvInfoList;
diff --git a/gnss/common/utils/default/include/Constants.h b/gnss/common/utils/default/include/Constants.h
index 489413e..e6605c4 100644
--- a/gnss/common/utils/default/include/Constants.h
+++ b/gnss/common/utils/default/include/Constants.h
@@ -31,6 +31,7 @@
const int64_t kMockTimestamp = 1519930775453L;
const float kGpsL1FreqHz = 1575.42 * 1e6;
const float kGpsL5FreqHz = 1176.45 * 1e6;
+const float kGalE1FreqHz = 1575.42 * 1e6;
const float kGloG1FreqHz = 1602.0 * 1e6;
const float kIrnssL5FreqHz = 1176.45 * 1e6;
diff --git a/gnss/common/utils/vts/Android.bp b/gnss/common/utils/vts/Android.bp
index ed5674c..b8b048a 100644
--- a/gnss/common/utils/vts/Android.bp
+++ b/gnss/common/utils/vts/Android.bp
@@ -44,7 +44,7 @@
"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 cdeb2e6..2213f15 100644
--- a/graphics/Android.bp
+++ b/graphics/Android.bp
@@ -35,9 +35,13 @@
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 {
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 @@
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 @@
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 6ed5bb2..7264a21 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 @@
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 63dca0a..b18d2be 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 @@
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 79737eb..8705aef 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/Dataspace.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/Dataspace.aidl
@@ -702,19 +702,32 @@
/**
* 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 <a href="https://developer.android.com/guide/topics/media/hdr-image-format">
* Ultra HDR Image format specification</a>.
- * 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)
*
* High-definition television
diff --git a/graphics/common/aidl/android/hardware/graphics/common/DisplayHotplugEvent.aidl b/graphics/common/aidl/android/hardware/graphics/common/DisplayHotplugEvent.aidl
index b35ada5..f779105 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 @@
@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 8cfdae6..e4da890 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 @@
* 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 cd47374..5b3a433 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 <algorithm>
-#include <limits>
-#include <memory>
#include <vector>
-#include <inttypes.h>
-#include <string.h>
-
#include <android/hardware/graphics/composer/2.2/IComposer.h>
#include <android/hardware/graphics/composer/2.2/IComposerClient.h>
#include <fmq/MessageQueue.h>
@@ -82,7 +76,7 @@
void setLayerPerFrameMetadata(const hidl_vec<IComposerClient::PerFrameMetadata>& metadataVec) {
beginCommand(IComposerClient::Command::SET_LAYER_PER_FRAME_METADATA,
- metadataVec.size() * 2);
+ static_cast<uint16_t>(metadataVec.size() * 2));
for (const auto& metadata : metadataVec) {
writeSigned(static_cast<int32_t>(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 1a9276c..46d8d4a 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 @@
public:
void setLayerPerFrameMetadata(const hidl_vec<IComposerClient::PerFrameMetadata>& metadataVec) {
beginCommand(IComposerClient::Command::SET_LAYER_PER_FRAME_METADATA,
- metadataVec.size() * 2);
+ static_cast<uint16_t>(metadataVec.size() * 2));
for (const auto& metadata : metadataVec) {
writeSigned(static_cast<int32_t>(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 e981da6..064fc57 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 @@
beginCommand(IComposerClient::Command::SET_LAYER_GENERIC_METADATA,
static_cast<uint16_t>(commandSize));
- write(key.size());
- writeBlob(key.size(), reinterpret_cast<const unsigned char*>(key.c_str()));
+ write(static_cast<uint32_t>(key.size()));
+ writeBlob(static_cast<uint32_t>(key.size()),
+ reinterpret_cast<const unsigned char*>(key.c_str()));
write(mandatory);
- write(value.size());
- writeBlob(value.size(), value.data());
+ write(static_cast<uint32_t>(value.size()));
+ writeBlob(static_cast<uint32_t>(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<uint32_t>((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 719318a..655188d 100644
--- a/graphics/composer/aidl/Android.bp
+++ b/graphics/composer/aidl/Android.bp
@@ -77,7 +77,6 @@
"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 0e2d72b..955ff89 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 @@
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 cce35e7..9e24a26 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 @@
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 040afd7..c522188 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 @@
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 a0cc9b0..06f2dde 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 @@
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 327e84c..4263140 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 @@
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 bc27cc7..1e568b9 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 @@
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 @@
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 8b2b13c..c26cb15 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 @@
@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/Lut.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Lut.aidl
deleted file mode 100644
index 5fae35b..0000000
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Lut.aidl
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-///////////////////////////////////////////////////////////////////////////////
-// 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 <name>-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;
-@VintfStability
-parcelable Lut {
- @nullable ParcelFileDescriptor pfd;
- android.hardware.graphics.composer3.LutProperties lutProperties;
-}
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 5edceb5..9516351 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 @@
@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 @@
enum SamplingKey {
RGB,
MAX_RGB,
+ CIE_Y,
}
}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Luts.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Luts.aidl
new file mode 100644
index 0000000..2890365
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Luts.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 <name>-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;
+@VintfStability
+parcelable Luts {
+ @nullable ParcelFileDescriptor pfd;
+ @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 0000000..e1149cb
--- /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 <name>-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 3bb09cd..5a77e22 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 @@
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 0000000..ff55370
--- /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 <name>-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 7154d74..fa58fb7 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 @@
* @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 02c1389..c3fd68e 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 @@
* 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 09c42dc..80d1337 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 @@
* 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 03ef8e6..a477eb6 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 @@
* 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 ac0a606..6b59a6f 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 @@
*/
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 213e8e9..7556962 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.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 @@
* 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 @@
* @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 @@
* 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 @@
*/
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 bf4f504..d7ef4c1 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.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 @@
/**
* 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/Lut.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/Lut.aidl
deleted file mode 100644
index abfeb14..0000000
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/Lut.aidl
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.graphics.composer3;
-
-import android.hardware.graphics.composer3.LutProperties;
-
-/**
- * LUT (Look-Up Table) Interface for Color Transformation.
- *
- * This interface allows the HWC (Hardware Composer) to define and communicate LUTs
- * with SurfaceFlinger.
- */
-
-@VintfStability
-parcelable Lut {
- /**
- * 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
- * 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.
- *
- * 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]`
- */
- @nullable ParcelFileDescriptor pfd;
-
- /**
- * The properties of the Lut.
- */
- LutProperties lutProperties;
-}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/LutProperties.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/LutProperties.aidl
index 47ec390..5f436d9 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 @@
* 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/Luts.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/Luts.aidl
new file mode 100644
index 0000000..393354e
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/Luts.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.graphics.composer3;
+
+import android.hardware.graphics.composer3.LutProperties;
+
+/**
+ * LUT (Look-Up Table) Interface for Color Transformation.
+ *
+ * This interface allows the HWC (Hardware Composer) to define and communicate LUTs
+ * with SurfaceFlinger.
+ */
+
+@VintfStability
+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 `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.
+ *
+ * For data precision, 32-bit float is used to specify a Lut 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 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;
+}
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 0000000..bf4a786
--- /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 b757656..0d8ea76 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 @@
* 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 0000000..48c1270
--- /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 331d717..2196530 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 @@
return std::move(data.releasedLayers);
}
+ // Get and clear saved layer present fences.
+ std::vector<PresentFence::LayerPresentFence> 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 @@
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 @@
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 @@
DisplayRequest displayRequests;
std::vector<ChangedCompositionLayer> changedLayers;
ndk::ScopedFileDescriptor presentFence;
+ std::vector<PresentFence::LayerPresentFence> layerPresentFences;
std::vector<ReleaseFences::Layer> 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 02fb3aa..71a04f3 100644
--- a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
+++ b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
@@ -25,21 +25,19 @@
#include <string.h>
#include <aidl/android/hardware/graphics/common/BlendMode.h>
-#include <aidl/android/hardware/graphics/composer3/Color.h>
-#include <aidl/android/hardware/graphics/composer3/Composition.h>
-#include <aidl/android/hardware/graphics/composer3/DisplayBrightness.h>
-#include <aidl/android/hardware/graphics/composer3/LayerBrightness.h>
-#include <aidl/android/hardware/graphics/composer3/LayerLifecycleBatchCommandType.h>
-#include <aidl/android/hardware/graphics/composer3/Lut.h>
-#include <aidl/android/hardware/graphics/composer3/PerFrameMetadata.h>
-#include <aidl/android/hardware/graphics/composer3/PerFrameMetadataBlob.h>
-
-#include <aidl/android/hardware/graphics/composer3/DisplayCommand.h>
-
#include <aidl/android/hardware/graphics/common/ColorTransform.h>
#include <aidl/android/hardware/graphics/common/FRect.h>
#include <aidl/android/hardware/graphics/common/Rect.h>
#include <aidl/android/hardware/graphics/common/Transform.h>
+#include <aidl/android/hardware/graphics/composer3/Color.h>
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+#include <aidl/android/hardware/graphics/composer3/DisplayBrightness.h>
+#include <aidl/android/hardware/graphics/composer3/DisplayCommand.h>
+#include <aidl/android/hardware/graphics/composer3/LayerBrightness.h>
+#include <aidl/android/hardware/graphics/composer3/LayerLifecycleBatchCommandType.h>
+#include <aidl/android/hardware/graphics/composer3/Luts.h>
+#include <aidl/android/hardware/graphics/composer3/PerFrameMetadata.h>
+#include <aidl/android/hardware/graphics/composer3/PerFrameMetadataBlob.h>
#include <log/log.h>
#include <sync/sync.h>
@@ -59,6 +57,8 @@
namespace aidl::android::hardware::graphics::composer3 {
+using PictureProfileId = decltype(LayerCommand().pictureProfileId);
+
class ComposerClientWriter final {
public:
static constexpr std::optional<ClockMonotonicTimestamp> kNoTimestamp = std::nullopt;
@@ -84,6 +84,10 @@
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<Rect>& damage,
float hdrSdrRatio) {
@@ -246,13 +250,13 @@
getLayerCommand(display, layer).blockingRegion.emplace(blocking.begin(), blocking.end());
}
- void setLayerLuts(int64_t display, int64_t layer, std::vector<Lut>& luts) {
- std::vector<std::optional<Lut>> currentLuts;
- for (auto& lut : luts) {
- currentLuts.push_back(std::make_optional<Lut>(
- {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<DisplayCommand> takePendingCommands() {
diff --git a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerServiceWriter.h b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerServiceWriter.h
index b50b84b..9dce140 100644
--- a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerServiceWriter.h
+++ b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerServiceWriter.h
@@ -116,6 +116,13 @@
mCommandsResults.emplace_back(std::move(clientTargetPropertyWithBrightness));
}
+ void setDisplayLuts(int64_t display, std::vector<DisplayLuts::LayerLut> layerLuts) {
+ DisplayLuts displayLuts;
+ displayLuts.display = display;
+ displayLuts.layerLuts = std::move(layerLuts);
+ mCommandsResults.emplace_back(std::move(displayLuts));
+ }
+
std::vector<CommandResultPayload> getPendingCommandResults() {
return std::move(mCommandsResults);
}
diff --git a/graphics/composer/aidl/vts/Android.bp b/graphics/composer/aidl/vts/Android.bp
index 894ca52..61c2593 100644
--- a/graphics/composer/aidl/vts/Android.bp
+++ b/graphics/composer/aidl/vts/Android.bp
@@ -71,6 +71,7 @@
"libarect",
"libbase",
"libfmq",
+ "libgmock",
"libgtest",
"libmath",
"librenderengine",
diff --git a/graphics/composer/aidl/vts/ReadbackVts.cpp b/graphics/composer/aidl/vts/ReadbackVts.cpp
index 9d5928d..b45c8c0 100644
--- a/graphics/composer/aidl/vts/ReadbackVts.cpp
+++ b/graphics/composer/aidl/vts/ReadbackVts.cpp
@@ -37,6 +37,12 @@
writer.setLayerBlendMode(mDisplay, mLayer, mBlendMode);
writer.setLayerBrightness(mDisplay, mLayer, mBrightness);
writer.setLayerDataspace(mDisplay, mLayer, mDataspace);
+ Luts luts{
+ .pfd = ::ndk::ScopedFileDescriptor(dup(mLuts.pfd.get())),
+ .offsets = mLuts.offsets,
+ .lutProperties = mLuts.lutProperties,
+ };
+ writer.setLayerLuts(mDisplay, mLayer, luts);
}
std::string ReadbackHelper::getColorModeString(ColorMode mode) {
@@ -103,6 +109,24 @@
layerSettings.geometry.positionTransform = scale * translation;
layerSettings.whitePointNits = mWhitePointNits;
layerSettings.sourceDataspace = static_cast<::android::ui::Dataspace>(mDataspace);
+ if (mLuts.pfd.get() >= 0 && mLuts.offsets) {
+ std::vector<int32_t> dimensions;
+ std::vector<int32_t> sizes;
+ std::vector<int32_t> keys;
+ dimensions.reserve(mLuts.lutProperties.size());
+ sizes.reserve(mLuts.lutProperties.size());
+ keys.reserve(mLuts.lutProperties.size());
+
+ for (auto& l : mLuts.lutProperties) {
+ dimensions.emplace_back(static_cast<int32_t>(l.dimension));
+ sizes.emplace_back(static_cast<int32_t>(l.size));
+ keys.emplace_back(static_cast<int32_t>(l.samplingKeys[0]));
+ }
+
+ layerSettings.luts = std::make_shared<::android::gui::DisplayLuts>(
+ ::android::base::unique_fd(dup(mLuts.pfd.get())), *mLuts.offsets, dimensions, sizes,
+ keys);
+ }
return layerSettings;
}
diff --git a/graphics/composer/aidl/vts/ReadbackVts.h b/graphics/composer/aidl/vts/ReadbackVts.h
index e3b2384..c04e37a 100644
--- a/graphics/composer/aidl/vts/ReadbackVts.h
+++ b/graphics/composer/aidl/vts/ReadbackVts.h
@@ -17,6 +17,7 @@
#pragma once
#include <aidl/android/hardware/graphics/composer3/IComposerClient.h>
+#include <aidl/android/hardware/graphics/composer3/Luts.h>
#include <android-base/unique_fd.h>
#include <android/hardware/graphics/composer3/ComposerClientReader.h>
#include <android/hardware/graphics/composer3/ComposerClientWriter.h>
@@ -26,6 +27,8 @@
#include "GraphicsComposerCallback.h"
#include "VtsComposerClient.h"
+using aidl::android::hardware::graphics::composer3::Luts;
+
namespace aidl::android::hardware::graphics::composer3::vts {
using ::android::renderengine::LayerSettings;
@@ -80,6 +83,7 @@
void setTransform(Transform transform) { mTransform = transform; }
void setAlpha(float alpha) { mAlpha = alpha; }
void setBlendMode(BlendMode blendMode) { mBlendMode = blendMode; }
+ void setLuts(Luts luts) { mLuts = std::move(luts); }
BlendMode getBlendMode() const { return mBlendMode; }
@@ -105,6 +109,7 @@
BlendMode mBlendMode = BlendMode::NONE;
uint32_t mZOrder = 0;
Dataspace mDataspace = Dataspace::UNKNOWN;
+ Luts mLuts;
};
class TestColorLayer : public TestLayer {
diff --git a/graphics/composer/aidl/vts/VtsComposerClient.cpp b/graphics/composer/aidl/vts/VtsComposerClient.cpp
index 89ba2e6..9b6a005 100644
--- a/graphics/composer/aidl/vts/VtsComposerClient.cpp
+++ b/graphics/composer/aidl/vts/VtsComposerClient.cpp
@@ -690,4 +690,10 @@
mDisplayResources.clear();
return true;
}
+
+std::pair<ScopedAStatus, int32_t> VtsComposerClient::getMaxLayerPictureProfiles(int64_t display) {
+ int32_t outMaxProfiles = 0;
+ return {mComposerClient->getMaxLayerPictureProfiles(display, &outMaxProfiles), outMaxProfiles};
+}
+
} // namespace aidl::android::hardware::graphics::composer3::vts
diff --git a/graphics/composer/aidl/vts/VtsComposerClient.h b/graphics/composer/aidl/vts/VtsComposerClient.h
index da6116f..53f5fae 100644
--- a/graphics/composer/aidl/vts/VtsComposerClient.h
+++ b/graphics/composer/aidl/vts/VtsComposerClient.h
@@ -198,6 +198,8 @@
std::vector<RefreshRateChangedDebugData> takeListOfRefreshRateChangedDebugData();
+ std::pair<ScopedAStatus, int32_t> getMaxLayerPictureProfiles(int64_t display);
+
static constexpr int32_t kMaxFrameIntervalNs = 50000000; // 20fps
static constexpr int32_t kNoFrameIntervalNs = 0;
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
index 9db8794..f81289a 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
@@ -20,6 +20,7 @@
#include <aidl/Vintf.h>
#include <aidl/android/hardware/graphics/common/BufferUsage.h>
#include <aidl/android/hardware/graphics/composer3/IComposer.h>
+#include <cutils/ashmem.h>
#include <gtest/gtest.h>
#include <ui/DisplayId.h>
#include <ui/DisplayIdentification.h>
@@ -527,6 +528,118 @@
}
}
+void generateLuts(Luts* luts, LutProperties::Dimension dimension, int32_t size,
+ LutProperties::SamplingKey key) {
+ size_t bufferSize = dimension == LutProperties::Dimension::ONE_D
+ ? static_cast<size_t>(size) * sizeof(float)
+ : static_cast<size_t>(size * size * 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<float> buffers(static_cast<size_t>(size), 0.5f);
+ memcpy(ptr, buffers.data(), bufferSize);
+ munmap(ptr, bufferSize);
+ luts->pfd = ndk::ScopedFileDescriptor(fd);
+ luts->offsets = std::vector<int32_t>{0};
+ luts->lutProperties = {LutProperties{dimension, size, {key}}};
+}
+
+TEST_P(GraphicsCompositionTest, Luts) {
+ ASSERT_TRUE(
+ mComposerClient->setClientTargetSlotCount(getPrimaryDisplayId(), kClientTargetSlotCount)
+ .isOk());
+ const auto& [status, properties] = mComposerClient->getOverlaySupport();
+ if (!status.isOk() && status.getExceptionCode() == EX_SERVICE_SPECIFIC &&
+ status.getServiceSpecificError() == IComposerClient::EX_UNSUPPORTED) {
+ GTEST_SKIP() << "getOverlaySupport is not supported";
+ return;
+ }
+
+ if (!properties.lutProperties) {
+ GTEST_SKIP() << "lutProperties is not supported";
+ return;
+ }
+
+ for (const auto& lutProperties : *properties.lutProperties) {
+ if (!lutProperties) {
+ continue;
+ }
+ auto& l = *lutProperties;
+
+ for (const auto& key : l.samplingKeys) {
+ for (ColorMode mode : mTestColorModes) {
+ EXPECT_TRUE(mComposerClient
+ ->setColorMode(getPrimaryDisplayId(), mode,
+ RenderIntent::COLORIMETRIC)
+ .isOk());
+
+ bool isSupported;
+ ASSERT_NO_FATAL_FAILURE(isSupported = getHasReadbackBuffer());
+ if (!isSupported) {
+ GTEST_SUCCEED()
+ << "Readback not supported or unsupported pixelFormat/dataspace";
+ return;
+ }
+
+ common::Rect coloredSquare({0, 0, getDisplayWidth(), getDisplayHeight()});
+
+ // expected color for each pixel
+ std::vector<Color> expectedColors(
+ static_cast<size_t>(getDisplayWidth() * getDisplayHeight()));
+ ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), coloredSquare,
+ WHITE);
+
+ auto layer = std::make_shared<TestBufferLayer>(
+ mComposerClient, *mTestRenderEngine, getPrimaryDisplayId(),
+ getDisplayWidth(), getDisplayHeight(), PixelFormat::RGBA_8888, *mWriter);
+ layer->setDisplayFrame(coloredSquare);
+ layer->setZOrder(10);
+ layer->setDataspace(Dataspace::SRGB);
+
+ Luts luts;
+ generateLuts(&luts, l.dimension, l.size, key);
+ layer->setLuts(std::move(luts));
+
+ ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors));
+
+ std::vector<std::shared_ptr<TestLayer>> layers = {layer};
+
+ ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient,
+ getDisplayWidth(), getDisplayHeight(), mPixelFormat,
+ mDataspace);
+ ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+ writeLayers(layers);
+ ASSERT_TRUE(mReader.takeErrors().empty());
+ mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
+ VtsComposerClient::kNoFrameIntervalNs);
+ execute();
+ // if hwc cannot handle and asks for composition change,
+ // just succeed the test
+ if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
+ GTEST_SUCCEED();
+ return;
+ }
+
+ auto changedCompositionTypes =
+ mReader.takeChangedCompositionTypes(getPrimaryDisplayId());
+ ASSERT_TRUE(changedCompositionTypes.empty());
+
+ mWriter->presentDisplay(getPrimaryDisplayId());
+ execute();
+ ASSERT_TRUE(mReader.takeErrors().empty());
+
+ ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), coloredSquare,
+ {188.f / 255.f, 188.f / 255.f, 188.f / 255.f, 1.0f});
+
+ ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+ mTestRenderEngine->setRenderLayers(layers);
+ ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->drawLayers());
+ ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->checkColorBuffer(expectedColors));
+ }
+ }
+ }
+}
+
TEST_P(GraphicsCompositionTest, MixedColorSpaces) {
ASSERT_TRUE(
mComposerClient->setClientTargetSlotCount(getPrimaryDisplayId(), kClientTargetSlotCount)
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
index eaf23b5..c1900d7 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
@@ -22,15 +22,19 @@
#include <aidl/android/hardware/graphics/common/PixelFormat.h>
#include <aidl/android/hardware/graphics/common/Rect.h>
#include <aidl/android/hardware/graphics/composer3/Composition.h>
+#include <aidl/android/hardware/graphics/composer3/OutputType.h>
#include <aidl/android/hardware/graphics/composer3/IComposer.h>
#include <android-base/properties.h>
#include <android/binder_process.h>
#include <android/hardware/graphics/composer3/ComposerClientReader.h>
#include <android/hardware/graphics/composer3/ComposerClientWriter.h>
#include <binder/ProcessState.h>
+#include <cutils/ashmem.h>
+#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <ui/Fence.h>
#include <ui/GraphicBuffer.h>
+#include <ui/PictureProfileHandle.h>
#include <ui/PixelFormat.h>
#include <algorithm>
#include <iterator>
@@ -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;
@@ -118,6 +124,15 @@
[&](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());
@@ -1254,6 +1269,16 @@
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);
@@ -2048,6 +2073,7 @@
EXPECT_TRUE(layerStatus.isOk());
writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, handle, /*acquireFence*/ -1);
execute();
+ ASSERT_TRUE(mReader.takeErrors().empty());
}
TEST_P(GraphicsComposerAidlCommandTest, SetLayerBufferMultipleTimes) {
@@ -3219,6 +3245,173 @@
});
}
+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();
+
+ // TODO (b/362319189): add Lut VTS enforcement
+ if ((!status.isOk() && status.getExceptionCode() == EX_SERVICE_SPECIFIC &&
+ status.getServiceSpecificError() == IComposerClient::EX_UNSUPPORTED) ||
+ (status.isOk() && !properties.lutProperties)) {
+ int32_t size = 7;
+ size_t bufferSize = static_cast<size_t>(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<float> 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);
+
+ const auto layer = createOnScreenLayer(getPrimaryDisplayId());
+ const auto buffer = allocate(::android::PIXEL_FORMAT_RGBA_8888);
+ ASSERT_NE(nullptr, buffer->handle);
+ writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, buffer->handle,
+ /*acquireFence*/ -1);
+ writer.setLayerLuts(getPrimaryDisplayId(), layer, luts);
+ writer.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
+ VtsComposerClient::kNoFrameIntervalNs);
+ execute();
+ const auto errors = mReader.takeErrors();
+ if (errors.size() == 1 && errors[0].errorCode == IComposerClient::EX_UNSUPPORTED) {
+ GTEST_SUCCEED() << "setLayerLuts is not supported";
+ return;
+ }
+ // change to client composition
+ ASSERT_FALSE(mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).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,
@@ -3249,6 +3442,11 @@
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 82306be..f4196b9 100644
--- a/graphics/mapper/stable-c/Android.bp
+++ b/graphics/mapper/stable-c/Android.bp
@@ -111,7 +111,7 @@
"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 97de0e2..d2ad3b1 100644
--- a/health/aidl/Android.bp
+++ b/health/aidl/Android.bp
@@ -50,9 +50,8 @@
version: "3",
imports: [],
},
-
],
- frozen: true,
+ frozen: false,
}
@@ -84,7 +83,7 @@
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 @@
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 e013e31..9303767 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 bfa1475..d993040 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 @@
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 0000000..b3c38ad
--- /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 <name>-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 b49dfff..e919f14 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 @@
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 af84089..1c953ee 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.BatteryStatus;
import android.hardware.health.DiskStats;
import android.hardware.health.StorageInfo;
+import android.hardware.health.HingeInfo;
/**
* Health Information.
@@ -115,7 +116,6 @@
* Battery capacity level. See {@link BatteryCapacityLevel} for more details.
*/
BatteryCapacityLevel batteryCapacityLevel;
-
/**
* Value of {@link #batteryChargeTimeToFullNowSeconds} if it is not
* supported.
@@ -148,4 +148,8 @@
* 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 0000000..ad38821
--- /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 bdfe07a..c88141c 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.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 @@
* 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 2071f08..cc5d0a0 100644
--- a/health/aidl/default/Android.bp
+++ b/health/aidl/default/Android.bp
@@ -29,7 +29,7 @@
"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 @@
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 @@
"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 37662ea..d0e2dac 100644
--- a/health/aidl/default/Health.cpp
+++ b/health/aidl/default/Health.cpp
@@ -192,6 +192,12 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
+ndk::ScopedAStatus Health::getHingeInfo(std::vector<HingeInfo>*) {
+ // 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 2acaaba..8ddfbda 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 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.health</name>
- <version>3</version>
+ <version>4</version>
<fqname>IHealth/default</fqname>
</hal>
</manifest>
diff --git a/health/aidl/default/include/health-impl/Health.h b/health/aidl/default/include/health-impl/Health.h
index 429ae2a..96df517 100644
--- a/health/aidl/default/include/health-impl/Health.h
+++ b/health/aidl/default/include/health-impl/Health.h
@@ -72,6 +72,7 @@
// The default implementations return nothing in |out|.
ndk::ScopedAStatus getDiskStats(std::vector<DiskStats>* out) override;
ndk::ScopedAStatus getStorageInfo(std::vector<StorageInfo>* out) override;
+ ndk::ScopedAStatus getHingeInfo(std::vector<HingeInfo>* 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 25ba5f8..75bec97 100644
--- a/health/aidl/vts/functional/Android.bp
+++ b/health/aidl/vts/functional/Android.bp
@@ -40,7 +40,7 @@
"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 45a1e40..a44cd5e 100644
--- a/health/aidl/vts/functional/VtsHalHealthTargetTest.cpp
+++ b/health/aidl/vts/functional/VtsHalHealthTargetTest.cpp
@@ -360,6 +360,20 @@
}
/*
+ * Tests the values returned by getHingeInfo() from interface IHealth.
+ */
+TEST_P(HealthAidl, getHingeInfo) {
+ std::vector<HingeInfo> 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.
*/
TEST_P(HealthAidl, getDiskStats) {
diff --git a/health/utils/libhealthshim/Android.bp b/health/utils/libhealthshim/Android.bp
index b0ea743..9f9970f 100644
--- a/health/utils/libhealthshim/Android.bp
+++ b/health/utils/libhealthshim/Android.bp
@@ -34,7 +34,7 @@
"-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 ff6849b..9a62601 100644
--- a/health/utils/libhealthshim/include/health-shim/shim.h
+++ b/health/utils/libhealthshim/include/health-shim/shim.h
@@ -43,6 +43,7 @@
ndk::ScopedAStatus getEnergyCounterNwh(int64_t* _aidl_return) override;
ndk::ScopedAStatus getChargeStatus(BatteryStatus* _aidl_return) override;
ndk::ScopedAStatus getStorageInfo(std::vector<StorageInfo>* _aidl_return) override;
+ ndk::ScopedAStatus getHingeInfo(std::vector<HingeInfo>* _aidl_return) override;
ndk::ScopedAStatus getDiskStats(std::vector<DiskStats>* _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 a5ba919..2ddf97e 100644
--- a/health/utils/libhealthshim/shim.cpp
+++ b/health/utils/libhealthshim/shim.cpp
@@ -190,6 +190,10 @@
return ReturnAndResultToStatus(ret, out_result);
}
+ScopedAStatus HealthShim::getHingeInfo(std::vector<HingeInfo>* /*out*/) {
+ return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
ScopedAStatus HealthShim::getDiskStats(std::vector<DiskStats>* out) {
Result out_result = Result::UNKNOWN;
auto ret = service_->getDiskStats([out, &out_result](auto result, const auto& value) {
diff --git a/power/OWNERS b/power/OWNERS
index 13895bd..9576e14 100644
--- a/power/OWNERS
+++ b/power/OWNERS
@@ -1,3 +1,2 @@
# Bug component: 826709
file:platform/frameworks/base:/ADPF_OWNERS
-wvw@google.com
diff --git a/power/aidl/Android.bp b/power/aidl/Android.bp
index dc57613..2c80aab 100644
--- a/power/aidl/Android.bp
+++ b/power/aidl/Android.bp
@@ -69,46 +69,53 @@
"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 0000000..9ab4818
--- /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 <name>-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 0000000..a0c4b21
--- /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 <name>-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 0000000..a38156a
--- /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 <name>-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 0000000..21b1e69
--- /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 <name>-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 0000000..0d9084b
--- /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 <name>-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 0000000..08ea3dc
--- /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 <name>-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 0000000..6faa938
--- /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 <name>-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 0000000..bbd3d8b
--- /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 <name>-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 8acdaf2..080c0bd 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 @@
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 0000000..01ce157
--- /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 <name>-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 df31618..f6b32d0 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 @@
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 d0ae0ba..448dbb3 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 @@
@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 862fbc5..71da2d4 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 @@
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 0000000..d2fcae2
--- /dev/null
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SupportInfo.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 <name>-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;
+ int cpuMinCalculationWindowMillis = 50;
+ int cpuMaxCalculationWindowMillis = 10000;
+ int gpuMinCalculationWindowMillis = 50;
+ int gpuMaxCalculationWindowMillis = 10000;
+ int cpuMaxTidCount = 5;
+ }
+}
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 45013dd..25a5350 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 @@
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 0000000..43c636f
--- /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 0000000..7cd451c
--- /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 0000000..83a46ae
--- /dev/null
+++ b/power/aidl/android/hardware/power/CpuHeadroomParams.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.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 device should support the range specified in SupportInfo#HeadroomSupportInfo 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.
+ *
+ * The device should support the maximum TID count specified SupportInfo#HeadroomSupportInfo.
+ */
+ 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 0000000..e7ed8b6
--- /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 0000000..9ff77d3
--- /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 0000000..3075a8e
--- /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 0000000..2d64bd3
--- /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 the range specified in SupportInfo#HeadroomSupportInfo 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 0000000..ef3257d
--- /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 e25714f..ce61af4 100644
--- a/power/aidl/android/hardware/power/IPower.aidl
+++ b/power/aidl/android/hardware/power/IPower.aidl
@@ -18,10 +18,17 @@
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 @@
* @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.
+ * <p>
+ * @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.
+ * <p>
+ * @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 0000000..0642669
--- /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 1a8c505..1b8a3dd 100644
--- a/power/aidl/android/hardware/power/SessionHint.aidl
+++ b/power/aidl/android/hardware/power/SessionHint.aidl
@@ -72,4 +72,18 @@
* 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 f1ee64e..5bd0e15 100644
--- a/power/aidl/android/hardware/power/SessionMode.aidl
+++ b/power/aidl/android/hardware/power/SessionMode.aidl
@@ -25,4 +25,27 @@
* 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 27bf3e3..e98cc77 100644
--- a/power/aidl/android/hardware/power/SessionTag.aidl
+++ b/power/aidl/android/hardware/power/SessionTag.aidl
@@ -46,4 +46,9 @@
* 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 0000000..011dc18
--- /dev/null
+++ b/power/aidl/android/hardware/power/SupportInfo.aidl
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+ /**
+ * Minimum calculation window size for getCpuHeadroom in milliseconds.
+ *
+ * This should be no larger than 50ms.
+ */
+ int cpuMinCalculationWindowMillis = 50;
+
+ /**
+ * Maximum calculation window size for getCpuHeadroom in milliseconds.
+ *
+ * This should be no smaller than 10000ms.
+ */
+ int cpuMaxCalculationWindowMillis = 10000;
+
+ /**
+ * Minimum calculation window size for getGpuHeadroom in milliseconds.
+ *
+ * This should be no larger than 50ms.
+ */
+ int gpuMinCalculationWindowMillis = 50;
+
+ /**
+ * Maximum calculation window size for getGpuHeadroom in milliseconds.
+ *
+ * This should be no smaller than 10000ms.
+ */
+ int gpuMaxCalculationWindowMillis = 10000;
+
+ /**
+ * Maximum number of TIDs this device can support.
+ * This should be no smaller than 5.
+ */
+ int cpuMaxTidCount = 5;
+ }
+}
diff --git a/power/aidl/android/hardware/power/WorkDuration.aidl b/power/aidl/android/hardware/power/WorkDuration.aidl
index fcd638b..bcf279a 100644
--- a/power/aidl/android/hardware/power/WorkDuration.aidl
+++ b/power/aidl/android/hardware/power/WorkDuration.aidl
@@ -19,7 +19,7 @@
@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 @@
* 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 64294e5..0a9c90f 100644
--- a/power/aidl/default/Power.cpp
+++ b/power/aidl/default/Power.cpp
@@ -33,6 +33,8 @@
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 @@
ndk::enum_range<Boost>().end()};
const std::vector<Mode> MODE_RANGE{ndk::enum_range<Mode>().begin(), ndk::enum_range<Mode>().end()};
+template <class T>
+constexpr size_t enum_size() {
+ return static_cast<size_t>(*(ndk::enum_range<T>().end() - 1)) + 1;
+}
+
ScopedAStatus Power::setMode(Mode type, bool enabled) {
LOG(VERBOSE) << "Power setMode: " << static_cast<int32_t>(type) << " to: " << enabled;
return ScopedAStatus::ok();
@@ -64,6 +71,14 @@
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<int32_t>& tids, int64_t,
std::shared_ptr<IPowerHintSession>* _aidl_return) {
if (tids.size() == 0) {
@@ -105,11 +120,50 @@
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 <class E>
+int64_t bitsForEnum() {
+ return static_cast<int64_t>(std::bitset<enum_size<E>()>().set().to_ullong());
+}
+
+ndk::ScopedAStatus Power::getSupportInfo(SupportInfo* _aidl_return) {
+ static SupportInfo supportInfo = {.usesSessions = false,
+ .modes = bitsForEnum<Mode>(),
+ .boosts = bitsForEnum<Boost>(),
+ .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<CompositionData>&) {
+ 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 baabaa7..118097f 100644
--- a/power/aidl/default/Power.h
+++ b/power/aidl/default/Power.h
@@ -44,6 +44,14 @@
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<CompositionData>& in_data) override;
+ ndk::ScopedAStatus sendCompositionUpdate(const CompositionUpdate& in_update) override;
private:
std::vector<std::shared_ptr<IPowerHintSession>> mPowerHintSessions;
diff --git a/power/aidl/default/power-default.xml b/power/aidl/default/power-default.xml
index 418fb83..1bb73f3 100644
--- a/power/aidl/default/power-default.xml
+++ b/power/aidl/default/power-default.xml
@@ -1,7 +1,7 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.power</name>
- <version>5</version>
+ <version>6</version>
<fqname>IPower/default</fqname>
</hal>
</manifest>
diff --git a/power/aidl/vts/VtsHalPowerTargetTest.cpp b/power/aidl/vts/VtsHalPowerTargetTest.cpp
index 272674f..87797ae 100644
--- a/power/aidl/vts/VtsHalPowerTargetTest.cpp
+++ b/power/aidl/vts/VtsHalPowerTargetTest.cpp
@@ -30,21 +30,30 @@
#include <unistd.h>
#include <cstdint>
#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 @@
static_cast<SessionMode>(static_cast<int32_t>(kSessionModes.back()) + 1),
};
+template <class T>
+constexpr size_t enum_size() {
+ return static_cast<size_t>(*(ndk::enum_range<T>().end() - 1)) + 1;
+}
+
+template <class E>
+bool supportFromBitset(int64_t& supportInt, E type) {
+ return (supportInt >> static_cast<int>(type)) % 2;
+}
+
class DurationWrapper : public WorkDuration {
public:
DurationWrapper(int64_t dur, int64_t time) {
@@ -126,12 +145,17 @@
status = power->createHintSession(getpid(), getuid(), kSelfTids, 16666666L, &mSession);
mSessionSupport = status.isOk();
}
+ if (mServiceVersion >= 6) {
+ mSupportInfo = std::make_optional<SupportInfo>();
+ ASSERT_TRUE(power->getSupportInfo(&(*mSupportInfo)).isOk());
+ }
}
std::shared_ptr<IPower> power;
int32_t mServiceVersion;
std::shared_ptr<IPowerHintSession> mSession;
bool mSessionSupport = false;
+ std::optional<SupportInfo> mSupportInfo = std::nullopt;
};
class HintSessionAidl : public PowerAidl {
@@ -280,6 +304,42 @@
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<CpuHeadroomResult::globalHeadroom>(), 0.0f);
+ ASSERT_LE(headroom.get<CpuHeadroomResult::globalHeadroom>(), 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<GpuHeadroomResult::globalHeadroom>(), 0.0f);
+ ASSERT_LE(headroom.get<GpuHeadroomResult::globalHeadroom>(), 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 @@
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<CompositionData> 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/1.0/vts/functional/radio_hidl_hal_data.cpp b/radio/1.0/vts/functional/radio_hidl_hal_data.cpp
index e89f4ee..38cb33b 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_data.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_data.cpp
@@ -16,7 +16,6 @@
#include <android-base/logging.h>
#include <android/hardware/radio/1.2/IRadio.h>
-#include <gtest/gtest.h>
#include <radio_hidl_hal_utils_v1_0.h>
using namespace ::android::hardware::radio::V1_0;
@@ -73,16 +72,11 @@
CellIdentityTdscdma cit = cellIdentities.cellIdentityTdscdma[0];
hidl_mcc = cit.mcc;
hidl_mnc = cit.mnc;
- } else if (cellInfoType == CellInfoType::CDMA) {
+ } else {
// CellIndentityCdma has no mcc and mnc.
EXPECT_EQ(CellInfoType::CDMA, cellInfoType);
EXPECT_EQ(1, cellIdentities.cellIdentityCdma.size());
checkMccMnc = false;
- } else {
- // This test can be skipped for newer networks if a new RAT (e.g. 5g) that was not
- // supported in this version is added to the response from a modem that supports a new
- // version of this interface.
- GTEST_SKIP() << "Exempt from 1.0 test: camped on a new network:" << (int)cellInfoType;
}
// Check only one CellIdentity is size 1, and others must be 0.
diff --git a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
index 51ca967..2bce2f9 100644
--- a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
@@ -807,16 +807,11 @@
cellIdentities.cellIdentityTdscdma[0];
hidl_mcc = cit.base.mcc;
hidl_mnc = cit.base.mnc;
- } else if (cellInfoType == CellInfoType::CDMA) {
+ } else {
// CellIndentityCdma has no mcc and mnc.
EXPECT_EQ(CellInfoType::CDMA, cellInfoType);
EXPECT_EQ(1, cellIdentities.cellIdentityCdma.size());
checkMccMnc = false;
- } else {
- // This test can be skipped for newer networks if a new RAT (e.g. 5g) that was not
- // supported in this version is added to the response from a modem that supports a new
- // version of this interface.
- GTEST_SKIP() << "Exempt from 1.2 test: camped on a new network:" << (int)cellInfoType;
}
// Check only one CellIdentity is size 1, and others must be 0.
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 bba6bdd..ded4835 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 @@
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 6ff7bd0..4e0e133 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 @@
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 0000000..b27c86f
--- /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 <name>-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 0000000..cba5dd9
--- /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 <name>-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 a0ca4bf..1f8cbdc 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 @@
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 @@
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 @@
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 @@
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 abfb308..99ab0ea 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 @@
/* @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 ee8371c..00e584b 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 @@
/* @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 7382b1f..6a64595 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 @@
/* @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 0e98f4b..bbf8983 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 @@
/* @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 9982395..95bfd4c 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 @@
/* @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 d6292e7..759407f 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 @@
/* @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 bf5fde5..c69fcac 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 @@
@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 389fb26..a5cde9a 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 @@
/* @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 9b10464..c2403e4 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 @@
@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 ff4a111..3af0f8d 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 @@
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 3f1d120..ae398a9 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 @@
/* @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 e9937f0..33c0d70 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 @@
@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 667a8a7..36b9cdd 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 @@
@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 bc9c0ba..5fbd6c4 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 @@
/* @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 84532e3..ed9a9eb 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 @@
/* @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 94430a8..6e68665 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 @@
/* @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 ba27b39..dbd1575 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 @@
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 63571bb..548afd2 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 @@
/* @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 6d76a26..18c9496 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 @@
/* @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 fd3239d..732e70f 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 @@
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 e97e17d..2a7eccb 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 @@
/* @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 8af617f..ad7473b 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
@@ -36,9 +36,15 @@
@VintfStability
interface IRadioNetwork {
oneway void getAllowedNetworkTypesBitmap(in int serial);
+ /**
+ * @deprecated Android Telephony framework doesn't use this.
+ */
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);
@@ -55,18 +61,30 @@
oneway void isNrDualConnectivityEnabled(in int serial);
oneway void responseAcknowledgement();
oneway void setAllowedNetworkTypesBitmap(in int serial, in int networkTypeBitmap);
+ /**
+ * @deprecated Android Telephony framework doesn't use this.
+ */
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);
oneway void setLinkCapacityReportingCriteria(in int serial, in int hysteresisMs, in int hysteresisDlKbps, in int hysteresisUlKbps, in int[] thresholdsDownlinkKbps, in int[] thresholdsUplinkKbps, in android.hardware.radio.AccessNetwork accessNetwork);
+ /**
+ * @deprecated Android Telephony framework doesn't use this.
+ */
oneway void setLocationUpdates(in int serial, in boolean enable);
oneway void setNetworkSelectionModeAutomatic(in int serial);
oneway void setNetworkSelectionModeManual(in int serial, in String operatorNumeric, in android.hardware.radio.AccessNetwork ran);
oneway void setNrDualConnectivityState(in int serial, in android.hardware.radio.network.NrDualConnectivityState nrDualConnectivityState);
oneway void setResponseFunctions(in android.hardware.radio.network.IRadioNetworkResponse radioNetworkResponse, in android.hardware.radio.network.IRadioNetworkIndication radioNetworkIndication);
oneway void setSignalStrengthReportingCriteria(in int serial, in android.hardware.radio.network.SignalThresholdInfo[] signalThresholdInfos);
+ /**
+ * @deprecated Android Telephony framework doesn't use this.
+ */
oneway void setSuppServiceNotifications(in int serial, in boolean enable);
oneway void setSystemSelectionChannels(in int serial, in boolean specifyChannels, in android.hardware.radio.network.RadioAccessSpecifier[] specifiers);
oneway void startNetworkScan(in int serial, in android.hardware.radio.network.NetworkScanRequest request);
@@ -86,4 +104,7 @@
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 8eea14f..d4d6118 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 @@
@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 e7f2918..3c220ab 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
@@ -37,9 +37,15 @@
interface IRadioNetworkResponse {
oneway void acknowledgeRequest(in int serial);
oneway void getAllowedNetworkTypesBitmapResponse(in android.hardware.radio.RadioResponseInfo info, in int networkTypeBitmap);
+ /**
+ * @deprecated Android Telephony framework doesn't use this.
+ */
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);
@@ -55,17 +61,29 @@
oneway void getVoiceRegistrationStateResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.RegStateResult voiceRegResponse);
oneway void isNrDualConnectivityEnabledResponse(in android.hardware.radio.RadioResponseInfo info, in boolean isEnabled);
oneway void setAllowedNetworkTypesBitmapResponse(in android.hardware.radio.RadioResponseInfo info);
+ /**
+ * @deprecated Android Telephony framework doesn't use this.
+ */
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);
oneway void setLinkCapacityReportingCriteriaResponse(in android.hardware.radio.RadioResponseInfo info);
+ /**
+ * @deprecated Android Telephony framework doesn't use this.
+ */
oneway void setLocationUpdatesResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void setNetworkSelectionModeAutomaticResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void setNetworkSelectionModeManualResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void setNrDualConnectivityStateResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void setSignalStrengthReportingCriteriaResponse(in android.hardware.radio.RadioResponseInfo info);
+ /**
+ * @deprecated Android Telephony framework doesn't use this.
+ */
oneway void setSuppServiceNotificationsResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void setSystemSelectionChannelsResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void startNetworkScanResponse(in android.hardware.radio.RadioResponseInfo info);
@@ -85,4 +103,7 @@
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/NasProtocolMessage.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NasProtocolMessage.aidl
index 4fbc802..870cee1 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NasProtocolMessage.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NasProtocolMessage.aidl
@@ -47,4 +47,6 @@
CM_REESTABLISHMENT_REQUEST = 9,
CM_SERVICE_REQUEST = 10,
IMSI_DETACH_INDICATION = 11,
+ THREAT_IDENTIFIER_FALSE = 12,
+ THREAT_IDENTIFIER_TRUE = 13,
}
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 da7db9a..196ff19 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 @@
@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 0d7e48a..788a2dc 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 @@
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 13b06e7..d3e8295 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 @@
/* @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 1728e41..c868f81 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 @@
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,10 +69,16 @@
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);
oneway void setSimCardPower(in int serial, in android.hardware.radio.sim.CardPowerState powerUp);
+ /**
+ * @deprecated Android Telephony framework doesn't use this.
+ */
oneway void setUiccSubscription(in int serial, in android.hardware.radio.sim.SelectUiccSub uiccSub);
oneway void supplyIccPin2ForApp(in int serial, in String pin2, in String aid);
oneway void supplyIccPinForApp(in int serial, in String pin, in String aid);
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 a74b65a..0c4df06 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 @@
@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 c653847..6526d8b 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 @@
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,9 +69,15 @@
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);
+ /**
+ * @deprecated Android Telephony framework doesn't use this.
+ */
oneway void setUiccSubscriptionResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void supplyIccPin2ForAppResponse(in android.hardware.radio.RadioResponseInfo info, in int remainingRetries);
oneway void supplyIccPinForAppResponse(in android.hardware.radio.RadioResponseInfo info, in int remainingRetries);
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 27130b4..33af1fd 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 @@
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 0b36be4..7eb8c4e 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 @@
/* @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 0142792..a673c93 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 @@
/* @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 c71a8be..143409f 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 @@
/* @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 4e4a7ee..6968a8a 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 @@
/* @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 974e795..684b171 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 @@
/* @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 ae35fba..0bf802d 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 @@
/* @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 818d107..ce7c7c6 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 @@
/* @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 69447b4..04e7bdc 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 @@
/* @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 69d79aa..733d822 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 @@
/* @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 83b6fb9..9cf931c 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 @@
/* @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 d0a9451..d519bd9 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 @@
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 4614ee1..fac27f4 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 @@
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 46927c2..8a0af44 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 @@
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 17a039f..e6c223c 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 @@
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 73a267b..c719846 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 @@
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 1298ab0..f44385a 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 @@
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 */,
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 7c6a657..7aae601 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 @@
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,
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 85e9850..9b05c97 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 @@
@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 4099f83..0d10009 100644
--- a/radio/aidl/android/hardware/radio/AccessNetwork.aidl
+++ b/radio/aidl/android/hardware/radio/AccessNetwork.aidl
@@ -39,6 +39,7 @@
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 9ab4583..9588ed9 100644
--- a/radio/aidl/android/hardware/radio/RadioAccessFamily.aidl
+++ b/radio/aidl/android/hardware/radio/RadioAccessFamily.aidl
@@ -27,15 +27,22 @@
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,
diff --git a/radio/aidl/android/hardware/radio/RadioError.aidl b/radio/aidl/android/hardware/radio/RadioError.aidl
index 6ce8f67..6a28893 100644
--- a/radio/aidl/android/hardware/radio/RadioError.aidl
+++ b/radio/aidl/android/hardware/radio/RadioError.aidl
@@ -61,12 +61,11 @@
*/
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 7ae428b..de93a2b 100644
--- a/radio/aidl/android/hardware/radio/RadioTechnology.aidl
+++ b/radio/aidl/android/hardware/radio/RadioTechnology.aidl
@@ -25,15 +25,22 @@
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,
/**
diff --git a/radio/aidl/android/hardware/radio/RadioTechnologyFamily.aidl b/radio/aidl/android/hardware/radio/RadioTechnologyFamily.aidl
index 4b5498c..a13c358 100644
--- a/radio/aidl/android/hardware/radio/RadioTechnologyFamily.aidl
+++ b/radio/aidl/android/hardware/radio/RadioTechnologyFamily.aidl
@@ -27,6 +27,7 @@
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 936315c..e819fe0 100644
--- a/radio/aidl/android/hardware/radio/config/IRadioConfig.aidl
+++ b/radio/aidl/android/hardware/radio/config/IRadioConfig.aidl
@@ -27,6 +27,7 @@
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 @@
* 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 8182cd1..d526c51 100644
--- a/radio/aidl/android/hardware/radio/config/IRadioConfigResponse.aidl
+++ b/radio/aidl/android/hardware/radio/config/IRadioConfigResponse.aidl
@@ -18,6 +18,7 @@
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 @@
*/
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 0000000..fc9915e
--- /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 0000000..0534626
--- /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 6f043d9..592fde6 100644
--- a/radio/aidl/android/hardware/radio/data/DataCallFailCause.aidl
+++ b/radio/aidl/android/hardware/radio/data/DataCallFailCause.aidl
@@ -421,6 +421,7 @@
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 @@
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 @@
CONCURRENT_SERVICES_INCOMPATIBLE = 0x823,
/**
* Device does not have CDMA service.
+ * @deprecated Legacy CDMA is unsupported.
*/
NO_CDMA_SERVICE = 0x824,
/**
@@ -578,6 +586,7 @@
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 @@
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 35a6a8d..cef8f5d 100644
--- a/radio/aidl/android/hardware/radio/messaging/CdmaBroadcastSmsConfigInfo.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/CdmaBroadcastSmsConfigInfo.aidl
@@ -23,15 +23,18 @@
/**
* 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 2544ab5..ea5d8b2 100644
--- a/radio/aidl/android/hardware/radio/messaging/CdmaSmsAck.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/CdmaSmsAck.aidl
@@ -20,10 +20,12 @@
@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 a7ad233..11d953b 100644
--- a/radio/aidl/android/hardware/radio/messaging/CdmaSmsAddress.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/CdmaSmsAddress.aidl
@@ -22,40 +22,60 @@
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 @@
* 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 @@
* 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 51388b6..5332d82 100644
--- a/radio/aidl/android/hardware/radio/messaging/CdmaSmsMessage.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/CdmaSmsMessage.aidl
@@ -23,13 +23,19 @@
@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 8c494bb..132bbbb 100644
--- a/radio/aidl/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl
@@ -23,23 +23,28 @@
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 897ec80..3047859 100644
--- a/radio/aidl/android/hardware/radio/messaging/CdmaSmsWriteArgs.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/CdmaSmsWriteArgs.aidl
@@ -22,15 +22,21 @@
@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 945453c..b60a225 100644
--- a/radio/aidl/android/hardware/radio/messaging/IRadioMessaging.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/IRadioMessaging.aidl
@@ -65,6 +65,8 @@
* 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 @@
* 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 @@
* 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 @@
* 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 @@
* 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 @@
* 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 @@
* 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 @@
* 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 a177c2c..4c6529b 100644
--- a/radio/aidl/android/hardware/radio/messaging/IRadioMessagingIndication.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/IRadioMessagingIndication.aidl
@@ -32,6 +32,7 @@
*
* @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 @@
* 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 f0d7999..9b6e461 100644
--- a/radio/aidl/android/hardware/radio/messaging/IRadioMessagingResponse.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/IRadioMessagingResponse.aidl
@@ -62,6 +62,7 @@
* RadioError:OPERATION_NOT_ALLOWED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
+ * @deprecated Legacy CDMA is unsupported.
*/
void acknowledgeLastIncomingCdmaSmsResponse(in RadioResponseInfo info);
@@ -108,6 +109,7 @@
* 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 @@
* 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 @@
* 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 @@
* 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 @@
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:INVALID_MODEM_STATE
+ * @deprecated Legacy CDMA is unsupported.
*/
void setCdmaBroadcastActivationResponse(in RadioResponseInfo info);
@@ -427,6 +433,7 @@
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:INVALID_MODEM_STATE
+ * @deprecated Legacy CDMA is unsupported.
*/
void setCdmaBroadcastConfigResponse(in RadioResponseInfo info);
@@ -520,6 +527,7 @@
* 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 bbcd1cb..c205323 100644
--- a/radio/aidl/android/hardware/radio/messaging/ImsSmsMessage.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/ImsSmsMessage.aidl
@@ -37,6 +37,7 @@
/**
* 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 ea93727..da41d84 100644
--- a/radio/aidl/android/hardware/radio/messaging/SendSmsResult.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/SendSmsResult.aidl
@@ -23,15 +23,18 @@
/**
* 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 bfca5a9..15a833e 100644
--- a/radio/aidl/android/hardware/radio/modem/IRadioModem.aidl
+++ b/radio/aidl/android/hardware/radio/modem/IRadioModem.aidl
@@ -139,15 +139,15 @@
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 6d2504c..498f228 100644
--- a/radio/aidl/android/hardware/radio/modem/IRadioModemResponse.aidl
+++ b/radio/aidl/android/hardware/radio/modem/IRadioModemResponse.aidl
@@ -175,8 +175,6 @@
* 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 b6be54d..95fa0d7 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 @@
@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 9c48a8d..10421d6 100644
--- a/radio/aidl/android/hardware/radio/network/AccessTechnologySpecificInfo.aidl
+++ b/radio/aidl/android/hardware/radio/network/AccessTechnologySpecificInfo.aidl
@@ -25,6 +25,7 @@
@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 91b8500..333a6c4 100644
--- a/radio/aidl/android/hardware/radio/network/Cdma2000RegistrationInfo.aidl
+++ b/radio/aidl/android/hardware/radio/network/Cdma2000RegistrationInfo.aidl
@@ -20,29 +20,36 @@
@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 0bb7c04..4cad136 100644
--- a/radio/aidl/android/hardware/radio/network/CdmaRoamingType.aidl
+++ b/radio/aidl/android/hardware/radio/network/CdmaRoamingType.aidl
@@ -21,7 +21,10 @@
@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 0e241d3..214a512 100644
--- a/radio/aidl/android/hardware/radio/network/CdmaSignalStrength.aidl
+++ b/radio/aidl/android/hardware/radio/network/CdmaSignalStrength.aidl
@@ -23,11 +23,13 @@
/**
* 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 6142087..76a6675 100644
--- a/radio/aidl/android/hardware/radio/network/CellIdentity.aidl
+++ b/radio/aidl/android/hardware/radio/network/CellIdentity.aidl
@@ -34,6 +34,7 @@
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 acf3db1..7f33d2d 100644
--- a/radio/aidl/android/hardware/radio/network/CellIdentityCdma.aidl
+++ b/radio/aidl/android/hardware/radio/network/CellIdentityCdma.aidl
@@ -24,30 +24,36 @@
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 0a2bc54..0a0c0c0 100644
--- a/radio/aidl/android/hardware/radio/network/CellInfoCdma.aidl
+++ b/radio/aidl/android/hardware/radio/network/CellInfoCdma.aidl
@@ -24,7 +24,10 @@
@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 10a4a5f..eebed9e 100644
--- a/radio/aidl/android/hardware/radio/network/CellInfoRatSpecificInfo.aidl
+++ b/radio/aidl/android/hardware/radio/network/CellInfoRatSpecificInfo.aidl
@@ -37,6 +37,7 @@
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 ac6928e..e89eb88 100644
--- a/radio/aidl/android/hardware/radio/network/EvdoSignalStrength.aidl
+++ b/radio/aidl/android/hardware/radio/network/EvdoSignalStrength.aidl
@@ -23,16 +23,19 @@
/**
* 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 81d21e1..2509b6d 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
@@ -61,6 +61,8 @@
* Response function is IRadioNetworkResponse.getAvailableBandModesResponse()
*
* This is available when android.hardware.telephony.radio.access is defined.
+ *
+ * @deprecated Android Telephony framework doesn't use this.
*/
void getAvailableBandModes(in int serial);
@@ -94,6 +96,8 @@
* 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);
@@ -245,6 +249,8 @@
* Response function is IRadioNetworkResponse.setBandModeResponse()
*
* This is available when android.hardware.telephony.radio.access is defined.
+ *
+ * @deprecated Android Telephony framework doesn't use this.
*/
void setBandMode(in int serial, in RadioBandMode mode);
@@ -272,6 +278,8 @@
* 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 +342,7 @@
/**
* 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.
*
@@ -344,6 +352,8 @@
* Response function is IRadioNetworkResponse.setLocationUpdatesResponse()
*
* This is available when android.hardware.telephony.radio.access is defined.
+ *
+ * @deprecated Android Telephony framework doesn't use this.
*/
void setLocationUpdates(in int serial, in boolean enable);
@@ -437,6 +447,8 @@
* Response function is IRadioNetworkResponse.setSuppServiceNotificationsResponse()
*
* This is available when android.hardware.telephony.calling is defined.
+ *
+ * @deprecated Android Telephony framework doesn't use this.
*/
void setSuppServiceNotifications(in int serial, in boolean enable);
@@ -713,4 +725,60 @@
* 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 7b6fc6e..295061b 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl
@@ -63,6 +63,7 @@
*
* @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 5dcdb69..fd332fc 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
@@ -80,6 +80,8 @@
* RadioError:MODEM_ERR
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
+ *
+ * @deprecated Android Telephony framework doesn't use this.
*/
void getAvailableBandModesResponse(in RadioResponseInfo info, in RadioBandMode[] bandModes);
@@ -136,6 +138,7 @@
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:SIM_ABSENT
+ * @deprecated Legacy CDMA is unsupported.
*/
void getCdmaRoamingPreferenceResponse(in RadioResponseInfo info, in CdmaRoamingType type);
@@ -331,6 +334,8 @@
* RadioError:MODEM_ERR
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
+ *
+ * @deprecated Android Telephony framework doesn't use this.
*/
void setBandModeResponse(in RadioResponseInfo info);
@@ -372,6 +377,7 @@
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:SIM_ABSENT
+ * @deprecated Legacy CDMA is unsupported.
*/
void setCdmaRoamingPreferenceResponse(in RadioResponseInfo info);
@@ -435,6 +441,8 @@
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:SIM_ABSENT
+ *
+ * @deprecated Android Telephony framework doesn't use this.
*/
void setLocationUpdatesResponse(in RadioResponseInfo info);
@@ -526,6 +534,8 @@
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:SIM_ABSENT
+ *
+ * @deprecated Android Telephony framework doesn't use this.
*/
void setSuppServiceNotificationsResponse(in RadioResponseInfo info);
@@ -814,4 +824,53 @@
*/
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/NasProtocolMessage.aidl b/radio/aidl/android/hardware/radio/network/NasProtocolMessage.aidl
index 5a23661..f96a884 100644
--- a/radio/aidl/android/hardware/radio/network/NasProtocolMessage.aidl
+++ b/radio/aidl/android/hardware/radio/network/NasProtocolMessage.aidl
@@ -21,6 +21,9 @@
* generation is noted for each message type. Sample spec references are provided, but generally
* only reference one network generation's spec.
*
+ * The exceptions to this rule are THREAT_IDENTIFIER_FALSE and THREAT_IDENTIIFER_TRUE, which are
+ * included to accommodate threat ranking of disclosures based on modem logic.
+ *
* @hide
*/
@VintfStability
@@ -64,5 +67,11 @@
CM_SERVICE_REQUEST = 10,
// Reference: 3GPP TS 24.008 9.2.14
// Applies to 2g and 3g networks. Used for circuit-switched detach.
- IMSI_DETACH_INDICATION = 11
+ IMSI_DETACH_INDICATION = 11,
+ // Vendor-specific enumeration to identify a disclosure as potentially benign.
+ // Enables vendors to semantically define disclosures based on their own classification logic.
+ THREAT_IDENTIFIER_FALSE = 12,
+ // Vendor-specific enumeration to identify a disclosure as potentially harmful.
+ // Enables vendors to semantically define disclosures based on their own classification logic.
+ THREAT_IDENTIFIER_TRUE = 13
}
diff --git a/radio/aidl/android/hardware/radio/network/RegStateResult.aidl b/radio/aidl/android/hardware/radio/network/RegStateResult.aidl
index a7857ef..a4cb647 100644
--- a/radio/aidl/android/hardware/radio/network/RegStateResult.aidl
+++ b/radio/aidl/android/hardware/radio/network/RegStateResult.aidl
@@ -27,7 +27,7 @@
@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 @@
*/
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 fbe3be2..4e3bcf0 100644
--- a/radio/aidl/android/hardware/radio/network/SignalStrength.aidl
+++ b/radio/aidl/android/hardware/radio/network/SignalStrength.aidl
@@ -36,11 +36,13 @@
/**
* 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 3933889..1305a2c 100644
--- a/radio/aidl/android/hardware/radio/network/SignalThresholdInfo.aidl
+++ b/radio/aidl/android/hardware/radio/network/SignalThresholdInfo.aidl
@@ -29,7 +29,7 @@
/**
* 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 90aa8e0..7321b36 100644
--- a/radio/aidl/android/hardware/radio/sim/CardStatus.aidl
+++ b/radio/aidl/android/hardware/radio/sim/CardStatus.aidl
@@ -54,7 +54,8 @@
*/
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 4c6c1ef..2dbd6a8 100644
--- a/radio/aidl/android/hardware/radio/sim/CdmaSubscriptionSource.aidl
+++ b/radio/aidl/android/hardware/radio/sim/CdmaSubscriptionSource.aidl
@@ -21,6 +21,8 @@
@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 1e010b9..16573f4 100644
--- a/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl
+++ b/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl
@@ -123,6 +123,8 @@
* 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 @@
* 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 @@
/**
* 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 @@
* 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);
@@ -479,6 +485,8 @@
* Response function is IRadioSimResponse.setUiccSubscriptionResponse()
*
* This is available when android.hardware.telephony.subscription is defined.
+ *
+ * @deprecated Android Telephony framework doesn't use this.
*/
void setUiccSubscription(in int serial, in SelectUiccSub uiccSub);
diff --git a/radio/aidl/android/hardware/radio/sim/IRadioSimIndication.aidl b/radio/aidl/android/hardware/radio/sim/IRadioSimIndication.aidl
index fc6355d..d9735d3 100644
--- a/radio/aidl/android/hardware/radio/sim/IRadioSimIndication.aidl
+++ b/radio/aidl/android/hardware/radio/sim/IRadioSimIndication.aidl
@@ -41,6 +41,7 @@
*
* @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 cf08bad..62fa674 100644
--- a/radio/aidl/android/hardware/radio/sim/IRadioSimResponse.aidl
+++ b/radio/aidl/android/hardware/radio/sim/IRadioSimResponse.aidl
@@ -145,6 +145,7 @@
* 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 @@
* 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 @@
* 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 @@
* RadioError:NO_MEMORY
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
+ * @deprecated Legacy CDMA is unsupported.
*/
void setCdmaSubscriptionSourceResponse(in RadioResponseInfo info);
@@ -540,6 +544,8 @@
* RadioError:INVALID_ARGUMENTS
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
+ *
+ * @deprecated Android Telephony framework doesn't use this.
*/
void setUiccSubscriptionResponse(in RadioResponseInfo info);
diff --git a/radio/aidl/android/hardware/radio/voice/Call.aidl b/radio/aidl/android/hardware/radio/voice/Call.aidl
index 9990f28..5f62faa 100644
--- a/radio/aidl/android/hardware/radio/voice/Call.aidl
+++ b/radio/aidl/android/hardware/radio/voice/Call.aidl
@@ -77,6 +77,7 @@
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 d97b319..c77f3ec 100644
--- a/radio/aidl/android/hardware/radio/voice/CdmaCallWaiting.aidl
+++ b/radio/aidl/android/hardware/radio/voice/CdmaCallWaiting.aidl
@@ -22,44 +22,64 @@
@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 90b2715..bba6e4d 100644
--- a/radio/aidl/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl
+++ b/radio/aidl/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl
@@ -28,9 +28,11 @@
@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 19903c6..7232eba 100644
--- a/radio/aidl/android/hardware/radio/voice/CdmaInformationRecord.aidl
+++ b/radio/aidl/android/hardware/radio/voice/CdmaInformationRecord.aidl
@@ -32,54 +32,74 @@
@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 15c22a0..9cf0103 100644
--- a/radio/aidl/android/hardware/radio/voice/CdmaLineControlInfoRecord.aidl
+++ b/radio/aidl/android/hardware/radio/voice/CdmaLineControlInfoRecord.aidl
@@ -23,8 +23,12 @@
@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 3a00cae..bc00acb 100644
--- a/radio/aidl/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl
+++ b/radio/aidl/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl
@@ -26,13 +26,19 @@
@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 b6444ab..1f003a8 100644
--- a/radio/aidl/android/hardware/radio/voice/CdmaOtaProvisionStatus.aidl
+++ b/radio/aidl/android/hardware/radio/voice/CdmaOtaProvisionStatus.aidl
@@ -21,16 +21,28 @@
@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 cb30da8..514b8e1 100644
--- a/radio/aidl/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl
+++ b/radio/aidl/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl
@@ -25,19 +25,28 @@
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 4302ba4..2ada10b 100644
--- a/radio/aidl/android/hardware/radio/voice/CdmaSignalInfoRecord.aidl
+++ b/radio/aidl/android/hardware/radio/voice/CdmaSignalInfoRecord.aidl
@@ -25,18 +25,22 @@
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 44ac2b4..68b19b8 100644
--- a/radio/aidl/android/hardware/radio/voice/CdmaT53AudioControlInfoRecord.aidl
+++ b/radio/aidl/android/hardware/radio/voice/CdmaT53AudioControlInfoRecord.aidl
@@ -23,6 +23,8 @@
@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 564d761..6a1b992 100644
--- a/radio/aidl/android/hardware/radio/voice/CdmaT53ClirInfoRecord.aidl
+++ b/radio/aidl/android/hardware/radio/voice/CdmaT53ClirInfoRecord.aidl
@@ -23,5 +23,6 @@
@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 0c2b51d..74b1d5f 100644
--- a/radio/aidl/android/hardware/radio/voice/IRadioVoice.aidl
+++ b/radio/aidl/android/hardware/radio/voice/IRadioVoice.aidl
@@ -369,6 +369,8 @@
* 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 9de6364..f8bd999 100644
--- a/radio/aidl/android/hardware/radio/voice/IRadioVoiceIndication.aidl
+++ b/radio/aidl/android/hardware/radio/voice/IRadioVoiceIndication.aidl
@@ -42,8 +42,8 @@
* 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 @@
*
* @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 @@
* @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 @@
*
* @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 a904eaa..cf36ef9 100644
--- a/radio/aidl/android/hardware/radio/voice/IRadioVoiceResponse.aidl
+++ b/radio/aidl/android/hardware/radio/voice/IRadioVoiceResponse.aidl
@@ -564,6 +564,7 @@
* 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 7737e94..f6f4585 100644
--- a/radio/aidl/android/hardware/radio/voice/LastCallFailCause.aidl
+++ b/radio/aidl/android/hardware/radio/voice/LastCallFailCause.aidl
@@ -142,18 +142,28 @@
* 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 837c626..3834ecc 100644
--- a/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp
+++ b/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp
@@ -109,4 +109,19 @@
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<aidl::SimType>& /*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 17d5985..a1e48dc 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfig.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfig.h
@@ -55,7 +55,11 @@
int32_t serial,
const std::vector<aidl::android::hardware::radio::config::SlotPortMapping>& slotMap)
override;
-
+ ::ndk::ScopedAStatus getSimTypeInfo(int32_t serial) override;
+ ::ndk::ScopedAStatus setSimType(
+ int32_t serial,
+ const std::vector<aidl::android::hardware::radio::config::SimType>& 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 56724ae..c9a3270 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
@@ -114,6 +114,13 @@
::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<std::string>& carrierPlmnArray,
+ const std::vector<std::string>& 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 1e43789..b5aee5c 100644
--- a/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
+++ b/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
@@ -402,4 +402,28 @@
return ok();
}
+ScopedAStatus RadioNetwork::setSatellitePlmn(
+ int32_t serial, int32_t /*simSlot*/, const std::vector<std::string>& /*carrierPlmnArray*/,
+ const std::vector<std::string>& /*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 c532440..49439fa 100644
--- a/radio/aidl/vts/radio_config_response.cpp
+++ b/radio/aidl/vts/radio_config_response.cpp
@@ -75,3 +75,17 @@
parent_config.notify(info.serial);
return ndk::ScopedAStatus::ok();
}
+
+ndk::ScopedAStatus RadioConfigResponse::getSimTypeInfoResponse(const RadioResponseInfo& info,
+ const std::vector<SimTypeInfo>& /* 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 84c74fc..cdcc1bc 100644
--- a/radio/aidl/vts/radio_config_utils.h
+++ b/radio/aidl/vts/radio_config_utils.h
@@ -62,6 +62,11 @@
virtual ndk::ScopedAStatus getHalDeviceCapabilitiesResponse(
const RadioResponseInfo& info, bool modemReducedFeatureSet1) override;
+
+ virtual ndk::ScopedAStatus getSimTypeInfoResponse(
+ const RadioResponseInfo& info, const std::vector<SimTypeInfo>& 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 4d452d0..df59687 100644
--- a/radio/aidl/vts/radio_network_response.cpp
+++ b/radio/aidl/vts/radio_network_response.cpp
@@ -350,3 +350,24 @@
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 914cad0..1778c3f 100644
--- a/radio/aidl/vts/radio_network_test.cpp
+++ b/radio/aidl/vts/radio_network_test.cpp
@@ -609,6 +609,11 @@
}
}
+ if (!deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
+ GTEST_SKIP() << "Skipping setSignalStrengthReportingCriteria_Cdma2000 "
+ "due to undefined FEATURE_TELEPHONY_CDMA";
+ }
+
serial = GetRandomSerialNumber();
SignalThresholdInfo signalThresholdInfo;
@@ -824,9 +829,12 @@
signalThresholdInfoNgran.isEnabled = true;
signalThresholdInfoNgran.ran = AccessNetwork::NGRAN;
- const static std::vector<SignalThresholdInfo> candidateSignalThresholdInfos = {
+ std::vector<SignalThresholdInfo> candidateSignalThresholdInfos = {
signalThresholdInfoGeran, signalThresholdInfoUtran, signalThresholdInfoEutran,
- signalThresholdInfoCdma2000, signalThresholdInfoNgran};
+ signalThresholdInfoNgran};
+ if (deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
+ candidateSignalThresholdInfos.push_back(signalThresholdInfoCdma2000);
+ }
std::vector<SignalThresholdInfo> supportedSignalThresholdInfos;
for (size_t i = 0; i < candidateSignalThresholdInfos.size(); i++) {
@@ -2606,3 +2614,82 @@
{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 ad530eb..17c0896 100644
--- a/radio/aidl/vts/radio_network_utils.h
+++ b/radio/aidl/vts/radio_network_utils.h
@@ -48,6 +48,7 @@
std::vector<RadioAccessSpecifier> specifiers;
bool isCellularIdentifierTransparencyEnabled = false;
bool isSecurityAlgorithmsUpdatedEnabled = false;
+ bool isSatelliteEnabledForCarrier = false;
virtual ndk::ScopedAStatus acknowledgeRequest(int32_t serial) override;
@@ -183,6 +184,14 @@
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/security/secretkeeper/aidl/vts/dice_sample.rs b/security/secretkeeper/aidl/vts/dice_sample.rs
index 4ef396a..d6379e5 100644
--- a/security/secretkeeper/aidl/vts/dice_sample.rs
+++ b/security/secretkeeper/aidl/vts/dice_sample.rs
@@ -283,7 +283,7 @@
SUBCOMPONENT_AUTHORITY_HASH => hex::decode("ed255ae9ea98826f3f3a966849f0aaaf356d140c766a869048016e0ba10141af039fec5c53658ddebdad9c2339587c5ef5487bde89237ca79802238d91aebba8").unwrap(),
},
{
- SUBCOMPONENT_NAME => "apex:com.android.btservices",
+ SUBCOMPONENT_NAME => "apex:com.android.bt",
SUBCOMPONENT_SECURITY_VERSION => 990090000,
SUBCOMPONENT_CODE_HASH => hex::decode("d7aa86dfdf92e662d2210cd2b3ad4e4522c917e9e287268363aa90e20f9ae16c").unwrap(),
SUBCOMPONENT_AUTHORITY_HASH => hex::decode("a0d577d4a56cfad09aaa7abcd2355cd78872df85672f2faf9ac2fdf15c06147394e704c7473f28bed737803581a3d097275cc26d8095a4a896ee76167f9ee40e").unwrap(),
diff --git a/sensors/aidl/Android.bp b/sensors/aidl/Android.bp
index 8877e6e..63ace90 100644
--- a/sensors/aidl/Android.bp
+++ b/sensors/aidl/Android.bp
@@ -43,6 +43,6 @@
},
],
- 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 5184723..a35b54c 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 @@
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 b26040b..0566a64 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 @@
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 @@
@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 996be3d..677e6c4 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 @@
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 4521710..f401dac 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 8c864e9..9332c63 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 @@
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 b95299c..7775cfc 100644
--- a/sensors/aidl/android/hardware/sensors/Event.aidl
+++ b/sensors/aidl/android/hardware/sensors/Event.aidl
@@ -88,7 +88,7 @@
* 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 4904c3f..adaf8e6 100644
--- a/sensors/aidl/android/hardware/sensors/SensorType.aidl
+++ b/sensors/aidl/android/hardware/sensors/SensorType.aidl
@@ -718,6 +718,20 @@
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 7217b2f..548308e 100644
--- a/sensors/aidl/convert/Android.bp
+++ b/sensors/aidl/convert/Android.bp
@@ -36,7 +36,7 @@
"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 6f011ee..4bdcfb0 100644
--- a/sensors/aidl/default/Android.bp
+++ b/sensors/aidl/default/Android.bp
@@ -32,7 +32,7 @@
"libfmq",
"libpower",
"libbinder_ndk",
- "android.hardware.sensors-V2-ndk",
+ "android.hardware.sensors-V3-ndk",
],
export_include_dirs: ["include"],
srcs: [
@@ -58,7 +58,7 @@
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 7482ffe..6ca81d9 100644
--- a/sensors/aidl/default/multihal/Android.bp
+++ b/sensors/aidl/default/multihal/Android.bp
@@ -39,7 +39,7 @@
"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 36b28ed..bed2538 100644
--- a/sensors/aidl/default/sensors-default.xml
+++ b/sensors/aidl/default/sensors-default.xml
@@ -1,7 +1,7 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.sensors</name>
- <version>2</version>
+ <version>3</version>
<fqname>ISensors/default</fqname>
</hal>
</manifest>
diff --git a/sensors/aidl/multihal/Android.bp b/sensors/aidl/multihal/Android.bp
index cac5fc2..cee3db6 100644
--- a/sensors/aidl/multihal/Android.bp
+++ b/sensors/aidl/multihal/Android.bp
@@ -41,7 +41,7 @@
"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 5da4fbd..9186f64 100644
--- a/sensors/aidl/multihal/android.hardware.sensors-multihal.xml
+++ b/sensors/aidl/multihal/android.hardware.sensors-multihal.xml
@@ -17,7 +17,7 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.sensors</name>
- <version>2</version>
+ <version>3</version>
<fqname>ISensors/default</fqname>
</hal>
</manifest>
diff --git a/sensors/aidl/vts/Android.bp b/sensors/aidl/vts/Android.bp
index 1f96bb4..63371cd 100644
--- a/sensors/aidl/vts/Android.bp
+++ b/sensors/aidl/vts/Android.bp
@@ -42,7 +42,7 @@
"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 597a166..db77783 100644
--- a/thermal/aidl/Android.bp
+++ b/thermal/aidl/Android.bp
@@ -48,8 +48,7 @@
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 904496c..3cff780 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 @@
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 5e1d753..779544b 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 @@
@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 4aa4090..7c0ee24 100644
--- a/thermal/aidl/android/hardware/thermal/IThermal.aidl
+++ b/thermal/aidl/android/hardware/thermal/IThermal.aidl
@@ -225,4 +225,20 @@
* getMessage() must be populated with human-readable error message.
*/
void unregisterCoolingDeviceChangedCallback(in ICoolingDeviceChangedCallback callback);
+
+ /**
+ * Retrieves the forecasted {@link TemperatureType#SKIN} type temperature in Celsius.
+ *
+ * @param forecastSeconds the number of seconds to forecast the skin temperature, it should
+ * support any value from a superset of range [0, 60] seconds.
+ *
+ * @return forecasted skin temperature in Celsius unit at the forecasted seconds in future.
+ *
+ * @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 105f085..b40b7c2 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,24 @@
@VintfStability
interface IThermalChangedCallback {
/**
- * Send a thermal throttling event to all ThermalHAL
- * thermal event listeners.
+ * 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.
+ *
+ * Some devices may change the thresholds based on hardware state or app workload changes.
+ * While this is generally not recommended, it should be used with caution at low frequency
+ * especially for the {@link TemperatureType#SKIN} type temperature thresholds. Since such
+ * a skin type callback to system may trigger notifications to apps that have preivously
+ * registered thermal headroom listeners with a new set of headroom and thresholds in case
+ * any of them changed.
+ *
+ * @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 9fe62ce..9d89903 100644
--- a/thermal/aidl/default/Android.bp
+++ b/thermal/aidl/default/Android.bp
@@ -27,7 +27,7 @@
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 41d0be8..04efbd6 100644
--- a/thermal/aidl/default/Thermal.cpp
+++ b/thermal/aidl/default/Thermal.cpp
@@ -47,27 +47,85 @@
return ScopedAStatus::ok();
}
-ScopedAStatus Thermal::getTemperatures(std::vector<Temperature>* /* out_temperatures */) {
+ScopedAStatus Thermal::getTemperatures(std::vector<Temperature>* out_temperatures) {
LOG(VERBOSE) << __func__;
+ std::vector<Temperature> 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<Temperature>* /* out_temperatures */) {
+ std::vector<Temperature>* out_temperatures) {
LOG(VERBOSE) << __func__ << " TemperatureType: " << static_cast<int32_t>(in_type);
+ if (in_type == TemperatureType::SKIN) {
+ std::vector<Temperature> temperatures;
+ temperatures.push_back(Temperature{
+ .name = "skin",
+ .type = TemperatureType::SKIN,
+ .value = 30.1f,
+ });
+ *out_temperatures = temperatures;
+ } else if (in_type == TemperatureType::BATTERY) {
+ std::vector<Temperature> temperatures;
+ temperatures.push_back(Temperature{
+ .name = "battery",
+ .type = TemperatureType::BATTERY,
+ .value = 30.2f,
+ });
+ *out_temperatures = temperatures;
+ }
return ScopedAStatus::ok();
}
ScopedAStatus Thermal::getTemperatureThresholds(
- std::vector<TemperatureThreshold>* /* out_temperatureThresholds */) {
+ std::vector<TemperatureThreshold>* out_temperatureThresholds) {
LOG(VERBOSE) << __func__;
+ std::vector<TemperatureThreshold> 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<TemperatureThreshold>* /* out_temperatureThresholds */) {
+ std::vector<TemperatureThreshold>* out_temperatureThresholds) {
LOG(VERBOSE) << __func__ << " TemperatureType: " << static_cast<int32_t>(in_type);
+ if (in_type == TemperatureType::SKIN) {
+ std::vector<TemperatureThreshold> 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<TemperatureThreshold> 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 @@
}
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 d3d8874..a4d8b00 100644
--- a/thermal/aidl/default/Thermal.h
+++ b/thermal/aidl/default/Thermal.h
@@ -60,6 +60,8 @@
ndk::ScopedAStatus unregisterCoolingDeviceChangedCallback(
const std::shared_ptr<ICoolingDeviceChangedCallback>& 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 08dc68c..148ddbf 100644
--- a/thermal/aidl/default/thermal-example.xml
+++ b/thermal/aidl/default/thermal-example.xml
@@ -1,7 +1,7 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.thermal</name>
- <version>2</version>
+ <version>3</version>
<fqname>IThermal/default</fqname>
</hal>
</manifest>
diff --git a/thermal/aidl/vts/Android.bp b/thermal/aidl/vts/Android.bp
index 35f7649..18cb051 100644
--- a/thermal/aidl/vts/Android.bp
+++ b/thermal/aidl/vts/Android.bp
@@ -33,7 +33,7 @@
"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 7f33e2d..17653b4 100644
--- a/thermal/aidl/vts/VtsHalThermalTargetTest.cpp
+++ b/thermal/aidl/vts/VtsHalThermalTargetTest.cpp
@@ -93,6 +93,10 @@
return ndk::ScopedAStatus::ok();
}
+ ndk::ScopedAStatus notifyThresholdChanged(const TemperatureThreshold&) {
+ return ndk::ScopedAStatus::ok();
+ }
+
template <typename R, typename P>
[[nodiscard]] bool waitForCallback(std::chrono::duration<R, P> duration) {
std::unique_lock<std::mutex> lock(mMutex);
@@ -422,6 +426,23 @@
}
}
+// Test Thermal->forecastSkinTemperature.
+TEST_P(ThermalAidlTest, ForecastSkinTemperatureTest) {
+ auto apiLevel = ::android::base::GetIntProperty<int32_t>("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 afc811a..8d36ab1 100644
--- a/tv/input/aidl/Android.bp
+++ b/tv/input/aidl/Android.bp
@@ -45,5 +45,5 @@
},
],
- 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 84fe2fb..2ff2719 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 @@
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<byte,android.hardware.common.fmq.SynchronizedReadWrite> 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 c63e0ac..e57edf9 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 @@
*/
void getTvMessageQueueDesc(
out MQDescriptor<byte, SynchronizedReadWrite> 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 0000000..35ca732
--- /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 0000000..49cfd80
--- /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/AmbientBacklightColorFormat.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/AmbientBacklightColorFormat.aidl
new file mode 100644
index 0000000..9ee9dcc
--- /dev/null
+++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/AmbientBacklightColorFormat.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 <name>-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 AmbientBacklightColorFormat {
+ int RGB888;
+}
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 0000000..d441370
--- /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 <name>-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 0000000..2fc2cc6
--- /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 <name>-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 0000000..2ea3198
--- /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 <name>-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;
+ android.hardware.tv.mediaquality.AmbientBacklightColorFormat[] 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 0000000..7770e18
--- /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 <name>-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 {
+ int uid;
+ android.hardware.tv.mediaquality.AmbientBacklightSource source;
+ int maxFramerate;
+ android.hardware.graphics.common.PixelFormat colorFormat;
+ int hZonesNumber;
+ int vZonesNumber;
+ boolean hasLetterbox;
+ int colorThreshold;
+}
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 0000000..22912f4
--- /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 <name>-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 0000000..c08c6cc
--- /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 <name>-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 0000000..9bcddcb
--- /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 <name>-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 0000000..2d26aca
--- /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 <name>-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 0000000..dad0e96
--- /dev/null
+++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/DigitalOutput.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 <name>-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,
+ DolbyDigitalPlus,
+ DolbyDigital,
+ DolbyMat,
+}
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 0000000..f21243c
--- /dev/null
+++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/DolbyAudioProcessing.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 <name>-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 dolbyAtmos;
+ enum SoundMode {
+ GAME,
+ MOVIE,
+ MUSIC,
+ NEWS,
+ STADIUM,
+ STANDARD,
+ USER,
+ }
+}
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 0000000..ecb7db2
--- /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 <name>-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 0000000..d136dd9
--- /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 <name>-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 0000000..99543e9
--- /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 <name>-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 0000000..89bb808
--- /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 <name>-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 0000000..26df461
--- /dev/null
+++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/IMediaQuality.aidl
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <name>-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 setAmbientBacklightCallback(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);
+}
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 0000000..014bf58
--- /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 <name>-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 0000000..1923043
--- /dev/null
+++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/IPictureProfileAdjustmentListener.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 <name>-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 requestPictureParameters(long pictureProfileId);
+ oneway void onStreamStatusChanged(long pictureProfileId, android.hardware.tv.mediaquality.StreamStatus status);
+}
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 0000000..c1bfc36
--- /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 <name>-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 0000000..d976cf7
--- /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 <name>-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 requestSoundParameters(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 0000000..d07abe7
--- /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 <name>-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 0000000..9fc9d0d
--- /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 <name>-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 0000000..c60f1d1
--- /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 <name>-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 0000000..14e5ff4
--- /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 <name>-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 0000000..522b8e6
--- /dev/null
+++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/ParameterName.aidl
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <name>-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,
+ LEVEL_RANGE,
+ GAMUT_MAPPING,
+ PC_MODE,
+ LOW_LATENCY,
+ VRR,
+ CVRR,
+ HDMI_RGB_RANGE,
+ COLOR_SPACE,
+ PANEL_INIT_MAX_LUMINCE_VALID,
+ GAMMA,
+ COLOR_TEMPERATURE_RED_GAIN,
+ COLOR_TEMPERATURE_GREEN_GAIN,
+ COLOR_TEMPERATURE_BLUE_GAIN,
+ COLOR_TEMPERATURE_RED_OFFSET,
+ COLOR_TEMPERATURE_GREEN_OFFSET,
+ COLOR_TEMPERATURE_BLUE_OFFSET,
+ ELEVEN_POINT_RED,
+ ELEVEN_POINT_GREEN,
+ ELEVEN_POINT_BLUE,
+ LOW_BLUE_LIGHT,
+ LD_MODE,
+ OSD_RED_GAIN,
+ OSD_GREEN_GAIN,
+ OSD_BLUE_GAIN,
+ OSD_RED_OFFSET,
+ OSD_GREEN_OFFSET,
+ OSD_BLUE_OFFSET,
+ OSD_HUE,
+ OSD_SATURATION,
+ OSD_CONTRAST,
+ COLOR_TUNER_SWITCH,
+ COLOR_TUNER_HUE_RED,
+ COLOR_TUNER_HUE_GREEN,
+ COLOR_TUNER_HUE_BLUE,
+ COLOR_TUNER_HUE_CYAN,
+ COLOR_TUNER_HUE_MAGENTA,
+ COLOR_TUNER_HUE_YELLOW,
+ COLOR_TUNER_HUE_FLESH,
+ COLOR_TUNER_SATURATION_RED,
+ COLOR_TUNER_SATURATION_GREEN,
+ COLOR_TUNER_SATURATION_BLUE,
+ COLOR_TUNER_SATURATION_CYAN,
+ COLOR_TUNER_SATURATION_MAGENTA,
+ COLOR_TUNER_SATURATION_YELLOW,
+ COLOR_TUNER_SATURATION_FLESH,
+ COLOR_TUNER_LUMINANCE_RED,
+ COLOR_TUNER_LUMINANCE_GREEN,
+ COLOR_TUNER_LUMINANCE_BLUE,
+ COLOR_TUNER_LUMINANCE_CYAN,
+ COLOR_TUNER_LUMINANCE_MAGENTA,
+ COLOR_TUNER_LUMINANCE_YELLOW,
+ COLOR_TUNER_LUMINANCE_FLESH,
+ 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,
+ SOUND_STYLE,
+}
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 0000000..66bc405
--- /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 <name>-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 0000000..3a9e4e4
--- /dev/null
+++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/PictureParameter.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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 <name>-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;
+ int colorTemperatureRedGain;
+ int colorTemperatureGreenGain;
+ int colorTemperatureBlueGain;
+ int colorTemperatureRedOffset;
+ int colorTemperatureGreenOffset;
+ int colorTemperatureBlueOffset;
+ int[11] elevenPointRed;
+ int[11] elevenPointGreen;
+ int[11] elevenPointBlue;
+ android.hardware.tv.mediaquality.QualityLevel lowBlueLight;
+ android.hardware.tv.mediaquality.QualityLevel LdMode;
+ int osdRedGain;
+ int osdGreenGain;
+ int osdBlueGain;
+ int osdRedOffset;
+ int osdGreenOffset;
+ int osdBlueOffset;
+ int osdHue;
+ int osdSaturation;
+ int osdContrast;
+ boolean colorTunerSwitch;
+ int colorTunerHueRed;
+ int colorTunerHueGreen;
+ int colorTunerHueBlue;
+ int colorTunerHueCyan;
+ int colorTunerHueMagenta;
+ int colorTunerHueYellow;
+ int colorTunerHueFlesh;
+ int colorTunerSaturationRed;
+ int colorTunerSaturationGreen;
+ int colorTunerSaturationBlue;
+ int colorTunerSaturationCyan;
+ int colorTunerSaturationMagenta;
+ int colorTunerSaturationYellow;
+ int colorTunerSaturationFlesh;
+ int colorTunerLuminanceRed;
+ int colorTunerLuminanceGreen;
+ int colorTunerLuminanceBlue;
+ int colorTunerLuminanceCyan;
+ int colorTunerLuminanceMagenta;
+ int colorTunerLuminanceYellow;
+ int colorTunerLuminanceFlesh;
+ boolean activeProfile;
+ android.hardware.tv.mediaquality.PictureQualityEventType pictureQualityEventType;
+}
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 0000000..627369d
--- /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 <name>-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 0000000..ec2f9ff
--- /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 <name>-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/PictureQualityEventType.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/PictureQualityEventType.aidl
new file mode 100644
index 0000000..11001f6
--- /dev/null
+++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/PictureQualityEventType.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 <name>-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 PictureQualityEventType {
+ NONE,
+ BBD_RESULT,
+ VIDEO_DELAY_CHANGE,
+ CAPTUREPOINT_INFO_CHANGE,
+ VIDEOPATH_CHANGE,
+ EXTRA_FRAME_CHANGE,
+ DOLBY_IQ_CHANGE,
+ DOLBY_APO_CHANGE,
+}
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 0000000..a7f130f
--- /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 <name>-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 0000000..8c0eaaf
--- /dev/null
+++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/SoundParameter.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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 <name>-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;
+ boolean activeProfile;
+ android.hardware.tv.mediaquality.SoundStyle soundStyle;
+}
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 0000000..6492163
--- /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 <name>-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 0000000..05f936f
--- /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 <name>-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/SoundStyle.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/SoundStyle.aidl
new file mode 100644
index 0000000..1dbaf2c
--- /dev/null
+++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/SoundStyle.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 <name>-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 SoundStyle {
+ USER,
+ STANDARD,
+ VIVID,
+ SPORTS,
+ MOVIE,
+ MUSIC,
+ NEWS,
+ AUTO,
+}
diff --git a/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/StreamStatus.aidl b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/StreamStatus.aidl
new file mode 100644
index 0000000..23e584b
--- /dev/null
+++ b/tv/mediaquality/aidl/aidl_api/android.hardware.tv.mediaquality/current/android/hardware/tv/mediaquality/StreamStatus.aidl
@@ -0,0 +1,54 @@
+/*
+ * 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 <name>-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 StreamStatus {
+ SDR,
+ DOLBYVISION,
+ HDR10,
+ TCH,
+ HLG,
+ HDR10PLUS,
+ HDRVIVID,
+ IMAXSDR,
+ IMAXHDR10,
+ IMAXHDR10PLUS,
+ FMMSDR,
+ FMMHDR10,
+ FMMHDR10PLUS,
+ FMMHLG,
+ FMMDOLBY,
+ FMMTCH,
+ FMMHDRVIVID,
+}
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 0000000..5f16de9
--- /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 <name>-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 0000000..016c22d
--- /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 <name>-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/AmbientBacklightColorFormat.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/AmbientBacklightColorFormat.aidl
new file mode 100644
index 0000000..f29de45
--- /dev/null
+++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/AmbientBacklightColorFormat.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.tv.mediaquality;
+
+@VintfStability
+union AmbientBacklightColorFormat {
+ /**
+ * The color format is RGB888.
+ */
+ int RGB888;
+}
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 0000000..e1c68b3
--- /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 0000000..237e531
--- /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 0000000..d2599bd
--- /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.AmbientBacklightColorFormat;
+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. Formats of the color will be AmbientBacklightColorFormat.
+ */
+ AmbientBacklightColorFormat[] 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 0000000..79bf02b
--- /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.
+ */
+ int uid;
+
+ /**
+ * 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 logical zones in horizontal direction desire by the package.
+ */
+ int hZonesNumber;
+
+ /**
+ * The number of logical zones in vertical direction desire by the package.
+ */
+ 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 colorThreshold;
+}
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 0000000..8051fb6
--- /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 0000000..29f12ef
--- /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 0000000..bd4511d
--- /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 0000000..4d4b01c
--- /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 0000000..a58ad79
--- /dev/null
+++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/DigitalOutput.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.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.
+ *
+ * This is the default value for digital output.
+ */
+ 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,
+
+ /**
+ * Dolby Digital Plus (E-AC-3) output. An enhanced version of Dolby Digital
+ * supporting more channels (up to 7.1 surround sound) and higher bitrates.
+ * Commonly used for streaming and online content.
+ */
+ DolbyDigitalPlus,
+
+ /**
+ * Dolby Digital (AC-3) output. Provides up to 5.1 channels
+ * of surround sound, a standard for DVDs, Blu-rays, and TV broadcasts.
+ */
+ DolbyDigital,
+
+ /**
+ * Dolby Multistream Audio (MAT) output. Carries multiple audio streams
+ * (e.g., different languages, audio descriptions) within a Dolby Digital Plus bitstream.
+ */
+ DolbyMat,
+}
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 0000000..3454556
--- /dev/null
+++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/DolbyAudioProcessing.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.
+ */
+
+package android.hardware.tv.mediaquality;
+
+@VintfStability
+parcelable DolbyAudioProcessing {
+ /* The default value for sound mode is standard. */
+ enum SoundMode {
+ GAME,
+ MOVIE,
+ MUSIC,
+ NEWS,
+ STADIUM,
+ STANDARD,
+ USER,
+ }
+
+ /**
+ * sound mode for dolby audio processing.
+ */
+ SoundMode soundMode;
+
+ /**
+ * Indicates whether Volume Leveler is enabled.
+ *
+ * <p>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.
+ *
+ * <p>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.
+ *
+ * <p>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.
+ *
+ * <p>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 dolbyAtmos;
+}
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 0000000..c30a0ba
--- /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 0000000..b26a41d
--- /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 0000000..6eebdc0
--- /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 0000000..c633557
--- /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 0000000..3da1495
--- /dev/null
+++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/IMediaQuality.aidl
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 setAmbientBacklightCallback(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.
+ *
+ * @return Status::ok on success
+ * UNSUPPORTED_OPERATION if this functionality is unsupported.
+ */
+ 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.
+ *
+ * @return Status::ok on success
+ * UNSUPPORTED_OPERATION if this functionality is unsupported.
+ */
+ 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.
+ *
+ * @return Status::ok on success
+ * UNSUPPORTED_OPERATION if this functionality is unsupported.
+ */
+ 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.
+ *
+ * @return Status::ok on success
+ * UNSUPPORTED_OPERATION if this functionality is unsupported.
+ */
+ 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);
+}
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 0000000..31ab255
--- /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 0000000..0e11fb0
--- /dev/null
+++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/IPictureProfileAdjustmentListener.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.tv.mediaquality;
+
+import android.hardware.tv.mediaquality.ParamCapability;
+import android.hardware.tv.mediaquality.PictureProfile;
+import android.hardware.tv.mediaquality.StreamStatus;
+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.
+ *
+ * <p>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 requestPictureParameters(long pictureProfileId);
+
+ /**
+ * Notifies Media Quality Manager when stream status changed.
+ *
+ * @param pictureProfileId the ID of the profile used by the media content. -1 if there
+ * is no associated profile.
+ * @param status the status of the current stream.
+ */
+ void onStreamStatusChanged(long pictureProfileId, StreamStatus status);
+}
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 0000000..7fc7ab2
--- /dev/null
+++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/IPictureProfileChangedListener.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.PictureProfile;
+
+@VintfStability
+oneway interface IPictureProfileChangedListener {
+ /**
+ * Notifies the service that the picture profile has changed.
+ *
+ * @param pictureProfile Picture profile that should be cached by the service.
+ */
+ 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 0000000..3f96762
--- /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.
+ *
+ * <p>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 requestSoundParameters(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 0000000..cb2d75e
--- /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 0000000..94a041c
--- /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 0000000..933a1a3
--- /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 0000000..3827134
--- /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 0000000..d451590
--- /dev/null
+++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/ParameterName.aidl
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.
+ * <p>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,
+ LEVEL_RANGE,
+ GAMUT_MAPPING,
+ PC_MODE,
+ LOW_LATENCY,
+ VRR,
+ CVRR,
+ HDMI_RGB_RANGE,
+ COLOR_SPACE,
+ PANEL_INIT_MAX_LUMINCE_VALID,
+ GAMMA,
+ COLOR_TEMPERATURE_RED_GAIN,
+ COLOR_TEMPERATURE_GREEN_GAIN,
+ COLOR_TEMPERATURE_BLUE_GAIN,
+ COLOR_TEMPERATURE_RED_OFFSET,
+ COLOR_TEMPERATURE_GREEN_OFFSET,
+ COLOR_TEMPERATURE_BLUE_OFFSET,
+ ELEVEN_POINT_RED,
+ ELEVEN_POINT_GREEN,
+ ELEVEN_POINT_BLUE,
+ LOW_BLUE_LIGHT,
+ LD_MODE,
+ OSD_RED_GAIN,
+ OSD_GREEN_GAIN,
+ OSD_BLUE_GAIN,
+ OSD_RED_OFFSET,
+ OSD_GREEN_OFFSET,
+ OSD_BLUE_OFFSET,
+ OSD_HUE,
+ OSD_SATURATION,
+ OSD_CONTRAST,
+ COLOR_TUNER_SWITCH,
+ COLOR_TUNER_HUE_RED,
+ COLOR_TUNER_HUE_GREEN,
+ COLOR_TUNER_HUE_BLUE,
+ COLOR_TUNER_HUE_CYAN,
+ COLOR_TUNER_HUE_MAGENTA,
+ COLOR_TUNER_HUE_YELLOW,
+ COLOR_TUNER_HUE_FLESH,
+ COLOR_TUNER_SATURATION_RED,
+ COLOR_TUNER_SATURATION_GREEN,
+ COLOR_TUNER_SATURATION_BLUE,
+ COLOR_TUNER_SATURATION_CYAN,
+ COLOR_TUNER_SATURATION_MAGENTA,
+ COLOR_TUNER_SATURATION_YELLOW,
+ COLOR_TUNER_SATURATION_FLESH,
+ COLOR_TUNER_LUMINANCE_RED,
+ COLOR_TUNER_LUMINANCE_GREEN,
+ COLOR_TUNER_LUMINANCE_BLUE,
+ COLOR_TUNER_LUMINANCE_CYAN,
+ COLOR_TUNER_LUMINANCE_MAGENTA,
+ COLOR_TUNER_LUMINANCE_YELLOW,
+ COLOR_TUNER_LUMINANCE_FLESH,
+
+ 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,
+ SOUND_STYLE,
+}
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 0000000..836b5b8
--- /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 0000000..2443d65
--- /dev/null
+++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/PictureParameter.aidl
@@ -0,0 +1,451 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.PictureQualityEventType;
+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;
+
+ /**
+ * The color gain value for color temperature adjustment.
+ * The value adjusts the intensity of color in the bright areas on the TV.
+ *
+ * The value range is from -100 to 100 where -100 would eliminate that color
+ * and 100 would significantly boost that color.
+ *
+ * The default/unmodified value is 0. No adjustment is applied to that color.
+ */
+ int colorTemperatureRedGain;
+
+ int colorTemperatureGreenGain;
+
+ int colorTemperatureBlueGain;
+
+ /**
+ * The color offset value for color temperature adjustment.
+ * This value adjusts the intensity of color in the dark areas on the TV.
+ *
+ * The value range is from -100 to 100 where -100 would eliminate that color
+ * and 100 would significantly boost that color.
+ *
+ * The default/unmodified value is 0. No adjustment is applied to that color.
+ */
+ int colorTemperatureRedOffset;
+
+ int colorTemperatureGreenOffset;
+
+ int colorTemperatureBlueOffset;
+
+ /**
+ * The parameters in this section is for 11-point white balance in advanced TV picture setting.
+ * 11-Point White Balance allows for very precise adjustment of the color temperature of the
+ * TV. It aims to make sure white looks truly white, without any unwanted color tints, across
+ * the entire range of brightness levels.
+ *
+ * The "11 points" refer to 11 different brightness levels from 0 (black) to 10 (white).
+ * At each of these points, we can fine-tune the mixture of red, green and blue to achieve
+ * neutral white.
+ *
+ * These parameters specifically control the amount of red, blue or green at each of the 11
+ * brightness points. The parameter type is an int array with a fix size of 11. The indexes
+ * 0 - 10 are the 11 different points. For example, elevenPointRed[0] adjusts the red level
+ * at the darkest black level. elevenPointRed[1] adjusts red at the next brightness level up,
+ * and so on.
+ *
+ * The value range is from 0 - 100 for each indexes, where 0 is the minimum intensity of
+ * that color(red, green, blue) at a specific brightness point and 100 is the maximum intensity
+ * of that color at that point.
+ *
+ * The default/unmodified value is 50. It can be other values depends on different TVs.
+ */
+ int[11] elevenPointRed;
+
+ int[11] elevenPointGreen;
+
+ int[11] elevenPointBlue;
+
+ /**
+ * Adjust gamma blue gain/offset.
+ *
+ * The default value is middle. Can be different depends on different TVs.
+ */
+ QualityLevel lowBlueLight;
+
+ /**
+ * Advance setting for local dimming level.
+ *
+ * The default value is off. Can be different depends on different TVs.
+ */
+ QualityLevel LdMode;
+
+ /**
+ * The parameter in this section is for on-screen display color gain and offset.
+ *
+ * Color gain is to adjust the intensity of that color (red, blue, green) in the brighter
+ * part of the image.
+ * Color offset is to adjust the intensity of that color in the darker part of the image.
+ *
+ * For example, increase OSD (on-screen display) red gain will make brighter reds even more
+ * intense, while decreasing it will make them less vibrant. Increase OSD red offset will add
+ * more red to the darker areas, while decreasing it will reduce the red in the shadows.
+ *
+ * The value range is from 0 to 2047. (11-bit resolution for the adjustment)
+ * The default value depends on different TVs.
+ */
+ int osdRedGain;
+
+ int osdGreenGain;
+
+ int osdBlueGain;
+
+ int osdRedOffset;
+
+ int osdGreenOffset;
+
+ int osdBlueOffset;
+
+ /* The value range is 0-100 */
+ int osdHue;
+
+ /* The value range is 0-255 */
+ int osdSaturation;
+
+ int osdContrast;
+
+ /**
+ * Enable/disable color tuner.
+ *
+ * The color tuner can adjust color temperature and picture color.
+ * The default is enabled.
+ */
+ boolean colorTunerSwitch;
+
+ /**
+ * The parameters in this section adjust the hue of each color.
+ *
+ * For example, increase colorTunerHueRed will make the image more purplish-red or more
+ * orange-red. increase colorTunerHueGreen will make the image more yellowish-green or
+ * more bluish-green. Flesh is a special one, it can make skin tones appear warmer (reddish)
+ * or cooler (more yellowish).
+ *
+ * The value range is from 0 - 100, and the default value is 50.
+ */
+ int colorTunerHueRed;
+
+ int colorTunerHueGreen;
+
+ int colorTunerHueBlue;
+
+ int colorTunerHueCyan;
+
+ int colorTunerHueMagenta;
+
+ int colorTunerHueYellow;
+
+ int colorTunerHueFlesh;
+
+ /**
+ * The parameters in this section adjust the saturation of each color.
+ *
+ * For example, increase colorTunerSaturationBlue will make the color blue more deeper
+ * and richer. Decrease will make the color blue more washed-out blues.
+ *
+ * The value range is from 0 -100, and the default value is 50.
+ */
+ int colorTunerSaturationRed;
+
+ int colorTunerSaturationGreen;
+
+ int colorTunerSaturationBlue;
+
+ int colorTunerSaturationCyan;
+
+ int colorTunerSaturationMagenta;
+
+ int colorTunerSaturationYellow;
+
+ int colorTunerSaturationFlesh;
+
+ /**
+ * The parameters in this section adjust the luminance (brightness) of each color.
+ *
+ * For example, increase colorTunerLuminanceRed will makes red appear brighter. Decrease
+ * will makes red appear darker.
+ *
+ * The value range is from 0 -100, and the default value is 50.
+ */
+ int colorTunerLuminanceRed;
+
+ int colorTunerLuminanceGreen;
+
+ int colorTunerLuminanceBlue;
+
+ int colorTunerLuminanceCyan;
+
+ int colorTunerLuminanceMagenta;
+
+ int colorTunerLuminanceYellow;
+
+ int colorTunerLuminanceFlesh;
+
+ /**
+ * Determines whether the current profile is actively in use or not.
+ */
+ boolean activeProfile;
+
+ /**
+ * This indicates non picture parameter status change about a profile.
+ *
+ * Those status can be found in PictureQualityEventType.
+ */
+ PictureQualityEventType pictureQualityEventType;
+}
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 0000000..e5f6b83
--- /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 0000000..7e02350
--- /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/PictureQualityEventType.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/PictureQualityEventType.aidl
new file mode 100644
index 0000000..4985707
--- /dev/null
+++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/PictureQualityEventType.aidl
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 PictureQualityEventType {
+ /* No status change */
+ NONE,
+
+ /**
+ * Black bar detection Event.
+ *
+ * TV has detected or lost track of black bars, potentially triggering a change in aspect
+ * ratio.
+ */
+ BBD_RESULT,
+
+ /**
+ * Video delay change event.
+ *
+ * This signifies a change in the video processing delay, might due to enabling or disabling
+ * certain picture quality features.
+ */
+ VIDEO_DELAY_CHANGE,
+
+ /**
+ * Capture point change event.
+ *
+ * A change in video processing pipeline the image is being captured for display. Changes here
+ * relates to switching between different video sources.
+ */
+ CAPTUREPOINT_INFO_CHANGE,
+
+ /**
+ * Video path change event.
+ *
+ * Indicates a change in the video signal path. This could involve switching between
+ * different input sources.
+ */
+ VIDEOPATH_CHANGE,
+
+ /**
+ * Extra frame change event.
+ *
+ * Some TVs use techniques like frame interpolation (inserting extra frames) to smooth motion.
+ * Change means the function is turned on or off.
+ */
+ EXTRA_FRAME_CHANGE,
+
+ /**
+ * Dolby Vision IQ change event.
+ *
+ * Dolby Vision IQ is a technology that adjusts HDR video based on the ambient light in the
+ * room. A change means the function is turned on or off.
+ */
+ DOLBY_IQ_CHANGE,
+
+ /**
+ * Dolby Vision audio processing object change event.
+ *
+ * This event might be triggered by changes in audio settings that affect the picture quality,
+ * such as enabling or disabling a feature that synchronizes audio and video processing.
+ */
+ DOLBY_APO_CHANGE,
+}
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 0000000..e0171ca
--- /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 0000000..7a8a031
--- /dev/null
+++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/SoundParameter.aidl
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+import android.hardware.tv.mediaquality.SoundStyle;
+
+/**
+ * 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;
+
+ /**
+ * Determines whether the current profile is actively in use or not.
+ */
+ boolean activeProfile;
+
+ /*
+ * Sound style of the profile.
+ *
+ * The default value is user customized profile.
+ */
+ SoundStyle soundStyle;
+}
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 0000000..2fe0ce7
--- /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 0000000..27628eb
--- /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/SoundStyle.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/SoundStyle.aidl
new file mode 100644
index 0000000..b8650d2
--- /dev/null
+++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/SoundStyle.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;
+
+@VintfStability
+enum SoundStyle {
+ /* User custom style is the default value for sound style */
+ USER,
+ STANDARD,
+ VIVID,
+ SPORTS,
+ MOVIE,
+ MUSIC,
+ NEWS,
+ AUTO,
+}
diff --git a/tv/mediaquality/aidl/android/hardware/tv/mediaquality/StreamStatus.aidl b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/StreamStatus.aidl
new file mode 100644
index 0000000..ec3b995
--- /dev/null
+++ b/tv/mediaquality/aidl/android/hardware/tv/mediaquality/StreamStatus.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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 StreamStatus {
+ SDR,
+ DOLBYVISION,
+ HDR10,
+ TCH,
+ HLG,
+ HDR10PLUS,
+ HDRVIVID,
+ IMAXSDR,
+ IMAXHDR10,
+ IMAXHDR10PLUS,
+ FMMSDR,
+ FMMHDR10,
+ FMMHDR10PLUS,
+ FMMHLG,
+ FMMDOLBY,
+ FMMTCH,
+ FMMHDRVIVID,
+}
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 0000000..bdc0188
--- /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 0000000..f974b16
--- /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 0000000..e25b01f
--- /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 0000000..087730f
--- /dev/null
+++ b/tv/mediaquality/aidl/default/hal/media_quality_hal_impl.rs
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 binder::ExceptionCode;
+use std::sync::{Arc, Mutex};
+use std::thread;
+
+/// Defined so we can implement the IMediaQuality AIDL interface.
+pub struct MediaQualityService {
+ callback: Arc<Mutex<Option<Strong<dyn IMediaQualityCallback>>>>,
+ ambient_backlight_supported: Arc<Mutex<bool>>,
+ ambient_backlight_enabled: Arc<Mutex<bool>>,
+ ambient_backlight_detector_settings: Arc<Mutex<AmbientBacklightSettings>>,
+ auto_pq_supported: Arc<Mutex<bool>>,
+ auto_pq_enabled: Arc<Mutex<bool>>,
+ auto_sr_supported: Arc<Mutex<bool>>,
+ auto_sr_enabled: Arc<Mutex<bool>>,
+ auto_aq_supported: Arc<Mutex<bool>>,
+ auto_aq_enabled: Arc<Mutex<bool>>,
+ picture_profile_adjustment_listener:
+ Arc<Mutex<Option<Strong<dyn IPictureProfileAdjustmentListener>>>>,
+ sound_profile_adjustment_listener:
+ Arc<Mutex<Option<Strong<dyn ISoundProfileAdjustmentListener>>>>,
+ picture_profile_changed_listener: Arc<Mutex<Option<Strong<dyn IPictureProfileChangedListener>>>>,
+ sound_profile_changed_listener: Arc<Mutex<Option<Strong<dyn ISoundProfileChangedListener>>>>,
+}
+
+impl MediaQualityService {
+
+ /// Create a new instance of the MediaQualityService.
+ pub fn new() -> Self {
+ Self {
+ callback: Arc::new(Mutex::new(None)),
+ ambient_backlight_supported: Arc::new(Mutex::new(false)),
+ 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 setAmbientBacklightCallback(
+ &self,
+ callback: &Strong<dyn IMediaQualityCallback>
+ ) -> 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.uid = settings.uid.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.colorThreshold = settings.colorThreshold;
+ Ok(())
+ }
+
+ fn setAmbientBacklightDetectionEnabled(&self, enabled: bool) -> binder::Result<()> {
+ println!("Received enabled: {}", enabled);
+ let mut ambient_backlight_enabled = self.ambient_backlight_enabled.lock().unwrap();
+ let ambient_backlight_supported = self.ambient_backlight_supported.lock().unwrap();
+ *ambient_backlight_enabled = enabled;
+
+ if *ambient_backlight_supported {
+ 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();
+ }
+ });
+ });
+ }
+ return Ok(());
+ } else {
+ return Err(ExceptionCode::UNSUPPORTED_OPERATION.into());
+ }
+ }
+
+ fn getAmbientBacklightDetectionEnabled(&self) -> binder::Result<bool> {
+ let ambient_backlight_enabled = self.ambient_backlight_enabled.lock().unwrap();
+ Ok(*ambient_backlight_enabled)
+ }
+
+ fn isAutoPqSupported(&self) -> binder::Result<bool> {
+ let auto_pq_supported = self.auto_pq_supported.lock().unwrap();
+ Ok(*auto_pq_supported)
+ }
+
+ fn getAutoPqEnabled(&self) -> binder::Result<bool> {
+ 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();
+ let auto_pq_supported = self.auto_pq_supported.lock().unwrap();
+ *auto_pq_enabled = enabled;
+
+ if *auto_pq_supported {
+ if enabled {
+ println!("Enable auto picture quality");
+ } else {
+ println!("Disable auto picture quality");
+ }
+ return Ok(());
+ } else {
+ return Err(ExceptionCode::UNSUPPORTED_OPERATION.into());
+ }
+ }
+
+ fn isAutoSrSupported(&self) -> binder::Result<bool> {
+ let auto_sr_supported = self.auto_sr_supported.lock().unwrap();
+ Ok(*auto_sr_supported)
+ }
+
+ fn getAutoSrEnabled(&self) -> binder::Result<bool> {
+ 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();
+ let auto_sr_supported = self.auto_sr_supported.lock().unwrap();
+ *auto_sr_enabled = enabled;
+
+ if *auto_sr_supported {
+ if enabled {
+ println!("Enable auto super resolution");
+ } else {
+ println!("Disable auto super resolution");
+ }
+ return Ok(());
+ } else {
+ return Err(ExceptionCode::UNSUPPORTED_OPERATION.into());
+ }
+ }
+
+ fn isAutoAqSupported(&self) -> binder::Result<bool> {
+ let auto_aq_supported = self.auto_aq_supported.lock().unwrap();
+ Ok(*auto_aq_supported)
+ }
+
+ fn getAutoAqEnabled(&self) -> binder::Result<bool> {
+ 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();
+ let auto_aq_supported = self.auto_aq_supported.lock().unwrap();
+ *auto_aq_enabled = enabled;
+
+ if *auto_aq_supported {
+ if enabled {
+ println!("Enable auto audio quality");
+ } else {
+ println!("Disable auto audio quality");
+ }
+ return Ok(());
+ } else {
+ return Err(ExceptionCode::UNSUPPORTED_OPERATION.into());
+ }
+ }
+
+ fn getPictureProfileListener(&self) -> binder::Result<binder::Strong<dyn IPictureProfileChangedListener>> {
+ 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<dyn IPictureProfileAdjustmentListener>
+ ) -> 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<binder::Strong<dyn ISoundProfileChangedListener>> {
+ 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<dyn ISoundProfileAdjustmentListener>
+ ) -> 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<ParamCapability>
+ ) -> binder::Result<()> {
+ println!("getParamCaps. len= {}", param_names.len());
+ Ok(())
+ }
+
+ fn getVendorParamCaps(
+ &self,
+ param_names: &[VendorParameterIdentifier],
+ _caps: &mut Vec<VendorParamCapability>
+ ) -> binder::Result<()> {
+ println!("getVendorParamCaps. len= {}", param_names.len());
+ Ok(())
+ }
+}
diff --git a/tv/mediaquality/aidl/default/hal/mod.rs b/tv/mediaquality/aidl/default/hal/mod.rs
new file mode 100644
index 0000000..5b5d4ac
--- /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 0000000..f0cccb4
--- /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 0000000..5a103a9
--- /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 0000000..865f663
--- /dev/null
+++ b/tv/mediaquality/aidl/default/mediaquality-default.xml
@@ -0,0 +1,6 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.tv.mediaquality</name>
+ <fqname>IMediaQuality/default</fqname>
+ </hal>
+</manifest>
\ 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 0000000..226569e
--- /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 0000000..a01d4b0
--- /dev/null
+++ b/tv/mediaquality/aidl/vts/functional/VtsHalMediaQualityTest.cpp
@@ -0,0 +1,694 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/tv/mediaquality/AmbientBacklightEvent.h>
+#include <aidl/android/hardware/tv/mediaquality/AmbientBacklightSettings.h>
+#include <aidl/android/hardware/tv/mediaquality/BnMediaQualityCallback.h>
+#include <aidl/android/hardware/tv/mediaquality/BnPictureProfileAdjustmentListener.h>
+#include <aidl/android/hardware/tv/mediaquality/BnSoundProfileAdjustmentListener.h>
+#include <aidl/android/hardware/tv/mediaquality/IMediaQuality.h>
+#include <aidl/android/hardware/tv/mediaquality/PictureParameter.h>
+#include <aidl/android/hardware/tv/mediaquality/PictureParameters.h>
+#include <aidl/android/hardware/tv/mediaquality/PictureProfile.h>
+#include <aidl/android/hardware/tv/mediaquality/SoundParameter.h>
+#include <aidl/android/hardware/tv/mediaquality/SoundParameters.h>
+#include <aidl/android/hardware/tv/mediaquality/SoundProfile.h>
+#include <aidl/android/hardware/tv/mediaquality/StreamStatus.h>
+
+#include <android/binder_auto_utils.h>
+#include <android/binder_manager.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <log/log.h>
+#include <future>
+
+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::StreamStatus;
+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())
+
+void validateParameterRange0To100(int value) {
+ EXPECT_GE(value, 0);
+ EXPECT_LE(value, 100);
+}
+
+void validateParameterRange0To2047(int value) {
+ EXPECT_GE(value, 0);
+ EXPECT_LE(value, 2047);
+}
+
+void validateColorTemperature(int value) {
+ EXPECT_GE(value, -100);
+ EXPECT_LE(value, 100);
+}
+
+void validatePictureParameter(const PictureParameter& param) {
+ switch (param.getTag()) {
+ case PictureParameter::Tag::brightness: {
+ ALOGD("[validatePictureParameter] validate brightness value");
+ float value = param.get<PictureParameter::Tag::brightness>();
+ EXPECT_TRUE(value >= 0.0f && value <= 1.0f);
+ break;
+ }
+ case PictureParameter::Tag::contrast: {
+ ALOGD("[validatePictureParameter] validate contrast value");
+ int value = param.get<PictureParameter::Tag::contrast>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::sharpness: {
+ ALOGD("[validatePictureParameter] validate sharpness value");
+ int value = param.get<PictureParameter::Tag::sharpness>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::saturation: {
+ ALOGD("[validatePictureParameter] validate saturation value");
+ int value = param.get<PictureParameter::Tag::saturation>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::hue: {
+ ALOGD("[validatePictureParameter] validate hue value");
+ int value = param.get<PictureParameter::Tag::hue>();
+ EXPECT_GE(value, -50);
+ EXPECT_LE(value, 50);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerBrightness: {
+ ALOGD("[validatePictureParameter] validate colorTunerBrightness value");
+ int value = param.get<PictureParameter::Tag::colorTunerBrightness>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerSaturation: {
+ ALOGD("[validatePictureParameter] validate colorTunerSaturation value");
+ int value = param.get<PictureParameter::Tag::colorTunerSaturation>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerHue: {
+ ALOGD("[validatePictureParameter] validate colorTunerHue value");
+ int value = param.get<PictureParameter::Tag::colorTunerHue>();
+ EXPECT_GE(value, -50);
+ EXPECT_LE(value, 50);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerRedOffset: {
+ ALOGD("[validatePictureParameter] validate colorTunerRedOffset value");
+ int value = param.get<PictureParameter::Tag::colorTunerRedOffset>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerGreenOffset: {
+ ALOGD("[validatePictureParameter] validate colorTunerGreenOffset value");
+ int value = param.get<PictureParameter::Tag::colorTunerGreenOffset>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerBlueOffset: {
+ ALOGD("[validatePictureParameter] validate colorTunerBlueOffset value");
+ int value = param.get<PictureParameter::Tag::colorTunerBlueOffset>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerRedGain: {
+ ALOGD("[validatePictureParameter] validate colorTunerRedGain value");
+ int value = param.get<PictureParameter::Tag::colorTunerRedGain>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerGreenGain: {
+ ALOGD("[validatePictureParameter] validate colorTunerGreenGain value");
+ int value = param.get<PictureParameter::Tag::colorTunerGreenGain>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerBlueGain: {
+ ALOGD("[validatePictureParameter] validate colorTunerBlueGain value");
+ int value = param.get<PictureParameter::Tag::colorTunerBlueGain>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::panelInitMaxLuminceNits: {
+ ALOGD("[validatePictureParameter] validate panelInitMaxLuminceNits value");
+ int value = param.get<PictureParameter::Tag::panelInitMaxLuminceNits>();
+ EXPECT_GE(value, 0);
+ EXPECT_LE(value, 10000);
+ break;
+ }
+ case PictureParameter::Tag::colorTemperatureRedGain: {
+ ALOGD("[validatePictureParameter] validate colorTemperatureRedGain value");
+ int value = param.get<PictureParameter::Tag::colorTemperatureRedGain>();
+ validateColorTemperature(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTemperatureGreenGain: {
+ ALOGD("[validatePictureParameter] validate colorTemperatureGreenGain value");
+ int value = param.get<PictureParameter::Tag::colorTemperatureGreenGain>();
+ validateColorTemperature(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTemperatureBlueGain: {
+ ALOGD("[validatePictureParameter] validate colorTemperatureBlueGain value");
+ int value = param.get<PictureParameter::Tag::colorTemperatureBlueGain>();
+ validateColorTemperature(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTemperatureRedOffset: {
+ ALOGD("[validatePictureParameter] validate ccolorTemperatureRedOffset value");
+ int value = param.get<PictureParameter::Tag::colorTemperatureRedOffset>();
+ validateColorTemperature(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTemperatureGreenOffset: {
+ ALOGD("[validatePictureParameter] validate colorTemperatureGreenOffset value");
+ int value = param.get<PictureParameter::Tag::colorTemperatureGreenOffset>();
+ validateColorTemperature(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTemperatureBlueOffset: {
+ ALOGD("[validatePictureParameter] validate colorTemperatureBlueOffset value");
+ int value = param.get<PictureParameter::Tag::colorTemperatureBlueOffset>();
+ validateColorTemperature(value);
+ break;
+ }
+ case PictureParameter::Tag::elevenPointRed: {
+ ALOGD("[validatePictureParameter] validate elevenPointRed value");
+ std::array<int, 11> elevenPointValues =
+ param.get<PictureParameter::Tag::elevenPointRed>();
+ for (int value : elevenPointValues) {
+ validateParameterRange0To100(value);
+ }
+ break;
+ }
+ case PictureParameter::Tag::elevenPointGreen: {
+ ALOGD("[validatePictureParameter] validate elevenPointGreen value");
+ std::array<int, 11> elevenPointValues =
+ param.get<PictureParameter::Tag::elevenPointGreen>();
+ for (int value : elevenPointValues) {
+ validateParameterRange0To100(value);
+ }
+ break;
+ }
+ case PictureParameter::Tag::elevenPointBlue: {
+ ALOGD("[validatePictureParameter] validate elevenPointBlue value");
+ std::array<int, 11> elevenPointValues =
+ param.get<PictureParameter::Tag::elevenPointBlue>();
+ for (int value : elevenPointValues) {
+ validateParameterRange0To100(value);
+ }
+ break;
+ }
+ case PictureParameter::Tag::osdRedGain: {
+ ALOGD("[validatePictureParameter] validate osdRedGain value");
+ int value = param.get<PictureParameter::Tag::osdRedGain>();
+ validateParameterRange0To2047(value);
+ break;
+ }
+ case PictureParameter::Tag::osdGreenGain: {
+ ALOGD("[validatePictureParameter] validate osdGreenGain value");
+ int value = param.get<PictureParameter::Tag::osdGreenGain>();
+ validateParameterRange0To2047(value);
+ break;
+ }
+ case PictureParameter::Tag::osdBlueGain: {
+ ALOGD("[validatePictureParameter] validate osdBlueGain value");
+ int value = param.get<PictureParameter::Tag::osdBlueGain>();
+ validateParameterRange0To2047(value);
+ break;
+ }
+ case PictureParameter::Tag::osdRedOffset: {
+ ALOGD("[validatePictureParameter] validate osdRedOffset value");
+ int value = param.get<PictureParameter::Tag::osdRedOffset>();
+ validateParameterRange0To2047(value);
+ break;
+ }
+ case PictureParameter::Tag::osdGreenOffset: {
+ ALOGD("[validatePictureParameter] validate osdGreenOffset value");
+ int value = param.get<PictureParameter::Tag::osdGreenOffset>();
+ validateParameterRange0To2047(value);
+ break;
+ }
+ case PictureParameter::Tag::osdBlueOffset: {
+ ALOGD("[validatePictureParameter] validate osdBlueOffset value");
+ int value = param.get<PictureParameter::Tag::osdBlueOffset>();
+ validateParameterRange0To2047(value);
+ break;
+ }
+ case PictureParameter::Tag::osdHue: {
+ ALOGD("[validatePictureParameter] validate osdHue value");
+ int value = param.get<PictureParameter::Tag::osdHue>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::osdSaturation: {
+ ALOGD("[validatePictureParameter] validate osdSaturation value");
+ int value = param.get<PictureParameter::Tag::osdSaturation>();
+ EXPECT_GE(value, 0);
+ EXPECT_LE(value, 255);
+ break;
+ }
+ case PictureParameter::Tag::osdContrast: {
+ ALOGD("[validatePictureParameter] validate osdContrast value");
+ int value = param.get<PictureParameter::Tag::osdContrast>();
+ validateParameterRange0To2047(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerHueRed: {
+ ALOGD("[validatePictureParameter] validate colorTunerHueRed value");
+ int value = param.get<PictureParameter::Tag::colorTunerHueRed>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerHueGreen: {
+ ALOGD("[validatePictureParameter] validate colorTunerHueGreen value");
+ int value = param.get<PictureParameter::Tag::colorTunerHueGreen>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerHueBlue: {
+ ALOGD("[validatePictureParameter] validate colorTunerHueBlue value");
+ int value = param.get<PictureParameter::Tag::colorTunerHueBlue>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerHueCyan: {
+ ALOGD("[validatePictureParameter] validate colorTunerHueCyan value");
+ int value = param.get<PictureParameter::Tag::colorTunerHueCyan>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerHueMagenta: {
+ ALOGD("[validatePictureParameter] validate colorTunerHueMagenta value");
+ int value = param.get<PictureParameter::Tag::colorTunerHueMagenta>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerHueYellow: {
+ ALOGD("[validatePictureParameter] validate colorTunerHueYellow value");
+ int value = param.get<PictureParameter::Tag::colorTunerHueYellow>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerHueFlesh: {
+ ALOGD("[validatePictureParameter] validate colorTunerHueFlesh value");
+ int value = param.get<PictureParameter::Tag::colorTunerHueFlesh>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerSaturationRed: {
+ ALOGD("[validatePictureParameter] validate colorTunerSaturationRed value");
+ int value = param.get<PictureParameter::Tag::colorTunerSaturationRed>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerSaturationGreen: {
+ ALOGD("[validatePictureParameter] validate colorTunerSaturationGreen value");
+ int value = param.get<PictureParameter::Tag::colorTunerSaturationGreen>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerSaturationBlue: {
+ ALOGD("[validatePictureParameter] validate colorTunerSaturationBlue value");
+ int value = param.get<PictureParameter::Tag::colorTunerSaturationBlue>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerSaturationCyan: {
+ ALOGD("[validatePictureParameter] validate colorTunerSaturationCyan value");
+ int value = param.get<PictureParameter::Tag::colorTunerSaturationCyan>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerSaturationMagenta: {
+ ALOGD("[validatePictureParameter] validate colorTunerSaturationMagenta value");
+ int value = param.get<PictureParameter::Tag::colorTunerSaturationMagenta>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerSaturationYellow: {
+ ALOGD("[validatePictureParameter] validate colorTunerSaturationYellow value");
+ int value = param.get<PictureParameter::Tag::colorTunerSaturationYellow>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerSaturationFlesh: {
+ ALOGD("[validatePictureParameter] validate colorTunerSaturationFlesh value");
+ int value = param.get<PictureParameter::Tag::colorTunerSaturationFlesh>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerLuminanceRed: {
+ ALOGD("[validatePictureParameter] validate colorTunerLuminanceRed value");
+ int value = param.get<PictureParameter::Tag::colorTunerLuminanceRed>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerLuminanceGreen: {
+ ALOGD("[validatePictureParameter] validate colorTunerLuminanceGreen value");
+ int value = param.get<PictureParameter::Tag::colorTunerLuminanceGreen>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerLuminanceBlue: {
+ ALOGD("[validatePictureParameter] validate colorTunerLuminanceBlue value");
+ int value = param.get<PictureParameter::Tag::colorTunerLuminanceBlue>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerLuminanceCyan: {
+ ALOGD("[validatePictureParameter] validate colorTunerLuminanceCyan value");
+ int value = param.get<PictureParameter::Tag::colorTunerLuminanceCyan>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerLuminanceMagenta: {
+ ALOGD("[validatePictureParameter] validate colorTunerLuminanceMagenta value");
+ int value = param.get<PictureParameter::Tag::colorTunerLuminanceMagenta>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerLuminanceYellow: {
+ ALOGD("[validatePictureParameter] validate colorTunerLuminanceYellow value");
+ int value = param.get<PictureParameter::Tag::colorTunerLuminanceYellow>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerLuminanceFlesh: {
+ ALOGD("[validatePictureParameter] validate colorTunerLuminanceFlesh value");
+ int value = param.get<PictureParameter::Tag::colorTunerLuminanceFlesh>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ default:
+ ALOGD("Those parameters don't need to check.");
+ break;
+ }
+}
+
+void validateSoundParameter(const SoundParameter& param) {
+ switch (param.getTag()) {
+ case SoundParameter::Tag::balance: {
+ ALOGD("[validateSoundParameter] validate balance value");
+ int value = param.get<SoundParameter::Tag::balance>();
+ EXPECT_GE(value, -50);
+ EXPECT_LE(value, 50);
+ break;
+ }
+ case SoundParameter::Tag::bass: {
+ ALOGD("[validateSoundParameter] validate bass value");
+ int value = param.get<SoundParameter::Tag::bass>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case SoundParameter::Tag::treble: {
+ ALOGD("[validateSoundParameter] validate treble value");
+ int value = param.get<SoundParameter::Tag::treble>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case SoundParameter::Tag::speakersDelayMs: {
+ ALOGD("[validateSoundParameter] validate speakersDelayMs value");
+ int value = param.get<SoundParameter::Tag::speakersDelayMs>();
+ EXPECT_GE(value, 0);
+ EXPECT_LE(value, 250);
+ break;
+ }
+ case SoundParameter::Tag::digitalOutputDelayMs: {
+ ALOGD("[validateSoundParameter] validate digitalOutputDelayMs value");
+ int value = param.get<SoundParameter::Tag::digitalOutputDelayMs>();
+ EXPECT_GE(value, 0);
+ EXPECT_LE(value, 250);
+ break;
+ }
+ default:
+ ALOGD("Those parameters don't need to check.");
+ break;
+ }
+}
+
+class MediaQualityCallback : public BnMediaQualityCallback {
+ public:
+ explicit MediaQualityCallback(
+ const std::function<void(const AmbientBacklightEvent& event)>& 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<void(const AmbientBacklightEvent& event)> on_hal_event_cb_;
+};
+
+class PictureProfileAdjustmentListener : public BnPictureProfileAdjustmentListener {
+ public:
+ explicit PictureProfileAdjustmentListener(
+ const std::function<void(const PictureProfile& pictureProfile)>&
+ on_hal_picture_profile_adjust)
+ : on_hal_picture_profile_adjust_(on_hal_picture_profile_adjust) {}
+
+ ScopedAStatus onPictureProfileAdjusted(const PictureProfile& pictureProfile) override {
+ for (const auto& param : pictureProfile.parameters.pictureParameters) {
+ validatePictureParameter(param);
+ }
+ on_hal_picture_profile_adjust_(pictureProfile);
+ return ScopedAStatus::ok();
+ }
+
+ ScopedAStatus onParamCapabilityChanged(int64_t, const std::vector<ParamCapability>&) override {
+ return ScopedAStatus::ok();
+ }
+
+ ScopedAStatus onVendorParamCapabilityChanged(int64_t,
+ const std::vector<VendorParamCapability>&) {
+ return ScopedAStatus::ok();
+ }
+
+ ScopedAStatus requestPictureParameters(int64_t) { return ScopedAStatus::ok(); }
+
+ ScopedAStatus onStreamStatusChanged(int64_t, StreamStatus) { return ScopedAStatus::ok(); }
+
+ private:
+ std::function<void(const PictureProfile& pictureProfile)> on_hal_picture_profile_adjust_;
+};
+
+class SoundProfileAdjustmentListener : public BnSoundProfileAdjustmentListener {
+ public:
+ explicit SoundProfileAdjustmentListener(
+ const std::function<void(const SoundProfile& soundProfile)>&
+ on_hal_sound_profile_adjust)
+ : on_hal_sound_profile_adjust_(on_hal_sound_profile_adjust) {}
+
+ ScopedAStatus onSoundProfileAdjusted(const SoundProfile& soundProfile) override {
+ for (const auto& param : soundProfile.parameters.soundParameters) {
+ validateSoundParameter(param);
+ }
+ on_hal_sound_profile_adjust_(soundProfile);
+ return ScopedAStatus::ok();
+ }
+
+ ScopedAStatus onParamCapabilityChanged(int64_t, const std::vector<ParamCapability>&) override {
+ return ScopedAStatus::ok();
+ }
+
+ ScopedAStatus onVendorParamCapabilityChanged(int64_t,
+ const std::vector<VendorParamCapability>&) {
+ return ScopedAStatus::ok();
+ }
+
+ ScopedAStatus requestSoundParameters(int64_t) { return ScopedAStatus::ok(); }
+
+ private:
+ std::function<void(const SoundProfile& soundProfile)> on_hal_sound_profile_adjust_;
+};
+
+class MediaQualityAidl : public testing::TestWithParam<std::string> {
+ public:
+ virtual void SetUp() override {
+ mediaquality = IMediaQuality::fromBinder(
+ SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+ ASSERT_NE(mediaquality, nullptr);
+ }
+ std::shared_ptr<IMediaQuality> mediaquality;
+};
+
+TEST_P(MediaQualityAidl, TestSetAmbientBacklightDetectionEnabled) {
+ std::promise<void> open_cb_promise;
+ std::future<void> open_cb_future{open_cb_promise.get_future()};
+ std::shared_ptr<MediaQualityCallback> callback =
+ ndk::SharedRefBase::make<MediaQualityCallback>([&open_cb_promise](auto event) {
+ EXPECT_EQ(event.getTag(), AmbientBacklightEvent::Tag::enabled);
+ EXPECT_EQ(event.template get<AmbientBacklightEvent::Tag::enabled>(), true);
+ open_cb_promise.set_value();
+ return ScopedAStatus::ok();
+ });
+ ASSERT_OK(mediaquality->setAmbientBacklightCallback(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<MediaQualityCallback> callback = ndk::SharedRefBase::make<MediaQualityCallback>(
+ [](auto /* event */) { return ScopedAStatus::ok(); });
+ ASSERT_OK(mediaquality->setAmbientBacklightCallback(callback));
+}
+
+TEST_P(MediaQualityAidl, TestSetPictureProfileAdjustmentListener) {
+ std::shared_ptr<PictureProfileAdjustmentListener> listener =
+ ndk::SharedRefBase::make<PictureProfileAdjustmentListener>(
+ [](auto /*picture profile*/) { return ScopedAStatus::ok(); });
+ ASSERT_OK(mediaquality->setPictureProfileAdjustmentListener(listener));
+}
+
+TEST_P(MediaQualityAidl, TestSendDefaultPictureParameters) {
+ PictureParameters pictureParameters;
+ std::vector<PictureParameter> picParams;
+
+ PictureParameter brightnessParam;
+ brightnessParam.set<PictureParameter::Tag::brightness>(0.5f);
+ picParams.push_back(brightnessParam);
+
+ PictureParameter contrastParam;
+ contrastParam.set<PictureParameter::Tag::contrast>(50);
+ picParams.push_back(contrastParam);
+
+ pictureParameters.pictureParameters = picParams;
+ ASSERT_OK(mediaquality->sendDefaultPictureParameters(pictureParameters));
+}
+
+TEST_P(MediaQualityAidl, TestSetSoundProfileAdjustmentListener) {
+ std::shared_ptr<SoundProfileAdjustmentListener> listener =
+ ndk::SharedRefBase::make<SoundProfileAdjustmentListener>(
+ [](auto /*sound profile*/) { return ScopedAStatus::ok(); });
+ ASSERT_OK(mediaquality->setSoundProfileAdjustmentListener(listener));
+}
+
+TEST_P(MediaQualityAidl, TestSendDefaultSoundParameters) {
+ SoundParameters soundParameters;
+ std::vector<SoundParameter> soundParams;
+
+ SoundParameter balanceParam;
+ balanceParam.set<SoundParameter::Tag::balance>(50);
+ soundParams.push_back(balanceParam);
+
+ SoundParameter bassParam;
+ bassParam.set<SoundParameter::Tag::bass>(50);
+ soundParams.push_back(bassParam);
+
+ soundParameters.soundParameters = soundParams;
+ ASSERT_OK(mediaquality->sendDefaultSoundParameters(soundParameters));
+}
+
+TEST_P(MediaQualityAidl, TestSetAmbientBacklightDetector) {
+ AmbientBacklightSettings in_settings = {
+ .uid = 1,
+ .source = AmbientBacklightSource::VIDEO,
+ .colorFormat = PixelFormat::RGB_888,
+ .hZonesNumber = 32,
+ .vZonesNumber = 20,
+ .hasLetterbox = true,
+ .colorThreshold = 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 efcc327..e53e84d 100644
--- a/tv/tuner/aidl/Android.bp
+++ b/tv/tuner/aidl/Android.bp
@@ -39,7 +39,7 @@
"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 783511f..2977ff6 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 @@
/* @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 96a6d98..eba820c 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 @@
@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 6c538ea..4754bb1 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 @@
/* @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 95ecc51..1f7153b 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 @@
/* @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 a56a0cf..ccbfd1a 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 @@
/* @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 3b8fee4..5fb34ba 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 @@
/* @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 f0df497..c164f19 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 @@
/* @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 ccca6de..59edc34 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 @@
@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 6abd87b..b78965d 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 @@
@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 61a9555..126c740 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 @@
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 5d27f76..062650b 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 @@
/* @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 1dc593a..cfc5838 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 @@
/* @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 872d963..12f9dc8 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 @@
/* @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 b78ac9a..7320aec 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 @@
/* @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 7e9e3a6..a89c5b1 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 @@
/* @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 bcd0aeb..ecb4e8b 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 @@
/* @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 fb4430b..5556bb2 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 @@
/* @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 651b66c..5c51793 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 @@
@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 670b34e..d07bcb7 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 @@
@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 25f0585..509c1ab 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 @@
@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 3e08d26..ac3a5e6 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 @@
@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 a4e1ff1..bd9e583 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 @@
/* @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 8b806bf..8be0e95 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 @@
/* @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 ed03477..9ca684f 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 @@
/* @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 3a0c1e4..6dab74b 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 @@
/* @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 8c5a3f5..af35c70 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 @@
/* @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 6b32110..45aa2af 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 @@
/* @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 3502522..8d19461 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 @@
@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 33fd93d..bf8b000 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 @@
@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 51a3fc5..9704f40 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 @@
@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 aec0718..2d09271 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 @@
@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 8702a49..22267e7 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 @@
@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 a2c140a..2e229c0 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 @@
@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 09e513d..cbe8c1f 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 @@
@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 a9747f0..4e70641 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 @@
@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 426fe20..7da48f1 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 @@
@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 ff71df3..61cbf12 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 @@
@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 18d71d2..6f62d91 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 @@
@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 c9454e7..d6be639 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 @@
@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 872eb6a..5626064 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 @@
@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 088aac5..036e64b 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 @@
@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 8321ad0..1223887 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 @@
@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 5298291..0498825 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 @@
@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 cdfedb6..985add1 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 @@
@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 f0fe460..c253cfe 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 @@
@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 0871777..c18e83e 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 @@
@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 f1e92c9..a6fbc6d 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 @@
@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 25951cc..71957d5 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 @@
@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 4f2c6eb..e3543b3 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 @@
/* @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 56ee37b..2181abf 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 @@
/* @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 110b1d8..46edb56 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 @@
@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 b9cb657..bcb1c6d 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 @@
@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 2cbff7c..af87423 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 @@
/* @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 f5d14e8..ff2d9e4 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 @@
@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 8bd0489..8d2df06 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 @@
@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 bc40901..4bd5691 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 @@
@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 073a77e..01c2b66 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 @@
@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 9ed5c8c..bd86479 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 @@
@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 c80bc2a..dc8e12c 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 @@
/* @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 c7ba68a..080cc5c 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 @@
@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 e3ca2e3..3731f86 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 @@
@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 443313f..101e347 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 @@
/* @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 19599a3..da91888 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 @@
@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 50a1208..5806cc5 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 @@
@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 aa08496..43ae523 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 @@
@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 08a01f1..2e4c478 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 @@
@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 1ee7f07..de865ca 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 @@
@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 3603292..adc902d 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 @@
@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 733760c..c93cf20 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 @@
/* @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 09e9c59..a0e436f 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 @@
@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 7b9bde6..61a21c3 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 @@
@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 a2ab154..b769231 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 @@
/* @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 089f611..77956b6 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 @@
/* @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 cd49214..209620f 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 @@
@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 2b747ed..4236b7c 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 @@
@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 42a023a..86225e2 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 @@
@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 54698ab..0e38c26 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 @@
@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 a31e0cf..4474c83 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 @@
@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 133887f..1387e66 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 @@
@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 50adde9..b9d76ee 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 @@
@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 6976ecd..186dbd7 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 @@
/* @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 ed42d0a..cef02cc 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 @@
@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 ff11bb8..14ec2fd 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 @@
/* @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 0000000..88637db
--- /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 <name>-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 b991ab6..e79eba6 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 @@
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 41944ce..13735fa 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 @@
/* @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 3791299..bfd2145 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 @@
/* @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 cbf5b47..455bbc0 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 @@
@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 e6e2b05..7bec809 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 @@
/* @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 5fc4d15..a4a5740 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 @@
/* @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 3217de9..0628354 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 @@
/* @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 034c7e6..b18ff0e 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 @@
/* @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 850b737..a8b6378 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 @@
/* @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 48bf9ec..e06b616 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 @@
/* @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 4e22f67..ae43350 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 @@
/* @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 656fe20..4d52de1 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 @@
/* @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 dbb6033..530f454 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 @@
/* @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 32f0cb2..06f087b 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 @@
* 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 0000000..0b68e89
--- /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 391f29b..a3902df 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.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 @@
* 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 6804b2d..3225c42 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 @@
* 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 5f7a4cd..946ec3a 100644
--- a/tv/tuner/aidl/default/Filter.cpp
+++ b/tv/tuner/aidl/default/Filter.cpp
@@ -333,8 +333,8 @@
// 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 @@
return (stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino);
}
-void Filter::createMediaEvent(vector<DemuxFilterEvent>& events, bool isAudioPresentation) {
+void Filter::createMediaEvent(vector<DemuxFilterEvent>& events, bool isAudioPresentation,
+ int indexInDataGroup) {
DemuxFilterMediaEvent mediaEvent;
mediaEvent.streamId = 1;
mediaEvent.isPtsPresent = true;
@@ -1302,6 +1303,10 @@
mediaEvent.avDataId = static_cast<int64_t>(dataId);
mediaEvent.avMemory = ::android::dupToAidl(nativeHandle);
+ mediaEvent.numDataPieces = 2;
+ mediaEvent.indexInDataGroup = indexInDataGroup;
+ mediaEvent.dataGroupId = 321;
+
events.push_back(DemuxFilterEvent::make<DemuxFilterEvent::Tag::media>(std::move(mediaEvent)));
native_handle_close(nativeHandle);
diff --git a/tv/tuner/aidl/default/Filter.h b/tv/tuner/aidl/default/Filter.h
index e2a0c7a..4be15e2 100644
--- a/tv/tuner/aidl/default/Filter.h
+++ b/tv/tuner/aidl/default/Filter.h
@@ -231,7 +231,8 @@
::ndk::ScopedAStatus createShareMemMediaEvents(vector<int8_t>& output);
bool sameFile(int fd1, int fd2);
- void createMediaEvent(vector<DemuxFilterEvent>&, bool isAudioPresentation);
+ void createMediaEvent(vector<DemuxFilterEvent>&, bool isAudioPresentation,
+ int indexInDataGroup);
void createTsRecordEvent(vector<DemuxFilterEvent>&);
void createMmtpRecordEvent(vector<DemuxFilterEvent>&);
void createSectionEvent(vector<DemuxFilterEvent>&);
diff --git a/tv/tuner/aidl/default/Frontend.cpp b/tv/tuner/aidl/default/Frontend.cpp
index 1031604..bba004a 100644
--- a/tv/tuner/aidl/default/Frontend.cpp
+++ b/tv/tuner/aidl/default/Frontend.cpp
@@ -81,6 +81,7 @@
FrontendStatusType::SIGNAL_STRENGTH, FrontendStatusType::SYMBOL_RATE,
FrontendStatusType::MODULATION, FrontendStatusType::MODULATIONS,
FrontendStatusType::ROLL_OFF, FrontendStatusType::IS_MISO,
+ FrontendStatusType::STANDARD_EXT,
};
break;
}
@@ -96,6 +97,7 @@
FrontendStatusType::TRANSMISSION_MODE,
FrontendStatusType::T2_SYSTEM_ID,
FrontendStatusType::DVBT_CELL_IDS,
+ FrontendStatusType::STANDARD_EXT,
};
break;
}
@@ -985,6 +987,17 @@
status.set<FrontendStatus::iptvAverageJitterMs>(5);
break;
}
+ case FrontendStatusType::STANDARD_EXT: {
+ FrontendStandardExt standardExt;
+ if (mType == FrontendType::DVBS) {
+ standardExt.set<FrontendStandardExt::dvbsStandardExt>(
+ FrontendDvbsStandard::S2X);
+ } else if (mType == FrontendType::DVBT) {
+ standardExt.set<FrontendStandardExt::dvbtStandardExt>(FrontendDvbtStandard::T2);
+ }
+ status.set<FrontendStatus::standardExt>(standardExt);
+ break;
+ }
default: {
continue;
}
diff --git a/tv/tuner/aidl/default/tuner-default.xml b/tv/tuner/aidl/default/tuner-default.xml
index bff8ff0..261fcbf 100644
--- a/tv/tuner/aidl/default/tuner-default.xml
+++ b/tv/tuner/aidl/default/tuner-default.xml
@@ -2,6 +2,6 @@
<hal format="aidl">
<name>android.hardware.tv.tuner</name>
<fqname>ITuner/default</fqname>
- <version>2</version>
+ <version>3</version>
</hal>
</manifest>
diff --git a/tv/tuner/aidl/vts/functional/FilterTests.cpp b/tv/tuner/aidl/vts/functional/FilterTests.cpp
index 533d0e6..788ebbd 100644
--- a/tv/tuner/aidl/vts/functional/FilterTests.cpp
+++ b/tv/tuner/aidl/vts/functional/FilterTests.cpp
@@ -105,17 +105,30 @@
// 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<DemuxFilterEvent::Tag::media>().avMemory.fds.size());
+ case DemuxFilterEvent::Tag::media: {
+ int numDataPieces = events[i].get<DemuxFilterEvent::Tag::media>().numDataPieces;
+ int indexInDataGroup
+ = events[i].get<DemuxFilterEvent::Tag::media>().indexInDataGroup;
+ ALOGD("[vts] Media filter event, avMemHandle numFds=%zu, numDataPieces=%d,"
+ " indexInDataGroup=%d, dataGroupId=%d.",
+ events[i].get<DemuxFilterEvent::Tag::media>().avMemory.fds.size(),
+ numDataPieces,
+ indexInDataGroup,
+ events[i].get<DemuxFilterEvent::Tag::media>().dataGroupId);
+ if (numDataPieces > 1) {
+ EXPECT_TRUE(indexInDataGroup >= 0);
+ EXPECT_TRUE(indexInDataGroup < numDataPieces);
+ }
dumpAvData(events[i].get<DemuxFilterEvent::Tag::media>());
break;
- case DemuxFilterEvent::Tag::tsRecord:
+ }
+ case DemuxFilterEvent::Tag::tsRecord: {
ALOGD("[vts] TS record filter event, pts=%" PRIu64 ", firstMbInSlice=%d",
events[i].get<DemuxFilterEvent::Tag::tsRecord>().pts,
events[i].get<DemuxFilterEvent::Tag::tsRecord>().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<DemuxFilterEvent::Tag::mmtpRecord>().pts,
@@ -123,7 +136,8 @@
events[i].get<DemuxFilterEvent::Tag::mmtpRecord>().mpuSequenceNumber,
events[i].get<DemuxFilterEvent::Tag::mmtpRecord>().tsIndexMask);
break;
- case DemuxFilterEvent::Tag::monitorEvent:
+ }
+ case DemuxFilterEvent::Tag::monitorEvent: {
switch (events[i].get<DemuxFilterEvent::Tag::monitorEvent>().getTag()) {
case DemuxFilterMonitorEvent::Tag::scramblingStatus:
mScramblingStatusEvent++;
@@ -135,13 +149,16 @@
break;
}
break;
- case DemuxFilterEvent::Tag::startId:
+ }
+ case DemuxFilterEvent::Tag::startId: {
ALOGD("[vts] Restart filter event, startId=%d",
events[i].get<DemuxFilterEvent::Tag::startId>());
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 85d0496..99c0283 100644
--- a/tv/tuner/aidl/vts/functional/FrontendTests.cpp
+++ b/tv/tuner/aidl/vts/functional/FrontendTests.cpp
@@ -636,7 +636,7 @@
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<int32_t>(FrontendStatusType::ATSC3_ALL_PLP_INFO); i++) {
+ for (int32_t i = 0; i <= static_cast<int32_t>(FrontendStatusType::STANDARD_EXT); i++) {
allTypes.push_back(static_cast<FrontendStatusType>(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 0000000..de0bdb5
--- /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 <name>-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/FrequencyAccelerationMapEntry.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/FrequencyAccelerationMapEntry.aidl
new file mode 100644
index 0000000..e6743f9
--- /dev/null
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/FrequencyAccelerationMapEntry.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 <name>-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 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 0000000..ec301b2
--- /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 <name>-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 0dcc657..9fad952 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 @@
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<android.hardware.vibrator.PwleV2OutputMapEntry> getPwleV2FrequencyToOutputAccelerationMap();
+ List<android.hardware.vibrator.FrequencyAccelerationMapEntry> 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 ef5794c..081d9dc 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 @@
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 @@
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/PwleV2OutputMapEntry.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
deleted file mode 100644
index a5eda52..0000000
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-///////////////////////////////////////////////////////////////////////////////
-// 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 <name>-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 PwleV2OutputMapEntry {
- float frequencyHz;
- float maxOutputAccelerationGs;
-}
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 0000000..01136aa
--- /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 <name>-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 0000000..f0d0970
--- /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/FrequencyAccelerationMapEntry.aidl b/vibrator/aidl/android/hardware/vibrator/FrequencyAccelerationMapEntry.aidl
new file mode 100644
index 0000000..013ae84
--- /dev/null
+++ b/vibrator/aidl/android/hardware/vibrator/FrequencyAccelerationMapEntry.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.vibrator;
+
+@VintfStability
+parcelable FrequencyAccelerationMapEntry {
+ /**
+ * Absolute frequency point in the units of hertz
+ *
+ */
+ float frequencyHz;
+
+ /**
+ * Max output acceleration for the specified frequency in units of Gs.
+ *
+ * This value represents the maximum safe output acceleration (in Gs) achievable at the
+ * specified frequency, typically determined during calibration. The actual output acceleration
+ * 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 0000000..88382e5
--- /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 11f36ba..81d7948 100644
--- a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
@@ -19,12 +19,12 @@
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 @@
*
* @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 @@
*
* @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 @@
*
* @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 @@
*
* @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 @@
*
* @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 @@
* 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 @@
* 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 @@
* 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 @@
*
*
* 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 @@
* mapping.
* @throws EX_UNSUPPORTED_OPERATION if unsupported, as reflected by getCapabilities.
*/
- List<PwleV2OutputMapEntry> getPwleV2FrequencyToOutputAccelerationMap();
+ List<FrequencyAccelerationMapEntry> getFrequencyToOutputAccelerationMap();
/**
* Retrieve the maximum duration allowed for any primitive PWLE in units of
@@ -436,8 +450,8 @@
* 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 @@
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 eb5e9cc..e8b85c5 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 @@
*/
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 @@
* 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 @@
* 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/PwleV2OutputMapEntry.aidl b/vibrator/aidl/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
deleted file mode 100644
index a8db87c..0000000
--- a/vibrator/aidl/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.vibrator;
-
-@VintfStability
-parcelable PwleV2OutputMapEntry {
- /**
- * Absolute frequency point in the units of hertz
- *
- */
- float frequencyHz;
-
- /**
- * Max output acceleration for the specified frequency in units of Gs.
- *
- * 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].
- */
- float maxOutputAccelerationGs;
-}
diff --git a/vibrator/aidl/android/hardware/vibrator/PwleV2Primitive.aidl b/vibrator/aidl/android/hardware/vibrator/PwleV2Primitive.aidl
index bd7bec6..1ad1a9f 100644
--- a/vibrator/aidl/android/hardware/vibrator/PwleV2Primitive.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/PwleV2Primitive.aidl
@@ -21,7 +21,7 @@
/**
* 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 @@
* 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 0000000..56cdde3
--- /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 b25a5ba..de228cd 100644
--- a/vibrator/aidl/default/Android.bp
+++ b/vibrator/aidl/default/Android.bp
@@ -19,6 +19,7 @@
],
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 0000000..4eac831
--- /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 <android-base/logging.h>
+#include <thread>
+
+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 4f8c2b8..165a3bf 100644
--- a/vibrator/aidl/default/Vibrator.cpp
+++ b/vibrator/aidl/default/Vibrator.cpp
@@ -45,11 +45,62 @@
// 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<IVibratorCallback>& 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<Vibrator>()] {
+ 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<IVibratorCallback>& 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 @@
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::off() {
LOG(VERBOSE) << "Vibrator off";
+ std::lock_guard lock(mMutex);
+ std::shared_ptr<IVibratorCallback> callback = mVibrationCallback;
+ std::shared_ptr<IVibratorCallback> 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<IVibratorCallback>& 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<Vibrator>()].
- 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 @@
}
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 @@
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 @@
}
}
- // The thread may theoretically outlive the vibrator, so take a proper reference to it.
- std::thread([sharedThis = this->ref<Vibrator>(), composite, callback] {
- LOG(VERBOSE) << "Starting compose on another thread";
+ int32_t totalDuration = 0;
+ for (auto& e : composite) {
+ int32_t durationMs;
+ getPrimitiveDuration(e.primitive, &durationMs);
+ totalDuration += e.delayMs + durationMs;
+ }
- for (auto& e : composite) {
- if (e.delayMs) {
- usleep(e.delayMs * 1000);
- }
- LOG(VERBOSE) << "triggering primitive " << static_cast<int>(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();
-
+ dispatchVibrate(totalDuration, callback);
return ndk::ScopedAStatus::ok();
}
@@ -460,21 +490,21 @@
}
}
- 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<PwleV2OutputMapEntry>* _aidl_return) {
- std::vector<PwleV2OutputMapEntry> frequencyToOutputAccelerationMap;
+ndk::ScopedAStatus Vibrator::getFrequencyToOutputAccelerationMap(
+ std::vector<FrequencyAccelerationMapEntry>* _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<FrequencyAccelerationMapEntry> frequencyToOutputAccelerationMap;
std::vector<std::pair<float, float>> 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 @@
{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 @@
return ndk::ScopedAStatus::ok();
}
-float getPwleV2FrequencyMinHz(std::vector<PwleV2OutputMapEntry> frequencyToOutputAccelerationMap) {
+float getPwleV2FrequencyMinHz(
+ std::vector<FrequencyAccelerationMapEntry> frequencyToOutputAccelerationMap) {
if (frequencyToOutputAccelerationMap.empty()) {
return 0.0f;
}
@@ -525,7 +556,8 @@
return minFrequency;
}
-float getPwleV2FrequencyMaxHz(std::vector<PwleV2OutputMapEntry> frequencyToOutputAccelerationMap) {
+float getPwleV2FrequencyMaxHz(
+ std::vector<FrequencyAccelerationMapEntry> frequencyToOutputAccelerationMap) {
if (frequencyToOutputAccelerationMap.empty()) {
return 0.0f;
}
@@ -541,29 +573,31 @@
return maxFrequency;
}
-ndk::ScopedAStatus Vibrator::composePwleV2(const std::vector<PwleV2Primitive>& composite,
+ndk::ScopedAStatus Vibrator::composePwleV2(const CompositePwleV2& composite,
const std::shared_ptr<IVibratorCallback>& 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<PwleV2OutputMapEntry> frequencyToOutputAccelerationMap;
- getPwleV2FrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap);
+ std::vector<FrequencyAccelerationMapEntry> 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 @@
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 26edf5a..c3be468 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 <aidl/android/hardware/vibrator/BnVibratorCallback.h>
#include <android-base/logging.h>
#include <thread>
@@ -26,25 +29,52 @@
static constexpr int32_t kDefaultVibratorId = 1;
+class VibratorCallback : public BnVibratorCallback {
+ public:
+ VibratorCallback(const std::function<void()>& callback) : mCallback(callback) {}
+ ndk::ScopedAStatus onComplete() override {
+ mCallback();
+ return ndk::ScopedAStatus::ok();
+ }
+
+ private:
+ std::function<void()> 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<int32_t>* _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<IVibrator>* _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::prepareSynced(const std::vector<int32_t>& 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<IVibratorCallback>& 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<int32_t>& vibratorIds,
+ const VibrationSessionConfig&,
+ const std::shared_ptr<IVibratorCallback>& callback,
+ std::shared_ptr<IVibrationSession>* _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<VibrationSession>(this->ref<VibratorManager>());
+ *_aidl_return = static_cast<std::shared_ptr<IVibrationSession>>(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<IVibrationSession> session;
+ {
+ std::lock_guard lock(mMutex);
+ session = mSession;
+ }
+ if (session) {
+ mDefaultVibrator->off();
+ clearSession(session);
+ }
+}
+
+void VibratorManager::closeSession(int32_t delayMs) {
+ std::shared_ptr<IVibrationSession> 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<VibratorCallback>(
+ [session, delayMs, sharedThis = this->ref<VibratorManager>()] {
+ 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<IVibrationSession>& 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<IVibratorCallback> 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 0000000..98bdd1c
--- /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 <aidl/android/hardware/vibrator/BnVibrationSession.h>
+#include <aidl/android/hardware/vibrator/IVibrator.h>
+#include <aidl/android/hardware/vibrator/IVibratorCallback.h>
+#include <android-base/thread_annotations.h>
+
+#include "vibrator-impl/VibratorManager.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace vibrator {
+
+class VibrationSession : public BnVibrationSession {
+ public:
+ VibrationSession(std::shared_ptr<VibratorManager> manager) : mManager(std::move(manager)) {};
+
+ ndk::ScopedAStatus close() override;
+ ndk::ScopedAStatus abort() override;
+
+ private:
+ mutable std::mutex mMutex;
+ std::shared_ptr<VibratorManager> 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 28bc763..354ba46 100644
--- a/vibrator/aidl/default/include/vibrator-impl/Vibrator.h
+++ b/vibrator/aidl/default/include/vibrator-impl/Vibrator.h
@@ -25,6 +25,7 @@
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 @@
ndk::ScopedAStatus getSupportedBraking(std::vector<Braking>* supported) override;
ndk::ScopedAStatus composePwle(const std::vector<PrimitivePwle> &composite,
const std::shared_ptr<IVibratorCallback> &callback) override;
- ndk::ScopedAStatus getPwleV2FrequencyToOutputAccelerationMap(
- std::vector<PwleV2OutputMapEntry>* _aidl_return) override;
+ ndk::ScopedAStatus getFrequencyToOutputAccelerationMap(
+ std::vector<FrequencyAccelerationMapEntry>* _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<PwleV2Primitive>& composite,
+ ndk::ScopedAStatus composePwleV2(const CompositePwleV2& composite,
const std::shared_ptr<IVibratorCallback>& callback) override;
+ void setGlobalVibrationCallback(const std::shared_ptr<IVibratorCallback>& 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<IVibratorCallback> mVibrationCallback GUARDED_BY(mMutex) = nullptr;
+ std::shared_ptr<IVibratorCallback> mGlobalVibrationCallback GUARDED_BY(mMutex) = nullptr;
+
+ void dispatchVibrate(int32_t timeoutMs, const std::shared_ptr<IVibratorCallback>& callback);
};
} // namespace vibrator
diff --git a/vibrator/aidl/default/include/vibrator-impl/VibratorManager.h b/vibrator/aidl/default/include/vibrator-impl/VibratorManager.h
index 319eb05..fe30394 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 <aidl/android/hardware/vibrator/BnVibratorManager.h>
+#include <android-base/thread_annotations.h>
+
+#include "vibrator-impl/Vibrator.h"
namespace aidl {
namespace android {
@@ -25,7 +28,8 @@
class VibratorManager : public BnVibratorManager {
public:
- VibratorManager(std::shared_ptr<IVibrator> vibrator) : mDefaultVibrator(std::move(vibrator)){};
+ VibratorManager(std::shared_ptr<Vibrator> vibrator) : mDefaultVibrator(std::move(vibrator)) {};
+
ndk::ScopedAStatus getCapabilities(int32_t* _aidl_return) override;
ndk::ScopedAStatus getVibratorIds(std::vector<int32_t>* _aidl_return) override;
ndk::ScopedAStatus getVibrator(int32_t vibratorId,
@@ -33,9 +37,25 @@
ndk::ScopedAStatus prepareSynced(const std::vector<int32_t>& vibratorIds) override;
ndk::ScopedAStatus triggerSynced(const std::shared_ptr<IVibratorCallback>& callback) override;
ndk::ScopedAStatus cancelSynced() override;
+ ndk::ScopedAStatus startSession(const std::vector<int32_t>& vibratorIds,
+ const VibrationSessionConfig& config,
+ const std::shared_ptr<IVibratorCallback>& callback,
+ std::shared_ptr<IVibrationSession>* _aidl_return) override;
+ ndk::ScopedAStatus clearSessions() override;
+
+ void abortSession();
+ void closeSession(int32_t delayMs);
private:
- std::shared_ptr<IVibrator> mDefaultVibrator;
+ std::shared_ptr<Vibrator> 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<IVibrationSession> mSession GUARDED_BY(mMutex) = nullptr;
+ std::shared_ptr<IVibratorCallback> mSessionCallback GUARDED_BY(mMutex) = nullptr;
+
+ void clearSession(const std::shared_ptr<IVibrationSession>& session);
};
} // namespace vibrator
diff --git a/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp
index 3c2a360..101d4f5 100644
--- a/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp
@@ -16,12 +16,14 @@
#include <aidl/Gtest.h>
#include <aidl/Vintf.h>
#include <aidl/android/hardware/vibrator/BnVibratorCallback.h>
+#include <aidl/android/hardware/vibrator/IVibrationSession.h>
#include <aidl/android/hardware/vibrator/IVibrator.h>
#include <aidl/android/hardware/vibrator/IVibratorManager.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
+#include <algorithm>
#include <cmath>
#include <future>
@@ -32,10 +34,14 @@
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<Effect> kEffects{ndk::enum_range<Effect>().begin(),
ndk::enum_range<Effect>().end()};
const std::vector<EffectStrength> kEffectStrengths{ndk::enum_range<EffectStrength>().begin(),
@@ -43,6 +49,11 @@
const std::vector<CompositePrimitive> kPrimitives{ndk::enum_range<CompositePrimitive>().begin(),
ndk::enum_range<CompositePrimitive>().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<void()>& callback) : mCallback(callback) {}
@@ -64,9 +75,29 @@
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<IVibrator> vibrator;
+ EXPECT_OK(manager->getVibrator(id, &vibrator));
+ ASSERT_NE(vibrator, nullptr);
+ EXPECT_OK(vibrator->off());
+ }
}
std::shared_ptr<IVibratorManager> manager;
+ std::shared_ptr<IVibrationSession> session;
+ int32_t version;
int32_t capabilities;
std::vector<int32_t> vibratorIds;
};
@@ -109,7 +140,7 @@
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<IVibrator> vibrator;
for (int32_t id : vibratorIds) {
@@ -170,7 +201,7 @@
std::future<void> completionFuture{completionPromise.get_future()};
auto callback = ndk::SharedRefBase::make<CompletionCallback>(
[&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, VibrationSessionsSupported) {
+ if (!(capabilities & IVibratorManager::CAP_START_SESSIONS)) return;
+ if (vibratorIds.empty()) return;
+
+ std::promise<void> sessionPromise;
+ std::future<void> sessionFuture{sessionPromise.get_future()};
+ auto sessionCallback = ndk::SharedRefBase::make<CompletionCallback>(
+ [&sessionPromise] { sessionPromise.set_value(); });
+
+ VibrationSessionConfig sessionConfig;
+ EXPECT_OK(manager->startSession(vibratorIds, sessionConfig, sessionCallback, &session));
+ ASSERT_NE(session, nullptr);
+
+ int32_t durationMs = 250;
+ std::vector<std::promise<void>> vibrationPromises;
+ std::vector<std::future<void>> vibrationFutures;
+ for (int32_t id : vibratorIds) {
+ std::shared_ptr<IVibrator> vibrator;
+ EXPECT_OK(manager->getVibrator(id, &vibrator));
+ ASSERT_NE(vibrator, nullptr);
+
+ std::promise<void>& vibrationPromise = vibrationPromises.emplace_back();
+ vibrationFutures.push_back(vibrationPromise.get_future());
+ auto vibrationCallback = ndk::SharedRefBase::make<CompletionCallback>(
+ [&vibrationPromise] { vibrationPromise.set_value(); });
+ EXPECT_OK(vibrator->on(durationMs, vibrationCallback));
+ }
+
+ auto timeout = std::chrono::milliseconds(durationMs) + VIBRATION_CALLBACK_TIMEOUT;
+ for (std::future<void>& 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<void> sessionPromise;
+ std::future<void> sessionFuture{sessionPromise.get_future()};
+ auto sessionCallback = ndk::SharedRefBase::make<CompletionCallback>(
+ [&sessionPromise] { sessionPromise.set_value(); });
+
+ VibrationSessionConfig sessionConfig;
+ EXPECT_OK(manager->startSession(vibratorIds, sessionConfig, sessionCallback, &session));
+ ASSERT_NE(session, nullptr);
+
+ std::vector<std::promise<void>> vibrationPromises;
+ std::vector<std::future<void>> vibrationFutures;
+ for (int32_t id : vibratorIds) {
+ std::shared_ptr<IVibrator> vibrator;
+ EXPECT_OK(manager->getVibrator(id, &vibrator));
+ ASSERT_NE(vibrator, nullptr);
+
+ std::promise<void>& vibrationPromise = vibrationPromises.emplace_back();
+ vibrationFutures.push_back(vibrationPromise.get_future());
+ auto vibrationCallback = ndk::SharedRefBase::make<CompletionCallback>(
+ [&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<void>& 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<void> sessionPromise;
+ std::future<void> sessionFuture{sessionPromise.get_future()};
+ auto sessionCallback = ndk::SharedRefBase::make<CompletionCallback>(
+ [&sessionPromise] { sessionPromise.set_value(); });
+
+ VibrationSessionConfig sessionConfig;
+ EXPECT_OK(manager->startSession(vibratorIds, sessionConfig, sessionCallback, &session));
+ ASSERT_NE(session, nullptr);
+
+ std::vector<std::promise<void>> vibrationPromises;
+ std::vector<std::future<void>> vibrationFutures;
+ for (int32_t id : vibratorIds) {
+ std::shared_ptr<IVibrator> vibrator;
+ EXPECT_OK(manager->getVibrator(id, &vibrator));
+ ASSERT_NE(vibrator, nullptr);
+
+ std::promise<void>& vibrationPromise = vibrationPromises.emplace_back();
+ vibrationFutures.push_back(vibrationPromise.get_future());
+ auto vibrationCallback = ndk::SharedRefBase::make<CompletionCallback>(
+ [&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<void>& 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<void> sessionPromise;
+ std::future<void> sessionFuture{sessionPromise.get_future()};
+ auto sessionCallback = ndk::SharedRefBase::make<CompletionCallback>(
+ [&sessionPromise] { sessionPromise.set_value(); });
+
+ VibrationSessionConfig sessionConfig;
+ EXPECT_OK(manager->startSession(vibratorIds, sessionConfig, sessionCallback, &session));
+ ASSERT_NE(session, nullptr);
+
+ int32_t durationMs = 250;
+ std::vector<std::promise<void>> vibrationPromises;
+ std::vector<std::future<void>> vibrationFutures;
+ for (int32_t id : vibratorIds) {
+ std::shared_ptr<IVibrator> vibrator;
+ EXPECT_OK(manager->getVibrator(id, &vibrator));
+ ASSERT_NE(vibrator, nullptr);
+
+ std::promise<void>& vibrationPromise = vibrationPromises.emplace_back();
+ vibrationFutures.push_back(vibrationPromise.get_future());
+ auto vibrationCallback = ndk::SharedRefBase::make<CompletionCallback>(
+ [&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<void>& 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<void> sessionPromise;
+ std::future<void> sessionFuture{sessionPromise.get_future()};
+ auto sessionCallback = ndk::SharedRefBase::make<CompletionCallback>(
+ [&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<std::promise<void>> vibrationPromises;
+ std::vector<std::future<void>> vibrationFutures;
+ for (int32_t id : vibratorIds) {
+ std::shared_ptr<IVibrator> vibrator;
+ EXPECT_OK(manager->getVibrator(id, &vibrator));
+ ASSERT_NE(vibrator, nullptr);
+
+ std::promise<void>& vibrationPromise = vibrationPromises.emplace_back();
+ vibrationFutures.push_back(vibrationPromise.get_future());
+ auto vibrationCallback = ndk::SharedRefBase::make<CompletionCallback>(
+ [&vibrationPromise] { vibrationPromise.set_value(); });
+ EXPECT_OK(vibrator->on(durationMs, vibrationCallback));
+ }
+
+ std::promise<void> triggerPromise;
+ std::future<void> triggerFuture{triggerPromise.get_future()};
+ auto triggerCallback = ndk::SharedRefBase::make<CompletionCallback>(
+ [&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<void>& 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<void> sessionPromise;
+ std::future<void> sessionFuture{sessionPromise.get_future()};
+ auto sessionCallback = ndk::SharedRefBase::make<CompletionCallback>(
+ [&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<IVibrator> 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<void> sessionPromise;
+ std::future<void> sessionFuture{sessionPromise.get_future()};
+ auto sessionCallback = ndk::SharedRefBase::make<CompletionCallback>(
+ [&sessionPromise] { sessionPromise.set_value(); });
+
+ VibrationSessionConfig sessionConfig;
+ EXPECT_OK(manager->startSession(vibratorIds, sessionConfig, sessionCallback, &session));
+ ASSERT_NE(session, nullptr);
+
+ std::shared_ptr<IVibrationSession> 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<IVibrator> 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<void> sessionPromise;
+ std::future<void> sessionFuture{sessionPromise.get_future()};
+ auto sessionCallback = ndk::SharedRefBase::make<CompletionCallback>(
+ [&sessionPromise] { sessionPromise.set_value(); });
+
+ VibrationSessionConfig sessionConfig;
+ EXPECT_OK(manager->startSession(vibratorIds, sessionConfig, sessionCallback, &session));
+ ASSERT_NE(session, nullptr);
+
+ int32_t durationMs = 250;
+ std::vector<std::promise<void>> vibrationPromises;
+ std::vector<std::future<void>> vibrationFutures;
+ for (int32_t id : vibratorIds) {
+ std::shared_ptr<IVibrator> vibrator;
+ EXPECT_OK(manager->getVibrator(id, &vibrator));
+ ASSERT_NE(vibrator, nullptr);
+
+ std::promise<void>& vibrationPromise = vibrationPromises.emplace_back();
+ vibrationFutures.push_back(vibrationPromise.get_future());
+ auto vibrationCallback = ndk::SharedRefBase::make<CompletionCallback>(
+ [&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<void>& 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<void> sessionPromise;
+ std::future<void> sessionFuture{sessionPromise.get_future()};
+ auto sessionCallback = ndk::SharedRefBase::make<CompletionCallback>(
+ [&sessionPromise] { sessionPromise.set_value(); });
+
+ VibrationSessionConfig sessionConfig;
+ EXPECT_OK(manager->startSession(vibratorIds, sessionConfig, sessionCallback, &session));
+ ASSERT_NE(session, nullptr);
+
+ int32_t durationMs = 250;
+ std::vector<std::promise<void>> vibrationPromises;
+ std::vector<std::future<void>> vibrationFutures;
+ for (int32_t id : vibratorIds) {
+ std::shared_ptr<IVibrator> vibrator;
+ EXPECT_OK(manager->getVibrator(id, &vibrator));
+ ASSERT_NE(vibrator, nullptr);
+
+ std::promise<void>& vibrationPromise = vibrationPromises.emplace_back();
+ vibrationFutures.push_back(vibrationPromise.get_future());
+ auto vibrationCallback = ndk::SharedRefBase::make<CompletionCallback>(
+ [&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<void>& 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<int32_t> emptyIds;
+ std::vector<int32_t> 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<std::string> FindVibratorManagerNames() {
std::vector<std::string> names;
constexpr auto callback = [](const char* instance, void* context) {
@@ -219,7 +679,7 @@
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 bc017ae..03ecb1a 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -41,12 +41,13 @@
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 @@
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<IVibrator>& 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 @@
return freqResolutionHz;
}
-static float getFrequencyMinimumHz(const std::shared_ptr<IVibrator>& vibrator,
- int32_t capabilities) {
+static float getFrequencyMinimumHz(const std::shared_ptr<IVibrator>& 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 @@
return freqMinimumHz;
}
-static float getFrequencyMaximumHz(const std::shared_ptr<IVibrator>& vibrator,
- int32_t capabilities) {
+static float getFrequencyMaximumHz(const std::shared_ptr<IVibrator>& vibrator, int32_t capabilities,
+ int32_t version) {
std::vector<float> 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 ActivePwle composeValidActivePwle(const std::shared_ptr<IVibrator>& 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, 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<float> 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, ComposeValidPwle) {
if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
- ActivePwle firstActive = composeValidActivePwle(vibrator, capabilities);
+ ActivePwle firstActive = composeValidActivePwle(vibrator, capabilities, version);
std::vector<Braking> supported;
EXPECT_OK(vibrator->getSupportedBraking(&supported));
@@ -921,13 +939,17 @@
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 @@
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<Braking> supported;
EXPECT_OK(vibrator->getSupportedBraking(&supported));
@@ -978,7 +1000,7 @@
// 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, 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, 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);
- ActivePwle active = composeValidActivePwle(vibrator, capabilities);
+ // 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, version);
active.startFrequency =
freqMaximumHz + freqResolutionHz; // Frequency greater than allowed
active.endFrequency = freqMaximumHz + freqResolutionHz; // Frequency greater than allowed
@@ -1040,7 +1069,7 @@
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, 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<PwleV2OutputMapEntry> frequencyToOutputAccelerationMap;
+ std::vector<FrequencyAccelerationMapEntry> 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 @@
ASSERT_TRUE(sharpnessRange.first < sharpnessRange.second);
}
+TEST_P(VibratorAidl, FrequencyToOutputAccelerationMapUnsupported) {
+ if ((capabilities & IVibrator::CAP_FREQUENCY_CONTROL)) return;
+
+ std::vector<FrequencyAccelerationMapEntry> 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 @@
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 @@
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<PwleV2Primitive> 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 @@
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 @@
EXPECT_OK(vibrator->getPwleV2PrimitiveDurationMinMillis(&minDurationMs));
EXPECT_OK(vibrator->getPwleV2PrimitiveDurationMaxMillis(&maxDurationMs));
- std::vector<PwleV2Primitive> 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 2163908..eaa024c 100644
--- a/vibrator/aidl/vts/pwle_v2_utils.h
+++ b/vibrator/aidl/vts/pwle_v2_utils.h
@@ -20,8 +20,8 @@
#include <aidl/android/hardware/vibrator/IVibrator.h>
#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 getPwleV2FrequencyMinHz(const std::shared_ptr<IVibrator>& vibrator) {
- std::vector<PwleV2OutputMapEntry> frequencyToOutputAccelerationMap;
- EXPECT_OK(
- vibrator->getPwleV2FrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap));
+ std::vector<FrequencyAccelerationMapEntry> 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 getPwleV2FrequencyMaxHz(const std::shared_ptr<IVibrator>& vibrator) {
- std::vector<PwleV2OutputMapEntry> frequencyToOutputAccelerationMap;
- EXPECT_OK(
- vibrator->getPwleV2FrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap));
+ std::vector<FrequencyAccelerationMapEntry> 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 @@
return entry->frequencyHz;
}
-static std::vector<PwleV2Primitive> composeValidPwleV2Effect(
- const std::shared_ptr<IVibrator>& vibrator) {
+static CompositePwleV2 composeValidPwleV2Effect(const std::shared_ptr<IVibrator>& vibrator) {
int32_t minDurationMs;
EXPECT_OK(vibrator->getPwleV2PrimitiveDurationMinMillis(&minDurationMs));
int32_t maxDurationMs;
@@ -162,20 +159,20 @@
int32_t maxCompositionSize;
EXPECT_OK(vibrator->getPwleV2CompositionSizeMax(&maxCompositionSize));
- std::vector<PwleV2Primitive> 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<PwleV2Primitive> composePwleV2EffectWithTooManyPoints(
+static CompositePwleV2 composePwleV2EffectWithTooManyPoints(
const std::shared_ptr<IVibrator>& vibrator) {
int32_t minDurationMs, maxCompositionSize;
EXPECT_OK(vibrator->getPwleV2PrimitiveDurationMinMillis(&minDurationMs));
@@ -187,12 +184,15 @@
std::fill(pwleEffect.begin(), pwleEffect.end(),
PwleV2Primitive(/*amplitude=*/0.2f, maxFrequency, minDurationMs));
- return pwleEffect;
+ CompositePwleV2 composite;
+ composite.pwlePrimitives = pwleEffect;
+
+ return composite;
}
static std::pair<float, float> getPwleV2SharpnessRange(
const std::shared_ptr<IVibrator>& vibrator,
- std::vector<PwleV2OutputMapEntry> freqToOutputAccelerationMap) {
+ std::vector<FrequencyAccelerationMapEntry> freqToOutputAccelerationMap) {
std::pair<float, float> 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 aaf3211..e884bbd 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 392d2e9..4b7e372 100644
--- a/wifi/aidl/Android.bp
+++ b/wifi/aidl/Android.bp
@@ -29,7 +29,7 @@
"android/hardware/wifi/*.aidl",
],
imports: [
- "android.hardware.wifi.common-V1",
+ "android.hardware.wifi.common-V2",
],
stability: "vintf",
backend: {
@@ -64,5 +64,5 @@
},
],
- 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 0000000..5baf2e8
--- /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 <name>-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 0000000..32fb5ba
--- /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 <name>-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 e71dde4..af95bee 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 @@
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 5ed7517..565f33a 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 @@
@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 @@
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 @@
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 @@
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 8c44330..9d982b8 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 @@
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 a30893a..0722a04 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 @@
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 96d940a..58e62db 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 @@
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 bdc8357..90e9a8b 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 @@
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 0000000..9b26c97
--- /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 <name>-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 6c64084..90caa26 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 @@
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 3613616..5507280 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 @@
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 13202ba..9d62431 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 @@
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 0000000..5cb1aaa
--- /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 <name>-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 2817497..08bca77 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 @@
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 cb25673..8545d73 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 @@
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 0000000..e3a913b
--- /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 0000000..02b62e8
--- /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 b14a800..a350e52 100644
--- a/wifi/aidl/android/hardware/wifi/IWifiApIface.aidl
+++ b/wifi/aidl/android/hardware/wifi/IWifiApIface.aidl
@@ -85,4 +85,11 @@
* |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 d12d26c..5a5e4a7 100644
--- a/wifi/aidl/android/hardware/wifi/IWifiChip.aidl
+++ b/wifi/aidl/android/hardware/wifi/IWifiChip.aidl
@@ -87,6 +87,18 @@
* 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 @@
* 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 @@
* 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 @@
* 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 @@
* |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 3649b7b..376dcac 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.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 @@
* |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 f581c5e..f9f825f 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 @@
* 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 4bedce0..725ed3c 100644
--- a/wifi/aidl/android/hardware/wifi/NanDiscoveryCommonConfig.aidl
+++ b/wifi/aidl/android/hardware/wifi/NanDiscoveryCommonConfig.aidl
@@ -18,6 +18,8 @@
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 @@
*/
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 @@
* |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 ae75caf..09ea496 100644
--- a/wifi/aidl/android/hardware/wifi/NanPublishRequest.aidl
+++ b/wifi/aidl/android/hardware/wifi/NanPublishRequest.aidl
@@ -61,4 +61,9 @@
* 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 0000000..37ef03c
--- /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 c193924..48e211d 100644
--- a/wifi/aidl/android/hardware/wifi/RttCapabilities.aidl
+++ b/wifi/aidl/android/hardware/wifi/RttCapabilities.aidl
@@ -84,4 +84,24 @@
* 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 496ffd2..8dfbea8 100644
--- a/wifi/aidl/android/hardware/wifi/RttConfig.aidl
+++ b/wifi/aidl/android/hardware/wifi/RttConfig.aidl
@@ -19,6 +19,7 @@
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 @@
* 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 2f9aefe..361d7e9 100644
--- a/wifi/aidl/android/hardware/wifi/RttResult.aidl
+++ b/wifi/aidl/android/hardware/wifi/RttResult.aidl
@@ -213,4 +213,41 @@
* 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 0000000..0d1350e
--- /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 600165c..94bc9e3 100644
--- a/wifi/aidl/android/hardware/wifi/RttStatus.aidl
+++ b/wifi/aidl/android/hardware/wifi/RttStatus.aidl
@@ -88,4 +88,24 @@
* 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 3f1a2f1..d7cf9fe 100644
--- a/wifi/aidl/android/hardware/wifi/RttType.aidl
+++ b/wifi/aidl/android/hardware/wifi/RttType.aidl
@@ -37,4 +37,8 @@
* 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 3fcb77f..c2e8541 100644
--- a/wifi/aidl/default/Android.bp
+++ b/wifi/aidl/default/Android.bp
@@ -106,7 +106,7 @@
"libwifi-hal",
"libwifi-system-iface",
"libxml2",
- "android.hardware.wifi-V2-ndk",
+ "android.hardware.wifi-V3-ndk",
],
export_include_dirs: ["."],
@@ -138,7 +138,7 @@
"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 @@
"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 @@
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 f8ba53b..d077683 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<void* /* callback */, void* /* handler */> callback_handler_map_;
std::mutex callback_handler_lock_;
+int32_t min_callback_version_ = INT_MAX;
}
namespace aidl {
@@ -45,6 +46,18 @@
~AidlCallbackHandler() { invalidate(); }
bool addCallback(const std::shared_ptr<CallbackType>& 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<std::mutex> lk(callback_handler_lock_);
void* cbPtr = reinterpret_cast<void*>(cb->asBinder().get());
const auto& cbPosition = findCbInSet(cbPtr);
@@ -106,6 +119,8 @@
// unique_lock unlocked here
}
+ int32_t getMinCallbackVersion() { return min_callback_version_; }
+
private:
std::set<std::shared_ptr<CallbackType>> cb_set_;
AIBinder_DeathRecipient* death_handler_;
@@ -140,6 +155,15 @@
}
}
+ static int32_t getCallbackInterfaceVersion(std::shared_ptr<CallbackType> 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 d99edaa..6de150e 100644
--- a/wifi/aidl/default/aidl_struct_util.cpp
+++ b/wifi/aidl/default/aidl_struct_util.cpp
@@ -26,6 +26,9 @@
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 @@
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 {};
@@ -116,7 +121,8 @@
WIFI_FEATURE_SET_LATENCY_MODE,
WIFI_FEATURE_P2P_RAND_MAC,
WIFI_FEATURE_AFC_CHANNEL,
- WIFI_FEATURE_SET_VOIP_MODE};
+ WIFI_FEATURE_SET_VOIP_MODE,
+ WIFI_FEATURE_MLO_SAP};
for (const auto feature : features) {
if (feature & legacy_feature_set) {
*aidl_feature_set |= static_cast<uint32_t>(convertLegacyChipFeatureToAidl(feature));
@@ -2294,6 +2300,10 @@
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;
+ // TODO: Retrieve values from the legacy HAL
+ aidl_response->supportsPeriodicRanging = false;
+ aidl_response->maxSupportedBandwidth = RttBw::BW_UNSPECIFIED;
+ aidl_response->maxNumRxChainsSupported = 2;
return true;
}
@@ -2476,6 +2486,8 @@
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 +2501,8 @@
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 +2735,16 @@
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;
}
@@ -2791,6 +2815,138 @@
return true;
}
+long convertLegacyAkmsToAidl(legacy_hal::wifi_rtt_akm akms) {
+ long aidl_akms = Akm::NONE;
+ if ((akms & legacy_hal::WPA_KEY_MGMT_PASN) != 0) {
+ aidl_akms |= Akm::PASN;
+ }
+ if ((akms & legacy_hal::WPA_KEY_MGMT_SAE) != 0) {
+ aidl_akms |= Akm::SAE;
+ }
+ if ((akms & legacy_hal::WPA_KEY_MGMT_EAP_FT_SHA256) != 0) {
+ aidl_akms |= Akm::FT_EAP_SHA256;
+ }
+ if ((akms & legacy_hal::WPA_KEY_MGMT_FT_PSK_SHA256) != 0) {
+ aidl_akms |= Akm::FT_PSK_SHA256;
+ }
+ if ((akms & legacy_hal::WPA_KEY_MGMT_EAP_FT_SHA384) != 0) {
+ aidl_akms |= Akm::FT_EAP_SHA384;
+ }
+ if ((akms & legacy_hal::WPA_KEY_MGMT_FT_PSK_SHA384) != 0) {
+ aidl_akms |= Akm::FT_PSK_SHA384;
+ }
+ if ((akms & legacy_hal::WPA_KEY_MGMT_EAP_FILS_SHA256) != 0) {
+ aidl_akms |= Akm::FILS_EAP_SHA256;
+ }
+ if ((akms & legacy_hal::WPA_KEY_MGMT_EAP_FILS_SHA384) != 0) {
+ aidl_akms |= Akm::FILS_EAP_SHA384;
+ }
+ return aidl_akms;
+}
+
+legacy_hal::wifi_rtt_akm convertAidlAkmToLegacy(long akm) {
+ switch (akm) {
+ case Akm::PASN:
+ return legacy_hal::WPA_KEY_MGMT_PASN;
+ case Akm::SAE:
+ return legacy_hal::WPA_KEY_MGMT_SAE;
+ case Akm::FT_EAP_SHA256:
+ return legacy_hal::WPA_KEY_MGMT_EAP_FT_SHA256;
+ case Akm::FT_PSK_SHA256:
+ return legacy_hal::WPA_KEY_MGMT_FT_PSK_SHA256;
+ case Akm::FT_EAP_SHA384:
+ return legacy_hal::WPA_KEY_MGMT_EAP_FT_SHA384;
+ case Akm::FT_PSK_SHA384:
+ return legacy_hal::WPA_KEY_MGMT_FT_PSK_SHA384;
+ case Akm::FILS_EAP_SHA256:
+ return legacy_hal::WPA_KEY_MGMT_EAP_FILS_SHA256;
+ case Akm::FILS_EAP_SHA384:
+ return legacy_hal::WPA_KEY_MGMT_EAP_FILS_SHA384;
+ default:
+ return legacy_hal::WPA_KEY_MGMT_NONE;
+ }
+}
+
+long convertLegacyCipherSuitesToAidl(legacy_hal::wifi_rtt_cipher_suite ciphers) {
+ long aidl_ciphers = CipherSuite::NONE;
+ if ((ciphers & legacy_hal::WPA_CIPHER_CCMP_128) != 0) {
+ aidl_ciphers |= CipherSuite::CCMP_128;
+ }
+ if ((ciphers & legacy_hal::WPA_CIPHER_CCMP_256) != 0) {
+ aidl_ciphers |= CipherSuite::CCMP_256;
+ }
+ if ((ciphers & legacy_hal::WPA_CIPHER_GCMP_128) != 0) {
+ aidl_ciphers |= CipherSuite::GCMP_128;
+ }
+ if ((ciphers & legacy_hal::WPA_CIPHER_GCMP_256) != 0) {
+ aidl_ciphers |= CipherSuite::GCMP_256;
+ }
+ return aidl_ciphers;
+}
+
+legacy_hal::wifi_rtt_cipher_suite convertAidlCipherSuiteToLegacy(long cipher) {
+ switch (cipher) {
+ case CipherSuite::CCMP_128:
+ return WPA_CIPHER_CCMP_128;
+ case CipherSuite::CCMP_256:
+ return WPA_CIPHER_CCMP_256;
+ case CipherSuite::GCMP_128:
+ return WPA_CIPHER_GCMP_128;
+ case CipherSuite::GCMP_256:
+ return WPA_CIPHER_GCMP_256;
+ default:
+ return WPA_CIPHER_NONE;
+ }
+}
+
+bool convertAidlRttConfigToLegacyV4(const RttConfig& aidl_config,
+ legacy_hal::wifi_rtt_config_v4* legacy_config) {
+ if (!legacy_config) {
+ return false;
+ }
+ *legacy_config = {};
+ if (!convertAidlRttConfigToLegacyV3(aidl_config, &(legacy_config->rtt_config))) {
+ return false;
+ }
+ if (aidl_config.secureConfig.has_value()) {
+ legacy_config->rtt_secure_config.enable_secure_he_ltf =
+ aidl_config.secureConfig->enableSecureHeLtf;
+ legacy_config->rtt_secure_config.enable_ranging_frame_protection =
+ aidl_config.secureConfig->enableRangingFrameProtection;
+ if (aidl_config.secureConfig->pasnComebackCookie.has_value() &&
+ aidl_config.secureConfig->pasnComebackCookie->size() <= RTT_MAX_COOKIE_LEN) {
+ legacy_config->rtt_secure_config.pasn_config.comeback_cookie_len =
+ aidl_config.secureConfig->pasnComebackCookie->size();
+ memcpy(legacy_config->rtt_secure_config.pasn_config.comeback_cookie,
+ aidl_config.secureConfig->pasnComebackCookie->data(),
+ aidl_config.secureConfig->pasnComebackCookie->size());
+ }
+ legacy_config->rtt_secure_config.pasn_config.base_akm =
+ convertAidlAkmToLegacy(aidl_config.secureConfig->pasnConfig.baseAkm);
+ legacy_config->rtt_secure_config.pasn_config.pairwise_cipher_suite =
+ convertAidlCipherSuiteToLegacy(aidl_config.secureConfig->pasnConfig.cipherSuite);
+ if (aidl_config.secureConfig->pasnConfig.passphrase.has_value() &&
+ aidl_config.secureConfig->pasnConfig.passphrase->size() <=
+ RTT_SECURITY_MAX_PASSPHRASE_LEN) {
+ legacy_config->rtt_secure_config.pasn_config.passphrase_len =
+ aidl_config.secureConfig->pasnConfig.passphrase->size();
+ memcpy(legacy_config->rtt_secure_config.pasn_config.passphrase,
+ aidl_config.secureConfig->pasnConfig.passphrase->data(),
+ aidl_config.secureConfig->pasnConfig.passphrase->size());
+ }
+ if (aidl_config.secureConfig->pasnConfig.pmkid.has_value() &&
+ aidl_config.secureConfig->pasnConfig.pmkid->size() == PMKID_LEN) {
+ legacy_config->rtt_secure_config.pasn_config.pmkid_len =
+ aidl_config.secureConfig->pasnConfig.pmkid->size();
+ memcpy(legacy_config->rtt_secure_config.pasn_config.pmkid,
+ aidl_config.secureConfig->pasnConfig.pmkid->data(),
+ aidl_config.secureConfig->pasnConfig.pmkid->size());
+ }
+ }
+
+ return true;
+}
+
bool convertAidlVectorOfRttConfigToLegacy(
const std::vector<RttConfig>& aidl_configs,
std::vector<legacy_hal::wifi_rtt_config>* legacy_configs) {
@@ -2825,6 +2981,23 @@
return true;
}
+bool convertAidlVectorOfRttConfigToLegacyV4(
+ const std::vector<RttConfig>& aidl_configs,
+ std::vector<legacy_hal::wifi_rtt_config_v4>* legacy_configs) {
+ if (!legacy_configs) {
+ return false;
+ }
+ *legacy_configs = {};
+ for (const auto& aidl_config : aidl_configs) {
+ legacy_hal::wifi_rtt_config_v4 legacy_config;
+ if (!convertAidlRttConfigToLegacyV4(aidl_config, &legacy_config)) {
+ return false;
+ }
+ legacy_configs->push_back(legacy_config);
+ }
+ return true;
+}
+
bool convertAidlRttLciInformationToLegacy(const RttLciInformation& aidl_info,
legacy_hal::wifi_lci_information* legacy_info) {
if (!legacy_info) {
@@ -2935,6 +3108,12 @@
aidl_capabilities->azBwSupport = (int)RttBw::BW_UNSPECIFIED;
aidl_capabilities->ntbInitiatorSupported = false;
aidl_capabilities->ntbResponderSupported = false;
+ // Initialize 11az secure ranging parameters to default
+ aidl_capabilities->akmsSupported = Akm::NONE;
+ aidl_capabilities->cipherSuitesSupported = CipherSuite::NONE;
+ aidl_capabilities->secureHeLtfSupported = false;
+ aidl_capabilities->rangingFrameProtectionSupported = false;
+ aidl_capabilities->maxSupportedSecureHeLtfProtocolVersion = false;
return true;
}
@@ -2962,6 +3141,53 @@
(int)convertLegacyRttBwBitmapToAidl(legacy_capabilities_v3.az_bw_support);
aidl_capabilities->ntbInitiatorSupported = legacy_capabilities_v3.ntb_initiator_supported;
aidl_capabilities->ntbResponderSupported = legacy_capabilities_v3.ntb_responder_supported;
+ // Initialize 11az secure ranging parameters to default
+ aidl_capabilities->akmsSupported = Akm::NONE;
+ aidl_capabilities->cipherSuitesSupported = CipherSuite::NONE;
+ aidl_capabilities->secureHeLtfSupported = false;
+ aidl_capabilities->rangingFrameProtectionSupported = false;
+ aidl_capabilities->maxSupportedSecureHeLtfProtocolVersion = false;
+
+ return true;
+}
+
+bool convertLegacyRttCapabilitiesV4ToAidl(
+ const legacy_hal::wifi_rtt_capabilities_v4& legacy_capabilities_v4,
+ RttCapabilities* aidl_capabilities) {
+ if (!aidl_capabilities) {
+ return false;
+ }
+ *aidl_capabilities = {};
+ aidl_capabilities->rttOneSidedSupported =
+ legacy_capabilities_v4.rtt_capab_v3.rtt_capab.rtt_one_sided_supported;
+ aidl_capabilities->rttFtmSupported =
+ legacy_capabilities_v4.rtt_capab_v3.rtt_capab.rtt_ftm_supported;
+ aidl_capabilities->lciSupported = legacy_capabilities_v4.rtt_capab_v3.rtt_capab.lci_support;
+ aidl_capabilities->lcrSupported = legacy_capabilities_v4.rtt_capab_v3.rtt_capab.lcr_support;
+ aidl_capabilities->responderSupported =
+ legacy_capabilities_v4.rtt_capab_v3.rtt_capab.responder_supported;
+ aidl_capabilities->preambleSupport = convertLegacyRttPreambleBitmapToAidl(
+ legacy_capabilities_v4.rtt_capab_v3.rtt_capab.preamble_support);
+ aidl_capabilities->bwSupport = convertLegacyRttBwBitmapToAidl(
+ legacy_capabilities_v4.rtt_capab_v3.rtt_capab.bw_support);
+ aidl_capabilities->mcVersion = legacy_capabilities_v4.rtt_capab_v3.rtt_capab.mc_version;
+ aidl_capabilities->azPreambleSupport = (int)convertLegacyRttPreambleBitmapToAidl(
+ legacy_capabilities_v4.rtt_capab_v3.az_preamble_support);
+ aidl_capabilities->azBwSupport =
+ (int)convertLegacyRttBwBitmapToAidl(legacy_capabilities_v4.rtt_capab_v3.az_bw_support);
+ aidl_capabilities->ntbInitiatorSupported =
+ legacy_capabilities_v4.rtt_capab_v3.ntb_initiator_supported;
+ aidl_capabilities->ntbResponderSupported =
+ legacy_capabilities_v4.rtt_capab_v3.ntb_responder_supported;
+ aidl_capabilities->akmsSupported =
+ convertLegacyAkmsToAidl(legacy_capabilities_v4.supported_akms);
+ aidl_capabilities->cipherSuitesSupported =
+ convertLegacyCipherSuitesToAidl(legacy_capabilities_v4.supported_cipher_suites);
+ aidl_capabilities->secureHeLtfSupported = legacy_capabilities_v4.secure_he_ltf_supported;
+ aidl_capabilities->rangingFrameProtectionSupported =
+ legacy_capabilities_v4.ranging_fame_protection_supported;
+ aidl_capabilities->maxSupportedSecureHeLtfProtocolVersion =
+ legacy_capabilities_v4.max_supported_secure_he_ltf_protocol_ver;
return true;
}
@@ -3042,6 +3268,13 @@
aidl_result.ntbMaxMeasurementTime = 0;
aidl_result.numTxSpatialStreams = 0;
aidl_result.numRxSpatialStreams = 0;
+ aidl_result.isRangingFrameProtectionEnabled = false;
+ aidl_result.isSecureLtfEnabled = false;
+ aidl_result.baseAkm = Akm::NONE;
+ aidl_result.cipherSuite = CipherSuite::NONE;
+ aidl_result.secureHeLtfProtocolVersion = 0;
+ aidl_result.pasnComebackAfterMillis = 0;
+ aidl_result.pasnComebackCookie = std::nullopt;
aidl_results->push_back(aidl_result);
}
return true;
@@ -3068,6 +3301,13 @@
aidl_result.ntbMaxMeasurementTime = 0;
aidl_result.numTxSpatialStreams = 0;
aidl_result.numRxSpatialStreams = 0;
+ aidl_result.isRangingFrameProtectionEnabled = false;
+ aidl_result.isSecureLtfEnabled = false;
+ aidl_result.baseAkm = Akm::NONE;
+ aidl_result.cipherSuite = CipherSuite::NONE;
+ aidl_result.secureHeLtfProtocolVersion = 0;
+ aidl_result.pasnComebackAfterMillis = 0;
+ aidl_result.pasnComebackCookie = std::nullopt;
aidl_results->push_back(aidl_result);
}
return true;
@@ -3095,6 +3335,57 @@
aidl_result.ntbMaxMeasurementTime = legacy_result->ntb_max_measurement_time;
aidl_result.numTxSpatialStreams = legacy_result->num_tx_sts;
aidl_result.numRxSpatialStreams = legacy_result->num_rx_sts;
+ aidl_result.isRangingFrameProtectionEnabled = false;
+ aidl_result.isSecureLtfEnabled = false;
+ aidl_result.baseAkm = Akm::NONE;
+ aidl_result.cipherSuite = CipherSuite::NONE;
+ aidl_result.secureHeLtfProtocolVersion = 0;
+ aidl_result.pasnComebackAfterMillis = 0;
+ aidl_result.pasnComebackCookie = std::nullopt;
+ aidl_results->push_back(aidl_result);
+ }
+ return true;
+}
+
+bool convertLegacyVectorOfRttResultV4ToAidl(
+ const std::vector<const legacy_hal::wifi_rtt_result_v4*>& legacy_results,
+ std::vector<RttResult>* aidl_results) {
+ if (!aidl_results) {
+ return false;
+ }
+ *aidl_results = {};
+ for (const auto legacy_result : legacy_results) {
+ RttResult aidl_result;
+ if (!convertLegacyRttResultToAidl(legacy_result->rtt_result_v3.rtt_result.rtt_result,
+ &aidl_result)) {
+ return false;
+ }
+ aidl_result.channelFreqMHz =
+ legacy_result->rtt_result_v3.rtt_result.frequency != UNSPECIFIED
+ ? legacy_result->rtt_result_v3.rtt_result.frequency
+ : 0;
+ aidl_result.packetBw =
+ convertLegacyRttBwToAidl(legacy_result->rtt_result_v3.rtt_result.packet_bw);
+ aidl_result.i2rTxLtfRepetitionCount =
+ legacy_result->rtt_result_v3.i2r_tx_ltf_repetition_count;
+ aidl_result.r2iTxLtfRepetitionCount =
+ legacy_result->rtt_result_v3.r2i_tx_ltf_repetition_count;
+ aidl_result.ntbMinMeasurementTime = legacy_result->rtt_result_v3.ntb_min_measurement_time;
+ aidl_result.ntbMaxMeasurementTime = legacy_result->rtt_result_v3.ntb_max_measurement_time;
+ aidl_result.numTxSpatialStreams = legacy_result->rtt_result_v3.num_tx_sts;
+ aidl_result.numRxSpatialStreams = legacy_result->rtt_result_v3.num_rx_sts;
+ aidl_result.isRangingFrameProtectionEnabled = legacy_result->is_ranging_protection_enabled;
+ aidl_result.isSecureLtfEnabled = legacy_result->is_secure_he_ltf_enabled;
+ aidl_result.baseAkm = convertLegacyAkmsToAidl(legacy_result->base_akm);
+ aidl_result.cipherSuite = convertLegacyCipherSuitesToAidl(legacy_result->cipher_suite);
+ aidl_result.secureHeLtfProtocolVersion = legacy_result->secure_he_ltf_protocol_version;
+ aidl_result.pasnComebackAfterMillis = legacy_result->pasn_comeback_after_millis;
+ if (legacy_result->pasn_comeback_cookie_len > 0 &&
+ legacy_result->pasn_comeback_cookie_len <= RTT_MAX_COOKIE_LEN) {
+ aidl_result.pasnComebackCookie = std::vector<uint8_t>(
+ legacy_result->pasn_comeback_cookie,
+ legacy_result->pasn_comeback_cookie + legacy_result->pasn_comeback_cookie_len);
+ }
aidl_results->push_back(aidl_result);
}
return true;
@@ -3592,7 +3883,8 @@
return false;
}
*aidl_scan_result = {};
- aidl_scan_result->timeStampInUs = ts_us - legacy_scan_result.age_ms * 1000;
+ aidl_scan_result->timeStampInUs =
+ ts_us - (static_cast<uint64_t>(legacy_scan_result.age_ms) * 1000);
if (aidl_scan_result->timeStampInUs < 0) {
aidl_scan_result->timeStampInUs = 0;
return false;
diff --git a/wifi/aidl/default/aidl_struct_util.h b/wifi/aidl/default/aidl_struct_util.h
index 2574f95..b6a06db 100644
--- a/wifi/aidl/default/aidl_struct_util.h
+++ b/wifi/aidl/default/aidl_struct_util.h
@@ -17,6 +17,8 @@
#ifndef AIDL_STRUCT_UTIL_H_
#define AIDL_STRUCT_UTIL_H_
+#include <aidl/android/hardware/wifi/Akm.h>
+#include <aidl/android/hardware/wifi/CipherSuite.h>
#include <aidl/android/hardware/wifi/IWifiChip.h>
#include <aidl/android/hardware/wifi/IWifiChipEventCallback.h>
#include <aidl/android/hardware/wifi/NanBandIndex.h>
@@ -153,6 +155,10 @@
const std::vector<RttConfig>& aidl_configs,
std::vector<legacy_hal::wifi_rtt_config_v3>* legacy_configs);
+bool convertAidlVectorOfRttConfigToLegacyV4(
+ const std::vector<RttConfig>& aidl_configs,
+ std::vector<legacy_hal::wifi_rtt_config_v4>* legacy_configs);
+
bool convertAidlRttLciInformationToLegacy(const RttLciInformation& aidl_info,
legacy_hal::wifi_lci_information* legacy_info);
bool convertAidlRttLcrInformationToLegacy(const RttLcrInformation& aidl_info,
@@ -169,6 +175,9 @@
bool convertLegacyRttCapabilitiesV3ToAidl(
const legacy_hal::wifi_rtt_capabilities_v3& legacy_capabilities_v3,
RttCapabilities* aidl_capabilities);
+bool convertLegacyRttCapabilitiesV4ToAidl(
+ const legacy_hal::wifi_rtt_capabilities_v4& legacy_capabilities_v4,
+ RttCapabilities* aidl_capabilities);
bool convertLegacyVectorOfRttResultToAidl(
const std::vector<const legacy_hal::wifi_rtt_result*>& legacy_results,
@@ -179,6 +188,9 @@
bool convertLegacyVectorOfRttResultV3ToAidl(
const std::vector<const legacy_hal::wifi_rtt_result_v3*>& legacy_results,
std::vector<RttResult>* aidl_results);
+bool convertLegacyVectorOfRttResultV4ToAidl(
+ const std::vector<const legacy_hal::wifi_rtt_result_v4*>& legacy_results,
+ std::vector<RttResult>* aidl_results);
uint32_t convertAidlWifiBandToLegacyMacBand(WifiBand band);
uint32_t convertAidlWifiIfaceModeToLegacy(uint32_t aidl_iface_mask);
uint32_t convertAidlUsableChannelFilterToLegacy(uint32_t aidl_filter_mask);
@@ -231,6 +243,8 @@
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 3b68c8e..9bfffb6 100644
--- a/wifi/aidl/default/android.hardware.wifi-service.xml
+++ b/wifi/aidl/default/android.hardware.wifi-service.xml
@@ -1,7 +1,7 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.wifi</name>
- <version>2</version>
+ <version>3</version>
<fqname>IWifi/default</fqname>
</hal>
</manifest>
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 d58a9b0..513f440 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 @@
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<RttResult>&, 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 7779750..6a73cc8 100644
--- a/wifi/aidl/default/wifi_ap_iface.cpp
+++ b/wifi/aidl/default/wifi_ap_iface.cpp
@@ -28,10 +28,12 @@
namespace wifi {
using aidl_return_util::validateAndCall;
-WifiApIface::WifiApIface(const std::string& ifname, const std::vector<std::string>& instances,
+WifiApIface::WifiApIface(const std::string& ifname, const bool usesMlo,
+ const std::vector<std::string>& instances,
const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util)
: ifname_(ifname),
+ uses_mlo_(usesMlo),
instances_(instances),
legacy_hal_(legacy_hal),
iface_util_(iface_util),
@@ -50,6 +52,10 @@
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::getFactoryMacAddress(std::array<uint8_t, 6>* _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 @@
}
ndk::ScopedAStatus WifiApIface::setCountryCodeInternal(const std::array<uint8_t, 2>& 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<uint8_t, 6>& 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<uint8_t, 6> rmac = mac;
@@ -131,7 +137,7 @@
ndk::ScopedAStatus WifiApIface::resetToFactoryMacAddressInternal() {
std::pair<std::array<uint8_t, 6>, 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 @@
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 7378f98..e07154d 100644
--- a/wifi/aidl/default/wifi_ap_iface.h
+++ b/wifi/aidl/default/wifi_ap_iface.h
@@ -33,13 +33,15 @@
*/
class WifiApIface : public BnWifiApIface {
public:
- WifiApIface(const std::string& ifname, const std::vector<std::string>& instances,
+ WifiApIface(const std::string& ifname, const bool usesMlo,
+ const std::vector<std::string>& instances,
const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
const std::weak_ptr<iface_util::WifiIfaceUtil> 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 @@
ndk::ScopedAStatus getFactoryMacAddress(std::array<uint8_t, 6>* _aidl_return) override;
ndk::ScopedAStatus resetToFactoryMacAddress() override;
ndk::ScopedAStatus getBridgedInstances(std::vector<std::string>* _aidl_return) override;
+ ndk::ScopedAStatus usesMlo(bool* _aidl_return) override;
private:
// Corresponding worker functions for the AIDL methods.
@@ -61,11 +64,18 @@
std::pair<std::vector<std::string>, ndk::ScopedAStatus> getBridgedInstancesInternal();
std::string ifname_;
+ bool uses_mlo_;
std::vector<std::string> instances_;
std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
std::weak_ptr<iface_util::WifiIfaceUtil> 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 fccfc15..045e07d 100644
--- a/wifi/aidl/default/wifi_chip.cpp
+++ b/wifi/aidl/default/wifi_chip.cpp
@@ -369,7 +369,7 @@
ndk::ScopedAStatus WifiChip::createBridgedApIface(std::shared_ptr<IWifiApIface>* _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 @@
&WifiChip::setVoipModeInternal, in_mode);
}
+ndk::ScopedAStatus WifiChip::createApOrBridgedApIfaceWithParams(
+ const ApIfaceParams& in_params, std::shared_ptr<IWifiApIface>* _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 @@
return ndk::ScopedAStatus::ok();
}
-std::shared_ptr<WifiApIface> WifiChip::newWifiApIface(std::string& ifname) {
+std::shared_ptr<WifiApIface> WifiChip::newWifiApIface(std::string& ifname, bool usesMlo) {
std::vector<std::string> ap_instances;
for (auto const& it : br_ifaces_ap_instances_) {
if (it.first == ifname) {
ap_instances = it.second;
}
}
- std::shared_ptr<WifiApIface> iface =
- ndk::SharedRefBase::make<WifiApIface>(ifname, ap_instances, legacy_hal_, iface_util_);
+ std::shared_ptr<WifiApIface> iface = ndk::SharedRefBase::make<WifiApIface>(
+ 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 @@
if (!status.isOk()) {
return {std::shared_ptr<WifiApIface>(), std::move(status)};
}
- std::shared_ptr<WifiApIface> iface = newWifiApIface(ifname);
+ std::shared_ptr<WifiApIface> iface = newWifiApIface(ifname, false);
return {iface, ndk::ScopedAStatus::ok()};
}
-std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus>
-WifiChip::createBridgedApIfaceInternal() {
+std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus> WifiChip::createBridgedApIfaceInternal(
+ bool usesMlo) {
if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::AP_BRIDGED)) {
return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
}
- std::vector<std::string> ap_instances = allocateBridgedApInstanceNames();
+ std::string br_ifname;
+ std::vector<std::string> 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<WifiApIface> iface = newWifiApIface(br_ifname);
+ std::shared_ptr<WifiApIface> iface = newWifiApIface(br_ifname, usesMlo);
return {iface, ndk::ScopedAStatus::ok()};
}
@@ -876,7 +896,18 @@
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<std::shared_ptr<IWifiApIface>, 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 @@
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<std::string> 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 @@
// 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 @@
return allocateApOrStaIfaceName(IfaceType::AP, startIdxOfApIface());
}
-std::vector<std::string> WifiChip::allocateBridgedApInstanceNames() {
- // Check if we have a dedicated iface for AP.
- std::vector<std::string> instances = getPredefinedApIfaceNames(true);
+std::vector<std::string> WifiChip::allocateBridgedApInstanceNames(bool usesMlo) {
+ std::vector<std::string> 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 @@
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::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 ffd507f..24dd00d 100644
--- a/wifi/aidl/default/wifi_chip.h
+++ b/wifi/aidl/default/wifi_chip.h
@@ -159,6 +159,8 @@
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<IWifiApIface>* _aidl_return) override;
private:
void invalidateAndRemoveAllIfaces();
@@ -178,12 +180,15 @@
std::pair<IWifiChip::ChipDebugInfo, ndk::ScopedAStatus> requestChipDebugInfoInternal();
std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> requestDriverDebugDumpInternal();
std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> requestFirmwareDebugDumpInternal();
- std::shared_ptr<WifiApIface> newWifiApIface(std::string& ifname);
+ std::shared_ptr<WifiApIface> newWifiApIface(std::string& ifname, bool usesMlo);
ndk::ScopedAStatus createVirtualApInterface(const std::string& apVirtIf);
std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus> createApIfaceInternal();
- std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus> createBridgedApIfaceInternal();
+ std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus> createBridgedApIfaceInternal(
+ bool usesMlo);
std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus> createApOrBridgedApIfaceInternal(
IfaceConcurrencyType ifaceType, const std::vector<common::OuiKeyedData>& vendorData);
+ std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus>
+ createApOrBridgedApIfaceWithParamsInternal(const ApIfaceParams& params);
std::pair<std::vector<std::string>, ndk::ScopedAStatus> getApIfaceNamesInternal();
std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus> getApIfaceInternal(
const std::string& ifname);
@@ -258,7 +263,7 @@
std::string getFirstActiveWlanIfaceName();
std::string allocateApOrStaIfaceName(IfaceType type, uint32_t start_idx);
std::string allocateApIfaceName();
- std::vector<std::string> allocateBridgedApInstanceNames();
+ std::vector<std::string> 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 bd92a20..c6d6177 100644
--- a/wifi/aidl/default/wifi_legacy_hal.cpp
+++ b/wifi/aidl/default/wifi_legacy_hal.cpp
@@ -185,11 +185,14 @@
on_rtt_results_internal_callback_v2;
std::function<void(wifi_request_id, unsigned num_results, wifi_rtt_result_v3* rtt_results_v3[])>
on_rtt_results_internal_callback_v3;
+std::function<void(wifi_request_id, unsigned num_results, wifi_rtt_result_v4* rtt_results_v4[])>
+ on_rtt_results_internal_callback_v4;
void invalidateRttResultsCallbacks() {
on_rtt_results_internal_callback = nullptr;
on_rtt_results_internal_callback_v2 = nullptr;
on_rtt_results_internal_callback_v3 = nullptr;
+ on_rtt_results_internal_callback_v4 = nullptr;
};
void onAsyncRttResults(wifi_request_id id, unsigned num_results, wifi_rtt_result* rtt_results[]) {
@@ -218,6 +221,15 @@
}
}
+void onAsyncRttResultsV4(wifi_request_id id, unsigned num_results,
+ wifi_rtt_result_v4* rtt_results_v4[]) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_rtt_results_internal_callback_v4) {
+ on_rtt_results_internal_callback_v4(id, num_results, rtt_results_v4);
+ invalidateRttResultsCallbacks();
+ }
+}
+
// Callbacks for the various NAN operations.
// NOTE: These have very little conversions to perform before invoking the user
// callbacks.
@@ -372,6 +384,16 @@
}
}
+std::function<void(wifi_rtt_result* rtt_results[], uint32_t num_results, uint16_t session_id)>
+ 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<void(const NanPairingRequestInd&)> on_nan_event_pairing_request_user_callback;
void onAsyncNanEventPairingRequest(NanPairingRequestInd* event) {
const auto lock = aidl_sync_util::acquireGlobalLock();
@@ -1334,6 +1356,38 @@
return status;
}
+wifi_error WifiLegacyHal::startRttRangeRequestV4(
+ const std::string& iface_name, wifi_request_id id,
+ const std::vector<wifi_rtt_config_v4>& rtt_configs,
+ const on_rtt_results_callback_v4& on_results_user_callback_v4) {
+ if (on_rtt_results_internal_callback_v4) {
+ return WIFI_ERROR_NOT_AVAILABLE;
+ }
+
+ on_rtt_results_internal_callback_v4 = [on_results_user_callback_v4](
+ wifi_request_id id, unsigned num_results,
+ wifi_rtt_result_v4* rtt_results_v4[]) {
+ if (num_results > 0 && !rtt_results_v4) {
+ LOG(ERROR) << "Unexpected nullptr in RTT v4 results";
+ return;
+ }
+ std::vector<const wifi_rtt_result_v4*> rtt_results_vec_v4;
+ std::copy_if(rtt_results_v4, rtt_results_v4 + num_results,
+ back_inserter(rtt_results_vec_v4),
+ [](wifi_rtt_result_v4* rtt_result_v4) { return rtt_result_v4 != nullptr; });
+ on_results_user_callback_v4(id, rtt_results_vec_v4);
+ };
+
+ std::vector<wifi_rtt_config_v4> rtt_configs_internal(rtt_configs);
+ wifi_error status = global_func_table_.wifi_rtt_range_request_v4(
+ id, getIfaceHandle(iface_name), rtt_configs.size(), rtt_configs_internal.data(),
+ {onAsyncRttResultsV4});
+ if (status != WIFI_SUCCESS) {
+ invalidateRttResultsCallbacks();
+ }
+ return status;
+}
+
wifi_error WifiLegacyHal::startRttRangeRequestV3(
const std::string& iface_name, wifi_request_id id,
const std::vector<wifi_rtt_config_v3>& rtt_configs,
@@ -1450,6 +1504,14 @@
return {status, rtt_caps_v3};
}
+std::pair<wifi_error, wifi_rtt_capabilities_v4> WifiLegacyHal::getRttCapabilitiesV4(
+ const std::string& iface_name) {
+ wifi_rtt_capabilities_v4 rtt_caps_v4;
+ wifi_error status = global_func_table_.wifi_get_rtt_capabilities_v4(getIfaceHandle(iface_name),
+ &rtt_caps_v4);
+ return {status, rtt_caps_v4};
+}
+
std::pair<wifi_error, wifi_rtt_responder> WifiLegacyHal::getRttResponderInfo(
const std::string& iface_name) {
wifi_rtt_responder rtt_responder;
@@ -1510,6 +1572,7 @@
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 +1597,8 @@
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 3fd567b..46bf790 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_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_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;
@@ -343,6 +350,7 @@
using ::wifi_ring_buffer_status;
using ::wifi_roaming_capabilities;
using ::wifi_roaming_config;
+using ::wifi_rtt_akm;
using ::wifi_rtt_bw;
using ::WIFI_RTT_BW_10;
using ::WIFI_RTT_BW_160;
@@ -354,8 +362,11 @@
using ::WIFI_RTT_BW_UNSPECIFIED;
using ::wifi_rtt_capabilities;
using ::wifi_rtt_capabilities_v3;
+using ::wifi_rtt_capabilities_v4;
+using ::wifi_rtt_cipher_suite;
using ::wifi_rtt_config;
using ::wifi_rtt_config_v3;
+using ::wifi_rtt_config_v4;
using ::wifi_rtt_preamble;
using ::WIFI_RTT_PREAMBLE_EHT;
using ::WIFI_RTT_PREAMBLE_HE;
@@ -367,6 +378,7 @@
using ::wifi_rtt_result;
using ::wifi_rtt_result_v2;
using ::wifi_rtt_result_v3;
+using ::wifi_rtt_result_v4;
using ::wifi_rtt_status;
using ::wifi_rtt_type;
using ::wifi_rx_packet_fate;
@@ -392,6 +404,20 @@
using ::WLAN_MAC_5_0_BAND;
using ::WLAN_MAC_60_0_BAND;
using ::WLAN_MAC_6_0_BAND;
+using ::WPA_CIPHER_CCMP_128;
+using ::WPA_CIPHER_CCMP_256;
+using ::WPA_CIPHER_GCMP_128;
+using ::WPA_CIPHER_GCMP_256;
+using ::WPA_CIPHER_NONE;
+using ::WPA_KEY_MGMT_EAP_FILS_SHA256;
+using ::WPA_KEY_MGMT_EAP_FILS_SHA384;
+using ::WPA_KEY_MGMT_EAP_FT_SHA256;
+using ::WPA_KEY_MGMT_EAP_FT_SHA384;
+using ::WPA_KEY_MGMT_FT_PSK_SHA256;
+using ::WPA_KEY_MGMT_FT_PSK_SHA384;
+using ::WPA_KEY_MGMT_NONE;
+using ::WPA_KEY_MGMT_PASN;
+using ::WPA_KEY_MGMT_SAE;
// APF capabilities supported by the iface.
struct PacketFilterCapabilities {
@@ -482,6 +508,8 @@
std::function<void(const NanBootstrappingRequestInd&)> on_event_bootstrapping_request;
std::function<void(const NanBootstrappingConfirmInd&)> on_event_bootstrapping_confirm;
std::function<void(const NanSuspensionModeChangeInd&)> on_event_suspension_mode_change;
+ std::function<void(wifi_rtt_result* rtt_results[], uint32_t num_results, uint16_t session_id)>
+ on_ranging_results;
};
// Full scan results contain IE info and are hence passed by reference, to
@@ -508,6 +536,8 @@
std::function<void(wifi_request_id, const std::vector<const wifi_rtt_result_v2*>&)>;
using on_rtt_results_callback_v3 =
std::function<void(wifi_request_id, const std::vector<const wifi_rtt_result_v3*>&)>;
+using on_rtt_results_callback_v4 =
+ std::function<void(wifi_request_id, const std::vector<const wifi_rtt_result_v4*>&)>;
// Callback for ring buffer data.
using on_ring_buffer_data_callback = std::function<void(
@@ -696,12 +726,17 @@
wifi_error startRttRangeRequestV3(const std::string& iface_name, wifi_request_id id,
const std::vector<wifi_rtt_config_v3>& rtt_configs,
const on_rtt_results_callback_v3& on_results_callback);
+ wifi_error startRttRangeRequestV4(const std::string& iface_name, wifi_request_id id,
+ const std::vector<wifi_rtt_config_v4>& rtt_configs,
+ const on_rtt_results_callback_v4& on_results_callback);
wifi_error cancelRttRangeRequest(const std::string& iface_name, wifi_request_id id,
const std::vector<std::array<uint8_t, ETH_ALEN>>& mac_addrs);
std::pair<wifi_error, wifi_rtt_capabilities> getRttCapabilities(const std::string& iface_name);
std::pair<wifi_error, wifi_rtt_capabilities_v3> getRttCapabilitiesV3(
const std::string& iface_name);
+ std::pair<wifi_error, wifi_rtt_capabilities_v4> getRttCapabilitiesV4(
+ const std::string& iface_name);
std::pair<wifi_error, wifi_rtt_responder> getRttResponderInfo(const std::string& iface_name);
wifi_error enableRttResponder(const std::string& iface_name, wifi_request_id id,
const wifi_channel_info& channel_hint, uint32_t max_duration_secs,
diff --git a/wifi/aidl/default/wifi_legacy_hal_stubs.cpp b/wifi/aidl/default/wifi_legacy_hal_stubs.cpp
index 878abf0..d39894e 100644
--- a/wifi/aidl/default/wifi_legacy_hal_stubs.cpp
+++ b/wifi/aidl/default/wifi_legacy_hal_stubs.cpp
@@ -180,7 +180,9 @@
populateStubFor(&hal_fn->wifi_set_mlo_mode);
populateStubFor(&hal_fn->wifi_get_supported_iface_concurrency_matrix);
populateStubFor(&hal_fn->wifi_get_rtt_capabilities_v3);
+ populateStubFor(&hal_fn->wifi_get_rtt_capabilities_v4);
populateStubFor(&hal_fn->wifi_rtt_range_request_v3);
+ populateStubFor(&hal_fn->wifi_rtt_range_request_v4);
populateStubFor(&hal_fn->wifi_twt_get_capabilities);
populateStubFor(&hal_fn->wifi_twt_register_events);
populateStubFor(&hal_fn->wifi_twt_session_setup);
diff --git a/wifi/aidl/default/wifi_nan_iface.cpp b/wifi/aidl/default/wifi_nan_iface.cpp
index cefe7f7..950e647 100644
--- a/wifi/aidl/default/wifi_nan_iface.cpp
+++ b/wifi/aidl/default/wifi_nan_iface.cpp
@@ -613,7 +613,36 @@
}
}
};
+ 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<const wifi_rtt_result*> 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<RttResult> 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 @@
return ifname_;
}
+int32_t WifiNanIface::getMinCallbackVersion() {
+ return event_cb_handler_.getMinCallbackVersion();
+}
+
std::set<std::shared_ptr<IWifiNanIfaceEventCallback>> 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 a49ae8c..d2d1d5c 100644
--- a/wifi/aidl/default/wifi_nan_iface.h
+++ b/wifi/aidl/default/wifi_nan_iface.h
@@ -134,6 +134,8 @@
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<std::shared_ptr<IWifiNanIfaceEventCallback>> getEventCallbacks();
diff --git a/wifi/aidl/default/wifi_rtt_controller.cpp b/wifi/aidl/default/wifi_rtt_controller.cpp
index 9dee45c..99dafe8 100644
--- a/wifi/aidl/default/wifi_rtt_controller.cpp
+++ b/wifi/aidl/default/wifi_rtt_controller.cpp
@@ -136,13 +136,46 @@
ndk::ScopedAStatus WifiRttController::rangeRequestInternal(
int32_t cmd_id, const std::vector<RttConfig>& rtt_configs) {
- // Try 11mc & 11az ranging (v3)
+ // Try 11az secure, 11az non-secure & 11mc ranging (v4)
+ std::vector<legacy_hal::wifi_rtt_config_v4> legacy_configs_v4;
+ if (!aidl_struct_util::convertAidlVectorOfRttConfigToLegacyV4(rtt_configs,
+ &legacy_configs_v4)) {
+ return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+ }
+ std::weak_ptr<WifiRttController> weak_ptr_this = weak_ptr_this_;
+ const auto& on_results_callback_v4 =
+ [weak_ptr_this](legacy_hal::wifi_request_id id,
+ const std::vector<const legacy_hal::wifi_rtt_result_v4*>& results) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "v4 Callback invoked on an invalid object";
+ return;
+ }
+ std::vector<RttResult> aidl_results;
+ if (!aidl_struct_util::convertLegacyVectorOfRttResultV4ToAidl(results,
+ &aidl_results)) {
+ LOG(ERROR) << "Failed to convert rtt results v4 to AIDL structs";
+ return;
+ }
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->onResults(id, aidl_results).isOk()) {
+ LOG(ERROR) << "Failed to invoke the v4 callback";
+ }
+ }
+ };
+ legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startRttRangeRequestV4(
+ ifname_, cmd_id, legacy_configs_v4, on_results_callback_v4);
+
+ if (legacy_status != legacy_hal::WIFI_ERROR_NOT_SUPPORTED) {
+ return createWifiStatusFromLegacyError(legacy_status);
+ }
+
+ // Fallback to 11az non-secure & 11mc ranging (v3)
std::vector<legacy_hal::wifi_rtt_config_v3> legacy_configs_v3;
if (!aidl_struct_util::convertAidlVectorOfRttConfigToLegacyV3(rtt_configs,
&legacy_configs_v3)) {
return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
}
- std::weak_ptr<WifiRttController> weak_ptr_this = weak_ptr_this_;
const auto& on_results_callback_v3 =
[weak_ptr_this](legacy_hal::wifi_request_id id,
const std::vector<const legacy_hal::wifi_rtt_result_v3*>& results) {
@@ -163,8 +196,8 @@
}
}
};
- legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startRttRangeRequestV3(
- ifname_, cmd_id, legacy_configs_v3, on_results_callback_v3);
+ legacy_status = legacy_hal_.lock()->startRttRangeRequestV3(ifname_, cmd_id, legacy_configs_v3,
+ on_results_callback_v3);
if (legacy_status != legacy_hal::WIFI_ERROR_NOT_SUPPORTED) {
return createWifiStatusFromLegacyError(legacy_status);
@@ -236,31 +269,46 @@
std::pair<RttCapabilities, ndk::ScopedAStatus> WifiRttController::getCapabilitiesInternal() {
legacy_hal::wifi_error legacy_status;
legacy_hal::wifi_rtt_capabilities_v3 legacy_caps_v3;
- std::tie(legacy_status, legacy_caps_v3) = legacy_hal_.lock()->getRttCapabilitiesV3(ifname_);
- // Try v3 API first, if it is not supported fallback.
- if (legacy_status == legacy_hal::WIFI_ERROR_NOT_SUPPORTED) {
- legacy_hal::wifi_rtt_capabilities legacy_caps;
- std::tie(legacy_status, legacy_caps) = legacy_hal_.lock()->getRttCapabilities(ifname_);
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- return {RttCapabilities{}, createWifiStatusFromLegacyError(legacy_status)};
- }
+ legacy_hal::wifi_rtt_capabilities_v4 legacy_caps_v4;
+ // Try v4 first
+ std::tie(legacy_status, legacy_caps_v4) = legacy_hal_.lock()->getRttCapabilitiesV4(ifname_);
+ if (legacy_status == legacy_hal::WIFI_SUCCESS) {
RttCapabilities aidl_caps;
- if (!aidl_struct_util::convertLegacyRttCapabilitiesToAidl(legacy_caps, &aidl_caps)) {
+ if (!aidl_struct_util::convertLegacyRttCapabilitiesV4ToAidl(legacy_caps_v4, &aidl_caps)) {
return {RttCapabilities{}, createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
}
return {aidl_caps, ndk::ScopedAStatus::ok()};
}
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- return {RttCapabilities{}, createWifiStatusFromLegacyError(legacy_status)};
+ // If not supported, fallback to v3
+ if (legacy_status == legacy_hal::WIFI_ERROR_NOT_SUPPORTED) {
+ std::tie(legacy_status, legacy_caps_v3) = legacy_hal_.lock()->getRttCapabilitiesV3(ifname_);
+ if (legacy_status == legacy_hal::WIFI_SUCCESS) {
+ RttCapabilities aidl_caps;
+ if (!aidl_struct_util::convertLegacyRttCapabilitiesV3ToAidl(legacy_caps_v3,
+ &aidl_caps)) {
+ return {RttCapabilities{}, createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
+ }
+ return {aidl_caps, ndk::ScopedAStatus::ok()};
+ }
}
- RttCapabilities aidl_caps;
- if (!aidl_struct_util::convertLegacyRttCapabilitiesV3ToAidl(legacy_caps_v3, &aidl_caps)) {
- return {RttCapabilities{}, createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
+ // If not supported, fallback to default
+ if (legacy_status == legacy_hal::WIFI_ERROR_NOT_SUPPORTED) {
+ legacy_hal::wifi_rtt_capabilities legacy_caps;
+ std::tie(legacy_status, legacy_caps) = legacy_hal_.lock()->getRttCapabilities(ifname_);
+ if (legacy_status == legacy_hal::WIFI_SUCCESS) {
+ RttCapabilities aidl_caps;
+ if (!aidl_struct_util::convertLegacyRttCapabilitiesToAidl(legacy_caps, &aidl_caps)) {
+ return {RttCapabilities{}, createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
+ }
+ return {aidl_caps, ndk::ScopedAStatus::ok()};
+ }
}
- return {aidl_caps, ndk::ScopedAStatus::ok()};
+
+ // Error, if all failed
+ return {RttCapabilities{}, createWifiStatusFromLegacyError(legacy_status)};
}
ndk::ScopedAStatus WifiRttController::setLciInternal(int32_t cmd_id, const RttLciInformation& lci) {
diff --git a/wifi/aidl/vts/functional/Android.bp b/wifi/aidl/vts/functional/Android.bp
index 9994d09..429c0c5 100644
--- a/wifi/aidl/vts/functional/Android.bp
+++ b/wifi/aidl/vts/functional/Android.bp
@@ -40,8 +40,8 @@
],
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 @@
],
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 @@
],
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 @@
],
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 @@
],
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 @@
"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_aidl_test_utils.cpp b/wifi/aidl/vts/functional/wifi_aidl_test_utils.cpp
index c68d8fd..202082e 100644
--- a/wifi/aidl/vts/functional/wifi_aidl_test_utils.cpp
+++ b/wifi/aidl/vts/functional/wifi_aidl_test_utils.cpp
@@ -276,3 +276,28 @@
}
return std::optional<std::vector<std::optional<OuiKeyedData>>>{dataList};
}
+
+IWifiChip::ApIfaceParams generateApIfaceParams(IfaceConcurrencyType type, bool uses_mlo,
+ int oui_size) {
+ IWifiChip::ApIfaceParams params;
+ params.ifaceType = type;
+ params.usesMlo = uses_mlo;
+ params.vendorData = generateOuiKeyedDataListOptional(oui_size);
+ return params;
+}
+
+std::shared_ptr<IWifiApIface> getWifiApOrBridgedApIface(std::shared_ptr<IWifiChip> wifi_chip,
+ IWifiChip::ApIfaceParams params) {
+ if (!wifi_chip.get()) {
+ return nullptr;
+ }
+ std::shared_ptr<IWifiApIface> iface;
+ if (!configureChipToSupportConcurrencyTypeInternal(wifi_chip, IfaceConcurrencyType::AP)) {
+ return nullptr;
+ }
+ auto status = wifi_chip->createApOrBridgedApIfaceWithParams(params, &iface);
+ if (!status.isOk()) {
+ return nullptr;
+ }
+ return iface;
+}
diff --git a/wifi/aidl/vts/functional/wifi_aidl_test_utils.h b/wifi/aidl/vts/functional/wifi_aidl_test_utils.h
index 9b47a9f..6d98bf0 100644
--- a/wifi/aidl/vts/functional/wifi_aidl_test_utils.h
+++ b/wifi/aidl/vts/functional/wifi_aidl_test_utils.h
@@ -43,6 +43,8 @@
std::shared_ptr<IWifiApIface> getWifiApIface(std::shared_ptr<IWifiChip> wifi_chip);
std::shared_ptr<IWifiApIface> getBridgedWifiApIface(const char* instance_name);
std::shared_ptr<IWifiApIface> getBridgedWifiApIface(std::shared_ptr<IWifiChip> wifi_chip);
+std::shared_ptr<IWifiApIface> getWifiApOrBridgedApIface(std::shared_ptr<IWifiChip> wifi_chip,
+ IWifiChip::ApIfaceParams params);
// Configure the chip in a mode to support the creation of the provided iface type.
bool configureChipToSupportConcurrencyType(const std::shared_ptr<IWifiChip>& wifi_chip,
IfaceConcurrencyType type, int* configured_mode_id);
@@ -57,3 +59,7 @@
// Generate test vendor data.
std::vector<OuiKeyedData> generateOuiKeyedDataList(int size);
std::optional<std::vector<std::optional<OuiKeyedData>>> generateOuiKeyedDataListOptional(int size);
+
+// Generate test ApIfaceParams
+IWifiChip::ApIfaceParams generateApIfaceParams(IfaceConcurrencyType type, bool uses_mlo,
+ int oui_size);
diff --git a/wifi/aidl/vts/functional/wifi_chip_aidl_test.cpp b/wifi/aidl/vts/functional/wifi_chip_aidl_test.cpp
index a1b9ce1..1ef02af 100644
--- a/wifi/aidl/vts/functional/wifi_chip_aidl_test.cpp
+++ b/wifi/aidl/vts/functional/wifi_chip_aidl_test.cpp
@@ -30,6 +30,9 @@
#include "wifi_aidl_test_utils.h"
+using aidl::android::hardware::wifi::AfcChannelAllowance;
+using aidl::android::hardware::wifi::AvailableAfcChannelInfo;
+using aidl::android::hardware::wifi::AvailableAfcFrequencyInfo;
using aidl::android::hardware::wifi::BnWifiChipEventCallback;
using aidl::android::hardware::wifi::IfaceType;
using aidl::android::hardware::wifi::IWifiApIface;
@@ -38,6 +41,7 @@
using aidl::android::hardware::wifi::IWifiP2pIface;
using aidl::android::hardware::wifi::IWifiRttController;
using aidl::android::hardware::wifi::WifiBand;
+using aidl::android::hardware::wifi::WifiChipCapabilities;
using aidl::android::hardware::wifi::WifiDebugHostWakeReasonStats;
using aidl::android::hardware::wifi::WifiDebugRingBufferStatus;
using aidl::android::hardware::wifi::WifiDebugRingBufferVerboseLevel;
@@ -52,6 +56,7 @@
stopWifiService(getInstanceName());
wifi_chip_ = getWifiChip(getInstanceName());
ASSERT_NE(nullptr, wifi_chip_.get());
+ ASSERT_TRUE(wifi_chip_->getInterfaceVersion(&interface_version_).isOk());
}
void TearDown() override { stopWifiService(getInstanceName()); }
@@ -139,6 +144,7 @@
const char* getInstanceName() { return GetParam().c_str(); }
std::shared_ptr<IWifiChip> wifi_chip_;
+ int interface_version_;
};
class WifiChipEventCallback : public BnWifiChipEventCallback {
@@ -268,6 +274,23 @@
}
/*
+ * Tests the setAfcChannelAllowance() API.
+ */
+TEST_P(WifiChipAidlTest, SetAfcChannelAllowance) {
+ configureChipForConcurrencyType(IfaceConcurrencyType::STA);
+ int32_t features = getChipFeatureSet(wifi_chip_);
+ AfcChannelAllowance allowance;
+ allowance.availableAfcChannelInfos = std::vector<AvailableAfcChannelInfo>();
+ allowance.availableAfcFrequencyInfos = std::vector<AvailableAfcFrequencyInfo>();
+ auto status = wifi_chip_->setAfcChannelAllowance(allowance);
+ if (features & static_cast<int32_t>(IWifiChip::FeatureSetMask::SET_AFC_CHANNEL_ALLOWANCE)) {
+ EXPECT_TRUE(status.isOk());
+ } else {
+ EXPECT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED));
+ }
+}
+
+/*
* SetLatencyMode_normal
* Tests the setLatencyMode() API with Latency mode NORMAL.
*/
@@ -902,6 +925,112 @@
}
}
+/**
+ * CreateApOrBridgedApIfaceWithParams for signal ap.
+ */
+TEST_P(WifiChipAidlTest, CreateApOrBridgedApIfaceWithParams_signal_ap) {
+ if (interface_version_ < 3) {
+ GTEST_SKIP() << "CreateApOrBridgedApIfaceWithParams is available as of WifiChip V3";
+ }
+ if (!isConcurrencyTypeSupported(IfaceConcurrencyType::AP)) {
+ GTEST_SKIP() << "AP is not supported";
+ }
+
+ std::shared_ptr<IWifiChip> wifi_chip = getWifiChip(getInstanceName());
+ ASSERT_NE(nullptr, wifi_chip.get());
+ std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApOrBridgedApIface(
+ wifi_chip, generateApIfaceParams(IfaceConcurrencyType::AP, false, 0));
+ ASSERT_NE(nullptr, wifi_ap_iface.get());
+}
+
+/**
+ * CreateApOrBridgedApIfaceWithParams for non mlo bridged ap.
+ */
+TEST_P(WifiChipAidlTest, CreateApOrBridgedApIfaceWithParams_non_mlo_bridged_ap) {
+ if (interface_version_ < 3) {
+ GTEST_SKIP() << "CreateApOrBridgedApIfaceWithParams is available as of WifiChip V3";
+ }
+ bool isBridgedSupport = testing::checkSubstringInCommandOutput(
+ "/system/bin/cmd wifi get-softap-supported-features",
+ "wifi_softap_bridged_ap_supported");
+ if (!isBridgedSupport) {
+ GTEST_SKIP() << "Missing Bridged AP support";
+ }
+
+ std::shared_ptr<IWifiChip> wifi_chip = getWifiChip(getInstanceName());
+ ASSERT_NE(nullptr, wifi_chip.get());
+ std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApOrBridgedApIface(
+ wifi_chip, generateApIfaceParams(IfaceConcurrencyType::AP_BRIDGED, false, 0));
+ ASSERT_NE(nullptr, wifi_ap_iface.get());
+
+ std::string br_name;
+ std::vector<std::string> instances;
+ bool uses_mlo;
+ EXPECT_TRUE(wifi_ap_iface->getName(&br_name).isOk());
+ EXPECT_TRUE(wifi_ap_iface->getBridgedInstances(&instances).isOk());
+ EXPECT_TRUE(wifi_ap_iface->usesMlo(&uses_mlo).isOk());
+ EXPECT_FALSE(uses_mlo);
+ EXPECT_EQ(instances.size(), 2);
+}
+
+/**
+ * CreateApOrBridgedApIfaceWithParams for mlo bridged ap.
+ */
+TEST_P(WifiChipAidlTest, CreateApOrBridgedApIfaceWithParams_mlo_bridged_ap) {
+ if (interface_version_ < 3) {
+ GTEST_SKIP() << "CreateApOrBridgedApIfaceWithParams is available as of WifiChip V3";
+ }
+ bool isBridgedSupport = testing::checkSubstringInCommandOutput(
+ "/system/bin/cmd wifi get-softap-supported-features",
+ "wifi_softap_bridged_ap_supported");
+ if (!isBridgedSupport) {
+ GTEST_SKIP() << "Missing Bridged AP support";
+ }
+
+ configureChipForConcurrencyType(IfaceConcurrencyType::STA);
+ int32_t features = getChipFeatureSet(wifi_chip_);
+ if (!(features & static_cast<int32_t>(IWifiChip::FeatureSetMask::MLO_SAP))) {
+ GTEST_SKIP() << "MLO_SAP is not supported by vendor.";
+ }
+ std::shared_ptr<IWifiChip> wifi_chip = getWifiChip(getInstanceName());
+ ASSERT_NE(nullptr, wifi_chip.get());
+ std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApOrBridgedApIface(
+ wifi_chip, generateApIfaceParams(IfaceConcurrencyType::AP_BRIDGED, true, 0));
+ ASSERT_NE(nullptr, wifi_ap_iface.get());
+
+ std::string br_name;
+ std::vector<std::string> instances;
+ bool uses_mlo;
+ EXPECT_TRUE(wifi_ap_iface->getName(&br_name).isOk());
+ EXPECT_TRUE(wifi_ap_iface->getBridgedInstances(&instances).isOk());
+ EXPECT_TRUE(wifi_ap_iface->usesMlo(&uses_mlo).isOk());
+ EXPECT_TRUE(uses_mlo);
+ EXPECT_EQ(instances.size(), 2);
+}
+
+/*
+ * GetWifiChipCapabilities
+ */
+TEST_P(WifiChipAidlTest, GetWifiChipCapabilities) {
+ WifiChipCapabilities chipCapabilities;
+ auto status = wifi_chip_->getWifiChipCapabilities(&chipCapabilities);
+ if (checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED)) {
+ GTEST_SKIP() << "getWifiChipCapabilities() is not supported by vendor.";
+ }
+ EXPECT_TRUE(status.isOk());
+}
+
+/*
+ * SetMloMode
+ */
+TEST_P(WifiChipAidlTest, SetMloMode) {
+ auto status = wifi_chip_->setMloMode(IWifiChip::ChipMloMode::LOW_LATENCY);
+ if (checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED)) {
+ GTEST_SKIP() << "setMloMode() is not supported by vendor.";
+ }
+ EXPECT_TRUE(status.isOk());
+}
+
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiChipAidlTest);
INSTANTIATE_TEST_SUITE_P(WifiTest, WifiChipAidlTest,
testing::ValuesIn(android::getAidlHalInstanceNames(IWifi::descriptor)),
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 bc169a4..d646162 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::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 @@
NOTIFY_SUSPEND_RESPONSE,
NOTIFY_RESUME_RESPONSE,
NOTIFY_TERMINATE_PAIRING_RESPONSE,
+ NOTIFY_RANGING_RESULTS,
EVENT_CLUSTER_EVENT,
EVENT_DISABLED,
@@ -400,6 +402,12 @@
parent_.notify(NOTIFY_TERMINATE_PAIRING_RESPONSE);
return ndk::ScopedAStatus::ok();
}
+ ::ndk::ScopedAStatus notifyRangingResults(const std::vector<RttResult>& /* 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/aidl/vts/functional/wifi_rtt_controller_aidl_test.cpp b/wifi/aidl/vts/functional/wifi_rtt_controller_aidl_test.cpp
index 1596602..aca1364 100644
--- a/wifi/aidl/vts/functional/wifi_rtt_controller_aidl_test.cpp
+++ b/wifi/aidl/vts/functional/wifi_rtt_controller_aidl_test.cpp
@@ -19,8 +19,10 @@
#include <VtsCoreUtil.h>
#include <aidl/Gtest.h>
#include <aidl/Vintf.h>
+#include <aidl/android/hardware/wifi/Akm.h>
#include <aidl/android/hardware/wifi/BnWifi.h>
#include <aidl/android/hardware/wifi/BnWifiRttControllerEventCallback.h>
+#include <aidl/android/hardware/wifi/RttSecureConfig.h>
#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/binder_status.h>
@@ -29,6 +31,7 @@
#include "wifi_aidl_test_utils.h"
+using aidl::android::hardware::wifi::Akm;
using aidl::android::hardware::wifi::BnWifiRttControllerEventCallback;
using aidl::android::hardware::wifi::IWifiRttController;
using aidl::android::hardware::wifi::RttBw;
@@ -38,6 +41,7 @@
using aidl::android::hardware::wifi::RttPreamble;
using aidl::android::hardware::wifi::RttResponder;
using aidl::android::hardware::wifi::RttResult;
+using aidl::android::hardware::wifi::RttSecureConfig;
using aidl::android::hardware::wifi::RttType;
using aidl::android::hardware::wifi::WifiChannelInfo;
using aidl::android::hardware::wifi::WifiChannelWidthInMhz;
@@ -87,6 +91,15 @@
return caps;
}
+ int getMostSignificantSetBitMask(int n) {
+ if (n == 0) return 0;
+ int pos = std::numeric_limits<int>::digits - 1;
+ while ((n & (1 << pos)) == 0) {
+ pos--;
+ }
+ return 1 << pos;
+ }
+
std::shared_ptr<IWifiRttController> wifi_rtt_controller_;
int interface_version_;
@@ -161,6 +174,66 @@
}
/*
+ * Request80211azNtbSecureRangeMeasurement
+ * Tests the two sided 11az non-trigger based secure ranging - 802.11az NTB FTM protocol.
+ */
+TEST_P(WifiRttControllerAidlTest, Request80211azNtbSecureRangeMeasurement) {
+ if (interface_version_ < 3) {
+ GTEST_SKIP() << "Request80211azNtbRangeMeasurement is available as of RttController V3";
+ }
+
+ RttCapabilities caps = getCapabilities();
+ if (!caps.ntbInitiatorSupported) {
+ GTEST_SKIP() << "Skipping 11az NTB RTT since driver/fw does not support";
+ }
+ if (!caps.secureHeLtfSupported && !caps.rangingFrameProtectionSupported) {
+ GTEST_SKIP() << "Skipping 11az NTB secure RTT since driver/fw does not support";
+ }
+ if (!(caps.akmsSupported & Akm::PASN)) {
+ GTEST_SKIP() << "Skipping 11az NTB secure RTT since driver/fw does not support PASN";
+ }
+ if (!caps.cipherSuitesSupported) {
+ GTEST_SKIP()
+ << "Skipping 11az NTB secure RTT since driver/fw does not support Cipher Suites";
+ }
+
+ RttConfig config;
+ config.addr = {{0x00, 0x01, 0x02, 0x03, 0x04, 0x05}};
+ config.type = RttType::TWO_SIDED_11AZ_NTB_SECURE;
+ config.peer = RttPeerType::AP;
+ config.channel.width = WifiChannelWidthInMhz::WIDTH_80;
+ config.channel.centerFreq = 5180;
+ config.channel.centerFreq0 = 5210;
+ config.channel.centerFreq1 = 0;
+ config.bw = RttBw::BW_20MHZ;
+ config.preamble = RttPreamble::HT;
+ config.mustRequestLci = false;
+ config.mustRequestLcr = false;
+ config.numFramesPerBurst = 8;
+ config.numRetriesPerRttFrame = 0;
+ config.numRetriesPerFtmr = 0;
+ // 11az non-trigger based minimum measurement time in units of 100 microseconds.
+ config.ntbMinMeasurementTime = 2500;
+ // 11az non-trigger based maximum measurement time in units of 10 milliseconds.
+ config.ntbMaxMeasurementTime = 1500;
+ RttSecureConfig secureConfig;
+ // PASN is a must to test secure config; which does not need any password.
+ secureConfig.pasnConfig.baseAkm = Akm::PASN;
+ // Get the best Cipher suite supported by the chip.
+ secureConfig.pasnConfig.cipherSuite = getMostSignificantSetBitMask(caps.cipherSuitesSupported);
+ secureConfig.enableSecureHeLtf = caps.secureHeLtfSupported;
+ secureConfig.enableRangingFrameProtection = caps.rangingFrameProtectionSupported;
+ config.secureConfig = secureConfig;
+
+ int cmdId = 55;
+ std::vector<RttConfig> configs = {config};
+ EXPECT_TRUE(wifi_rtt_controller_->rangeRequest(cmdId, configs).isOk());
+
+ // Sleep for 2 seconds to wait for driver/firmware to complete RTT.
+ sleep(2);
+}
+
+/*
* Request80211azNtbRangeMeasurement
* Tests the two sided 11az non-trigger based ranging - 802.11az NTB FTM protocol.
*/
diff --git a/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp b/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp
index f659bf6..f997c43 100644
--- a/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp
+++ b/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp
@@ -36,6 +36,7 @@
using aidl::android::hardware::wifi::Ssid;
using aidl::android::hardware::wifi::StaApfPacketFilterCapabilities;
using aidl::android::hardware::wifi::StaBackgroundScanCapabilities;
+using aidl::android::hardware::wifi::StaBackgroundScanParameters;
using aidl::android::hardware::wifi::StaLinkLayerStats;
using aidl::android::hardware::wifi::StaRoamingCapabilities;
using aidl::android::hardware::wifi::StaRoamingConfig;
@@ -47,6 +48,12 @@
using aidl::android::hardware::wifi::WifiDebugTxPacketFateReport;
using aidl::android::hardware::wifi::WifiStatusCode;
+namespace {
+const int kTestCmdId = 123;
+const std::array<uint8_t, 6> kTestMacAddr1 = {0x1a, 0x2b, 0x3c, 0x4d, 0x5e, 0x6f};
+const std::array<uint8_t, 6> kTestMacAddr2 = {0x4a, 0x5b, 0x6c, 0x7d, 0x8e, 0x9f};
+} // namespace
+
class WifiStaIfaceAidlTest : public testing::TestWithParam<std::string> {
public:
void SetUp() override {
@@ -65,6 +72,12 @@
return features & static_cast<int32_t>(expected);
}
+ bool isTwtSupported() {
+ TwtCapabilities twt_capabilities = {};
+ auto status = wifi_sta_iface_->twtGetCapabilities(&twt_capabilities);
+ return status.isOk() && twt_capabilities.isTwtRequesterSupported;
+ }
+
ndk::ScopedAStatus createStaIface(std::shared_ptr<IWifiStaIface>* sta_iface) {
std::shared_ptr<IWifiChip> wifi_chip = getWifiChip(getInstanceName());
EXPECT_NE(nullptr, wifi_chip.get());
@@ -379,6 +392,9 @@
}
}
+/**
+ * TwtGetCapabilities
+ */
TEST_P(WifiStaIfaceAidlTest, TwtGetCapabilities) {
if (interface_version_ < 2) {
GTEST_SKIP() << "TwtGetCapabilities is available as of sta_iface V2";
@@ -400,6 +416,9 @@
EXPECT_GT(twt_capabilities.maxWakeIntervalUs, 0);
}
+/**
+ * TwtSessionSetup
+ */
TEST_P(WifiStaIfaceAidlTest, TwtSessionSetup) {
if (interface_version_ < 2) {
GTEST_SKIP() << "TwtSessionSetup is available as of sta_iface V2";
@@ -424,18 +443,14 @@
EXPECT_TRUE(wifi_sta_iface_->twtSessionSetup(1, twtRequest).isOk());
}
+/**
+ * TwtSessionGetStats
+ */
TEST_P(WifiStaIfaceAidlTest, TwtSessionGetStats) {
if (interface_version_ < 2) {
GTEST_SKIP() << "TwtSessionGetStats is available as of sta_iface V2";
}
-
- TwtCapabilities twt_capabilities = {};
- auto status = wifi_sta_iface_->twtGetCapabilities(&twt_capabilities);
- if (checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED)) {
- GTEST_SKIP() << "twtGetCapabilities() is not supported by the vendor";
- }
- EXPECT_TRUE(status.isOk());
- if (!twt_capabilities.isTwtRequesterSupported) {
+ if (!isTwtSupported()) {
GTEST_SKIP() << "TWT is not supported";
}
@@ -444,26 +459,123 @@
EXPECT_TRUE(wifi_sta_iface_->twtSessionGetStats(1, 10).isOk());
}
+/**
+ * TwtSessionTeardown
+ */
TEST_P(WifiStaIfaceAidlTest, TwtSessionTeardown) {
if (interface_version_ < 2) {
- GTEST_SKIP() << "TwtSessionTeardown is available as of sta_iface V3";
+ GTEST_SKIP() << "TwtSessionTeardown is available as of sta_iface V2";
}
-
- TwtCapabilities twt_capabilities = {};
- auto status = wifi_sta_iface_->twtGetCapabilities(&twt_capabilities);
- if (checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED)) {
- GTEST_SKIP() << "twtGetCapabilities() is not supported by the vendor";
- }
- EXPECT_TRUE(status.isOk());
- if (!twt_capabilities.isTwtRequesterSupported) {
+ if (!isTwtSupported()) {
GTEST_SKIP() << "TWT is not supported";
}
// Expecting a IWifiStaIfaceEventCallback.onTwtFailure() with INVALID_PARAMS
- // as the error code.
+ // as the error code.
EXPECT_TRUE(wifi_sta_iface_->twtSessionTeardown(1, 10).isOk());
}
+/**
+ * TwtSessionUpdate
+ */
+TEST_P(WifiStaIfaceAidlTest, TwtSessionUpdate) {
+ if (interface_version_ < 2) {
+ GTEST_SKIP() << "TwtSessionUpdate is available as of sta_iface V2";
+ }
+ if (!isTwtSupported()) {
+ GTEST_SKIP() << "TWT is not supported";
+ }
+
+ TwtRequest twtRequest;
+ twtRequest.mloLinkId = 0;
+ twtRequest.minWakeDurationUs = 1000;
+ twtRequest.maxWakeDurationUs = 10000;
+ twtRequest.minWakeIntervalUs = 10000;
+ twtRequest.maxWakeIntervalUs = 100000;
+
+ // Expecting a IWifiStaIfaceEventCallback.onTwtFailure() with INVALID_PARAMS
+ // as the error code.
+ EXPECT_TRUE(wifi_sta_iface_->twtSessionUpdate(1, 10, twtRequest).isOk());
+}
+
+/**
+ * TwtSessionSuspend
+ */
+TEST_P(WifiStaIfaceAidlTest, TwtSessionSuspend) {
+ if (interface_version_ < 2) {
+ GTEST_SKIP() << "TwtSessionSuspend is available as of sta_iface V2";
+ }
+ if (!isTwtSupported()) {
+ GTEST_SKIP() << "TWT is not supported";
+ }
+
+ // Expecting a IWifiStaIfaceEventCallback.onTwtFailure() with INVALID_PARAMS
+ // as the error code.
+ EXPECT_TRUE(wifi_sta_iface_->twtSessionSuspend(1, 10).isOk());
+}
+
+/**
+ * TwtSessionResume
+ */
+TEST_P(WifiStaIfaceAidlTest, TwtSessionResume) {
+ if (interface_version_ < 2) {
+ GTEST_SKIP() << "TwtSessionResume is available as of sta_iface V2";
+ }
+ if (!isTwtSupported()) {
+ GTEST_SKIP() << "TWT is not supported";
+ }
+
+ // Expecting a IWifiStaIfaceEventCallback.onTwtFailure() with INVALID_PARAMS
+ // as the error code.
+ EXPECT_TRUE(wifi_sta_iface_->twtSessionResume(1, 10).isOk());
+}
+
+/*
+ * GetName
+ */
+TEST_P(WifiStaIfaceAidlTest, GetName) {
+ std::string ifaceName;
+ EXPECT_TRUE(wifi_sta_iface_->getName(&ifaceName).isOk());
+}
+
+/*
+ * SetDtimMultiplier
+ */
+TEST_P(WifiStaIfaceAidlTest, SetDtimMultiplier) {
+ // Multiplied value
+ EXPECT_TRUE(wifi_sta_iface_->setDtimMultiplier(2).isOk());
+ // Driver default value
+ EXPECT_TRUE(wifi_sta_iface_->setDtimMultiplier(0).isOk());
+}
+
+/*
+ * Start/Stop Background Scan
+ */
+TEST_P(WifiStaIfaceAidlTest, StartAndStopBackgroundScan) {
+ if (!isFeatureSupported(IWifiStaIface::FeatureSetMask::BACKGROUND_SCAN)) {
+ GTEST_SKIP() << "Background scan is not supported";
+ }
+ StaBackgroundScanParameters scanParams;
+ EXPECT_TRUE(wifi_sta_iface_->startBackgroundScan(kTestCmdId, scanParams).isOk());
+ EXPECT_TRUE(wifi_sta_iface_->stopBackgroundScan(kTestCmdId).isOk());
+}
+
+/*
+ * Start/Stop Sending Keep-Alive Packets
+ */
+TEST_P(WifiStaIfaceAidlTest, StartAndStopSendingKeepAlivePackets) {
+ std::vector<uint8_t> ipPacketData(20);
+ uint16_t etherType = 0x0800; // IPv4
+ uint32_t periodInMs = 1000; // 1 sec
+
+ // Expected to fail with test values
+ EXPECT_FALSE(wifi_sta_iface_
+ ->startSendingKeepAlivePackets(kTestCmdId, ipPacketData, etherType,
+ kTestMacAddr1, kTestMacAddr2, periodInMs)
+ .isOk());
+ EXPECT_FALSE(wifi_sta_iface_->stopSendingKeepAlivePackets(kTestCmdId).isOk());
+}
+
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiStaIfaceAidlTest);
INSTANTIATE_TEST_SUITE_P(WifiTest, WifiStaIfaceAidlTest,
testing::ValuesIn(android::getAidlHalInstanceNames(IWifi::descriptor)),
diff --git a/wifi/common/aidl/Android.bp b/wifi/common/aidl/Android.bp
index 0920a55..8ea54be 100644
--- a/wifi/common/aidl/Android.bp
+++ b/wifi/common/aidl/Android.bp
@@ -54,6 +54,6 @@
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 0000000..2404b2c
--- /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 <name>-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 0000000..95eb31d
--- /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 88f4ef2..85d71f3 100644
--- a/wifi/hostapd/aidl/Android.bp
+++ b/wifi/hostapd/aidl/Android.bp
@@ -29,7 +29,7 @@
"android/hardware/wifi/hostapd/*.aidl",
],
imports: [
- "android.hardware.wifi.common-V1",
+ "android.hardware.wifi.common-V2",
],
stability: "vintf",
backend: {
@@ -41,7 +41,9 @@
],
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 1a66105..0af90d2 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 @@
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 c4d62b6..c4db789 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 @@
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 ff941fd..3898bb8 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 @@
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 8da3441..7b67102 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 @@
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 4554223..b6c5cf2 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 @@
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 f2b2ee6..8aea70c 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 @@
* 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 7bed658..a7ca1ec 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 @@
* 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 d2f4795..cd552ab 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 @@
* 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 bb646e3..f4e4647 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 @@
*/
@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 47d9e6f..acc2cad 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 @@
* 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 4329e12..23fe690 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"/>
</issue>
-</issues>
\ No newline at end of file
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.os.Binder#markVintfStability`"
+ errorLine1=" this.markVintfStability();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/hardware/interfaces/wifi/hostapd/aidl/android.hardware.wifi.hostapd-V4-java-source/gen/android/hardware/wifi/hostapd/IHostapd.java"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.os.Binder#markVintfStability`"
+ errorLine1=" this.markVintfStability();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/hardware/interfaces/wifi/hostapd/aidl/android.hardware.wifi.hostapd-V4-java-source/gen/android/hardware/wifi/hostapd/IHostapdCallback.java"/>
+ </issue>
+
+</issues>
diff --git a/wifi/hostapd/aidl/vts/functional/Android.bp b/wifi/hostapd/aidl/vts/functional/Android.bp
index bf1b0d0..de31e14 100644
--- a/wifi/hostapd/aidl/vts/functional/Android.bp
+++ b/wifi/hostapd/aidl/vts/functional/Android.bp
@@ -37,8 +37,8 @@
"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/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp b/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp
index 590c58b..6723b1f 100644
--- a/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp
+++ b/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp
@@ -86,6 +86,8 @@
isBridgedSupport = testing::checkSubstringInCommandOutput(
"/system/bin/cmd wifi get-softap-supported-features",
"wifi_softap_bridged_ap_supported");
+ isMloSupport = testing::checkSubstringInCommandOutput(
+ "/system/bin/cmd wifi get-softap-supported-features", "wifi_softap_mlo_supported");
}
virtual void TearDown() override {
@@ -100,6 +102,7 @@
bool isAcsSupport;
bool isWpa3SaeSupport;
bool isBridgedSupport;
+ bool isMloSupport;
int interface_version_;
IfaceParams getIfaceParamsWithoutAcs(std::string iface_name) {
@@ -476,6 +479,34 @@
EXPECT_TRUE(status.isOk());
}
+/**
+ * AddAccessPointWithMloConfig and remove link should pass
+ */
+TEST_P(HostapdAidl, AddAccessPointWithMloConfigAndRemoveInstance) {
+ if (interface_version_ < 3) {
+ GTEST_SKIP() << "MLO SAP is available in IfaceParams as of Hostapd V3";
+ }
+ if (!isMloSupport) GTEST_SKIP() << "Missing MLO AP support";
+ std::shared_ptr<IWifiApIface> wifi_ap_iface = HostapdAidlTestUtils::setupMloApIface();
+ EXPECT_TRUE(wifi_ap_iface.get() != nullptr);
+ std::string br_name;
+ std::vector<std::string> instances;
+ bool uses_mlo;
+ EXPECT_TRUE(wifi_ap_iface->getName(&br_name).isOk());
+ EXPECT_TRUE(wifi_ap_iface->getBridgedInstances(&instances).isOk());
+ EXPECT_TRUE(wifi_ap_iface->usesMlo(&uses_mlo).isOk());
+ EXPECT_TRUE(uses_mlo);
+
+ IfaceParams iface_params = getIfaceParamsWithBridgedModeACS(br_name);
+ iface_params.instanceIdentities = {instances[0], instances[1]};
+ iface_params.usesMlo = uses_mlo;
+ iface_params.hwModeParams.enable80211AX = true;
+ iface_params.hwModeParams.enable80211BE = true;
+
+ EXPECT_TRUE(hostapd->addAccessPoint(iface_params, getSaeNwParams()).isOk());
+ EXPECT_TRUE(hostapd->removeLinkFromMultipleLinkBridgedApIface(br_name, instances[0]).isOk());
+}
+
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HostapdAidl);
INSTANTIATE_TEST_SUITE_P(
Hostapd, HostapdAidl,
diff --git a/wifi/hostapd/aidl/vts/functional/hostapd_aidl_test_utils.h b/wifi/hostapd/aidl/vts/functional/hostapd_aidl_test_utils.h
index 93540b2..3876998 100644
--- a/wifi/hostapd/aidl/vts/functional/hostapd_aidl_test_utils.h
+++ b/wifi/hostapd/aidl/vts/functional/hostapd_aidl_test_utils.h
@@ -77,4 +77,11 @@
return ap_iface_name;
}
+std::shared_ptr<IWifiApIface> setupMloApIface() {
+ std::shared_ptr<IWifiChip> wifi_chip = getWifiChip(kWifiInstanceName);
+ EXPECT_TRUE(wifi_chip.get() != nullptr);
+ return getWifiApOrBridgedApIface(
+ wifi_chip, generateApIfaceParams(IfaceConcurrencyType::AP_BRIDGED, true, 0));
+}
+
} // namespace HostapdAidlTestUtils
diff --git a/wifi/legacy_headers/include/hardware_legacy/rtt.h b/wifi/legacy_headers/include/hardware_legacy/rtt.h
index 426abe0..3fa4e95 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 @@
/* 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 @@
// 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 @@
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 @@
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_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 @@
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 9baa2c7..a757954 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 @@
#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))
@@ -789,10 +790,13 @@
wifi_rtt_config[], wifi_rtt_event_handler);
wifi_error (* wifi_rtt_range_request_v3)(wifi_request_id, wifi_interface_handle, unsigned,
wifi_rtt_config_v3[], wifi_rtt_event_handler_v3);
+ wifi_error (*wifi_rtt_range_request_v4)(wifi_request_id, wifi_interface_handle, unsigned,
+ wifi_rtt_config_v4[], wifi_rtt_event_handler_v4);
wifi_error (* wifi_rtt_range_cancel)(wifi_request_id, wifi_interface_handle, unsigned,
mac_addr[]);
wifi_error (* wifi_get_rtt_capabilities)(wifi_interface_handle, wifi_rtt_capabilities *);
wifi_error (* wifi_get_rtt_capabilities_v3)(wifi_interface_handle, wifi_rtt_capabilities_v3 *);
+ wifi_error (*wifi_get_rtt_capabilities_v4)(wifi_interface_handle, wifi_rtt_capabilities_v4*);
wifi_error (* wifi_rtt_get_responder_info)(wifi_interface_handle iface,
wifi_rtt_responder *responder_info);
wifi_error (* wifi_enable_responder)(wifi_request_id id, wifi_interface_handle iface,
diff --git a/wifi/legacy_headers/include/hardware_legacy/wifi_nan.h b/wifi/legacy_headers/include/hardware_legacy/wifi_nan.h
index 4e490d9..37368af 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 <net/if.h>
#include <stdbool.h>
+#include "rtt.h"
#include "wifi_hal.h"
#ifdef __cplusplus
@@ -3103,6 +3104,7 @@
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 8d16cb7..1fbe8e9 100644
--- a/wifi/supplicant/aidl/Android.bp
+++ b/wifi/supplicant/aidl/Android.bp
@@ -29,7 +29,7 @@
"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 0000000..6d16580
--- /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 <name>-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 0b068e0..c584d57 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 @@
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 @@
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 65ad4c1..3b283b8 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 @@
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 917668e..cb96dfc 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 @@
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 9fa8f56..b0141df 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,25 @@
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, in android.hardware.wifi.supplicant.ISupplicantStaIfaceCallback.UsdConfigErrorCode errorCode);
+ oneway void onUsdSubscribeConfigFailed(in int cmdId, in android.hardware.wifi.supplicant.ISupplicantStaIfaceCallback.UsdConfigErrorCode errorCode);
+ oneway void onUsdPublishTerminated(in int publishId, in android.hardware.wifi.supplicant.UsdTerminateReasonCode reasonCode);
+ oneway void onUsdSubscribeTerminated(in int subscribeId, in android.hardware.wifi.supplicant.UsdTerminateReasonCode 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,
+ }
+ @Backing(type="int") @VintfStability
+ enum UsdConfigErrorCode {
+ FAILURE_UNKNOWN = 0,
+ FAILURE_TIMEOUT = 1,
+ FAILURE_NOT_AVAILABLE = 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 8bda324..05226c8 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 @@
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 f4662de..a88a829 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 @@
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 4451fb5..901b9d1 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 @@
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 ee8e6dc..184fbd0 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 @@
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 0000000..2c55410
--- /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 <name>-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 e19ae44..227626c 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 @@
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 0000000..182c091
--- /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 <name>-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 40c8ff6..578176a 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 @@
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 46366cc..60da924 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 @@
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 0000000..b5dc4b1
--- /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 <name>-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 0000000..0743a64
--- /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 <name>-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 0000000..36ce742
--- /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 <name>-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 0000000..a13d107
--- /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 <name>-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 0000000..da129cf
--- /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 <name>-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 c31b167..b1269ba 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 @@
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 d7ff798..8675ab3 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 @@
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 0000000..73531e1
--- /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 <name>-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 0000000..1c5ad67
--- /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 <name>-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 0000000..40468bd
--- /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 <name>-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 0000000..99ac16d
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdPublishConfig.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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 <name>-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;
+ boolean eventsEnabled;
+ 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 0000000..9486cd0
--- /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 <name>-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/UsdServiceDiscoveryInfo.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/UsdServiceDiscoveryInfo.aidl
new file mode 100644
index 0000000..3940ece
--- /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 <name>-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 0000000..4d4a4f5
--- /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 <name>-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 0000000..6aede8c
--- /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 <name>-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 0000000..0f84783
--- /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 <name>-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 0000000..e36c4f2
--- /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 <name>-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 177d218..58ac0eb 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 0000000..6d1b2be
--- /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 1230793..75e65ff 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.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;
@@ -39,6 +44,15 @@
@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.
*
* @param query Hex dump of the query data.
@@ -398,6 +412,9 @@
* 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.
+ * <p>
+ * @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 @@
/**
* Reinvoke a device from a persistent group.
+ * <p>
+ * @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 @@
* |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 44a5465..a52e150 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.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 @@
* @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 fb1673e..5c6024a 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.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 @@
* |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 172fcda..efbd066 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.StaIfaceCallbackState;
import android.hardware.wifi.supplicant.StaIfaceReasonCode;
import android.hardware.wifi.supplicant.SupplicantStateChangeData;
+import android.hardware.wifi.supplicant.UsdMessageInfo;
+import android.hardware.wifi.supplicant.UsdServiceDiscoveryInfo;
+import android.hardware.wifi.supplicant.UsdTerminateReasonCode;
import android.hardware.wifi.supplicant.WpsConfigError;
import android.hardware.wifi.supplicant.WpsErrorIndication;
@@ -336,13 +339,24 @@
*/
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,100 @@
*
*/
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);
+
+ /**
+ * Error codes returned by |onUsdPublishConfigFailed| and |onUsdSubscribeConfigFailed|.
+ */
+ @VintfStability
+ @Backing(type="int")
+ enum UsdConfigErrorCode {
+ /**
+ * Unknown failure.
+ */
+ FAILURE_UNKNOWN = 0,
+ /**
+ * The requested operation timed out.
+ */
+ FAILURE_TIMEOUT = 1,
+ /**
+ * The requested operation is currently not available.
+ */
+ FAILURE_NOT_AVAILABLE = 2,
+ }
+
+ /**
+ * 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, in UsdConfigErrorCode errorCode);
+
+ /**
+ * 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, in UsdConfigErrorCode errorCode);
+
+ /**
+ * 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 UsdTerminateReasonCode 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 UsdTerminateReasonCode 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 0b4d66e..6215263 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 @@
* 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 f09b476..6467436 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 @@
@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 @@
* 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 51e6ed9..83d480e 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 @@
* 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 15917b6..e320954 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 @@
* 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 0000000..22037ed
--- /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 9db7a1e..55e2b23 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 @@
* 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 0000000..03c2703
--- /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 4f46d70..2b04461 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 @@
* 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 05152a9..97659b6 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 @@
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 @@
* 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 0000000..37f2374
--- /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 0000000..f5f4562
--- /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 0000000..c657d03
--- /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 0000000..9d6bf72
--- /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 0000000..6b60d68
--- /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 e0f1d31..4071179 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 @@
* 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 e97d6ee..271da7f 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 @@
* 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 0000000..68321f6
--- /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 <length, value> 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 <length, value> 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 0000000..ffec893
--- /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 0000000..fa7cc0e
--- /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 0000000..222edce
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdPublishConfig.aidl
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+ /**
+ * Whether to enable publish replied events. If disabled, then
+ * |ISupplicantStaIfaceCallback.onUsdPublishReplied| will not be
+ * called for this session.
+ */
+ boolean eventsEnabled;
+}
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 0000000..45a3cf4
--- /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/UsdServiceDiscoveryInfo.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/UsdServiceDiscoveryInfo.aidl
new file mode 100644
index 0000000..4f6eaf1
--- /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 0000000..de9beb5
--- /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 0000000..4e8893e
--- /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 0000000..6725c3d
--- /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 0000000..39c7eba
--- /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 5b59392..b8ad3b8 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 @@
@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 4ffec3f..95ff6cd 100644
--- a/wifi/supplicant/aidl/vts/functional/Android.bp
+++ b/wifi/supplicant/aidl/vts/functional/Android.bp
@@ -43,7 +43,7 @@
"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 @@
"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 @@
"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 @@
"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 @@
"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,46 @@
"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: [
+ "general-tests",
+ "vts",
+ ],
+}
+
+cc_test {
+ name: "VtsHalWifiSupplicantP2pNetworkTargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: ["supplicant_p2p_network_aidl_test.cpp"],
+ shared_libs: [
+ "libbinder",
+ "libbinder_ndk",
+ "libvndksupport",
+ ],
+ static_libs: [
+ "android.hardware.wifi@1.0",
+ "android.hardware.wifi@1.1",
+ "android.hardware.wifi@1.2",
+ "android.hardware.wifi@1.3",
+ "android.hardware.wifi@1.4",
+ "android.hardware.wifi@1.5",
+ "android.hardware.wifi.common-V2-ndk",
+ "android.hardware.wifi.supplicant@1.0",
+ "android.hardware.wifi.supplicant@1.1",
+ "android.hardware.wifi.supplicant-V4-ndk",
+ "libwifi-system",
+ "libwifi-system-iface",
+ "VtsHalWifiV1_0TargetTestUtil",
+ "VtsHalWifiV1_5TargetTestUtil",
+ "VtsHalWifiSupplicantV1_0TargetTestUtil",
+ "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 8f1c4bd..778e20a 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 <VtsCoreUtil.h>
#include <aidl/Gtest.h>
#include <aidl/Vintf.h>
+#include <aidl/android/hardware/wifi/supplicant/BandMask.h>
#include <aidl/android/hardware/wifi/supplicant/BnSupplicant.h>
#include <aidl/android/hardware/wifi/supplicant/BnSupplicantP2pIfaceCallback.h>
+#include <aidl/android/hardware/wifi/supplicant/P2pPairingBootstrappingMethodMask.h>
#include <aidl/android/hardware/wifi/supplicant/SupplicantStatusCode.h>
#include <android/binder_manager.h>
#include <android/binder_status.h>
@@ -29,17 +31,20 @@
#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;
using aidl::android::hardware::wifi::supplicant::IfaceType;
using aidl::android::hardware::wifi::supplicant::ISupplicant;
using aidl::android::hardware::wifi::supplicant::ISupplicantP2pIface;
+using aidl::android::hardware::wifi::supplicant::ISupplicantP2pNetwork;
using aidl::android::hardware::wifi::supplicant::MiracastMode;
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 +52,20 @@
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 +79,20 @@
const std::vector<uint8_t> kTestPeerMacAddr = {0x56, 0x67, 0x55,
0xf4, 0x56, 0x92};
const std::vector<uint8_t> kTestZeroMacAddr = std::vector<uint8_t>(6, 0);
+const std::string kTestServiceSpecificInfoStr = "TestServiceSpecificInfo";
+const std::vector<uint8_t> kTestServiceSpecificInfo = std::vector<uint8_t>(
+ kTestServiceSpecificInfoStr.begin(), kTestServiceSpecificInfoStr.end());
+const std::vector<uint8_t> kTestNonce = {0x11, 0x22, 0x33, 0x44, 0x55, 0x92, 0x22, 0x33};
+const std::vector<uint8_t> 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 +241,18 @@
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<std::string> {
@@ -246,6 +277,9 @@
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 +291,7 @@
std::shared_ptr<ISupplicant> supplicant_;
std::shared_ptr<ISupplicantP2pIface> p2p_iface_;
int interface_version_;
+ int64_t supported_features_;
};
/*
@@ -364,8 +399,8 @@
* SetWpsModelNumber
*/
TEST_P(SupplicantP2pIfaceAidlTest, SetWpsModelNumber) {
- const std::string modelNumber = "TestModelNumber";
- EXPECT_TRUE(p2p_iface_->setWpsModelName(modelNumber).isOk());
+ const std::string modelNumber = "Model1234";
+ EXPECT_TRUE(p2p_iface_->setWpsModelNumber(modelNumber).isOk());
}
/*
@@ -814,6 +849,229 @@
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());
+}
+
+/*
+ * Test the P2P network management functions.
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, ManageNetworks) {
+ std::shared_ptr<ISupplicantP2pNetwork> network;
+ EXPECT_TRUE(p2p_iface_->addNetwork(&network).isOk());
+ ASSERT_NE(network, nullptr);
+
+ std::vector<int32_t> networkList;
+ EXPECT_TRUE(p2p_iface_->listNetworks(&networkList).isOk());
+ ASSERT_FALSE(networkList.empty());
+
+ int networkId = networkList[0];
+ EXPECT_TRUE(p2p_iface_->getNetwork(networkId, &network).isOk());
+ ASSERT_NE(network, nullptr);
+ EXPECT_TRUE(p2p_iface_->removeNetwork(networkId).isOk());
+}
+
+/*
+ * Request and cancel service discovery
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, RequestAndCancelServiceDiscovery) {
+ int64_t discoveryId;
+ std::vector<uint8_t> query = {0x11, 0x22, 0x33};
+ EXPECT_TRUE(p2p_iface_->requestServiceDiscovery(kTestMacAddr, query, &discoveryId).isOk());
+ EXPECT_TRUE(p2p_iface_->cancelServiceDiscovery(discoveryId).isOk());
+}
+
+/*
+ * Start and stop WPS
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, StartAndStopWps) {
+ // Expected to fail with test values
+ std::string generatedPin;
+ EXPECT_FALSE(p2p_iface_->startWpsPbc(kTestGroupIfName, kTestMacAddr).isOk());
+ EXPECT_FALSE(
+ p2p_iface_->startWpsPinDisplay(kTestGroupIfName, kTestMacAddr, &generatedPin).isOk());
+ EXPECT_FALSE(p2p_iface_->startWpsPinKeypad(kTestGroupIfName, kTestConnectPin).isOk());
+ EXPECT_FALSE(p2p_iface_->cancelWps(kTestGroupIfName).isOk());
+}
+
+/*
+ * Create message and report handover for NFC Request
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, CreateAndReportNfcRequest) {
+ std::vector<uint8_t> requestMsg;
+ EXPECT_TRUE(p2p_iface_->createNfcHandoverRequestMessage(&requestMsg).isOk());
+ EXPECT_FALSE(requestMsg.empty());
+ EXPECT_TRUE(p2p_iface_->reportNfcHandoverResponse(requestMsg).isOk());
+}
+
+/*
+ * Create message and report handover for NFC Select
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, CreateAndReportNfcSelect) {
+ std::vector<uint8_t> selectMsg;
+ EXPECT_TRUE(p2p_iface_->createNfcHandoverSelectMessage(&selectMsg).isOk());
+ EXPECT_FALSE(selectMsg.empty());
+ EXPECT_TRUE(p2p_iface_->reportNfcHandoverInitiation(selectMsg).isOk());
+}
+
+/*
+ * RemoveClient
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, RemoveClient) {
+ // Method returns success for any valid MAC address
+ EXPECT_TRUE(p2p_iface_->removeClient(kTestMacAddr, false).isOk());
+ // Returns failure for any invalid MAC address
+ std::vector<uint8_t> invalidMacAddr = {0x11, 0x22};
+ EXPECT_FALSE(p2p_iface_->removeClient(invalidMacAddr, false).isOk());
+}
+
+/*
+ * ConfigureEapolIpAddressAllocationParams
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, ConfigureEapolIpAddressAllocationParams) {
+ if (interface_version_ < 2) {
+ GTEST_SKIP() << "ConfigureEapolIpAddressAllocationParams is available as of Supplicant V2";
+ }
+ // The IP addresses are IPV4 addresses and higher-order address bytes are in the
+ // lower-order int bytes (e.g. 192.168.1.1 is represented as 0x0101A8C0)
+ EXPECT_TRUE(p2p_iface_
+ ->configureEapolIpAddressAllocationParams(0x0101A8C0, 0x00FFFFFF,
+ 0x0501A8C0, 0x0801A8C0)
+ .isOk());
+
+ // Clear the configuration.
+ EXPECT_TRUE(p2p_iface_->configureEapolIpAddressAllocationParams(0, 0, 0, 0).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_p2p_network_aidl_test.cpp b/wifi/supplicant/aidl/vts/functional/supplicant_p2p_network_aidl_test.cpp
new file mode 100644
index 0000000..c5a73f1
--- /dev/null
+++ b/wifi/supplicant/aidl/vts/functional/supplicant_p2p_network_aidl_test.cpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <VtsCoreUtil.h>
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/wifi/supplicant/BnSupplicant.h>
+#include <android/binder_manager.h>
+#include <android/binder_status.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <cutils/properties.h>
+
+#include "supplicant_test_utils.h"
+#include "wifi_aidl_test_utils.h"
+
+using aidl::android::hardware::wifi::supplicant::DebugLevel;
+using aidl::android::hardware::wifi::supplicant::IfaceType;
+using aidl::android::hardware::wifi::supplicant::ISupplicantP2pNetwork;
+using aidl::android::hardware::wifi::supplicant::MacAddress;
+using android::ProcessState;
+
+class SupplicantP2pNetworkAidlTest : public testing::TestWithParam<std::string> {
+ public:
+ void SetUp() override {
+ initializeService();
+ supplicant_ = getSupplicant(GetParam().c_str());
+ ASSERT_NE(supplicant_, nullptr);
+ ASSERT_TRUE(supplicant_->setDebugParams(DebugLevel::EXCESSIVE, true, true).isOk());
+
+ bool p2pEnabled = testing::deviceSupportsFeature("android.hardware.wifi.direct");
+ if (!p2pEnabled) {
+ GTEST_SKIP() << "Wi-Fi Direct is not supported, skip this test.";
+ }
+
+ EXPECT_TRUE(supplicant_->getP2pInterface(getP2pIfaceName(), &p2p_iface_).isOk());
+ ASSERT_NE(p2p_iface_, nullptr);
+ EXPECT_TRUE(p2p_iface_->addNetwork(&p2p_network_).isOk());
+ ASSERT_NE(p2p_network_, nullptr);
+ }
+
+ void TearDown() override {
+ stopSupplicantService();
+ startWifiFramework();
+ }
+
+ protected:
+ std::shared_ptr<ISupplicant> supplicant_;
+ std::shared_ptr<ISupplicantP2pIface> p2p_iface_;
+ std::shared_ptr<ISupplicantP2pNetwork> p2p_network_;
+};
+
+/*
+ * GetBssid
+ */
+TEST_P(SupplicantP2pNetworkAidlTest, GetBssid) {
+ std::vector<uint8_t> bssid;
+ EXPECT_TRUE(p2p_network_->getBssid(&bssid).isOk());
+}
+
+/*
+ * GetClientList
+ */
+TEST_P(SupplicantP2pNetworkAidlTest, GetClientList) {
+ // Expect failure if there are no clients
+ std::vector<MacAddress> clientList;
+ EXPECT_FALSE(p2p_network_->getClientList(&clientList).isOk());
+}
+
+/*
+ * GetId
+ */
+TEST_P(SupplicantP2pNetworkAidlTest, GetId) {
+ int networkId;
+ EXPECT_TRUE(p2p_network_->getId(&networkId).isOk());
+}
+
+/*
+ * GetInterfaceName
+ */
+TEST_P(SupplicantP2pNetworkAidlTest, GetInterfaceName) {
+ std::string expectedName = getP2pIfaceName();
+ std::string retrievedName;
+ EXPECT_TRUE(p2p_network_->getInterfaceName(&retrievedName).isOk());
+ EXPECT_EQ(retrievedName, expectedName);
+}
+
+/*
+ * GetSsid
+ */
+TEST_P(SupplicantP2pNetworkAidlTest, GetSsid) {
+ std::vector<uint8_t> ssid;
+ EXPECT_TRUE(p2p_network_->getSsid(&ssid).isOk());
+}
+
+/*
+ * GetType
+ */
+TEST_P(SupplicantP2pNetworkAidlTest, GetType) {
+ IfaceType ifaceType;
+ EXPECT_TRUE(p2p_network_->getType(&ifaceType).isOk());
+ EXPECT_EQ(ifaceType, IfaceType::P2P);
+}
+
+/*
+ * IsCurrent
+ */
+TEST_P(SupplicantP2pNetworkAidlTest, IsCurrent) {
+ bool isCurrent;
+ EXPECT_TRUE(p2p_network_->isCurrent(&isCurrent).isOk());
+ EXPECT_FALSE(isCurrent);
+}
+
+/*
+ * IsGroupOwner
+ */
+TEST_P(SupplicantP2pNetworkAidlTest, IsGroupOwner) {
+ bool isGroupOwner;
+ EXPECT_TRUE(p2p_network_->isGroupOwner(&isGroupOwner).isOk());
+ EXPECT_FALSE(isGroupOwner);
+}
+
+/*
+ * IsPersistent
+ */
+TEST_P(SupplicantP2pNetworkAidlTest, IsPersistent) {
+ bool isPersistent;
+ EXPECT_TRUE(p2p_network_->isPersistent(&isPersistent).isOk());
+ EXPECT_FALSE(isPersistent);
+}
+
+/*
+ * SetClientList
+ */
+TEST_P(SupplicantP2pNetworkAidlTest, SetClientList) {
+ MacAddress client = {{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc}};
+ std::vector clientList = {client};
+ EXPECT_TRUE(p2p_network_->setClientList(clientList).isOk());
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantP2pNetworkAidlTest);
+INSTANTIATE_TEST_SUITE_P(
+ Supplicant, SupplicantP2pNetworkAidlTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(ISupplicant::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/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp b/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp
index 6b04aa9..257607f 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
@@ -43,10 +43,20 @@
using aidl::android::hardware::wifi::supplicant::ISupplicantStaIface;
using aidl::android::hardware::wifi::supplicant::ISupplicantStaNetwork;
using aidl::android::hardware::wifi::supplicant::KeyMgmtMask;
+using aidl::android::hardware::wifi::supplicant::MloLinksInfo;
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::RxFilterType;
+using aidl::android::hardware::wifi::supplicant::SignalPollResult;
+using aidl::android::hardware::wifi::supplicant::UsdBaseConfig;
+using aidl::android::hardware::wifi::supplicant::UsdCapabilities;
+using aidl::android::hardware::wifi::supplicant::UsdMessageInfo;
+using aidl::android::hardware::wifi::supplicant::UsdPublishConfig;
+using aidl::android::hardware::wifi::supplicant::UsdServiceDiscoveryInfo;
+using aidl::android::hardware::wifi::supplicant::UsdSubscribeConfig;
+using aidl::android::hardware::wifi::supplicant::UsdTerminateReasonCode;
using aidl::android::hardware::wifi::supplicant::WpaDriverCapabilitiesMask;
using aidl::android::hardware::wifi::supplicant::WpsConfigMethods;
using android::ProcessState;
@@ -243,6 +253,40 @@
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 */,
+ UsdConfigErrorCode /* errorCode */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onUsdSubscribeConfigFailed(int32_t /* cmdId */,
+ UsdConfigErrorCode /* errorCode */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onUsdPublishTerminated(int32_t /* publishId */,
+ UsdTerminateReasonCode /* reasonCode */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onUsdSubscribeTerminated(
+ int32_t /* subscribeId */, UsdTerminateReasonCode /* 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<std::string> {
@@ -843,6 +887,183 @@
EXPECT_EQ(1, responseList.size());
}
+/*
+ * Verify that all USD methods check the Service Specific Info (SSI) length
+ * and fail if the provided SSI is too long.
+ */
+TEST_P(SupplicantStaIfaceAidlTest, InvalidUsdServiceSpecificInfo) {
+ if (interface_version_ < 4) {
+ GTEST_SKIP() << "USD is available as of Supplicant V4";
+ }
+
+ UsdCapabilities caps;
+ EXPECT_TRUE(sta_iface_->getUsdCapabilities(&caps).isOk());
+ if (!caps.isUsdPublisherSupported && !caps.isUsdSubscriberSupported) {
+ GTEST_SKIP() << "USD publish and subscribe are not supported";
+ }
+
+ int commandId = 123;
+ std::vector<uint8_t> invalidSsi(caps.maxLocalSsiLengthBytes + 1);
+ UsdBaseConfig invalidBaseConfig;
+ invalidBaseConfig.serviceSpecificInfo = invalidSsi;
+
+ if (caps.isUsdPublisherSupported) {
+ UsdPublishConfig publishConfig;
+ publishConfig.usdBaseConfig = invalidBaseConfig;
+ EXPECT_FALSE(sta_iface_->startUsdPublish(commandId, publishConfig).isOk());
+ EXPECT_FALSE(sta_iface_->updateUsdPublish(commandId, invalidSsi).isOk());
+ }
+
+ if (caps.isUsdSubscriberSupported) {
+ UsdSubscribeConfig subscribeConfig;
+ subscribeConfig.usdBaseConfig = invalidBaseConfig;
+ EXPECT_FALSE(sta_iface_->startUsdSubscribe(commandId, subscribeConfig).isOk());
+ }
+
+ UsdMessageInfo messageInfo;
+ messageInfo.message = invalidSsi;
+ EXPECT_FALSE(sta_iface_->sendUsdMessage(messageInfo).isOk());
+}
+
+/*
+ * Cancel a USD Publish and Subscribe session.
+ */
+TEST_P(SupplicantStaIfaceAidlTest, CancelUsdSession) {
+ if (interface_version_ < 4) {
+ GTEST_SKIP() << "USD is available as of Supplicant V4";
+ }
+
+ UsdCapabilities caps;
+ EXPECT_TRUE(sta_iface_->getUsdCapabilities(&caps).isOk());
+ if (!caps.isUsdPublisherSupported && !caps.isUsdSubscriberSupported) {
+ GTEST_SKIP() << "USD publish and subscribe are not supported";
+ }
+
+ int sessionId = 123;
+ if (caps.isUsdPublisherSupported) {
+ // Method is expected to succeed, even if the session does not exist.
+ EXPECT_TRUE(sta_iface_->cancelUsdPublish(sessionId).isOk());
+ }
+ if (caps.isUsdSubscriberSupported) {
+ EXPECT_TRUE(sta_iface_->cancelUsdSubscribe(sessionId).isOk());
+ }
+}
+
+/*
+ * GenerateSelfDppConfiguration
+ */
+TEST_P(SupplicantStaIfaceAidlTest, GenerateSelfDppConfiguration) {
+ if (!keyMgmtSupported(sta_iface_, KeyMgmtMask::DPP)) {
+ GTEST_SKIP() << "Missing DPP support";
+ }
+ const std::string ssid = "my_test_ssid";
+ const std::vector<uint8_t> eckey_in = {0x2, 0x3, 0x4};
+
+ // Expect to fail as this test requires a DPP AKM supported AP and a valid private EC
+ // key generated by wpa_supplicant.
+ EXPECT_FALSE(sta_iface_->generateSelfDppConfiguration(ssid, eckey_in).isOk());
+}
+
+/*
+ * getSignalPollResults
+ */
+TEST_P(SupplicantStaIfaceAidlTest, GetSignalPollResults) {
+ if (interface_version_ < 2) {
+ GTEST_SKIP() << "getSignalPollResults is available as of Supplicant V2";
+ }
+
+ std::vector<SignalPollResult> results;
+ EXPECT_TRUE(sta_iface_->getSignalPollResults(&results).isOk());
+}
+
+/*
+ * Test that we can add, remove, start, and stop an RX filter.
+ */
+TEST_P(SupplicantStaIfaceAidlTest, ConfigureRxFilter) {
+ RxFilterType filterType = RxFilterType::V4_MULTICAST;
+ EXPECT_TRUE(sta_iface_->addRxFilter(filterType).isOk());
+ EXPECT_TRUE(sta_iface_->startRxFilter().isOk());
+ EXPECT_TRUE(sta_iface_->stopRxFilter().isOk());
+ EXPECT_TRUE(sta_iface_->removeRxFilter(filterType).isOk());
+}
+
+/*
+ * Test that we can start and cancel all WPS methods.
+ */
+TEST_P(SupplicantStaIfaceAidlTest, StartAndCancelWps) {
+ std::vector<uint8_t> zeroMacAddr = {0, 0, 0, 0, 0, 0};
+ std::string pin = "12345678";
+
+ EXPECT_TRUE(sta_iface_->startWpsPbc(zeroMacAddr).isOk());
+ EXPECT_TRUE(sta_iface_->cancelWps().isOk());
+
+ std::string generatedPin;
+ EXPECT_TRUE(sta_iface_->startWpsPinDisplay(zeroMacAddr, &generatedPin).isOk());
+ EXPECT_TRUE(sta_iface_->cancelWps().isOk());
+
+ EXPECT_TRUE(sta_iface_->startWpsPinKeypad(pin).isOk());
+ EXPECT_TRUE(sta_iface_->cancelWps().isOk());
+
+ EXPECT_TRUE(sta_iface_->startWpsRegistrar(zeroMacAddr, pin).isOk());
+ EXPECT_TRUE(sta_iface_->cancelWps().isOk());
+}
+
+/*
+ * Test that we can add, list, get, and remove a network.
+ */
+TEST_P(SupplicantStaIfaceAidlTest, ManageNetwork) {
+ std::shared_ptr<ISupplicantStaNetwork> network;
+ EXPECT_TRUE(sta_iface_->addNetwork(&network).isOk());
+ EXPECT_NE(network, nullptr);
+
+ std::vector<int32_t> networkList;
+ EXPECT_TRUE(sta_iface_->listNetworks(&networkList).isOk());
+ EXPECT_EQ(networkList.size(), 1);
+
+ int networkId;
+ EXPECT_TRUE(network->getId(&networkId).isOk());
+ EXPECT_EQ(networkId, networkList[0]);
+
+ std::shared_ptr<ISupplicantStaNetwork> retrievedNetwork;
+ EXPECT_TRUE(sta_iface_->getNetwork(networkId, &retrievedNetwork).isOk());
+ EXPECT_NE(retrievedNetwork, nullptr);
+ EXPECT_TRUE(sta_iface_->removeNetwork(networkId).isOk());
+}
+
+/*
+ * EnableAutoReconnect
+ */
+TEST_P(SupplicantStaIfaceAidlTest, EnableAutoReconnect) {
+ EXPECT_TRUE(sta_iface_->enableAutoReconnect(true).isOk());
+ EXPECT_TRUE(sta_iface_->enableAutoReconnect(false).isOk());
+}
+
+/*
+ * SetQosPolicyFeatureEnabled
+ */
+TEST_P(SupplicantStaIfaceAidlTest, SetQosPolicyFeatureEnabled) {
+ EXPECT_TRUE(sta_iface_->setQosPolicyFeatureEnabled(true).isOk());
+ EXPECT_TRUE(sta_iface_->setQosPolicyFeatureEnabled(false).isOk());
+}
+
+/*
+ * GetConnectionMloLinksInfo
+ */
+TEST_P(SupplicantStaIfaceAidlTest, GetConnectionMloLinksInfo) {
+ MloLinksInfo mloInfo;
+ EXPECT_TRUE(sta_iface_->getConnectionMloLinksInfo(&mloInfo).isOk());
+}
+
+/*
+ * StopDppInitiator
+ */
+TEST_P(SupplicantStaIfaceAidlTest, StopDppInitiator) {
+ if (!keyMgmtSupported(sta_iface_, KeyMgmtMask::DPP)) {
+ GTEST_SKIP() << "Missing DPP support";
+ }
+ EXPECT_TRUE(sta_iface_->stopDppInitiator().isOk());
+}
+
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantStaIfaceAidlTest);
INSTANTIATE_TEST_SUITE_P(Supplicant, SupplicantStaIfaceAidlTest,
testing::ValuesIn(android::getAidlHalInstanceNames(
diff --git a/wifi/supplicant/aidl/vts/functional/supplicant_sta_network_aidl_test.cpp b/wifi/supplicant/aidl/vts/functional/supplicant_sta_network_aidl_test.cpp
index 9bdd2f5..2f0053a 100644
--- a/wifi/supplicant/aidl/vts/functional/supplicant_sta_network_aidl_test.cpp
+++ b/wifi/supplicant/aidl/vts/functional/supplicant_sta_network_aidl_test.cpp
@@ -32,6 +32,7 @@
using aidl::android::hardware::wifi::supplicant::AuthAlgMask;
using aidl::android::hardware::wifi::supplicant::BnSupplicantStaNetworkCallback;
using aidl::android::hardware::wifi::supplicant::DebugLevel;
+using aidl::android::hardware::wifi::supplicant::DppConnectionKeys;
using aidl::android::hardware::wifi::supplicant::EapMethod;
using aidl::android::hardware::wifi::supplicant::EapPhase2Method;
using aidl::android::hardware::wifi::supplicant::GroupCipherMask;
@@ -837,6 +838,21 @@
}
/*
+ * SetDppKeys
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetDppKeys) {
+ if (!keyMgmtSupported(sta_iface_, KeyMgmtMask::DPP)) {
+ GTEST_SKIP() << "Missing DPP support";
+ }
+
+ DppConnectionKeys in_keys;
+ in_keys.connector = std::vector<uint8_t>({0x11, 0x22, 0x33, 0x44});
+ in_keys.cSign = std::vector<uint8_t>({0x55, 0x66, 0x77, 0x88});
+ in_keys.netAccessKey = std::vector<uint8_t>({0xaa, 0xbb, 0xcc, 0xdd});
+ EXPECT_TRUE(sta_network_->setDppKeys(in_keys).isOk());
+}
+
+/*
* SetVendorData
*/
TEST_P(SupplicantStaNetworkAidlTest, SetVendorData) {
@@ -846,6 +862,20 @@
EXPECT_TRUE(sta_network_->setVendorData(kTestVendorData).isOk());
}
+/*
+ * Set/Get EDMG
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetEdmg) {
+ bool retrievedValue = false;
+ EXPECT_TRUE(sta_network_->setEdmg(true).isOk());
+ EXPECT_TRUE(sta_network_->getEdmg(&retrievedValue).isOk());
+ EXPECT_EQ(retrievedValue, true);
+
+ EXPECT_TRUE(sta_network_->setEdmg(false).isOk());
+ EXPECT_TRUE(sta_network_->getEdmg(&retrievedValue).isOk());
+ EXPECT_EQ(retrievedValue, false);
+}
+
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantStaNetworkAidlTest);
INSTANTIATE_TEST_SUITE_P(Supplicant, SupplicantStaNetworkAidlTest,
testing::ValuesIn(android::getAidlHalInstanceNames(