[automerger skipped] Merge 2024-06 Release (ab/AP2A.240605.024) to aosp-main-future am: 9c2c02ddef -s ours
am skip reason: Merged-In If12d978ee69ee7f087a7e8758513a9c6bacf817f with SHA-1 53238b1afd is already in history
Original change: https://googleplex-android-review.googlesource.com/c/platform/hardware/interfaces/+/27555390
Change-Id: I378eec7cea2180de6258bd833d986fd70dd76a26
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp
index 8bb8cd5..b67b9d2 100644
--- a/audio/aidl/Android.bp
+++ b/audio/aidl/Android.bp
@@ -64,6 +64,9 @@
],
min_sdk_version: "31",
},
+ rust: {
+ enabled: true,
+ },
},
versions_with_info: [
{
@@ -112,6 +115,13 @@
],
}
+rust_defaults {
+ name: "latest_android_hardware_audio_common_rust",
+ rustlibs: [
+ latest_android_hardware_audio_common + "-rust",
+ ],
+}
+
aidl_interface_defaults {
name: "latest_android_hardware_audio_common_import_interface",
imports: [
diff --git a/audio/aidl/common/include/Utils.h b/audio/aidl/common/include/Utils.h
index a1008a4..b431340 100644
--- a/audio/aidl/common/include/Utils.h
+++ b/audio/aidl/common/include/Utils.h
@@ -47,6 +47,9 @@
namespace aidl::android::hardware::audio::common {
+// TODO: b/275135031 - move this string to AIDL interfaces.
+static constexpr char kDumpFromAudioServerArgument[] = "dump_from_audioserver";
+
// Some values are reserved for use by the system code only.
// HALs must not accept or emit values outside from the provided list.
constexpr std::array<::aidl::android::media::audio::common::AudioMode, 5> kValidAudioModes = {
diff --git a/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp b/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
index b023df1..0c201cc 100644
--- a/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
+++ b/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
@@ -453,12 +453,11 @@
ENGINE_TEST_INSTANCE_NAME,
ENGINE_TEST_RESOLUTION_PREFERENCE,
ENGINE_TEST_PREFERRED_DURATION,
- ENGINE_TEST_STAGE_ENABLEMENT,
- ENGINE_TEST_LIMITER_IN_USE
+ ENGINE_TEST_STAGE_ENABLEMENT
};
using EngineArchitectureTestParams = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>,
DynamicsProcessing::ResolutionPreference, float,
- DynamicsProcessing::StageEnablement, bool>;
+ DynamicsProcessing::StageEnablement>;
void fillEngineArchConfig(DynamicsProcessing::EngineArchitecture& cfg,
const EngineArchitectureTestParams& params) {
@@ -466,7 +465,7 @@
cfg.preferredProcessingDurationMs = std::get<ENGINE_TEST_PREFERRED_DURATION>(params);
cfg.preEqStage = cfg.postEqStage = cfg.mbcStage =
std::get<ENGINE_TEST_STAGE_ENABLEMENT>(params);
- cfg.limiterInUse = std::get<ENGINE_TEST_LIMITER_IN_USE>(params);
+ cfg.limiterInUse = true;
}
class DynamicsProcessingTestEngineArchitecture
@@ -501,8 +500,8 @@
static_cast<DynamicsProcessing::ResolutionPreference>(-1)), // variant
testing::Values(-10.f, 0.f, 10.f), // processing duration
testing::ValuesIn(
- DynamicsProcessingTestHelper::kStageEnablementTestSet), // preEQ/postEQ/mbc
- testing::Bool()), // limiter enable
+ DynamicsProcessingTestHelper::kStageEnablementTestSet) // preEQ/postEQ/mbc
+ ),
[](const auto& info) {
auto descriptor = std::get<ENGINE_TEST_INSTANCE_NAME>(info.param).second;
DynamicsProcessing::EngineArchitecture cfg;
@@ -568,7 +567,6 @@
LIMITER_CHANNEL,
LIMITER_ENABLE,
LIMITER_LINK_GROUP,
- LIMITER_ENGINE_IN_USE,
LIMITER_ADDITIONAL,
};
enum LimiterConfigTestAdditionalParam {
@@ -587,9 +585,8 @@
{1, -60, 2.5, -2, 3.14},
{1, 60, 2.5, -2, 3.14}}};
-using LimiterConfigTestParams =
- std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int32_t, bool, int32_t, bool,
- LimiterConfigTestAdditional>;
+using LimiterConfigTestParams = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>,
+ int32_t, bool, int32_t, LimiterConfigTestAdditional>;
void fillLimiterConfig(DynamicsProcessing::LimiterConfig& cfg,
const LimiterConfigTestParams& params) {
@@ -609,8 +606,7 @@
public DynamicsProcessingTestHelper {
public:
DynamicsProcessingTestLimiterConfig()
- : DynamicsProcessingTestHelper(std::get<LIMITER_INSTANCE_NAME>(GetParam())),
- mLimiterInUseEngine(std::get<LIMITER_ENGINE_IN_USE>(GetParam())) {
+ : DynamicsProcessingTestHelper(std::get<LIMITER_INSTANCE_NAME>(GetParam())) {
fillLimiterConfig(mCfg, GetParam());
}
@@ -619,11 +615,9 @@
void TearDown() override { TearDownDynamicsProcessingEffect(); }
DynamicsProcessing::LimiterConfig mCfg;
- bool mLimiterInUseEngine;
};
TEST_P(DynamicsProcessingTestLimiterConfig, SetAndGetLimiterConfig) {
- mEngineConfigPreset.limiterInUse = mLimiterInUseEngine;
EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
EXPECT_NO_FATAL_FAILURE(addLimiterConfig({mCfg}));
SetAndGetDynamicsProcessingParameters();
@@ -633,21 +627,18 @@
DynamicsProcessingTest, DynamicsProcessingTestLimiterConfig,
::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
- testing::Values(-1, 0, 1, 2), // channel count
- testing::Bool(), // enable
- testing::Values(3), // link group
- testing::Bool(), // engine limiter enable
+ testing::Values(-1, 0, 1, 2), // channel count
+ testing::Bool(), // enable
+ testing::Values(3), // link group
testing::ValuesIn(kLimiterConfigTestAdditionalParam)), // Additional
[](const auto& info) {
auto descriptor = std::get<LIMITER_INSTANCE_NAME>(info.param).second;
DynamicsProcessing::LimiterConfig cfg;
fillLimiterConfig(cfg, info.param);
- std::string engineLimiterInUse =
- std::to_string(std::get<LIMITER_ENGINE_IN_USE>(info.param));
std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
descriptor.common.name + "_UUID_" +
toString(descriptor.common.id.uuid) + "_limiterConfig_" +
- cfg.toString() + "_engineSetting_" + engineLimiterInUse;
+ cfg.toString();
std::replace_if(
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
return name;
@@ -659,11 +650,10 @@
*/
enum ChannelConfigTestParamName {
BAND_CHANNEL_TEST_INSTANCE_NAME,
- BAND_CHANNEL_TEST_CHANNEL_CONFIG,
- BAND_CHANNEL_TEST_ENGINE_IN_USE
+ BAND_CHANNEL_TEST_CHANNEL_CONFIG
};
using ChannelConfigTestParams = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>,
- std::vector<DynamicsProcessing::ChannelConfig>, bool>;
+ std::vector<DynamicsProcessing::ChannelConfig>>;
class DynamicsProcessingTestChannelConfig
: public ::testing::TestWithParam<ChannelConfigTestParams>,
@@ -671,33 +661,28 @@
public:
DynamicsProcessingTestChannelConfig()
: DynamicsProcessingTestHelper(std::get<BAND_CHANNEL_TEST_INSTANCE_NAME>(GetParam())),
- mCfg(std::get<BAND_CHANNEL_TEST_CHANNEL_CONFIG>(GetParam())),
- mInUseEngine(std::get<BAND_CHANNEL_TEST_ENGINE_IN_USE>(GetParam())) {}
+ mCfg(std::get<BAND_CHANNEL_TEST_CHANNEL_CONFIG>(GetParam())) {}
void SetUp() override { SetUpDynamicsProcessingEffect(); }
void TearDown() override { TearDownDynamicsProcessingEffect(); }
std::vector<DynamicsProcessing::ChannelConfig> mCfg;
- const bool mInUseEngine;
};
TEST_P(DynamicsProcessingTestChannelConfig, SetAndGetPreEqChannelConfig) {
- mEngineConfigPreset.preEqStage.inUse = mInUseEngine;
EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
EXPECT_NO_FATAL_FAILURE(addPreEqChannelConfig(mCfg));
SetAndGetDynamicsProcessingParameters();
}
TEST_P(DynamicsProcessingTestChannelConfig, SetAndGetPostEqChannelConfig) {
- mEngineConfigPreset.postEqStage.inUse = mInUseEngine;
EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
EXPECT_NO_FATAL_FAILURE(addPostEqChannelConfig(mCfg));
SetAndGetDynamicsProcessingParameters();
}
TEST_P(DynamicsProcessingTestChannelConfig, SetAndGetMbcChannelConfig) {
- mEngineConfigPreset.mbcStage.inUse = mInUseEngine;
EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
EXPECT_NO_FATAL_FAILURE(addMbcChannelConfig(mCfg));
SetAndGetDynamicsProcessingParameters();
@@ -709,19 +694,15 @@
testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
testing::ValuesIn(
- DynamicsProcessingTestHelper::kChannelConfigTestSet), // channel config
- testing::Bool()), // Engine inUse
+ DynamicsProcessingTestHelper::kChannelConfigTestSet)), // channel config
[](const auto& info) {
auto descriptor = std::get<BAND_CHANNEL_TEST_INSTANCE_NAME>(info.param).second;
- std::string engineInUse =
- std::to_string(std::get<BAND_CHANNEL_TEST_ENGINE_IN_USE>(info.param));
std::string channelConfig = ::android::internal::ToString(
std::get<BAND_CHANNEL_TEST_CHANNEL_CONFIG>(info.param));
std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
descriptor.common.name + "_UUID_" +
- toString(descriptor.common.id.uuid) + "_" + channelConfig +
- "_engineInUse_" + engineInUse;
+ toString(descriptor.common.id.uuid) + "_" + channelConfig;
std::replace_if(
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
return name;
@@ -736,11 +717,10 @@
EQ_BAND_CHANNEL,
EQ_BAND_ENABLE,
EQ_BAND_CUT_OFF_FREQ,
- EQ_BAND_GAIN,
- EQ_BAND_STAGE_IN_USE
+ EQ_BAND_GAIN
};
using EqBandConfigTestParams = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int32_t,
- bool, std::vector<std::pair<int, float>>, float, bool>;
+ bool, std::vector<std::pair<int, float>>, float>;
void fillEqBandConfig(std::vector<DynamicsProcessing::EqBandConfig>& cfgs,
const EqBandConfigTestParams& params) {
@@ -760,8 +740,7 @@
public DynamicsProcessingTestHelper {
public:
DynamicsProcessingTestEqBandConfig()
- : DynamicsProcessingTestHelper(std::get<EQ_BAND_INSTANCE_NAME>(GetParam())),
- mStageInUse(std::get<EQ_BAND_STAGE_IN_USE>(GetParam())) {
+ : DynamicsProcessingTestHelper(std::get<EQ_BAND_INSTANCE_NAME>(GetParam())) {
fillEqBandConfig(mCfgs, GetParam());
}
@@ -770,11 +749,9 @@
void TearDown() override { TearDownDynamicsProcessingEffect(); }
std::vector<DynamicsProcessing::EqBandConfig> mCfgs;
- const bool mStageInUse;
};
TEST_P(DynamicsProcessingTestEqBandConfig, SetAndGetPreEqBandConfig) {
- mEngineConfigPreset.preEqStage.inUse = mStageInUse;
mEngineConfigPreset.preEqStage.bandCount = mCfgs.size();
EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
std::vector<DynamicsProcessing::ChannelConfig> cfgs(mChannelCount);
@@ -788,7 +765,6 @@
}
TEST_P(DynamicsProcessingTestEqBandConfig, SetAndGetPostEqBandConfig) {
- mEngineConfigPreset.postEqStage.inUse = mStageInUse;
mEngineConfigPreset.postEqStage.bandCount = mCfgs.size();
EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
std::vector<DynamicsProcessing::ChannelConfig> cfgs(mChannelCount);
@@ -849,21 +825,19 @@
DynamicsProcessingTest, DynamicsProcessingTestEqBandConfig,
::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
- testing::Values(-1, 0, 10), // channel ID
- testing::Bool(), // band enable
- testing::ValuesIn(kBands), // cut off frequencies
- testing::Values(-3.14f, 3.14f), // gain
- testing::Values(true)), // stage in use
+ testing::Values(-1, 0, 10), // channel ID
+ testing::Bool(), // band enable
+ testing::ValuesIn(kBands), // cut off frequencies
+ testing::Values(-3.14f, 3.14f) // gain
+ ),
[](const auto& info) {
auto descriptor = std::get<EQ_BAND_INSTANCE_NAME>(info.param).second;
std::vector<DynamicsProcessing::EqBandConfig> cfgs;
fillEqBandConfig(cfgs, info.param);
std::string bands = ::android::internal::ToString(cfgs);
- std::string stageInUse = std::to_string(std::get<EQ_BAND_STAGE_IN_USE>(info.param));
std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
descriptor.common.name + "_UUID_" +
- toString(descriptor.common.id.uuid) + "_bands_" + bands +
- "_stageInUse_" + stageInUse;
+ toString(descriptor.common.id.uuid) + "_bands_" + bands;
std::replace_if(
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
return name;
@@ -879,7 +853,6 @@
MBC_BAND_CHANNEL,
MBC_BAND_ENABLE,
MBC_BAND_CUTOFF_FREQ,
- MBC_BAND_STAGE_IN_USE,
MBC_BAND_ADDITIONAL
};
enum MbcBandConfigAdditional {
@@ -905,7 +878,7 @@
using TestParamsMbcBandConfig =
std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int32_t, bool,
- std::vector<std::pair<int, float>>, bool, TestParamsMbcBandConfigAdditional>;
+ std::vector<std::pair<int, float>>, TestParamsMbcBandConfigAdditional>;
void fillMbcBandConfig(std::vector<DynamicsProcessing::MbcBandConfig>& cfgs,
const TestParamsMbcBandConfig& params) {
@@ -936,8 +909,7 @@
public DynamicsProcessingTestHelper {
public:
DynamicsProcessingTestMbcBandConfig()
- : DynamicsProcessingTestHelper(std::get<MBC_BAND_INSTANCE_NAME>(GetParam())),
- mStageInUse(std::get<MBC_BAND_STAGE_IN_USE>(GetParam())) {
+ : DynamicsProcessingTestHelper(std::get<MBC_BAND_INSTANCE_NAME>(GetParam())) {
fillMbcBandConfig(mCfgs, GetParam());
}
@@ -946,11 +918,9 @@
void TearDown() override { TearDownDynamicsProcessingEffect(); }
std::vector<DynamicsProcessing::MbcBandConfig> mCfgs;
- const bool mStageInUse;
};
TEST_P(DynamicsProcessingTestMbcBandConfig, SetAndGetMbcBandConfig) {
- mEngineConfigPreset.mbcStage.inUse = mStageInUse;
mEngineConfigPreset.mbcStage.bandCount = mCfgs.size();
EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
std::vector<DynamicsProcessing::ChannelConfig> cfgs(mChannelCount);
@@ -970,18 +940,15 @@
testing::Values(-1, 0, 10), // channel count
testing::Bool(), // enable
testing::ValuesIn(kBands), // cut off frequencies
- testing::Bool(), // stage in use
testing::ValuesIn(kMbcBandConfigAdditionalParam)), // Additional
[](const auto& info) {
auto descriptor = std::get<MBC_BAND_INSTANCE_NAME>(info.param).second;
std::vector<DynamicsProcessing::MbcBandConfig> cfgs;
fillMbcBandConfig(cfgs, info.param);
std::string mbcBands = ::android::internal::ToString(cfgs);
- std::string stageInUse = std::to_string(std::get<MBC_BAND_STAGE_IN_USE>(info.param));
std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
descriptor.common.name + "_UUID_" +
- toString(descriptor.common.id.uuid) + "_bands_" + mbcBands +
- "_stageInUse_" + stageInUse;
+ toString(descriptor.common.id.uuid) + "_bands_" + mbcBands;
std::replace_if(
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
return name;
diff --git a/audio/aidl/vts/VtsHalVolumeTargetTest.cpp b/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
index db2f4a9..4115eca 100644
--- a/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
@@ -140,7 +140,9 @@
class VolumeDataTest : public ::testing::TestWithParam<VolumeDataTestParam>,
public VolumeControlHelper {
public:
- VolumeDataTest() {
+ VolumeDataTest()
+ : kVsrApiLevel(
+ android::base::GetIntProperty("ro.vendor.api_level", __ANDROID_API_FUTURE__)) {
std::tie(mFactory, mDescriptor) = GetParam();
mInput.resize(kBufferSize);
mInputMag.resize(mTestFrequencies.size());
@@ -165,13 +167,17 @@
void SetUp() override {
SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+ // Skips test fixture if api_level <= 34 (__ANDROID_API_U__).
+ if (kVsrApiLevel <= __ANDROID_API_U__) GTEST_SKIP();
ASSERT_NO_FATAL_FAILURE(SetUpVolumeControl());
}
void TearDown() override {
SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+ if (kVsrApiLevel <= __ANDROID_API_U__) GTEST_SKIP();
TearDownVolumeControl();
}
+ const int kVsrApiLevel;
static constexpr int kMaxAudioSample = 1;
static constexpr int kTransitionDuration = 300;
static constexpr int kNPointFFT = 32768;
diff --git a/automotive/audiocontrol/aidl/Android.bp b/automotive/audiocontrol/aidl/Android.bp
index bedf5e4..0eb17fe 100644
--- a/automotive/audiocontrol/aidl/Android.bp
+++ b/automotive/audiocontrol/aidl/Android.bp
@@ -27,6 +27,9 @@
"com.android.car.framework",
],
},
+ rust: {
+ enabled: true,
+ },
},
versions_with_info: [
{
@@ -93,3 +96,17 @@
latest_android_hardware_automotive_audiocontrol + "-ndk",
],
}
+
+java_defaults {
+ name: "latest_android_hardware_automotive_audiocontrol_java_static",
+ static_libs: [
+ latest_android_hardware_automotive_audiocontrol + "-java",
+ ],
+}
+
+rust_defaults {
+ name: "latest_android_hardware_automotive_audiocontrol_rust",
+ rustlibs: [
+ latest_android_hardware_automotive_audiocontrol + "-rust",
+ ],
+}
diff --git a/automotive/audiocontrol/aidl/default/Android.bp b/automotive/audiocontrol/aidl/default/Android.bp
index a48d228..fd7e167 100644
--- a/automotive/audiocontrol/aidl/default/Android.bp
+++ b/automotive/audiocontrol/aidl/default/Android.bp
@@ -30,15 +30,14 @@
defaults: [
"latest_android_hardware_audio_common_ndk_shared",
"latest_android_hardware_automotive_audiocontrol_ndk_shared",
+ "powerpolicyclient_defaults",
],
shared_libs: [
"android.hardware.audio.common@7.0-enums",
- "android.frameworks.automotive.powerpolicy-V2-ndk",
"libbase",
"libbinder_ndk",
"libcutils",
"liblog",
- "libpowerpolicyclient",
],
srcs: [
"AudioControl.cpp",
diff --git a/automotive/audiocontrol/aidl/rust_impl/Android.bp b/automotive/audiocontrol/aidl/rust_impl/Android.bp
new file mode 100644
index 0000000..062d989
--- /dev/null
+++ b/automotive/audiocontrol/aidl/rust_impl/Android.bp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+rust_binary {
+ name: "android.hardware.automotive.audiocontrol-V4-rust-service",
+ relative_install_path: "hw",
+ vendor: true,
+ srcs: ["src/*.rs"],
+ crate_root: "src/main.rs",
+ defaults: [
+ "latest_android_hardware_automotive_audiocontrol_rust",
+ "latest_android_hardware_audio_common_rust",
+ ],
+ vintf_fragments: ["audiocontrol-rust-service.xml"],
+ init_rc: ["audiocontrol-rust-service.rc"],
+ rustlibs: [
+ "libbinder_rs",
+ ],
+}
diff --git a/automotive/audiocontrol/aidl/rust_impl/README.md b/automotive/audiocontrol/aidl/rust_impl/README.md
new file mode 100644
index 0000000..ed22356
--- /dev/null
+++ b/automotive/audiocontrol/aidl/rust_impl/README.md
@@ -0,0 +1,13 @@
+# Rust Skeleton Audio Control HAL implementation.
+
+WARNING: This is not a reference audio control HAl implementation and does
+not contain any actual implementation.
+
+This folder contains a skeleton audio control HAL implementation in Rust to
+demonstrate how vendor may implement a Rust audio control HAL. To run this
+audio control HAL, include
+`android.hardware.automotive.audiocontrol-V4-rust-service` in your image.
+
+This implementation returns `StatusCode::UNKNOWN_ERROR` for all operations
+and does not pass VTS/CTS. Vendor must replace the logic in
+`default_audio_control_hal.rs` with the actual implementation.
diff --git a/automotive/audiocontrol/aidl/rust_impl/audiocontrol-rust-service.rc b/automotive/audiocontrol/aidl/rust_impl/audiocontrol-rust-service.rc
new file mode 100644
index 0000000..88d180d
--- /dev/null
+++ b/automotive/audiocontrol/aidl/rust_impl/audiocontrol-rust-service.rc
@@ -0,0 +1,4 @@
+service vendor.audiocontrol-default /vendor/bin/hw/android.hardware.automotive.audiocontrol-service.example
+ class hal
+ user audioserver
+ group system
diff --git a/automotive/audiocontrol/aidl/rust_impl/audiocontrol-rust-service.xml b/automotive/audiocontrol/aidl/rust_impl/audiocontrol-rust-service.xml
new file mode 100644
index 0000000..e54c1d3
--- /dev/null
+++ b/automotive/audiocontrol/aidl/rust_impl/audiocontrol-rust-service.xml
@@ -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.
+ -->
+
+<manifest version="2.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.automotive.audiocontrol</name>
+ <version>4</version>
+ <fqname>IAudioControl/default</fqname>
+ </hal>
+</manifest>
diff --git a/automotive/audiocontrol/aidl/rust_impl/src/default_audio_control_hal.rs b/automotive/audiocontrol/aidl/rust_impl/src/default_audio_control_hal.rs
new file mode 100644
index 0000000..ba0ca23
--- /dev/null
+++ b/automotive/audiocontrol/aidl/rust_impl/src/default_audio_control_hal.rs
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+use android_hardware_automotive_audiocontrol::aidl::android::hardware::automotive::audiocontrol::{
+ AudioFocusChange::AudioFocusChange,
+ AudioGainConfigInfo::AudioGainConfigInfo,
+ DuckingInfo::DuckingInfo,
+ IAudioControl::IAudioControl,
+ IAudioGainCallback::IAudioGainCallback,
+ IFocusListener::IFocusListener,
+ IModuleChangeCallback::IModuleChangeCallback,
+ MutingInfo::MutingInfo,
+ Reasons::Reasons,
+};
+use android_hardware_audio_common::aidl::android::hardware::audio::common::PlaybackTrackMetadata::PlaybackTrackMetadata;
+use binder::{Interface, Result as BinderResult, StatusCode, Strong};
+
+/// This struct is defined to implement IAudioControl AIDL interface.
+pub struct DefaultAudioControlHal;
+
+impl Interface for DefaultAudioControlHal {}
+
+impl IAudioControl for DefaultAudioControlHal {
+ fn onAudioFocusChange(&self, _usage : &str, _zone_id : i32, _focus_change : AudioFocusChange
+ ) -> BinderResult<()> {
+ Err(StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn onDevicesToDuckChange(&self, _ducking_infos : &[DuckingInfo]) -> BinderResult<()> {
+ Err(StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn onDevicesToMuteChange(&self, _muting_infos : &[MutingInfo]) -> BinderResult<()> {
+ Err(StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn registerFocusListener(&self, _listener : &Strong<dyn IFocusListener>) -> BinderResult<()> {
+ Err(StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn setBalanceTowardRight(&self, _value : f32) -> BinderResult<()> {
+ Err(StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn setFadeTowardFront(&self, _value : f32) -> BinderResult<()> {
+ Err(StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn onAudioFocusChangeWithMetaData(&self, _playback_metadata : &PlaybackTrackMetadata,
+ _zone_id : i32, _focus_change : AudioFocusChange) -> BinderResult<()> {
+ Err(StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn setAudioDeviceGainsChanged(&self, _reasons : &[Reasons], _gains : &[AudioGainConfigInfo]
+ ) -> BinderResult<()> {
+ Err(StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn registerGainCallback(&self, _callback : &Strong<dyn IAudioGainCallback>
+ ) -> BinderResult<()> {
+ Err(StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn setModuleChangeCallback(&self, _callback : &Strong<dyn IModuleChangeCallback>
+ ) -> BinderResult<()> {
+ Err(StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn clearModuleChangeCallback(&self) -> BinderResult<()> {
+ Err(StatusCode::UNKNOWN_ERROR.into())
+ }
+}
diff --git a/automotive/audiocontrol/aidl/rust_impl/src/main.rs b/automotive/audiocontrol/aidl/rust_impl/src/main.rs
new file mode 100644
index 0000000..2ed4810
--- /dev/null
+++ b/automotive/audiocontrol/aidl/rust_impl/src/main.rs
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+mod default_audio_control_hal;
+
+use android_hardware_automotive_audiocontrol::aidl::android::hardware::automotive::audiocontrol::IAudioControl::BnAudioControl;
+use crate::default_audio_control_hal::DefaultAudioControlHal;
+
+fn main() {
+ binder::ProcessState::start_thread_pool();
+ let my_service = DefaultAudioControlHal;
+ let service_name = "android.hardware.automotive.audiocontrol.IAudioControl/default";
+ let my_service_binder = BnAudioControl::new_binder(
+ my_service,
+ binder::BinderFeatures::default(),
+ );
+ binder::add_service(service_name, my_service_binder.as_binder())
+ .expect(format!("Failed to register {}?", service_name).as_str());
+ // Does not return.
+ binder::ProcessState::join_thread_pool()
+}
diff --git a/automotive/can/1.0/default/libc++fs/.clang-format b/automotive/can/1.0/default/libc++fs/.clang-format
deleted file mode 100644
index dd59681..0000000
--- a/automotive/can/1.0/default/libc++fs/.clang-format
+++ /dev/null
@@ -1,13 +0,0 @@
-BasedOnStyle: LLVM
-
----
-Language: Cpp
-Standard: Cpp03
-
-AlwaysBreakTemplateDeclarations: true
-PointerAlignment: Left
-
-# Disable formatting options which may break tests.
-SortIncludes: false
-ReflowComments: false
----
diff --git a/automotive/can/1.0/default/libc++fs/Android.bp b/automotive/can/1.0/default/libc++fs/Android.bp
deleted file mode 100644
index 0641991..0000000
--- a/automotive/can/1.0/default/libc++fs/Android.bp
+++ /dev/null
@@ -1,70 +0,0 @@
-//
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-// TODO(152067309): Stop building this yourself once it's ABI stable and has
-// been made vendor available. Just use libc++fs instead of this.
-
-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-NCSA
- default_applicable_licenses: ["hardware_interfaces_license"],
-}
-
-cc_defaults {
- name: "android.hardware.automotive@libc++fsdefaults",
- local_include_dirs: ["include"],
- export_include_dirs: ["include"],
- cflags: [
- "-Wall",
- "-Werror",
- "-Wno-unused-parameter",
- ],
- cppflags: [
- "-std=c++17",
- "-fexceptions",
- "-DLIBCXX_BUILDING_LIBCXXABI",
- "-D_LIBCPP_BUILDING_LIBRARY",
- ],
- rtti: true,
-}
-
-cc_library_static {
- name: "android.hardware.automotive@libc++fs",
- recovery_available: true,
- vendor: true,
- defaults: ["android.hardware.automotive@libc++fsdefaults"],
- srcs: [
- "src/filesystem/directory_iterator.cpp",
- "src/filesystem/operations.cpp",
- ],
- multilib: {
- lib32: {
- // off_t usage is constrained to within the libc++ source (not the
- // headers), so we can build the filesystem library with a 64-bit
- // off_t on LP32 to get large file support without needing all users
- // of the library to match.
- cflags: ["-D_FILE_OFFSET_BITS=64"],
- },
- },
- target: {
- windows: {
- enabled: false,
- },
- },
-}
diff --git a/automotive/can/1.0/default/libc++fs/include/automotive/filesystem b/automotive/can/1.0/default/libc++fs/include/automotive/filesystem
deleted file mode 100644
index bd3dda5..0000000
--- a/automotive/can/1.0/default/libc++fs/include/automotive/filesystem
+++ /dev/null
@@ -1,2713 +0,0 @@
-// -*- C++ -*-
-//===--------------------------- filesystem -------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef _LIBAUTO_FILESYSTEM
-#define _LIBAUTO_FILESYSTEM
-
-// TODO(152067309): Remove this once the libc++ upgrade is complete.
-#include <__config>
-#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION > 8000
-
-#include <filesystem>
-namespace android::hardware::automotive {
-namespace filesystem = std::filesystem;
-}
-
-#else
-
-/*
- filesystem synopsis
-
- namespace android::hardware::automotive { namespace filesystem {
-
- class path;
-
- void swap(path& lhs, path& rhs) noexcept;
- size_t hash_value(const path& p) noexcept;
-
- bool operator==(const path& lhs, const path& rhs) noexcept;
- bool operator!=(const path& lhs, const path& rhs) noexcept;
- bool operator< (const path& lhs, const path& rhs) noexcept;
- bool operator<=(const path& lhs, const path& rhs) noexcept;
- bool operator> (const path& lhs, const path& rhs) noexcept;
- bool operator>=(const path& lhs, const path& rhs) noexcept;
-
- path operator/ (const path& lhs, const path& rhs);
-
- // fs.path.io operators are friends of path.
- template <class charT, class traits>
- friend basic_ostream<charT, traits>&
- operator<<(basic_ostream<charT, traits>& os, const path& p);
-
- template <class charT, class traits>
- friend basic_istream<charT, traits>&
- operator>>(basic_istream<charT, traits>& is, path& p);
-
- template <class Source>
- path u8path(const Source& source);
- template <class InputIterator>
- path u8path(InputIterator first, InputIterator last);
-
- class filesystem_error;
- class directory_entry;
-
- class directory_iterator;
-
- // enable directory_iterator range-based for statements
- directory_iterator begin(directory_iterator iter) noexcept;
- directory_iterator end(const directory_iterator&) noexcept;
-
- class recursive_directory_iterator;
-
- // enable recursive_directory_iterator range-based for statements
- recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept;
- recursive_directory_iterator end(const recursive_directory_iterator&) noexcept;
-
- class file_status;
-
- struct space_info
- {
- uintmax_t capacity;
- uintmax_t free;
- uintmax_t available;
- };
-
- enum class file_type;
- enum class perms;
- enum class perm_options;
- enum class copy_options;
- enum class directory_options;
-
- typedef chrono::time_point<trivial-clock> file_time_type;
-
- // operational functions
-
- path absolute(const path& p);
- path absolute(const path& p, error_code &ec);
-
- path canonical(const path& p);
- path canonical(const path& p, error_code& ec);
-
- void copy(const path& from, const path& to);
- void copy(const path& from, const path& to, error_code& ec);
- void copy(const path& from, const path& to, copy_options options);
- void copy(const path& from, const path& to, copy_options options,
- error_code& ec);
-
- bool copy_file(const path& from, const path& to);
- bool copy_file(const path& from, const path& to, error_code& ec);
- bool copy_file(const path& from, const path& to, copy_options option);
- bool copy_file(const path& from, const path& to, copy_options option,
- error_code& ec);
-
- void copy_symlink(const path& existing_symlink, const path& new_symlink);
- void copy_symlink(const path& existing_symlink, const path& new_symlink,
- error_code& ec) noexcept;
-
- bool create_directories(const path& p);
- bool create_directories(const path& p, error_code& ec);
-
- bool create_directory(const path& p);
- bool create_directory(const path& p, error_code& ec) noexcept;
-
- bool create_directory(const path& p, const path& attributes);
- bool create_directory(const path& p, const path& attributes,
- error_code& ec) noexcept;
-
- void create_directory_symlink(const path& to, const path& new_symlink);
- void create_directory_symlink(const path& to, const path& new_symlink,
- error_code& ec) noexcept;
-
- void create_hard_link(const path& to, const path& new_hard_link);
- void create_hard_link(const path& to, const path& new_hard_link,
- error_code& ec) noexcept;
-
- void create_symlink(const path& to, const path& new_symlink);
- void create_symlink(const path& to, const path& new_symlink,
- error_code& ec) noexcept;
-
- path current_path();
- path current_path(error_code& ec);
- void current_path(const path& p);
- void current_path(const path& p, error_code& ec) noexcept;
-
- bool exists(file_status s) noexcept;
- bool exists(const path& p);
- bool exists(const path& p, error_code& ec) noexcept;
-
- bool equivalent(const path& p1, const path& p2);
- bool equivalent(const path& p1, const path& p2, error_code& ec) noexcept;
-
- uintmax_t file_size(const path& p);
- uintmax_t file_size(const path& p, error_code& ec) noexcept;
-
- uintmax_t hard_link_count(const path& p);
- uintmax_t hard_link_count(const path& p, error_code& ec) noexcept;
-
- bool is_block_file(file_status s) noexcept;
- bool is_block_file(const path& p);
- bool is_block_file(const path& p, error_code& ec) noexcept;
-
- bool is_character_file(file_status s) noexcept;
- bool is_character_file(const path& p);
- bool is_character_file(const path& p, error_code& ec) noexcept;
-
- bool is_directory(file_status s) noexcept;
- bool is_directory(const path& p);
- bool is_directory(const path& p, error_code& ec) noexcept;
-
- bool is_empty(const path& p);
- bool is_empty(const path& p, error_code& ec) noexcept;
-
- bool is_fifo(file_status s) noexcept;
- bool is_fifo(const path& p);
- bool is_fifo(const path& p, error_code& ec) noexcept;
-
- bool is_other(file_status s) noexcept;
- bool is_other(const path& p);
- bool is_other(const path& p, error_code& ec) noexcept;
-
- bool is_regular_file(file_status s) noexcept;
- bool is_regular_file(const path& p);
- bool is_regular_file(const path& p, error_code& ec) noexcept;
-
- bool is_socket(file_status s) noexcept;
- bool is_socket(const path& p);
- bool is_socket(const path& p, error_code& ec) noexcept;
-
- bool is_symlink(file_status s) noexcept;
- bool is_symlink(const path& p);
- bool is_symlink(const path& p, error_code& ec) noexcept;
-
- file_time_type last_write_time(const path& p);
- file_time_type last_write_time(const path& p, error_code& ec) noexcept;
- void last_write_time(const path& p, file_time_type new_time);
- void last_write_time(const path& p, file_time_type new_time,
- error_code& ec) noexcept;
-
- void permissions(const path& p, perms prms,
- perm_options opts=perm_options::replace);
- void permissions(const path& p, perms prms, error_code& ec) noexcept;
- void permissions(const path& p, perms prms, perm_options opts,
- error_code& ec);
-
- path proximate(const path& p, error_code& ec);
- path proximate(const path& p, const path& base = current_path());
- path proximate(const path& p, const path& base, error_code &ec);
-
- path read_symlink(const path& p);
- path read_symlink(const path& p, error_code& ec);
-
- path relative(const path& p, error_code& ec);
- path relative(const path& p, const path& base=current_path());
- path relative(const path& p, const path& base, error_code& ec);
-
- bool remove(const path& p);
- bool remove(const path& p, error_code& ec) noexcept;
-
- uintmax_t remove_all(const path& p);
- uintmax_t remove_all(const path& p, error_code& ec);
-
- void rename(const path& from, const path& to);
- void rename(const path& from, const path& to, error_code& ec) noexcept;
-
- void resize_file(const path& p, uintmax_t size);
- void resize_file(const path& p, uintmax_t size, error_code& ec) noexcept;
-
- space_info space(const path& p);
- space_info space(const path& p, error_code& ec) noexcept;
-
- file_status status(const path& p);
- file_status status(const path& p, error_code& ec) noexcept;
-
- bool status_known(file_status s) noexcept;
-
- file_status symlink_status(const path& p);
- file_status symlink_status(const path& p, error_code& ec) noexcept;
-
- path temp_directory_path();
- path temp_directory_path(error_code& ec);
-
- path weakly_canonical(path const& p);
- path weakly_canonical(path const& p, error_code& ec);
-
-
-} } // namespace android::hardware::automotive::filesystem
-
-*/
-
-#include <__config>
-#include <cstddef>
-#include <cstdlib>
-#include <chrono>
-#include <iterator>
-#include <iosfwd>
-#include <locale>
-#include <memory>
-#include <stack>
-#include <string>
-#include <system_error>
-#include <utility>
-#include <iomanip> // for quoted
-#include <string_view>
-#include <version>
-
-#include <__debug>
-
-#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
-#pragma GCC system_header
-#endif
-
-_LIBCPP_PUSH_MACROS
-#include <__undef_macros>
-
-#ifndef _LIBCPP_CXX03_LANG
-
-namespace android::hardware::automotive::filesystem {
-using namespace std;
-using namespace std::chrono;
-
-using std::basic_string;
-using std::enable_if;
-using std::error_code;
-using std::false_type;
-
-#ifndef _VSTD
-#define _LIBAUTO_UNDEF_VSTD
-#define _VSTD std
-#endif
-
-#ifdef _VSTD_FS
-#pragma push_macro("_VSTD_FS")
-#else
-#define _LIBAUTO_UNDEF_VSTD_FS
-#endif
-#define _VSTD_FS android::hardware::automotive::filesystem
-
-/* Begin copy of _FilesystemClock from include/chrono */
-struct _FilesystemClock {
-#if !defined(_LIBCPP_HAS_NO_INT128)
- typedef __int128_t rep;
- typedef nano period;
-#else
- typedef long long rep;
- typedef nano period;
-#endif
-
- typedef chrono::duration<rep, period> duration;
- typedef chrono::time_point<_FilesystemClock> time_point;
-
- static _LIBCPP_CONSTEXPR_AFTER_CXX11 const bool is_steady = false;
-
- _LIBCPP_FUNC_VIS static time_point now() noexcept;
-
- _LIBCPP_INLINE_VISIBILITY
- static time_t to_time_t(const time_point& __t) noexcept {
- typedef chrono::duration<rep> __secs;
- return time_t(
- chrono::duration_cast<__secs>(__t.time_since_epoch()).count());
- }
-
- _LIBCPP_INLINE_VISIBILITY
- static time_point from_time_t(time_t __t) noexcept {
- typedef chrono::duration<rep> __secs;
- return time_point(__secs(__t));
- }
-};
-/* End copy of _FilesystemClock from include/chrono */
-
-typedef chrono::time_point<_FilesystemClock> file_time_type;
-
-struct _LIBCPP_TYPE_VIS space_info {
- uintmax_t capacity;
- uintmax_t free;
- uintmax_t available;
-};
-
-enum class _LIBCPP_ENUM_VIS file_type : signed char {
- none = 0,
- not_found = -1,
- regular = 1,
- directory = 2,
- symlink = 3,
- block = 4,
- character = 5,
- fifo = 6,
- socket = 7,
- unknown = 8
-};
-
-enum class _LIBCPP_ENUM_VIS perms : unsigned {
- none = 0,
-
- owner_read = 0400,
- owner_write = 0200,
- owner_exec = 0100,
- owner_all = 0700,
-
- group_read = 040,
- group_write = 020,
- group_exec = 010,
- group_all = 070,
-
- others_read = 04,
- others_write = 02,
- others_exec = 01,
- others_all = 07,
-
- all = 0777,
-
- set_uid = 04000,
- set_gid = 02000,
- sticky_bit = 01000,
- mask = 07777,
- unknown = 0xFFFF,
-};
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr perms operator&(perms _LHS, perms _RHS) {
- return static_cast<perms>(static_cast<unsigned>(_LHS) &
- static_cast<unsigned>(_RHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr perms operator|(perms _LHS, perms _RHS) {
- return static_cast<perms>(static_cast<unsigned>(_LHS) |
- static_cast<unsigned>(_RHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr perms operator^(perms _LHS, perms _RHS) {
- return static_cast<perms>(static_cast<unsigned>(_LHS) ^
- static_cast<unsigned>(_RHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr perms operator~(perms _LHS) {
- return static_cast<perms>(~static_cast<unsigned>(_LHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline perms& operator&=(perms& _LHS, perms _RHS) { return _LHS = _LHS & _RHS; }
-
-_LIBCPP_INLINE_VISIBILITY
-inline perms& operator|=(perms& _LHS, perms _RHS) { return _LHS = _LHS | _RHS; }
-
-_LIBCPP_INLINE_VISIBILITY
-inline perms& operator^=(perms& _LHS, perms _RHS) { return _LHS = _LHS ^ _RHS; }
-
-enum class _LIBCPP_ENUM_VIS perm_options : unsigned char {
- replace = 1,
- add = 2,
- remove = 4,
- nofollow = 8
-};
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr perm_options operator&(perm_options _LHS, perm_options _RHS) {
- return static_cast<perm_options>(static_cast<unsigned>(_LHS) &
- static_cast<unsigned>(_RHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr perm_options operator|(perm_options _LHS, perm_options _RHS) {
- return static_cast<perm_options>(static_cast<unsigned>(_LHS) |
- static_cast<unsigned>(_RHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr perm_options operator^(perm_options _LHS, perm_options _RHS) {
- return static_cast<perm_options>(static_cast<unsigned>(_LHS) ^
- static_cast<unsigned>(_RHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr perm_options operator~(perm_options _LHS) {
- return static_cast<perm_options>(~static_cast<unsigned>(_LHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline perm_options& operator&=(perm_options& _LHS, perm_options _RHS) {
- return _LHS = _LHS & _RHS;
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline perm_options& operator|=(perm_options& _LHS, perm_options _RHS) {
- return _LHS = _LHS | _RHS;
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline perm_options& operator^=(perm_options& _LHS, perm_options _RHS) {
- return _LHS = _LHS ^ _RHS;
-}
-
-enum class _LIBCPP_ENUM_VIS copy_options : unsigned short {
- none = 0,
- skip_existing = 1,
- overwrite_existing = 2,
- update_existing = 4,
- recursive = 8,
- copy_symlinks = 16,
- skip_symlinks = 32,
- directories_only = 64,
- create_symlinks = 128,
- create_hard_links = 256,
- __in_recursive_copy = 512,
-};
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr copy_options operator&(copy_options _LHS, copy_options _RHS) {
- return static_cast<copy_options>(static_cast<unsigned short>(_LHS) &
- static_cast<unsigned short>(_RHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr copy_options operator|(copy_options _LHS, copy_options _RHS) {
- return static_cast<copy_options>(static_cast<unsigned short>(_LHS) |
- static_cast<unsigned short>(_RHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr copy_options operator^(copy_options _LHS, copy_options _RHS) {
- return static_cast<copy_options>(static_cast<unsigned short>(_LHS) ^
- static_cast<unsigned short>(_RHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr copy_options operator~(copy_options _LHS) {
- return static_cast<copy_options>(~static_cast<unsigned short>(_LHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline copy_options& operator&=(copy_options& _LHS, copy_options _RHS) {
- return _LHS = _LHS & _RHS;
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline copy_options& operator|=(copy_options& _LHS, copy_options _RHS) {
- return _LHS = _LHS | _RHS;
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline copy_options& operator^=(copy_options& _LHS, copy_options _RHS) {
- return _LHS = _LHS ^ _RHS;
-}
-
-enum class _LIBCPP_ENUM_VIS directory_options : unsigned char {
- none = 0,
- follow_directory_symlink = 1,
- skip_permission_denied = 2
-};
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr directory_options operator&(directory_options _LHS,
- directory_options _RHS) {
- return static_cast<directory_options>(static_cast<unsigned char>(_LHS) &
- static_cast<unsigned char>(_RHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr directory_options operator|(directory_options _LHS,
- directory_options _RHS) {
- return static_cast<directory_options>(static_cast<unsigned char>(_LHS) |
- static_cast<unsigned char>(_RHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr directory_options operator^(directory_options _LHS,
- directory_options _RHS) {
- return static_cast<directory_options>(static_cast<unsigned char>(_LHS) ^
- static_cast<unsigned char>(_RHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr directory_options operator~(directory_options _LHS) {
- return static_cast<directory_options>(~static_cast<unsigned char>(_LHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline directory_options& operator&=(directory_options& _LHS,
- directory_options _RHS) {
- return _LHS = _LHS & _RHS;
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline directory_options& operator|=(directory_options& _LHS,
- directory_options _RHS) {
- return _LHS = _LHS | _RHS;
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline directory_options& operator^=(directory_options& _LHS,
- directory_options _RHS) {
- return _LHS = _LHS ^ _RHS;
-}
-
-class _LIBCPP_TYPE_VIS file_status {
-public:
- // constructors
- _LIBCPP_INLINE_VISIBILITY
- file_status() noexcept : file_status(file_type::none) {}
- _LIBCPP_INLINE_VISIBILITY
- explicit file_status(file_type __ft, perms __prms = perms::unknown) noexcept
- : __ft_(__ft),
- __prms_(__prms) {}
-
- file_status(const file_status&) noexcept = default;
- file_status(file_status&&) noexcept = default;
-
- _LIBCPP_INLINE_VISIBILITY
- ~file_status() {}
-
- file_status& operator=(const file_status&) noexcept = default;
- file_status& operator=(file_status&&) noexcept = default;
-
- // observers
- _LIBCPP_INLINE_VISIBILITY
- file_type type() const noexcept { return __ft_; }
-
- _LIBCPP_INLINE_VISIBILITY
- perms permissions() const noexcept { return __prms_; }
-
- // modifiers
- _LIBCPP_INLINE_VISIBILITY
- void type(file_type __ft) noexcept { __ft_ = __ft; }
-
- _LIBCPP_INLINE_VISIBILITY
- void permissions(perms __p) noexcept { __prms_ = __p; }
-
-private:
- file_type __ft_;
- perms __prms_;
-};
-
-class _LIBCPP_TYPE_VIS directory_entry;
-
-template <class _Tp>
-struct __can_convert_char {
- static const bool value = false;
-};
-template <class _Tp>
-struct __can_convert_char<const _Tp> : public __can_convert_char<_Tp> {};
-template <>
-struct __can_convert_char<char> {
- static const bool value = true;
- using __char_type = char;
-};
-template <>
-struct __can_convert_char<wchar_t> {
- static const bool value = true;
- using __char_type = wchar_t;
-};
-template <>
-struct __can_convert_char<char16_t> {
- static const bool value = true;
- using __char_type = char16_t;
-};
-template <>
-struct __can_convert_char<char32_t> {
- static const bool value = true;
- using __char_type = char32_t;
-};
-
-template <class _ECharT>
-typename enable_if<__can_convert_char<_ECharT>::value, bool>::type
-__is_separator(_ECharT __e) {
- return __e == _ECharT('/');
-}
-
-struct _NullSentinal {};
-
-template <class _Tp>
-using _Void = void;
-
-template <class _Tp, class = void>
-struct __is_pathable_string : public false_type {};
-
-template <class _ECharT, class _Traits, class _Alloc>
-struct __is_pathable_string<
- basic_string<_ECharT, _Traits, _Alloc>,
- _Void<typename __can_convert_char<_ECharT>::__char_type> >
- : public __can_convert_char<_ECharT> {
- using _Str = basic_string<_ECharT, _Traits, _Alloc>;
- using _Base = __can_convert_char<_ECharT>;
- static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
- static _ECharT const* __range_end(_Str const& __s) {
- return __s.data() + __s.length();
- }
- static _ECharT __first_or_null(_Str const& __s) {
- return __s.empty() ? _ECharT{} : __s[0];
- }
-};
-
-template <class _ECharT, class _Traits>
-struct __is_pathable_string<
- basic_string_view<_ECharT, _Traits>,
- _Void<typename __can_convert_char<_ECharT>::__char_type> >
- : public __can_convert_char<_ECharT> {
- using _Str = basic_string_view<_ECharT, _Traits>;
- using _Base = __can_convert_char<_ECharT>;
- static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
- static _ECharT const* __range_end(_Str const& __s) {
- return __s.data() + __s.length();
- }
- static _ECharT __first_or_null(_Str const& __s) {
- return __s.empty() ? _ECharT{} : __s[0];
- }
-};
-
-template <class _Source, class _DS = typename decay<_Source>::type,
- class _UnqualPtrType =
- typename remove_const<typename remove_pointer<_DS>::type>::type,
- bool _IsCharPtr = is_pointer<_DS>::value&&
- __can_convert_char<_UnqualPtrType>::value>
-struct __is_pathable_char_array : false_type {};
-
-template <class _Source, class _ECharT, class _UPtr>
-struct __is_pathable_char_array<_Source, _ECharT*, _UPtr, true>
- : __can_convert_char<typename remove_const<_ECharT>::type> {
- using _Base = __can_convert_char<typename remove_const<_ECharT>::type>;
-
- static _ECharT const* __range_begin(const _ECharT* __b) { return __b; }
- static _ECharT const* __range_end(const _ECharT* __b) {
- using _Iter = const _ECharT*;
- const _ECharT __sentinal = _ECharT{};
- _Iter __e = __b;
- for (; *__e != __sentinal; ++__e)
- ;
- return __e;
- }
-
- static _ECharT __first_or_null(const _ECharT* __b) { return *__b; }
-};
-
-template <class _Iter, bool _IsIt = __is_input_iterator<_Iter>::value,
- class = void>
-struct __is_pathable_iter : false_type {};
-
-template <class _Iter>
-struct __is_pathable_iter<
- _Iter, true,
- _Void<typename __can_convert_char<
- typename iterator_traits<_Iter>::value_type>::__char_type> >
- : __can_convert_char<typename iterator_traits<_Iter>::value_type> {
- using _ECharT = typename iterator_traits<_Iter>::value_type;
- using _Base = __can_convert_char<_ECharT>;
-
- static _Iter __range_begin(_Iter __b) { return __b; }
- static _NullSentinal __range_end(_Iter) { return _NullSentinal{}; }
-
- static _ECharT __first_or_null(_Iter __b) { return *__b; }
-};
-
-template <class _Tp, bool _IsStringT = __is_pathable_string<_Tp>::value,
- bool _IsCharIterT = __is_pathable_char_array<_Tp>::value,
- bool _IsIterT = !_IsCharIterT && __is_pathable_iter<_Tp>::value>
-struct __is_pathable : false_type {
- static_assert(!_IsStringT && !_IsCharIterT && !_IsIterT, "Must all be false");
-};
-
-template <class _Tp>
-struct __is_pathable<_Tp, true, false, false> : __is_pathable_string<_Tp> {};
-
-template <class _Tp>
-struct __is_pathable<_Tp, false, true, false> : __is_pathable_char_array<_Tp> {
-};
-
-template <class _Tp>
-struct __is_pathable<_Tp, false, false, true> : __is_pathable_iter<_Tp> {};
-
-template <class _ECharT>
-struct _PathCVT {
- static_assert(__can_convert_char<_ECharT>::value,
- "Char type not convertible");
-
- typedef __narrow_to_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Narrower;
-
- static void __append_range(string& __dest, _ECharT const* __b,
- _ECharT const* __e) {
- _Narrower()(back_inserter(__dest), __b, __e);
- }
-
- template <class _Iter>
- static void __append_range(string& __dest, _Iter __b, _Iter __e) {
- static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
- if (__b == __e)
- return;
- basic_string<_ECharT> __tmp(__b, __e);
- _Narrower()(back_inserter(__dest), __tmp.data(),
- __tmp.data() + __tmp.length());
- }
-
- template <class _Iter>
- static void __append_range(string& __dest, _Iter __b, _NullSentinal) {
- static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
- const _ECharT __sentinal = _ECharT{};
- if (*__b == __sentinal)
- return;
- basic_string<_ECharT> __tmp;
- for (; *__b != __sentinal; ++__b)
- __tmp.push_back(*__b);
- _Narrower()(back_inserter(__dest), __tmp.data(),
- __tmp.data() + __tmp.length());
- }
-
- template <class _Source>
- static void __append_source(string& __dest, _Source const& __s) {
- using _Traits = __is_pathable<_Source>;
- __append_range(__dest, _Traits::__range_begin(__s),
- _Traits::__range_end(__s));
- }
-};
-
-template <>
-struct _PathCVT<char> {
-
- template <class _Iter>
- static typename enable_if<__is_exactly_input_iterator<_Iter>::value>::type
- __append_range(string& __dest, _Iter __b, _Iter __e) {
- for (; __b != __e; ++__b)
- __dest.push_back(*__b);
- }
-
- template <class _Iter>
- static typename enable_if<__is_forward_iterator<_Iter>::value>::type
- __append_range(string& __dest, _Iter __b, _Iter __e) {
- __dest.__append_forward_unsafe(__b, __e);
- }
-
- template <class _Iter>
- static void __append_range(string& __dest, _Iter __b, _NullSentinal) {
- const char __sentinal = char{};
- for (; *__b != __sentinal; ++__b)
- __dest.push_back(*__b);
- }
-
- template <class _Source>
- static void __append_source(string& __dest, _Source const& __s) {
- using _Traits = __is_pathable<_Source>;
- __append_range(__dest, _Traits::__range_begin(__s),
- _Traits::__range_end(__s));
- }
-};
-
-class _LIBCPP_TYPE_VIS path {
- template <class _SourceOrIter, class _Tp = path&>
- using _EnableIfPathable =
- typename enable_if<__is_pathable<_SourceOrIter>::value, _Tp>::type;
-
- template <class _Tp>
- using _SourceChar = typename __is_pathable<_Tp>::__char_type;
-
- template <class _Tp>
- using _SourceCVT = _PathCVT<_SourceChar<_Tp> >;
-
-public:
- typedef char value_type;
- typedef basic_string<value_type> string_type;
- typedef _VSTD::string_view __string_view;
- static constexpr value_type preferred_separator = '/';
-
- enum class _LIBCPP_ENUM_VIS format : unsigned char {
- auto_format,
- native_format,
- generic_format
- };
-
- // constructors and destructor
- _LIBCPP_INLINE_VISIBILITY path() noexcept {}
- _LIBCPP_INLINE_VISIBILITY path(const path& __p) : __pn_(__p.__pn_) {}
- _LIBCPP_INLINE_VISIBILITY path(path&& __p) noexcept
- : __pn_(_VSTD::move(__p.__pn_)) {}
-
- _LIBCPP_INLINE_VISIBILITY
- path(string_type&& __s, format = format::auto_format) noexcept
- : __pn_(_VSTD::move(__s)) {}
-
- template <class _Source, class = _EnableIfPathable<_Source, void> >
- path(const _Source& __src, format = format::auto_format) {
- _SourceCVT<_Source>::__append_source(__pn_, __src);
- }
-
- template <class _InputIt>
- path(_InputIt __first, _InputIt __last, format = format::auto_format) {
- typedef typename iterator_traits<_InputIt>::value_type _ItVal;
- _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
- }
-
- // TODO Implement locale conversions.
- template <class _Source, class = _EnableIfPathable<_Source, void> >
- path(const _Source& __src, const locale& __loc, format = format::auto_format);
- template <class _InputIt>
- path(_InputIt __first, _InputIt _last, const locale& __loc,
- format = format::auto_format);
-
- _LIBCPP_INLINE_VISIBILITY
- ~path() = default;
-
- // assignments
- _LIBCPP_INLINE_VISIBILITY
- path& operator=(const path& __p) {
- __pn_ = __p.__pn_;
- return *this;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- path& operator=(path&& __p) noexcept {
- __pn_ = _VSTD::move(__p.__pn_);
- return *this;
- }
-
- template <class = void>
- _LIBCPP_INLINE_VISIBILITY path& operator=(string_type&& __s) noexcept {
- __pn_ = _VSTD::move(__s);
- return *this;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- path& assign(string_type&& __s) noexcept {
- __pn_ = _VSTD::move(__s);
- return *this;
- }
-
- template <class _Source>
- _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source>
- operator=(const _Source& __src) {
- return this->assign(__src);
- }
-
- template <class _Source>
- _EnableIfPathable<_Source> assign(const _Source& __src) {
- __pn_.clear();
- _SourceCVT<_Source>::__append_source(__pn_, __src);
- return *this;
- }
-
- template <class _InputIt>
- path& assign(_InputIt __first, _InputIt __last) {
- typedef typename iterator_traits<_InputIt>::value_type _ItVal;
- __pn_.clear();
- _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
- return *this;
- }
-
-private:
- template <class _ECharT>
- static bool __source_is_absolute(_ECharT __first_or_null) {
- return __is_separator(__first_or_null);
- }
-
-public:
- // appends
- path& operator/=(const path& __p) {
- if (__p.is_absolute()) {
- __pn_ = __p.__pn_;
- return *this;
- }
- if (has_filename())
- __pn_ += preferred_separator;
- __pn_ += __p.native();
- return *this;
- }
-
- // FIXME: Use _LIBCPP_DIAGNOSE_WARNING to produce a diagnostic when __src
- // is known at compile time to be "/' since the user almost certainly intended
- // to append a separator instead of overwriting the path with "/"
- template <class _Source>
- _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source>
- operator/=(const _Source& __src) {
- return this->append(__src);
- }
-
- template <class _Source>
- _EnableIfPathable<_Source> append(const _Source& __src) {
- using _Traits = __is_pathable<_Source>;
- using _CVT = _PathCVT<_SourceChar<_Source> >;
- if (__source_is_absolute(_Traits::__first_or_null(__src)))
- __pn_.clear();
- else if (has_filename())
- __pn_ += preferred_separator;
- _CVT::__append_source(__pn_, __src);
- return *this;
- }
-
- template <class _InputIt>
- path& append(_InputIt __first, _InputIt __last) {
- typedef typename iterator_traits<_InputIt>::value_type _ItVal;
- static_assert(__can_convert_char<_ItVal>::value, "Must convertible");
- using _CVT = _PathCVT<_ItVal>;
- if (__first != __last && __source_is_absolute(*__first))
- __pn_.clear();
- else if (has_filename())
- __pn_ += preferred_separator;
- _CVT::__append_range(__pn_, __first, __last);
- return *this;
- }
-
- // concatenation
- _LIBCPP_INLINE_VISIBILITY
- path& operator+=(const path& __x) {
- __pn_ += __x.__pn_;
- return *this;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- path& operator+=(const string_type& __x) {
- __pn_ += __x;
- return *this;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- path& operator+=(__string_view __x) {
- __pn_ += __x;
- return *this;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- path& operator+=(const value_type* __x) {
- __pn_ += __x;
- return *this;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- path& operator+=(value_type __x) {
- __pn_ += __x;
- return *this;
- }
-
- template <class _ECharT>
- typename enable_if<__can_convert_char<_ECharT>::value, path&>::type
- operator+=(_ECharT __x) {
- basic_string<_ECharT> __tmp;
- __tmp += __x;
- _PathCVT<_ECharT>::__append_source(__pn_, __tmp);
- return *this;
- }
-
- template <class _Source>
- _EnableIfPathable<_Source> operator+=(const _Source& __x) {
- return this->concat(__x);
- }
-
- template <class _Source>
- _EnableIfPathable<_Source> concat(const _Source& __x) {
- _SourceCVT<_Source>::__append_source(__pn_, __x);
- return *this;
- }
-
- template <class _InputIt>
- path& concat(_InputIt __first, _InputIt __last) {
- typedef typename iterator_traits<_InputIt>::value_type _ItVal;
- _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
- return *this;
- }
-
- // modifiers
- _LIBCPP_INLINE_VISIBILITY
- void clear() noexcept { __pn_.clear(); }
-
- path& make_preferred() { return *this; }
-
- _LIBCPP_INLINE_VISIBILITY
- path& remove_filename() {
- auto __fname = __filename();
- if (!__fname.empty())
- __pn_.erase(__fname.data() - __pn_.data());
- return *this;
- }
-
- path& replace_filename(const path& __replacement) {
- remove_filename();
- return (*this /= __replacement);
- }
-
- path& replace_extension(const path& __replacement = path());
-
- _LIBCPP_INLINE_VISIBILITY
- void swap(path& __rhs) noexcept { __pn_.swap(__rhs.__pn_); }
-
- // private helper to allow reserving memory in the path
- _LIBCPP_INLINE_VISIBILITY
- void __reserve(size_t __s) { __pn_.reserve(__s); }
-
- // native format observers
- _LIBCPP_INLINE_VISIBILITY
- const string_type& native() const noexcept { return __pn_; }
-
- _LIBCPP_INLINE_VISIBILITY
- const value_type* c_str() const noexcept { return __pn_.c_str(); }
-
- _LIBCPP_INLINE_VISIBILITY operator string_type() const { return __pn_; }
-
- template <class _ECharT, class _Traits = char_traits<_ECharT>,
- class _Allocator = allocator<_ECharT> >
- basic_string<_ECharT, _Traits, _Allocator>
- string(const _Allocator& __a = _Allocator()) const {
- using _CVT = __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__>;
- using _Str = basic_string<_ECharT, _Traits, _Allocator>;
- _Str __s(__a);
- __s.reserve(__pn_.size());
- _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
- return __s;
- }
-
- _LIBCPP_INLINE_VISIBILITY std::string string() const { return __pn_; }
- _LIBCPP_INLINE_VISIBILITY std::wstring wstring() const {
- return string<wchar_t>();
- }
- _LIBCPP_INLINE_VISIBILITY std::string u8string() const { return __pn_; }
- _LIBCPP_INLINE_VISIBILITY std::u16string u16string() const {
- return string<char16_t>();
- }
- _LIBCPP_INLINE_VISIBILITY std::u32string u32string() const {
- return string<char32_t>();
- }
-
- // generic format observers
- template <class _ECharT, class _Traits = char_traits<_ECharT>,
- class _Allocator = allocator<_ECharT> >
- basic_string<_ECharT, _Traits, _Allocator>
- generic_string(const _Allocator& __a = _Allocator()) const {
- return string<_ECharT, _Traits, _Allocator>(__a);
- }
-
- std::string generic_string() const { return __pn_; }
- std::wstring generic_wstring() const { return string<wchar_t>(); }
- std::string generic_u8string() const { return __pn_; }
- std::u16string generic_u16string() const { return string<char16_t>(); }
- std::u32string generic_u32string() const { return string<char32_t>(); }
-
-private:
- int __compare(__string_view) const;
- __string_view __root_name() const;
- __string_view __root_directory() const;
- __string_view __root_path_raw() const;
- __string_view __relative_path() const;
- __string_view __parent_path() const;
- __string_view __filename() const;
- __string_view __stem() const;
- __string_view __extension() const;
-
-public:
- // compare
- _LIBCPP_INLINE_VISIBILITY int compare(const path& __p) const noexcept {
- return __compare(__p.__pn_);
- }
- _LIBCPP_INLINE_VISIBILITY int compare(const string_type& __s) const {
- return __compare(__s);
- }
- _LIBCPP_INLINE_VISIBILITY int compare(__string_view __s) const {
- return __compare(__s);
- }
- _LIBCPP_INLINE_VISIBILITY int compare(const value_type* __s) const {
- return __compare(__s);
- }
-
- // decomposition
- _LIBCPP_INLINE_VISIBILITY path root_name() const {
- return string_type(__root_name());
- }
- _LIBCPP_INLINE_VISIBILITY path root_directory() const {
- return string_type(__root_directory());
- }
- _LIBCPP_INLINE_VISIBILITY path root_path() const {
- return root_name().append(string_type(__root_directory()));
- }
- _LIBCPP_INLINE_VISIBILITY path relative_path() const {
- return string_type(__relative_path());
- }
- _LIBCPP_INLINE_VISIBILITY path parent_path() const {
- return string_type(__parent_path());
- }
- _LIBCPP_INLINE_VISIBILITY path filename() const {
- return string_type(__filename());
- }
- _LIBCPP_INLINE_VISIBILITY path stem() const { return string_type(__stem()); }
- _LIBCPP_INLINE_VISIBILITY path extension() const {
- return string_type(__extension());
- }
-
- // query
- _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY bool
- empty() const noexcept {
- return __pn_.empty();
- }
-
- _LIBCPP_INLINE_VISIBILITY bool has_root_name() const {
- return !__root_name().empty();
- }
- _LIBCPP_INLINE_VISIBILITY bool has_root_directory() const {
- return !__root_directory().empty();
- }
- _LIBCPP_INLINE_VISIBILITY bool has_root_path() const {
- return !__root_path_raw().empty();
- }
- _LIBCPP_INLINE_VISIBILITY bool has_relative_path() const {
- return !__relative_path().empty();
- }
- _LIBCPP_INLINE_VISIBILITY bool has_parent_path() const {
- return !__parent_path().empty();
- }
- _LIBCPP_INLINE_VISIBILITY bool has_filename() const {
- return !__filename().empty();
- }
- _LIBCPP_INLINE_VISIBILITY bool has_stem() const { return !__stem().empty(); }
- _LIBCPP_INLINE_VISIBILITY bool has_extension() const {
- return !__extension().empty();
- }
-
- _LIBCPP_INLINE_VISIBILITY bool is_absolute() const {
- return has_root_directory();
- }
- _LIBCPP_INLINE_VISIBILITY bool is_relative() const { return !is_absolute(); }
-
- // relative paths
- path lexically_normal() const;
- path lexically_relative(const path& __base) const;
-
- _LIBCPP_INLINE_VISIBILITY path lexically_proximate(const path& __base) const {
- path __result = this->lexically_relative(__base);
- if (__result.native().empty())
- return *this;
- return __result;
- }
-
- // iterators
- class _LIBCPP_TYPE_VIS iterator;
- typedef iterator const_iterator;
-
- iterator begin() const;
- iterator end() const;
-
- template <class _CharT, class _Traits>
- _LIBCPP_INLINE_VISIBILITY friend
- typename enable_if<is_same<_CharT, char>::value &&
- is_same<_Traits, char_traits<char> >::value,
- basic_ostream<_CharT, _Traits>&>::type
- operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
- __os << std::__quoted(__p.native());
- return __os;
- }
-
- template <class _CharT, class _Traits>
- _LIBCPP_INLINE_VISIBILITY friend
- typename enable_if<!is_same<_CharT, char>::value ||
- !is_same<_Traits, char_traits<char> >::value,
- basic_ostream<_CharT, _Traits>&>::type
- operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
- __os << std::__quoted(__p.string<_CharT, _Traits>());
- return __os;
- }
-
- template <class _CharT, class _Traits>
- _LIBCPP_INLINE_VISIBILITY friend basic_istream<_CharT, _Traits>&
- operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) {
- basic_string<_CharT, _Traits> __tmp;
- __is >> __quoted(__tmp);
- __p = __tmp;
- return __is;
- }
-
- friend _LIBCPP_INLINE_VISIBILITY bool operator==(const path& __lhs, const path& __rhs) noexcept {
- return __lhs.compare(__rhs) == 0;
- }
- friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const path& __lhs, const path& __rhs) noexcept {
- return __lhs.compare(__rhs) != 0;
- }
- friend _LIBCPP_INLINE_VISIBILITY bool operator<(const path& __lhs, const path& __rhs) noexcept {
- return __lhs.compare(__rhs) < 0;
- }
- friend _LIBCPP_INLINE_VISIBILITY bool operator<=(const path& __lhs, const path& __rhs) noexcept {
- return __lhs.compare(__rhs) <= 0;
- }
- friend _LIBCPP_INLINE_VISIBILITY bool operator>(const path& __lhs, const path& __rhs) noexcept {
- return __lhs.compare(__rhs) > 0;
- }
- friend _LIBCPP_INLINE_VISIBILITY bool operator>=(const path& __lhs, const path& __rhs) noexcept {
- return __lhs.compare(__rhs) >= 0;
- }
-
- friend _LIBCPP_INLINE_VISIBILITY path operator/(const path& __lhs,
- const path& __rhs) {
- path __result(__lhs);
- __result /= __rhs;
- return __result;
- }
-private:
- inline _LIBCPP_INLINE_VISIBILITY path&
- __assign_view(__string_view const& __s) noexcept {
- __pn_ = string_type(__s);
- return *this;
- }
- string_type __pn_;
-};
-
-inline _LIBCPP_INLINE_VISIBILITY void swap(path& __lhs, path& __rhs) noexcept {
- __lhs.swap(__rhs);
-}
-
-_LIBCPP_FUNC_VIS
-size_t hash_value(const path& __p) noexcept;
-
-template <class _Source>
-_LIBCPP_INLINE_VISIBILITY
- typename enable_if<__is_pathable<_Source>::value, path>::type
- u8path(const _Source& __s) {
- static_assert(
- is_same<typename __is_pathable<_Source>::__char_type, char>::value,
- "u8path(Source const&) requires Source have a character type of type "
- "'char'");
- return path(__s);
-}
-
-template <class _InputIt>
-_LIBCPP_INLINE_VISIBILITY
- typename enable_if<__is_pathable<_InputIt>::value, path>::type
- u8path(_InputIt __f, _InputIt __l) {
- static_assert(
- is_same<typename __is_pathable<_InputIt>::__char_type, char>::value,
- "u8path(Iter, Iter) requires Iter have a value_type of type 'char'");
- return path(__f, __l);
-}
-
-class _LIBCPP_TYPE_VIS path::iterator {
-public:
- enum _ParserState : unsigned char {
- _Singular,
- _BeforeBegin,
- _InRootName,
- _InRootDir,
- _InFilenames,
- _InTrailingSep,
- _AtEnd
- };
-
-public:
- typedef bidirectional_iterator_tag iterator_category;
-
- typedef path value_type;
- typedef std::ptrdiff_t difference_type;
- typedef const path* pointer;
- typedef const path& reference;
-
- typedef void
- __stashing_iterator_tag; // See reverse_iterator and __is_stashing_iterator
-
-public:
- _LIBCPP_INLINE_VISIBILITY
- iterator()
- : __stashed_elem_(), __path_ptr_(nullptr), __entry_(),
- __state_(_Singular) {}
-
- iterator(const iterator&) = default;
- ~iterator() = default;
-
- iterator& operator=(const iterator&) = default;
-
- _LIBCPP_INLINE_VISIBILITY
- reference operator*() const { return __stashed_elem_; }
-
- _LIBCPP_INLINE_VISIBILITY
- pointer operator->() const { return &__stashed_elem_; }
-
- _LIBCPP_INLINE_VISIBILITY
- iterator& operator++() {
- _LIBCPP_ASSERT(__state_ != _Singular,
- "attempting to increment a singular iterator");
- _LIBCPP_ASSERT(__state_ != _AtEnd,
- "attempting to increment the end iterator");
- return __increment();
- }
-
- _LIBCPP_INLINE_VISIBILITY
- iterator operator++(int) {
- iterator __it(*this);
- this->operator++();
- return __it;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- iterator& operator--() {
- _LIBCPP_ASSERT(__state_ != _Singular,
- "attempting to decrement a singular iterator");
- _LIBCPP_ASSERT(__entry_.data() != __path_ptr_->native().data(),
- "attempting to decrement the begin iterator");
- return __decrement();
- }
-
- _LIBCPP_INLINE_VISIBILITY
- iterator operator--(int) {
- iterator __it(*this);
- this->operator--();
- return __it;
- }
-
-private:
- friend class path;
-
- inline _LIBCPP_INLINE_VISIBILITY friend bool operator==(const iterator&,
- const iterator&);
-
- iterator& __increment();
- iterator& __decrement();
-
- path __stashed_elem_;
- const path* __path_ptr_;
- path::__string_view __entry_;
- _ParserState __state_;
-};
-
-inline _LIBCPP_INLINE_VISIBILITY bool operator==(const path::iterator& __lhs,
- const path::iterator& __rhs) {
- return __lhs.__path_ptr_ == __rhs.__path_ptr_ &&
- __lhs.__entry_.data() == __rhs.__entry_.data();
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const path::iterator& __lhs,
- const path::iterator& __rhs) {
- return !(__lhs == __rhs);
-}
-
-class _LIBCPP_EXCEPTION_ABI filesystem_error : public system_error {
-public:
- _LIBCPP_INLINE_VISIBILITY
- filesystem_error(const string& __what, error_code __ec)
- : system_error(__ec, __what),
- __storage_(make_shared<_Storage>(path(), path())) {
- __create_what(0);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- filesystem_error(const string& __what, const path& __p1, error_code __ec)
- : system_error(__ec, __what),
- __storage_(make_shared<_Storage>(__p1, path())) {
- __create_what(1);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- filesystem_error(const string& __what, const path& __p1, const path& __p2,
- error_code __ec)
- : system_error(__ec, __what),
- __storage_(make_shared<_Storage>(__p1, __p2)) {
- __create_what(2);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- const path& path1() const noexcept { return __storage_->__p1_; }
-
- _LIBCPP_INLINE_VISIBILITY
- const path& path2() const noexcept { return __storage_->__p2_; }
-
- ~filesystem_error() override; // key function
-
- _LIBCPP_INLINE_VISIBILITY
- const char* what() const noexcept override {
- return __storage_->__what_.c_str();
- }
-
- _LIBCPP_FUNC_VIS
- void __create_what(int __num_paths);
-
-private:
- struct _Storage {
- _LIBCPP_INLINE_VISIBILITY
- _Storage(const path& __p1, const path& __p2) : __p1_(__p1), __p2_(__p2) {}
-
- path __p1_;
- path __p2_;
- string __what_;
- };
- shared_ptr<_Storage> __storage_;
-};
-
-template <class... _Args>
-_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY
-#ifndef _LIBCPP_NO_EXCEPTIONS
- void
- __throw_filesystem_error(_Args&&... __args) {
- throw filesystem_error(std::forward<_Args>(__args)...);
-}
-#else
- void
- __throw_filesystem_error(_Args&&...) {
- _VSTD::abort();
-}
-#endif
-
-// operational functions
-
-_LIBCPP_FUNC_VIS
-path __absolute(const path&, error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-path __canonical(const path&, error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-void __copy(const path& __from, const path& __to, copy_options __opt,
- error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-bool __copy_file(const path& __from, const path& __to, copy_options __opt,
- error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-void __copy_symlink(const path& __existing_symlink, const path& __new_symlink,
- error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-bool __create_directories(const path& p, error_code* ec = nullptr);
-_LIBCPP_FUNC_VIS
-bool __create_directory(const path& p, error_code* ec = nullptr);
-_LIBCPP_FUNC_VIS
-bool __create_directory(const path& p, const path& attributes,
- error_code* ec = nullptr);
-_LIBCPP_FUNC_VIS
-void __create_directory_symlink(const path& __to, const path& __new_symlink,
- error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-void __create_hard_link(const path& __to, const path& __new_hard_link,
- error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-void __create_symlink(const path& __to, const path& __new_symlink,
- error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-path __current_path(error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-void __current_path(const path&, error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-bool __equivalent(const path&, const path&, error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-uintmax_t __file_size(const path&, error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-uintmax_t __hard_link_count(const path&, error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-bool __fs_is_empty(const path& p, error_code* ec = nullptr);
-_LIBCPP_FUNC_VIS
-file_time_type __last_write_time(const path& p, error_code* ec = nullptr);
-_LIBCPP_FUNC_VIS
-void __last_write_time(const path& p, file_time_type new_time,
- error_code* ec = nullptr);
-_LIBCPP_FUNC_VIS
-void __permissions(const path&, perms, perm_options, error_code* = nullptr);
-_LIBCPP_FUNC_VIS
-path __read_symlink(const path& p, error_code* ec = nullptr);
-_LIBCPP_FUNC_VIS
-bool __remove(const path& p, error_code* ec = nullptr);
-_LIBCPP_FUNC_VIS
-uintmax_t __remove_all(const path& p, error_code* ec = nullptr);
-_LIBCPP_FUNC_VIS
-void __rename(const path& from, const path& to, error_code* ec = nullptr);
-_LIBCPP_FUNC_VIS
-void __resize_file(const path& p, uintmax_t size, error_code* ec = nullptr);
-_LIBCPP_FUNC_VIS
-space_info __space(const path&, error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-file_status __status(const path&, error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-file_status __symlink_status(const path&, error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-path __system_complete(const path&, error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-path __temp_directory_path(error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-path __weakly_canonical(path const& __p, error_code* __ec = nullptr);
-
-inline _LIBCPP_INLINE_VISIBILITY path current_path() {
- return __current_path();
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path current_path(error_code& __ec) {
- return __current_path(&__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void current_path(const path& __p) {
- __current_path(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void current_path(const path& __p,
- error_code& __ec) noexcept {
- __current_path(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path absolute(const path& __p) {
- return __absolute(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path absolute(const path& __p,
- error_code& __ec) {
- return __absolute(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path canonical(const path& __p) {
- return __canonical(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path canonical(const path& __p,
- error_code& __ec) {
- return __canonical(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from,
- const path& __to) {
- __copy(__from, __to, copy_options::none);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
- error_code& __ec) {
- __copy(__from, __to, copy_options::none, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
- copy_options __opt) {
- __copy(__from, __to, __opt);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
- copy_options __opt,
- error_code& __ec) {
- __copy(__from, __to, __opt, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from,
- const path& __to) {
- return __copy_file(__from, __to, copy_options::none);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool
-copy_file(const path& __from, const path& __to, error_code& __ec) {
- return __copy_file(__from, __to, copy_options::none, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool
-copy_file(const path& __from, const path& __to, copy_options __opt) {
- return __copy_file(__from, __to, __opt);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from,
- const path& __to,
- copy_options __opt,
- error_code& __ec) {
- return __copy_file(__from, __to, __opt, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void copy_symlink(const path& __existing,
- const path& __new) {
- __copy_symlink(__existing, __new);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void
-copy_symlink(const path& __ext, const path& __new, error_code& __ec) noexcept {
- __copy_symlink(__ext, __new, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool create_directories(const path& __p) {
- return __create_directories(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool create_directories(const path& __p,
- error_code& __ec) {
- return __create_directories(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p) {
- return __create_directory(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool
-create_directory(const path& __p, error_code& __ec) noexcept {
- return __create_directory(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p,
- const path& __attrs) {
- return __create_directory(__p, __attrs);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool
-create_directory(const path& __p, const path& __attrs,
- error_code& __ec) noexcept {
- return __create_directory(__p, __attrs, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void
-create_directory_symlink(const path& __to, const path& __new) {
- __create_directory_symlink(__to, __new);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void
-create_directory_symlink(const path& __to, const path& __new,
- error_code& __ec) noexcept {
- __create_directory_symlink(__to, __new, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void create_hard_link(const path& __to,
- const path& __new) {
- __create_hard_link(__to, __new);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void
-create_hard_link(const path& __to, const path& __new,
- error_code& __ec) noexcept {
- __create_hard_link(__to, __new, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void create_symlink(const path& __to,
- const path& __new) {
- __create_symlink(__to, __new);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void
-create_symlink(const path& __to, const path& __new, error_code& __ec) noexcept {
- return __create_symlink(__to, __new, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool status_known(file_status __s) noexcept {
- return __s.type() != file_type::none;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool exists(file_status __s) noexcept {
- return status_known(__s) && __s.type() != file_type::not_found;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool exists(const path& __p) {
- return exists(__status(__p));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool exists(const path& __p,
- error_code& __ec) noexcept {
- auto __s = __status(__p, &__ec);
- if (status_known(__s))
- __ec.clear();
- return exists(__s);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool equivalent(const path& __p1,
- const path& __p2) {
- return __equivalent(__p1, __p2);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool
-equivalent(const path& __p1, const path& __p2, error_code& __ec) noexcept {
- return __equivalent(__p1, __p2, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY uintmax_t file_size(const path& __p) {
- return __file_size(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY uintmax_t
-file_size(const path& __p, error_code& __ec) noexcept {
- return __file_size(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY uintmax_t hard_link_count(const path& __p) {
- return __hard_link_count(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY uintmax_t
-hard_link_count(const path& __p, error_code& __ec) noexcept {
- return __hard_link_count(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(file_status __s) noexcept {
- return __s.type() == file_type::block;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(const path& __p) {
- return is_block_file(__status(__p));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(const path& __p,
- error_code& __ec) noexcept {
- return is_block_file(__status(__p, &__ec));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool
-is_character_file(file_status __s) noexcept {
- return __s.type() == file_type::character;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_character_file(const path& __p) {
- return is_character_file(__status(__p));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool
-is_character_file(const path& __p, error_code& __ec) noexcept {
- return is_character_file(__status(__p, &__ec));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_directory(file_status __s) noexcept {
- return __s.type() == file_type::directory;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_directory(const path& __p) {
- return is_directory(__status(__p));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_directory(const path& __p,
- error_code& __ec) noexcept {
- return is_directory(__status(__p, &__ec));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_empty(const path& __p) {
- return __fs_is_empty(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_empty(const path& __p,
- error_code& __ec) {
- return __fs_is_empty(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(file_status __s) noexcept {
- return __s.type() == file_type::fifo;
-}
-inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(const path& __p) {
- return is_fifo(__status(__p));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(const path& __p,
- error_code& __ec) noexcept {
- return is_fifo(__status(__p, &__ec));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool
-is_regular_file(file_status __s) noexcept {
- return __s.type() == file_type::regular;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_regular_file(const path& __p) {
- return is_regular_file(__status(__p));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool
-is_regular_file(const path& __p, error_code& __ec) noexcept {
- return is_regular_file(__status(__p, &__ec));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_socket(file_status __s) noexcept {
- return __s.type() == file_type::socket;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_socket(const path& __p) {
- return is_socket(__status(__p));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_socket(const path& __p,
- error_code& __ec) noexcept {
- return is_socket(__status(__p, &__ec));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(file_status __s) noexcept {
- return __s.type() == file_type::symlink;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(const path& __p) {
- return is_symlink(__symlink_status(__p));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(const path& __p,
- error_code& __ec) noexcept {
- return is_symlink(__symlink_status(__p, &__ec));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_other(file_status __s) noexcept {
- return exists(__s) && !is_regular_file(__s) && !is_directory(__s) &&
- !is_symlink(__s);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_other(const path& __p) {
- return is_other(__status(__p));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_other(const path& __p,
- error_code& __ec) noexcept {
- return is_other(__status(__p, &__ec));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY file_time_type
-last_write_time(const path& __p) {
- return __last_write_time(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY file_time_type
-last_write_time(const path& __p, error_code& __ec) noexcept {
- return __last_write_time(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void last_write_time(const path& __p,
- file_time_type __t) {
- __last_write_time(__p, __t);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void
-last_write_time(const path& __p, file_time_type __t,
- error_code& __ec) noexcept {
- __last_write_time(__p, __t, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void
-permissions(const path& __p, perms __prms,
- perm_options __opts = perm_options::replace) {
- __permissions(__p, __prms, __opts);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void permissions(const path& __p, perms __prms,
- error_code& __ec) noexcept {
- __permissions(__p, __prms, perm_options::replace, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void permissions(const path& __p, perms __prms,
- perm_options __opts,
- error_code& __ec) {
- __permissions(__p, __prms, __opts, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path proximate(const path& __p,
- const path& __base,
- error_code& __ec) {
- path __tmp = __weakly_canonical(__p, &__ec);
- if (__ec)
- return {};
- path __tmp_base = __weakly_canonical(__base, &__ec);
- if (__ec)
- return {};
- return __tmp.lexically_proximate(__tmp_base);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path proximate(const path& __p,
- error_code& __ec) {
- return proximate(__p, current_path(), __ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path
-proximate(const path& __p, const path& __base = current_path()) {
- return __weakly_canonical(__p).lexically_proximate(
- __weakly_canonical(__base));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path read_symlink(const path& __p) {
- return __read_symlink(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path read_symlink(const path& __p,
- error_code& __ec) {
- return __read_symlink(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path relative(const path& __p,
- const path& __base,
- error_code& __ec) {
- path __tmp = __weakly_canonical(__p, &__ec);
- if (__ec)
- return path();
- path __tmpbase = __weakly_canonical(__base, &__ec);
- if (__ec)
- return path();
- return __tmp.lexically_relative(__tmpbase);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path relative(const path& __p,
- error_code& __ec) {
- return relative(__p, current_path(), __ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path
-relative(const path& __p, const path& __base = current_path()) {
- return __weakly_canonical(__p).lexically_relative(__weakly_canonical(__base));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool remove(const path& __p) {
- return __remove(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool remove(const path& __p,
- error_code& __ec) noexcept {
- return __remove(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY uintmax_t remove_all(const path& __p) {
- return __remove_all(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY uintmax_t remove_all(const path& __p,
- error_code& __ec) {
- return __remove_all(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void rename(const path& __from,
- const path& __to) {
- return __rename(__from, __to);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void
-rename(const path& __from, const path& __to, error_code& __ec) noexcept {
- return __rename(__from, __to, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void resize_file(const path& __p,
- uintmax_t __ns) {
- return __resize_file(__p, __ns);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void
-resize_file(const path& __p, uintmax_t __ns, error_code& __ec) noexcept {
- return __resize_file(__p, __ns, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY space_info space(const path& __p) {
- return __space(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY space_info space(const path& __p,
- error_code& __ec) noexcept {
- return __space(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY file_status status(const path& __p) {
- return __status(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY file_status status(const path& __p,
- error_code& __ec) noexcept {
- return __status(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY file_status symlink_status(const path& __p) {
- return __symlink_status(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY file_status
-symlink_status(const path& __p, error_code& __ec) noexcept {
- return __symlink_status(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path temp_directory_path() {
- return __temp_directory_path();
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path temp_directory_path(error_code& __ec) {
- return __temp_directory_path(&__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path weakly_canonical(path const& __p) {
- return __weakly_canonical(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path weakly_canonical(path const& __p,
- error_code& __ec) {
- return __weakly_canonical(__p, &__ec);
-}
-
-class directory_iterator;
-class recursive_directory_iterator;
-class __dir_stream;
-
-class directory_entry {
- typedef _VSTD_FS::path _Path;
-
-public:
- // constructors and destructors
- directory_entry() noexcept = default;
- directory_entry(directory_entry const&) = default;
- directory_entry(directory_entry&&) noexcept = default;
-
- _LIBCPP_INLINE_VISIBILITY
- explicit directory_entry(_Path const& __p) : __p_(__p) {
- error_code __ec;
- __refresh(&__ec);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- directory_entry(_Path const& __p, error_code& __ec) : __p_(__p) {
- __refresh(&__ec);
- }
-
- ~directory_entry() {}
-
- directory_entry& operator=(directory_entry const&) = default;
- directory_entry& operator=(directory_entry&&) noexcept = default;
-
- _LIBCPP_INLINE_VISIBILITY
- void assign(_Path const& __p) {
- __p_ = __p;
- error_code __ec;
- __refresh(&__ec);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- void assign(_Path const& __p, error_code& __ec) {
- __p_ = __p;
- __refresh(&__ec);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- void replace_filename(_Path const& __p) {
- __p_.replace_filename(__p);
- error_code __ec;
- __refresh(&__ec);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- void replace_filename(_Path const& __p, error_code& __ec) {
- __p_ = __p_.parent_path() / __p;
- __refresh(&__ec);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- void refresh() { __refresh(); }
-
- _LIBCPP_INLINE_VISIBILITY
- void refresh(error_code& __ec) noexcept { __refresh(&__ec); }
-
- _LIBCPP_INLINE_VISIBILITY
- _Path const& path() const noexcept { return __p_; }
-
- _LIBCPP_INLINE_VISIBILITY
- operator const _Path&() const noexcept { return __p_; }
-
- _LIBCPP_INLINE_VISIBILITY
- bool exists() const { return _VSTD_FS::exists(file_status{__get_ft()}); }
-
- _LIBCPP_INLINE_VISIBILITY
- bool exists(error_code& __ec) const noexcept {
- return _VSTD_FS::exists(file_status{__get_ft(&__ec)});
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_block_file() const { return __get_ft() == file_type::block; }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_block_file(error_code& __ec) const noexcept {
- return __get_ft(&__ec) == file_type::block;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_character_file() const { return __get_ft() == file_type::character; }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_character_file(error_code& __ec) const noexcept {
- return __get_ft(&__ec) == file_type::character;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_directory() const { return __get_ft() == file_type::directory; }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_directory(error_code& __ec) const noexcept {
- return __get_ft(&__ec) == file_type::directory;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_fifo() const { return __get_ft() == file_type::fifo; }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_fifo(error_code& __ec) const noexcept {
- return __get_ft(&__ec) == file_type::fifo;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_other() const { return _VSTD_FS::is_other(file_status{__get_ft()}); }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_other(error_code& __ec) const noexcept {
- return _VSTD_FS::is_other(file_status{__get_ft(&__ec)});
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_regular_file() const { return __get_ft() == file_type::regular; }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_regular_file(error_code& __ec) const noexcept {
- return __get_ft(&__ec) == file_type::regular;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_socket() const { return __get_ft() == file_type::socket; }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_socket(error_code& __ec) const noexcept {
- return __get_ft(&__ec) == file_type::socket;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_symlink() const { return __get_sym_ft() == file_type::symlink; }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_symlink(error_code& __ec) const noexcept {
- return __get_sym_ft(&__ec) == file_type::symlink;
- }
- _LIBCPP_INLINE_VISIBILITY
- uintmax_t file_size() const { return __get_size(); }
-
- _LIBCPP_INLINE_VISIBILITY
- uintmax_t file_size(error_code& __ec) const noexcept {
- return __get_size(&__ec);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- uintmax_t hard_link_count() const { return __get_nlink(); }
-
- _LIBCPP_INLINE_VISIBILITY
- uintmax_t hard_link_count(error_code& __ec) const noexcept {
- return __get_nlink(&__ec);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- file_time_type last_write_time() const { return __get_write_time(); }
-
- _LIBCPP_INLINE_VISIBILITY
- file_time_type last_write_time(error_code& __ec) const noexcept {
- return __get_write_time(&__ec);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- file_status status() const { return __get_status(); }
-
- _LIBCPP_INLINE_VISIBILITY
- file_status status(error_code& __ec) const noexcept {
- return __get_status(&__ec);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- file_status symlink_status() const { return __get_symlink_status(); }
-
- _LIBCPP_INLINE_VISIBILITY
- file_status symlink_status(error_code& __ec) const noexcept {
- return __get_symlink_status(&__ec);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool operator<(directory_entry const& __rhs) const noexcept {
- return __p_ < __rhs.__p_;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool operator==(directory_entry const& __rhs) const noexcept {
- return __p_ == __rhs.__p_;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool operator!=(directory_entry const& __rhs) const noexcept {
- return __p_ != __rhs.__p_;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool operator<=(directory_entry const& __rhs) const noexcept {
- return __p_ <= __rhs.__p_;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool operator>(directory_entry const& __rhs) const noexcept {
- return __p_ > __rhs.__p_;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool operator>=(directory_entry const& __rhs) const noexcept {
- return __p_ >= __rhs.__p_;
- }
-
-private:
- friend class directory_iterator;
- friend class recursive_directory_iterator;
- friend class __dir_stream;
-
- enum _CacheType : unsigned char {
- _Empty,
- _IterSymlink,
- _IterNonSymlink,
- _RefreshSymlink,
- _RefreshSymlinkUnresolved,
- _RefreshNonSymlink
- };
-
- struct __cached_data {
- uintmax_t __size_;
- uintmax_t __nlink_;
- file_time_type __write_time_;
- perms __sym_perms_;
- perms __non_sym_perms_;
- file_type __type_;
- _CacheType __cache_type_;
-
- _LIBCPP_INLINE_VISIBILITY
- __cached_data() noexcept { __reset(); }
-
- _LIBCPP_INLINE_VISIBILITY
- void __reset() {
- __cache_type_ = _Empty;
- __type_ = file_type::none;
- __sym_perms_ = __non_sym_perms_ = perms::unknown;
- __size_ = __nlink_ = uintmax_t(-1);
- __write_time_ = file_time_type::min();
- }
- };
-
- _LIBCPP_INLINE_VISIBILITY
- static __cached_data __create_iter_result(file_type __ft) {
- __cached_data __data;
- __data.__type_ = __ft;
- __data.__cache_type_ = [&]() {
- switch (__ft) {
- case file_type::none:
- return _Empty;
- case file_type::symlink:
- return _IterSymlink;
- default:
- return _IterNonSymlink;
- }
- }();
- return __data;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- void __assign_iter_entry(_Path&& __p, __cached_data __dt) {
- __p_ = std::move(__p);
- __data_ = __dt;
- }
-
- _LIBCPP_FUNC_VIS
- error_code __do_refresh() noexcept;
-
- _LIBCPP_INLINE_VISIBILITY
- static bool __is_dne_error(error_code const& __ec) {
- if (!__ec)
- return true;
- switch (static_cast<errc>(__ec.value())) {
- case errc::no_such_file_or_directory:
- case errc::not_a_directory:
- return true;
- default:
- return false;
- }
- }
-
- _LIBCPP_INLINE_VISIBILITY
- void __handle_error(const char* __msg, error_code* __dest_ec,
- error_code const& __ec, bool __allow_dne = false) const {
- if (__dest_ec) {
- *__dest_ec = __ec;
- return;
- }
- if (__ec && (!__allow_dne || !__is_dne_error(__ec)))
- __throw_filesystem_error(__msg, __p_, __ec);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- void __refresh(error_code* __ec = nullptr) {
- __handle_error("in directory_entry::refresh", __ec, __do_refresh(),
- /*allow_dne*/ true);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- file_type __get_sym_ft(error_code* __ec = nullptr) const {
- switch (__data_.__cache_type_) {
- case _Empty:
- return __symlink_status(__p_, __ec).type();
- case _IterSymlink:
- case _RefreshSymlink:
- case _RefreshSymlinkUnresolved:
- if (__ec)
- __ec->clear();
- return file_type::symlink;
- case _IterNonSymlink:
- case _RefreshNonSymlink:
- file_status __st(__data_.__type_);
- if (__ec && !_VSTD_FS::exists(__st))
- *__ec = make_error_code(errc::no_such_file_or_directory);
- else if (__ec)
- __ec->clear();
- return __data_.__type_;
- }
- _LIBCPP_UNREACHABLE();
- }
-
- _LIBCPP_INLINE_VISIBILITY
- file_type __get_ft(error_code* __ec = nullptr) const {
- switch (__data_.__cache_type_) {
- case _Empty:
- case _IterSymlink:
- case _RefreshSymlinkUnresolved:
- return __status(__p_, __ec).type();
- case _IterNonSymlink:
- case _RefreshNonSymlink:
- case _RefreshSymlink: {
- file_status __st(__data_.__type_);
- if (__ec && !_VSTD_FS::exists(__st))
- *__ec = make_error_code(errc::no_such_file_or_directory);
- else if (__ec)
- __ec->clear();
- return __data_.__type_;
- }
- }
- _LIBCPP_UNREACHABLE();
- }
-
- _LIBCPP_INLINE_VISIBILITY
- file_status __get_status(error_code* __ec = nullptr) const {
- switch (__data_.__cache_type_) {
- case _Empty:
- case _IterNonSymlink:
- case _IterSymlink:
- case _RefreshSymlinkUnresolved:
- return __status(__p_, __ec);
- case _RefreshNonSymlink:
- case _RefreshSymlink:
- return file_status(__get_ft(__ec), __data_.__non_sym_perms_);
- }
- _LIBCPP_UNREACHABLE();
- }
-
- _LIBCPP_INLINE_VISIBILITY
- file_status __get_symlink_status(error_code* __ec = nullptr) const {
- switch (__data_.__cache_type_) {
- case _Empty:
- case _IterNonSymlink:
- case _IterSymlink:
- return __symlink_status(__p_, __ec);
- case _RefreshNonSymlink:
- return file_status(__get_sym_ft(__ec), __data_.__non_sym_perms_);
- case _RefreshSymlink:
- case _RefreshSymlinkUnresolved:
- return file_status(__get_sym_ft(__ec), __data_.__sym_perms_);
- }
- _LIBCPP_UNREACHABLE();
- }
-
- _LIBCPP_INLINE_VISIBILITY
- uintmax_t __get_size(error_code* __ec = nullptr) const {
- switch (__data_.__cache_type_) {
- case _Empty:
- case _IterNonSymlink:
- case _IterSymlink:
- case _RefreshSymlinkUnresolved:
- return _VSTD_FS::__file_size(__p_, __ec);
- case _RefreshSymlink:
- case _RefreshNonSymlink: {
- error_code __m_ec;
- file_status __st(__get_ft(&__m_ec));
- __handle_error("in directory_entry::file_size", __ec, __m_ec);
- if (_VSTD_FS::exists(__st) && !_VSTD_FS::is_regular_file(__st)) {
- errc __err_kind = _VSTD_FS::is_directory(__st) ? errc::is_a_directory
- : errc::not_supported;
- __handle_error("in directory_entry::file_size", __ec,
- make_error_code(__err_kind));
- }
- return __data_.__size_;
- }
- }
- _LIBCPP_UNREACHABLE();
- }
-
- _LIBCPP_INLINE_VISIBILITY
- uintmax_t __get_nlink(error_code* __ec = nullptr) const {
- switch (__data_.__cache_type_) {
- case _Empty:
- case _IterNonSymlink:
- case _IterSymlink:
- case _RefreshSymlinkUnresolved:
- return _VSTD_FS::__hard_link_count(__p_, __ec);
- case _RefreshSymlink:
- case _RefreshNonSymlink: {
- error_code __m_ec;
- (void)__get_ft(&__m_ec);
- __handle_error("in directory_entry::hard_link_count", __ec, __m_ec);
- return __data_.__nlink_;
- }
- }
- _LIBCPP_UNREACHABLE();
- }
-
- _LIBCPP_INLINE_VISIBILITY
- file_time_type __get_write_time(error_code* __ec = nullptr) const {
- switch (__data_.__cache_type_) {
- case _Empty:
- case _IterNonSymlink:
- case _IterSymlink:
- case _RefreshSymlinkUnresolved:
- return _VSTD_FS::__last_write_time(__p_, __ec);
- case _RefreshSymlink:
- case _RefreshNonSymlink: {
- error_code __m_ec;
- file_status __st(__get_ft(&__m_ec));
- __handle_error("in directory_entry::last_write_time", __ec, __m_ec);
- if (_VSTD_FS::exists(__st) &&
- __data_.__write_time_ == file_time_type::min())
- __handle_error("in directory_entry::last_write_time", __ec,
- make_error_code(errc::value_too_large));
- return __data_.__write_time_;
- }
- }
- _LIBCPP_UNREACHABLE();
- }
-
-private:
- _Path __p_;
- __cached_data __data_;
-};
-
-class __dir_element_proxy {
-public:
- inline _LIBCPP_INLINE_VISIBILITY directory_entry operator*() {
- return _VSTD::move(__elem_);
- }
-
-private:
- friend class directory_iterator;
- friend class recursive_directory_iterator;
- explicit __dir_element_proxy(directory_entry const& __e) : __elem_(__e) {}
- __dir_element_proxy(__dir_element_proxy&& __o)
- : __elem_(_VSTD::move(__o.__elem_)) {}
- directory_entry __elem_;
-};
-
-class directory_iterator {
-public:
- typedef directory_entry value_type;
- typedef ptrdiff_t difference_type;
- typedef value_type const* pointer;
- typedef value_type const& reference;
- typedef input_iterator_tag iterator_category;
-
-public:
- //ctor & dtor
- directory_iterator() noexcept {}
-
- explicit directory_iterator(const path& __p)
- : directory_iterator(__p, nullptr) {}
-
- directory_iterator(const path& __p, directory_options __opts)
- : directory_iterator(__p, nullptr, __opts) {}
-
- directory_iterator(const path& __p, error_code& __ec)
- : directory_iterator(__p, &__ec) {}
-
- directory_iterator(const path& __p, directory_options __opts,
- error_code& __ec)
- : directory_iterator(__p, &__ec, __opts) {}
-
- directory_iterator(const directory_iterator&) = default;
- directory_iterator(directory_iterator&&) = default;
- directory_iterator& operator=(const directory_iterator&) = default;
-
- directory_iterator& operator=(directory_iterator&& __o) noexcept {
- // non-default implementation provided to support self-move assign.
- if (this != &__o) {
- __imp_ = _VSTD::move(__o.__imp_);
- }
- return *this;
- }
-
- ~directory_iterator() = default;
-
- const directory_entry& operator*() const {
- _LIBCPP_ASSERT(__imp_, "The end iterator cannot be dereferenced");
- return __dereference();
- }
-
- const directory_entry* operator->() const { return &**this; }
-
- directory_iterator& operator++() { return __increment(); }
-
- __dir_element_proxy operator++(int) {
- __dir_element_proxy __p(**this);
- __increment();
- return __p;
- }
-
- directory_iterator& increment(error_code& __ec) { return __increment(&__ec); }
-
-private:
- inline _LIBCPP_INLINE_VISIBILITY friend bool
- operator==(const directory_iterator& __lhs,
- const directory_iterator& __rhs) noexcept;
-
- // construct the dir_stream
- _LIBCPP_FUNC_VIS
- directory_iterator(const path&, error_code*,
- directory_options = directory_options::none);
-
- _LIBCPP_FUNC_VIS
- directory_iterator& __increment(error_code* __ec = nullptr);
-
- _LIBCPP_FUNC_VIS
- const directory_entry& __dereference() const;
-
-private:
- shared_ptr<__dir_stream> __imp_;
-};
-
-inline _LIBCPP_INLINE_VISIBILITY bool
-operator==(const directory_iterator& __lhs,
- const directory_iterator& __rhs) noexcept {
- return __lhs.__imp_ == __rhs.__imp_;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool
-operator!=(const directory_iterator& __lhs,
- const directory_iterator& __rhs) noexcept {
- return !(__lhs == __rhs);
-}
-
-// enable directory_iterator range-based for statements
-inline _LIBCPP_INLINE_VISIBILITY directory_iterator
-begin(directory_iterator __iter) noexcept {
- return __iter;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY directory_iterator
-end(const directory_iterator&) noexcept {
- return directory_iterator();
-}
-
-class recursive_directory_iterator {
-public:
- using value_type = directory_entry;
- using difference_type = std::ptrdiff_t;
- using pointer = directory_entry const*;
- using reference = directory_entry const&;
- using iterator_category = std::input_iterator_tag;
-
-public:
- // constructors and destructor
- _LIBCPP_INLINE_VISIBILITY
- recursive_directory_iterator() noexcept : __rec_(false) {}
-
- _LIBCPP_INLINE_VISIBILITY
- explicit recursive_directory_iterator(
- const path& __p, directory_options __xoptions = directory_options::none)
- : recursive_directory_iterator(__p, __xoptions, nullptr) {}
-
- _LIBCPP_INLINE_VISIBILITY
- recursive_directory_iterator(const path& __p, directory_options __xoptions,
- error_code& __ec)
- : recursive_directory_iterator(__p, __xoptions, &__ec) {}
-
- _LIBCPP_INLINE_VISIBILITY
- recursive_directory_iterator(const path& __p, error_code& __ec)
- : recursive_directory_iterator(__p, directory_options::none, &__ec) {}
-
- recursive_directory_iterator(const recursive_directory_iterator&) = default;
- recursive_directory_iterator(recursive_directory_iterator&&) = default;
-
- recursive_directory_iterator&
- operator=(const recursive_directory_iterator&) = default;
-
- _LIBCPP_INLINE_VISIBILITY
- recursive_directory_iterator&
- operator=(recursive_directory_iterator&& __o) noexcept {
- // non-default implementation provided to support self-move assign.
- if (this != &__o) {
- __imp_ = _VSTD::move(__o.__imp_);
- __rec_ = __o.__rec_;
- }
- return *this;
- }
-
- ~recursive_directory_iterator() = default;
-
- _LIBCPP_INLINE_VISIBILITY
- const directory_entry& operator*() const { return __dereference(); }
-
- _LIBCPP_INLINE_VISIBILITY
- const directory_entry* operator->() const { return &__dereference(); }
-
- recursive_directory_iterator& operator++() { return __increment(); }
-
- _LIBCPP_INLINE_VISIBILITY
- __dir_element_proxy operator++(int) {
- __dir_element_proxy __p(**this);
- __increment();
- return __p;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- recursive_directory_iterator& increment(error_code& __ec) {
- return __increment(&__ec);
- }
-
- _LIBCPP_FUNC_VIS directory_options options() const;
- _LIBCPP_FUNC_VIS int depth() const;
-
- _LIBCPP_INLINE_VISIBILITY
- void pop() { __pop(); }
-
- _LIBCPP_INLINE_VISIBILITY
- void pop(error_code& __ec) { __pop(&__ec); }
-
- _LIBCPP_INLINE_VISIBILITY
- bool recursion_pending() const { return __rec_; }
-
- _LIBCPP_INLINE_VISIBILITY
- void disable_recursion_pending() { __rec_ = false; }
-
-private:
- recursive_directory_iterator(const path& __p, directory_options __opt,
- error_code* __ec);
-
- _LIBCPP_FUNC_VIS
- const directory_entry& __dereference() const;
-
- _LIBCPP_FUNC_VIS
- bool __try_recursion(error_code* __ec);
-
- _LIBCPP_FUNC_VIS
- void __advance(error_code* __ec = nullptr);
-
- _LIBCPP_FUNC_VIS
- recursive_directory_iterator& __increment(error_code* __ec = nullptr);
-
- _LIBCPP_FUNC_VIS
- void __pop(error_code* __ec = nullptr);
-
- inline _LIBCPP_INLINE_VISIBILITY friend bool
- operator==(const recursive_directory_iterator&,
- const recursive_directory_iterator&) noexcept;
-
- struct __shared_imp;
- shared_ptr<__shared_imp> __imp_;
- bool __rec_;
-}; // class recursive_directory_iterator
-
-inline _LIBCPP_INLINE_VISIBILITY bool
-operator==(const recursive_directory_iterator& __lhs,
- const recursive_directory_iterator& __rhs) noexcept {
- return __lhs.__imp_ == __rhs.__imp_;
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline bool operator!=(const recursive_directory_iterator& __lhs,
- const recursive_directory_iterator& __rhs) noexcept {
- return !(__lhs == __rhs);
-}
-// enable recursive_directory_iterator range-based for statements
-inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator
-begin(recursive_directory_iterator __iter) noexcept {
- return __iter;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator
-end(const recursive_directory_iterator&) noexcept {
- return recursive_directory_iterator();
-}
-
-} // namespace android::hardware::automotive::filesystem
-#ifdef _LIBAUTO_UNDEF_VSTD
-#undef _VSTD
-#undef _LIBAUTO_UNDEF_VSTD
-#endif
-
-#ifndef _LIBAUTO_UNDEF_VSTD_FS
-#pragma pop_macro("_VSTD_FS")
-#else
-#undef _VSTD
-#undef _LIBAUTO_UNDEF_VSTD_FS
-#endif
-
-#endif // !_LIBCPP_CXX03_LANG
-
-_LIBCPP_POP_MACROS
-
-#endif // defined(_LIBCPP_VERSION) && _LIBCPP_VERSION > 8000
-
-#endif // _LIBAUTO_FILESYSTEM
diff --git a/automotive/can/1.0/default/libc++fs/src/filesystem/directory_iterator.cpp b/automotive/can/1.0/default/libc++fs/src/filesystem/directory_iterator.cpp
deleted file mode 100644
index 0dbf492..0000000
--- a/automotive/can/1.0/default/libc++fs/src/filesystem/directory_iterator.cpp
+++ /dev/null
@@ -1,405 +0,0 @@
-//===------------------ directory_iterator.cpp ----------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// TODO(152067309): Remove this once the libc++ upgrade is complete.
-#include <__config>
-#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 8000
-
-/* clang-format off */
-#include "automotive/filesystem"
-#include <__config>
-
-#if defined(_LIBCPP_WIN32API)
-#define WIN32_LEAN_AND_MEAN
-#include <Windows.h>
-#else
-#include <dirent.h>
-#endif
-#include <errno.h>
-
-#include "filesystem_common.h"
-
-namespace android::hardware::automotive::filesystem {
-
-namespace detail {
-namespace {
-
-#if !defined(_LIBCPP_WIN32API)
-template <class DirEntT, class = decltype(DirEntT::d_type)>
-static file_type get_file_type(DirEntT* ent, int) {
- switch (ent->d_type) {
- case DT_BLK:
- return file_type::block;
- case DT_CHR:
- return file_type::character;
- case DT_DIR:
- return file_type::directory;
- case DT_FIFO:
- return file_type::fifo;
- case DT_LNK:
- return file_type::symlink;
- case DT_REG:
- return file_type::regular;
- case DT_SOCK:
- return file_type::socket;
- // Unlike in lstat, hitting "unknown" here simply means that the underlying
- // filesystem doesn't support d_type. Report is as 'none' so we correctly
- // set the cache to empty.
- case DT_UNKNOWN:
- break;
- }
- return file_type::none;
-}
-
-template <class DirEntT>
-static file_type get_file_type(DirEntT* ent, long) {
- return file_type::none;
-}
-
-static pair<string_view, file_type> posix_readdir(DIR* dir_stream,
- error_code& ec) {
- struct dirent* dir_entry_ptr = nullptr;
- errno = 0; // zero errno in order to detect errors
- ec.clear();
- if ((dir_entry_ptr = ::readdir(dir_stream)) == nullptr) {
- if (errno)
- ec = capture_errno();
- return {};
- } else {
- return {dir_entry_ptr->d_name, get_file_type(dir_entry_ptr, 0)};
- }
-}
-#else
-
-static file_type get_file_type(const WIN32_FIND_DATA& data) {
- //auto attrs = data.dwFileAttributes;
- // FIXME(EricWF)
- return file_type::unknown;
-}
-static uintmax_t get_file_size(const WIN32_FIND_DATA& data) {
- return (data.nFileSizeHight * (MAXDWORD + 1)) + data.nFileSizeLow;
-}
-static file_time_type get_write_time(const WIN32_FIND_DATA& data) {
- ULARGE_INTEGER tmp;
- FILETIME& time = data.ftLastWriteTime;
- tmp.u.LowPart = time.dwLowDateTime;
- tmp.u.HighPart = time.dwHighDateTime;
- return file_time_type(file_time_type::duration(time.QuadPart));
-}
-
-#endif
-
-} // namespace
-} // namespace detail
-
-using detail::ErrorHandler;
-
-#if defined(_LIBCPP_WIN32API)
-class __dir_stream {
-public:
- __dir_stream() = delete;
- __dir_stream& operator=(const __dir_stream&) = delete;
-
- __dir_stream(__dir_stream&& __ds) noexcept : __stream_(__ds.__stream_),
- __root_(move(__ds.__root_)),
- __entry_(move(__ds.__entry_)) {
- __ds.__stream_ = INVALID_HANDLE_VALUE;
- }
-
- __dir_stream(const path& root, directory_options opts, error_code& ec)
- : __stream_(INVALID_HANDLE_VALUE), __root_(root) {
- __stream_ = ::FindFirstFileEx(root.c_str(), &__data_);
- if (__stream_ == INVALID_HANDLE_VALUE) {
- ec = error_code(::GetLastError(), generic_category());
- const bool ignore_permission_denied =
- bool(opts & directory_options::skip_permission_denied);
- if (ignore_permission_denied && ec.value() == ERROR_ACCESS_DENIED)
- ec.clear();
- return;
- }
- }
-
- ~__dir_stream() noexcept {
- if (__stream_ == INVALID_HANDLE_VALUE)
- return;
- close();
- }
-
- bool good() const noexcept { return __stream_ != INVALID_HANDLE_VALUE; }
-
- bool advance(error_code& ec) {
- while (::FindNextFile(__stream_, &__data_)) {
- if (!strcmp(__data_.cFileName, ".") || strcmp(__data_.cFileName, ".."))
- continue;
- // FIXME: Cache more of this
- //directory_entry::__cached_data cdata;
- //cdata.__type_ = get_file_type(__data_);
- //cdata.__size_ = get_file_size(__data_);
- //cdata.__write_time_ = get_write_time(__data_);
- __entry_.__assign_iter_entry(
- __root_ / __data_.cFileName,
- directory_entry::__create_iter_result(get_file_type(__data)));
- return true;
- }
- ec = error_code(::GetLastError(), generic_category());
- close();
- return false;
- }
-
-private:
- error_code close() noexcept {
- error_code ec;
- if (!::FindClose(__stream_))
- ec = error_code(::GetLastError(), generic_category());
- __stream_ = INVALID_HANDLE_VALUE;
- return ec;
- }
-
- HANDLE __stream_{INVALID_HANDLE_VALUE};
- WIN32_FIND_DATA __data_;
-
-public:
- path __root_;
- directory_entry __entry_;
-};
-#else
-class __dir_stream {
-public:
- __dir_stream() = delete;
- __dir_stream& operator=(const __dir_stream&) = delete;
-
- __dir_stream(__dir_stream&& other) noexcept : __stream_(other.__stream_),
- __root_(std::move(other.__root_)),
- __entry_(std::move(other.__entry_)) {
- other.__stream_ = nullptr;
- }
-
- __dir_stream(const path& root, directory_options opts, error_code& ec)
- : __stream_(nullptr), __root_(root) {
- if ((__stream_ = ::opendir(root.c_str())) == nullptr) {
- ec = detail::capture_errno();
- const bool allow_eacess =
- bool(opts & directory_options::skip_permission_denied);
- if (allow_eacess && ec.value() == EACCES)
- ec.clear();
- return;
- }
- advance(ec);
- }
-
- ~__dir_stream() noexcept {
- if (__stream_)
- close();
- }
-
- bool good() const noexcept { return __stream_ != nullptr; }
-
- bool advance(error_code& ec) {
- while (true) {
- auto str_type_pair = detail::posix_readdir(__stream_, ec);
- auto& str = str_type_pair.first;
- if (str == "." || str == "..") {
- continue;
- } else if (ec || str.empty()) {
- close();
- return false;
- } else {
- __entry_.__assign_iter_entry(
- __root_ / str,
- directory_entry::__create_iter_result(str_type_pair.second));
- return true;
- }
- }
- }
-
-private:
- error_code close() noexcept {
- error_code m_ec;
- if (::closedir(__stream_) == -1)
- m_ec = detail::capture_errno();
- __stream_ = nullptr;
- return m_ec;
- }
-
- DIR* __stream_{nullptr};
-
-public:
- path __root_;
- directory_entry __entry_;
-};
-#endif
-
-// directory_iterator
-
-directory_iterator::directory_iterator(const path& p, error_code* ec,
- directory_options opts) {
- ErrorHandler<void> err("directory_iterator::directory_iterator(...)", ec, &p);
-
- error_code m_ec;
- __imp_ = make_shared<__dir_stream>(p, opts, m_ec);
- if (ec)
- *ec = m_ec;
- if (!__imp_->good()) {
- __imp_.reset();
- if (m_ec)
- err.report(m_ec);
- }
-}
-
-directory_iterator& directory_iterator::__increment(error_code* ec) {
- _LIBCPP_ASSERT(__imp_, "Attempting to increment an invalid iterator");
- ErrorHandler<void> err("directory_iterator::operator++()", ec);
-
- error_code m_ec;
- if (!__imp_->advance(m_ec)) {
- path root = std::move(__imp_->__root_);
- __imp_.reset();
- if (m_ec)
- err.report(m_ec, "at root \"%s\"", root);
- }
- return *this;
-}
-
-directory_entry const& directory_iterator::__dereference() const {
- _LIBCPP_ASSERT(__imp_, "Attempting to dereference an invalid iterator");
- return __imp_->__entry_;
-}
-
-// recursive_directory_iterator
-
-struct recursive_directory_iterator::__shared_imp {
- stack<__dir_stream> __stack_;
- directory_options __options_;
-};
-
-recursive_directory_iterator::recursive_directory_iterator(
- const path& p, directory_options opt, error_code* ec)
- : __imp_(nullptr), __rec_(true) {
- ErrorHandler<void> err("recursive_directory_iterator", ec, &p);
-
- error_code m_ec;
- __dir_stream new_s(p, opt, m_ec);
- if (m_ec)
- err.report(m_ec);
- if (m_ec || !new_s.good())
- return;
-
- __imp_ = make_shared<__shared_imp>();
- __imp_->__options_ = opt;
- __imp_->__stack_.push(std::move(new_s));
-}
-
-void recursive_directory_iterator::__pop(error_code* ec) {
- _LIBCPP_ASSERT(__imp_, "Popping the end iterator");
- if (ec)
- ec->clear();
- __imp_->__stack_.pop();
- if (__imp_->__stack_.size() == 0)
- __imp_.reset();
- else
- __advance(ec);
-}
-
-directory_options recursive_directory_iterator::options() const {
- return __imp_->__options_;
-}
-
-int recursive_directory_iterator::depth() const {
- return __imp_->__stack_.size() - 1;
-}
-
-const directory_entry& recursive_directory_iterator::__dereference() const {
- return __imp_->__stack_.top().__entry_;
-}
-
-recursive_directory_iterator&
-recursive_directory_iterator::__increment(error_code* ec) {
- if (ec)
- ec->clear();
- if (recursion_pending()) {
- if (__try_recursion(ec) || (ec && *ec))
- return *this;
- }
- __rec_ = true;
- __advance(ec);
- return *this;
-}
-
-void recursive_directory_iterator::__advance(error_code* ec) {
- ErrorHandler<void> err("recursive_directory_iterator::operator++()", ec);
-
- const directory_iterator end_it;
- auto& stack = __imp_->__stack_;
- error_code m_ec;
- while (stack.size() > 0) {
- if (stack.top().advance(m_ec))
- return;
- if (m_ec)
- break;
- stack.pop();
- }
-
- if (m_ec) {
- path root = std::move(stack.top().__root_);
- __imp_.reset();
- err.report(m_ec, "at root \"%s\"", root);
- } else {
- __imp_.reset();
- }
-}
-
-bool recursive_directory_iterator::__try_recursion(error_code* ec) {
- ErrorHandler<void> err("recursive_directory_iterator::operator++()", ec);
-
- bool rec_sym = bool(options() & directory_options::follow_directory_symlink);
-
- auto& curr_it = __imp_->__stack_.top();
-
- bool skip_rec = false;
- error_code m_ec;
- if (!rec_sym) {
- file_status st(curr_it.__entry_.__get_sym_ft(&m_ec));
- if (m_ec && status_known(st))
- m_ec.clear();
- if (m_ec || is_symlink(st) || !is_directory(st))
- skip_rec = true;
- } else {
- file_status st(curr_it.__entry_.__get_ft(&m_ec));
- if (m_ec && status_known(st))
- m_ec.clear();
- if (m_ec || !is_directory(st))
- skip_rec = true;
- }
-
- if (!skip_rec) {
- __dir_stream new_it(curr_it.__entry_.path(), __imp_->__options_, m_ec);
- if (new_it.good()) {
- __imp_->__stack_.push(std::move(new_it));
- return true;
- }
- }
- if (m_ec) {
- const bool allow_eacess =
- bool(__imp_->__options_ & directory_options::skip_permission_denied);
- if (m_ec.value() == EACCES && allow_eacess) {
- if (ec)
- ec->clear();
- } else {
- path at_ent = std::move(curr_it.__entry_.__p_);
- __imp_.reset();
- err.report(m_ec, "attempting recursion into \"%s\"", at_ent);
- }
- }
- return false;
-}
-
-} // namespace android::hardware::automotive::filesystem
-/* clang-format on */
-
-#endif // defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 8000
diff --git a/automotive/can/1.0/default/libc++fs/src/filesystem/filesystem_common.h b/automotive/can/1.0/default/libc++fs/src/filesystem/filesystem_common.h
deleted file mode 100644
index 4f44661..0000000
--- a/automotive/can/1.0/default/libc++fs/src/filesystem/filesystem_common.h
+++ /dev/null
@@ -1,441 +0,0 @@
-//===----------------------------------------------------------------------===////
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===////
-/* clang-format off */
-#ifndef AUTO_FILESYSTEM_COMMON_H
-#define AUTO_FILESYSTEM_COMMON_H
-
-#include "automotive/filesystem"
-#include <array>
-#include <chrono>
-#include <cstdlib>
-#include <climits>
-
-#include <unistd.h>
-#include <sys/stat.h>
-#include <sys/statvfs.h>
-#include <sys/time.h> // for ::utimes as used in __last_write_time
-#include <fcntl.h> /* values for fchmodat */
-
-#if !defined(__APPLE__)
-// We can use the presence of UTIME_OMIT to detect platforms that provide
-// utimensat.
-#if defined(UTIME_OMIT)
-#define _LIBCPP_USE_UTIMENSAT
-#endif
-#endif
-
-#if defined(__GNUC__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-function"
-#endif
-
-namespace android::hardware::automotive::filesystem {
-using namespace std::chrono;
-
-using std::error_code;
-using std::is_floating_point;
-using std::micro;
-using std::nano;
-using std::ratio;
-
-namespace detail {
-namespace {
-
-static string format_string_imp(const char* msg, ...) {
- // we might need a second shot at this, so pre-emptivly make a copy
- struct GuardVAList {
- va_list& target;
- bool active = true;
- GuardVAList(va_list& target) : target(target), active(true) {}
- void clear() {
- if (active)
- va_end(target);
- active = false;
- }
- ~GuardVAList() {
- if (active)
- va_end(target);
- }
- };
- va_list args;
- va_start(args, msg);
- GuardVAList args_guard(args);
-
- va_list args_cp;
- va_copy(args_cp, args);
- GuardVAList args_copy_guard(args_cp);
-
- std::string result;
-
- array<char, 256> local_buff;
- size_t size_with_null = local_buff.size();
- auto ret = ::vsnprintf(local_buff.data(), size_with_null, msg, args_cp);
-
- args_copy_guard.clear();
-
- // handle empty expansion
- if (ret == 0)
- return result;
- if (static_cast<size_t>(ret) < size_with_null) {
- result.assign(local_buff.data(), static_cast<size_t>(ret));
- return result;
- }
-
- // we did not provide a long enough buffer on our first attempt. The
- // return value is the number of bytes (excluding the null byte) that are
- // needed for formatting.
- size_with_null = static_cast<size_t>(ret) + 1;
- result.__resize_default_init(size_with_null - 1);
- ret = ::vsnprintf(&result[0], size_with_null, msg, args);
- _LIBCPP_ASSERT(static_cast<size_t>(ret) == (size_with_null - 1), "TODO");
-
- return result;
-}
-
-const char* unwrap(string const& s) { return s.c_str(); }
-const char* unwrap(path const& p) { return p.native().c_str(); }
-template <class Arg>
-Arg const& unwrap(Arg const& a) {
- static_assert(!is_class<Arg>::value, "cannot pass class here");
- return a;
-}
-
-template <class... Args>
-string format_string(const char* fmt, Args const&... args) {
- return format_string_imp(fmt, unwrap(args)...);
-}
-
-error_code capture_errno() {
- _LIBCPP_ASSERT(errno, "Expected errno to be non-zero");
- return error_code(errno, generic_category());
-}
-
-template <class T>
-T error_value();
-template <>
-_LIBCPP_CONSTEXPR_AFTER_CXX11 void error_value<void>() {}
-template <>
-bool error_value<bool>() {
- return false;
-}
-template <>
-uintmax_t error_value<uintmax_t>() {
- return uintmax_t(-1);
-}
-template <>
-_LIBCPP_CONSTEXPR_AFTER_CXX11 file_time_type error_value<file_time_type>() {
- return file_time_type::min();
-}
-template <>
-path error_value<path>() {
- return {};
-}
-
-template <class T>
-struct ErrorHandler {
- const char* func_name;
- error_code* ec = nullptr;
- const path* p1 = nullptr;
- const path* p2 = nullptr;
-
- ErrorHandler(const char* fname, error_code* ec, const path* p1 = nullptr,
- const path* p2 = nullptr)
- : func_name(fname), ec(ec), p1(p1), p2(p2) {
- if (ec)
- ec->clear();
- }
-
- T report(const error_code& m_ec) const {
- if (ec) {
- *ec = m_ec;
- return error_value<T>();
- }
- string what = string("in ") + func_name;
- switch (bool(p1) + bool(p2)) {
- case 0:
- __throw_filesystem_error(what, m_ec);
- case 1:
- __throw_filesystem_error(what, *p1, m_ec);
- case 2:
- __throw_filesystem_error(what, *p1, *p2, m_ec);
- }
- _LIBCPP_UNREACHABLE();
- }
-
- template <class... Args>
- T report(const error_code& m_ec, const char* msg, Args const&... args) const {
- if (ec) {
- *ec = m_ec;
- return error_value<T>();
- }
- string what =
- string("in ") + func_name + ": " + format_string(msg, args...);
- switch (bool(p1) + bool(p2)) {
- case 0:
- __throw_filesystem_error(what, m_ec);
- case 1:
- __throw_filesystem_error(what, *p1, m_ec);
- case 2:
- __throw_filesystem_error(what, *p1, *p2, m_ec);
- }
- _LIBCPP_UNREACHABLE();
- }
-
- T report(errc const& err) const { return report(make_error_code(err)); }
-
- template <class... Args>
- T report(errc const& err, const char* msg, Args const&... args) const {
- return report(make_error_code(err), msg, args...);
- }
-
-private:
- ErrorHandler(ErrorHandler const&) = delete;
- ErrorHandler& operator=(ErrorHandler const&) = delete;
-};
-
-using chrono::duration;
-using chrono::duration_cast;
-
-using TimeSpec = struct ::timespec;
-using StatT = struct ::stat;
-
-template <class FileTimeT, class TimeT,
- bool IsFloat = is_floating_point<typename FileTimeT::rep>::value>
-struct time_util_base {
- using rep = typename FileTimeT::rep;
- using fs_duration = typename FileTimeT::duration;
- using fs_seconds = duration<rep>;
- using fs_nanoseconds = duration<rep, nano>;
- using fs_microseconds = duration<rep, micro>;
-
- static constexpr rep max_seconds =
- duration_cast<fs_seconds>(FileTimeT::duration::max()).count();
-
- static constexpr rep max_nsec =
- duration_cast<fs_nanoseconds>(FileTimeT::duration::max() -
- fs_seconds(max_seconds))
- .count();
-
- static constexpr rep min_seconds =
- duration_cast<fs_seconds>(FileTimeT::duration::min()).count();
-
- static constexpr rep min_nsec_timespec =
- duration_cast<fs_nanoseconds>(
- (FileTimeT::duration::min() - fs_seconds(min_seconds)) +
- fs_seconds(1))
- .count();
-
-private:
-#if _LIBCPP_STD_VER > 11 && !defined(_LIBCPP_HAS_NO_CXX14_CONSTEXPR)
- static constexpr fs_duration get_min_nsecs() {
- return duration_cast<fs_duration>(
- fs_nanoseconds(min_nsec_timespec) -
- duration_cast<fs_nanoseconds>(fs_seconds(1)));
- }
- // Static assert that these values properly round trip.
- static_assert(fs_seconds(min_seconds) + get_min_nsecs() ==
- FileTimeT::duration::min(),
- "value doesn't roundtrip");
-
- static constexpr bool check_range() {
- // This kinda sucks, but it's what happens when we don't have __int128_t.
- if (sizeof(TimeT) == sizeof(rep)) {
- typedef duration<long long, ratio<3600 * 24 * 365> > Years;
- return duration_cast<Years>(fs_seconds(max_seconds)) > Years(250) &&
- duration_cast<Years>(fs_seconds(min_seconds)) < Years(-250);
- }
- return max_seconds >= numeric_limits<TimeT>::max() &&
- min_seconds <= numeric_limits<TimeT>::min();
- }
- static_assert(check_range(), "the representable range is unacceptable small");
-#endif
-};
-
-template <class FileTimeT, class TimeT>
-struct time_util_base<FileTimeT, TimeT, true> {
- using rep = typename FileTimeT::rep;
- using fs_duration = typename FileTimeT::duration;
- using fs_seconds = duration<rep>;
- using fs_nanoseconds = duration<rep, nano>;
- using fs_microseconds = duration<rep, micro>;
-
- static const rep max_seconds;
- static const rep max_nsec;
- static const rep min_seconds;
- static const rep min_nsec_timespec;
-};
-
-template <class FileTimeT, class TimeT>
-const typename FileTimeT::rep
- time_util_base<FileTimeT, TimeT, true>::max_seconds =
- duration_cast<fs_seconds>(FileTimeT::duration::max()).count();
-
-template <class FileTimeT, class TimeT>
-const typename FileTimeT::rep time_util_base<FileTimeT, TimeT, true>::max_nsec =
- duration_cast<fs_nanoseconds>(FileTimeT::duration::max() -
- fs_seconds(max_seconds))
- .count();
-
-template <class FileTimeT, class TimeT>
-const typename FileTimeT::rep
- time_util_base<FileTimeT, TimeT, true>::min_seconds =
- duration_cast<fs_seconds>(FileTimeT::duration::min()).count();
-
-template <class FileTimeT, class TimeT>
-const typename FileTimeT::rep
- time_util_base<FileTimeT, TimeT, true>::min_nsec_timespec =
- duration_cast<fs_nanoseconds>((FileTimeT::duration::min() -
- fs_seconds(min_seconds)) +
- fs_seconds(1))
- .count();
-
-template <class FileTimeT, class TimeT, class TimeSpecT>
-struct time_util : time_util_base<FileTimeT, TimeT> {
- using Base = time_util_base<FileTimeT, TimeT>;
- using Base::max_nsec;
- using Base::max_seconds;
- using Base::min_nsec_timespec;
- using Base::min_seconds;
-
- using typename Base::fs_duration;
- using typename Base::fs_microseconds;
- using typename Base::fs_nanoseconds;
- using typename Base::fs_seconds;
-
-public:
- template <class CType, class ChronoType>
- static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool checked_set(CType* out,
- ChronoType time) {
- using Lim = numeric_limits<CType>;
- if (time > Lim::max() || time < Lim::min())
- return false;
- *out = static_cast<CType>(time);
- return true;
- }
-
- static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool is_representable(TimeSpecT tm) {
- if (tm.tv_sec >= 0) {
- return tm.tv_sec < max_seconds ||
- (tm.tv_sec == max_seconds && tm.tv_nsec <= max_nsec);
- } else if (tm.tv_sec == (min_seconds - 1)) {
- return tm.tv_nsec >= min_nsec_timespec;
- } else {
- return tm.tv_sec >= min_seconds;
- }
- }
-
- static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool is_representable(FileTimeT tm) {
- auto secs = duration_cast<fs_seconds>(tm.time_since_epoch());
- auto nsecs = duration_cast<fs_nanoseconds>(tm.time_since_epoch() - secs);
- if (nsecs.count() < 0) {
- secs = secs + fs_seconds(1);
- nsecs = nsecs + fs_seconds(1);
- }
- using TLim = numeric_limits<TimeT>;
- if (secs.count() >= 0)
- return secs.count() <= TLim::max();
- return secs.count() >= TLim::min();
- }
-
- static _LIBCPP_CONSTEXPR_AFTER_CXX11 FileTimeT
- convert_from_timespec(TimeSpecT tm) {
- if (tm.tv_sec >= 0 || tm.tv_nsec == 0) {
- return FileTimeT(fs_seconds(tm.tv_sec) +
- duration_cast<fs_duration>(fs_nanoseconds(tm.tv_nsec)));
- } else { // tm.tv_sec < 0
- auto adj_subsec = duration_cast<fs_duration>(fs_seconds(1) -
- fs_nanoseconds(tm.tv_nsec));
- auto Dur = fs_seconds(tm.tv_sec + 1) - adj_subsec;
- return FileTimeT(Dur);
- }
- }
-
- template <class SubSecT>
- static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool
- set_times_checked(TimeT* sec_out, SubSecT* subsec_out, FileTimeT tp) {
- auto dur = tp.time_since_epoch();
- auto sec_dur = duration_cast<fs_seconds>(dur);
- auto subsec_dur = duration_cast<fs_nanoseconds>(dur - sec_dur);
- // The tv_nsec and tv_usec fields must not be negative so adjust accordingly
- if (subsec_dur.count() < 0) {
- if (sec_dur.count() > min_seconds) {
- sec_dur = sec_dur - fs_seconds(1);
- subsec_dur = subsec_dur + fs_seconds(1);
- } else {
- subsec_dur = fs_nanoseconds::zero();
- }
- }
- return checked_set(sec_out, sec_dur.count()) &&
- checked_set(subsec_out, subsec_dur.count());
- }
- static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool convert_to_timespec(TimeSpecT& dest,
- FileTimeT tp) {
- if (!is_representable(tp))
- return false;
- return set_times_checked(&dest.tv_sec, &dest.tv_nsec, tp);
- }
-};
-
-using fs_time = time_util<file_time_type, time_t, TimeSpec>;
-
-#if defined(__APPLE__)
-TimeSpec extract_mtime(StatT const& st) { return st.st_mtimespec; }
-TimeSpec extract_atime(StatT const& st) { return st.st_atimespec; }
-#else
-TimeSpec extract_mtime(StatT const& st) { return st.st_mtim; }
-TimeSpec extract_atime(StatT const& st) { return st.st_atim; }
-#endif
-
-// allow the utimes implementation to compile even it we're not going
-// to use it.
-
-bool posix_utimes(const path& p, std::array<TimeSpec, 2> const& TS,
- error_code& ec) {
- using namespace chrono;
- auto Convert = [](long nsec) {
- using int_type = decltype(std::declval< ::timeval>().tv_usec);
- auto dur = duration_cast<microseconds>(nanoseconds(nsec)).count();
- return static_cast<int_type>(dur);
- };
- struct ::timeval ConvertedTS[2] = {{TS[0].tv_sec, Convert(TS[0].tv_nsec)},
- {TS[1].tv_sec, Convert(TS[1].tv_nsec)}};
- if (::utimes(p.c_str(), ConvertedTS) == -1) {
- ec = capture_errno();
- return true;
- }
- return false;
-}
-
-#if defined(_LIBCPP_USE_UTIMENSAT)
-bool posix_utimensat(const path& p, std::array<TimeSpec, 2> const& TS,
- error_code& ec) {
- if (::utimensat(AT_FDCWD, p.c_str(), TS.data(), 0) == -1) {
- ec = capture_errno();
- return true;
- }
- return false;
-}
-#endif
-
-bool set_file_times(const path& p, std::array<TimeSpec, 2> const& TS,
- error_code& ec) {
-#if !defined(_LIBCPP_USE_UTIMENSAT)
- return posix_utimes(p, TS, ec);
-#else
- return posix_utimensat(p, TS, ec);
-#endif
-}
-
-} // namespace
-} // end namespace detail
-
-} // namespace android::hardware::automotive::filesystem
-
-#endif // AUTO_FILESYSTEM_COMMON_H
-/* clang-format on */
diff --git a/automotive/can/1.0/default/libc++fs/src/filesystem/operations.cpp b/automotive/can/1.0/default/libc++fs/src/filesystem/operations.cpp
deleted file mode 100644
index 6a76bdc..0000000
--- a/automotive/can/1.0/default/libc++fs/src/filesystem/operations.cpp
+++ /dev/null
@@ -1,1780 +0,0 @@
-//===--------------------- filesystem/ops.cpp -----------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// TODO(152067309): Remove this once the libc++ upgrade is complete.
-#include <__config>
-#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 8000
-
-/* clang-format off */
-#include "automotive/filesystem"
-#include <array>
-#include <iterator>
-#include <fstream>
-#include <random> /* for unique_path */
-#include <string_view>
-#include <type_traits>
-#include <vector>
-#include <cstdlib>
-#include <climits>
-
-#include "filesystem_common.h"
-
-#include <unistd.h>
-#include <sys/stat.h>
-#include <sys/statvfs.h>
-#include <time.h>
-#include <fcntl.h> /* values for fchmodat */
-
-#if defined(__linux__)
-#include <linux/version.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
-#include <sys/sendfile.h>
-#define _LIBCPP_USE_SENDFILE
-#endif
-#elif defined(__APPLE__) || __has_include(<copyfile.h>)
-#include <copyfile.h>
-#define _LIBCPP_USE_COPYFILE
-#endif
-
-#if !defined(__APPLE__)
-#define _LIBCPP_USE_CLOCK_GETTIME
-#endif
-
-#if !defined(CLOCK_REALTIME) || !defined(_LIBCPP_USE_CLOCK_GETTIME)
-#include <sys/time.h> // for gettimeofday and timeval
-#endif // !defined(CLOCK_REALTIME)
-
-#if defined(_LIBCPP_COMPILER_GCC)
-#if _GNUC_VER < 500
-#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
-#endif
-#endif
-
-namespace android::hardware::automotive::filesystem {
-
-#ifdef _VSTD_FS
-#pragma push_macro("_VSTD_FS")
-#else
-#define _LIBAUTO_UNDEF_VSTD_FS
-#endif
-#define _VSTD_FS android::hardware::automotive::filesystem
-
-namespace {
-namespace parser {
-
-using string_view_t = path::__string_view;
-using string_view_pair = pair<string_view_t, string_view_t>;
-using PosPtr = path::value_type const*;
-
-struct PathParser {
- enum ParserState : unsigned char {
- // Zero is a special sentinel value used by default constructed iterators.
- PS_BeforeBegin = path::iterator::_BeforeBegin,
- PS_InRootName = path::iterator::_InRootName,
- PS_InRootDir = path::iterator::_InRootDir,
- PS_InFilenames = path::iterator::_InFilenames,
- PS_InTrailingSep = path::iterator::_InTrailingSep,
- PS_AtEnd = path::iterator::_AtEnd
- };
-
- const string_view_t Path;
- string_view_t RawEntry;
- ParserState State;
-
-private:
- PathParser(string_view_t P, ParserState State) noexcept : Path(P),
- State(State) {}
-
-public:
- PathParser(string_view_t P, string_view_t E, unsigned char S)
- : Path(P), RawEntry(E), State(static_cast<ParserState>(S)) {
- // S cannot be '0' or PS_BeforeBegin.
- }
-
- static PathParser CreateBegin(string_view_t P) noexcept {
- PathParser PP(P, PS_BeforeBegin);
- PP.increment();
- return PP;
- }
-
- static PathParser CreateEnd(string_view_t P) noexcept {
- PathParser PP(P, PS_AtEnd);
- return PP;
- }
-
- PosPtr peek() const noexcept {
- auto TkEnd = getNextTokenStartPos();
- auto End = getAfterBack();
- return TkEnd == End ? nullptr : TkEnd;
- }
-
- void increment() noexcept {
- const PosPtr End = getAfterBack();
- const PosPtr Start = getNextTokenStartPos();
- if (Start == End)
- return makeState(PS_AtEnd);
-
- switch (State) {
- case PS_BeforeBegin: {
- PosPtr TkEnd = consumeSeparator(Start, End);
- if (TkEnd)
- return makeState(PS_InRootDir, Start, TkEnd);
- else
- return makeState(PS_InFilenames, Start, consumeName(Start, End));
- }
- case PS_InRootDir:
- return makeState(PS_InFilenames, Start, consumeName(Start, End));
-
- case PS_InFilenames: {
- PosPtr SepEnd = consumeSeparator(Start, End);
- if (SepEnd != End) {
- PosPtr TkEnd = consumeName(SepEnd, End);
- if (TkEnd)
- return makeState(PS_InFilenames, SepEnd, TkEnd);
- }
- return makeState(PS_InTrailingSep, Start, SepEnd);
- }
-
- case PS_InTrailingSep:
- return makeState(PS_AtEnd);
-
- case PS_InRootName:
- case PS_AtEnd:
- _LIBCPP_UNREACHABLE();
- }
- }
-
- void decrement() noexcept {
- const PosPtr REnd = getBeforeFront();
- const PosPtr RStart = getCurrentTokenStartPos() - 1;
- if (RStart == REnd) // we're decrementing the begin
- return makeState(PS_BeforeBegin);
-
- switch (State) {
- case PS_AtEnd: {
- // Try to consume a trailing separator or root directory first.
- if (PosPtr SepEnd = consumeSeparator(RStart, REnd)) {
- if (SepEnd == REnd)
- return makeState(PS_InRootDir, Path.data(), RStart + 1);
- return makeState(PS_InTrailingSep, SepEnd + 1, RStart + 1);
- } else {
- PosPtr TkStart = consumeName(RStart, REnd);
- return makeState(PS_InFilenames, TkStart + 1, RStart + 1);
- }
- }
- case PS_InTrailingSep:
- return makeState(PS_InFilenames, consumeName(RStart, REnd) + 1,
- RStart + 1);
- case PS_InFilenames: {
- PosPtr SepEnd = consumeSeparator(RStart, REnd);
- if (SepEnd == REnd)
- return makeState(PS_InRootDir, Path.data(), RStart + 1);
- PosPtr TkEnd = consumeName(SepEnd, REnd);
- return makeState(PS_InFilenames, TkEnd + 1, SepEnd + 1);
- }
- case PS_InRootDir:
- // return makeState(PS_InRootName, Path.data(), RStart + 1);
- case PS_InRootName:
- case PS_BeforeBegin:
- _LIBCPP_UNREACHABLE();
- }
- }
-
- /// \brief Return a view with the "preferred representation" of the current
- /// element. For example trailing separators are represented as a '.'
- string_view_t operator*() const noexcept {
- switch (State) {
- case PS_BeforeBegin:
- case PS_AtEnd:
- return "";
- case PS_InRootDir:
- return "/";
- case PS_InTrailingSep:
- return "";
- case PS_InRootName:
- case PS_InFilenames:
- return RawEntry;
- }
- _LIBCPP_UNREACHABLE();
- }
-
- explicit operator bool() const noexcept {
- return State != PS_BeforeBegin && State != PS_AtEnd;
- }
-
- PathParser& operator++() noexcept {
- increment();
- return *this;
- }
-
- PathParser& operator--() noexcept {
- decrement();
- return *this;
- }
-
- bool atEnd() const noexcept {
- return State == PS_AtEnd;
- }
-
- bool inRootDir() const noexcept {
- return State == PS_InRootDir;
- }
-
- bool inRootName() const noexcept {
- return State == PS_InRootName;
- }
-
- bool inRootPath() const noexcept {
- return inRootName() || inRootDir();
- }
-
-private:
- void makeState(ParserState NewState, PosPtr Start, PosPtr End) noexcept {
- State = NewState;
- RawEntry = string_view_t(Start, End - Start);
- }
- void makeState(ParserState NewState) noexcept {
- State = NewState;
- RawEntry = {};
- }
-
- PosPtr getAfterBack() const noexcept { return Path.data() + Path.size(); }
-
- PosPtr getBeforeFront() const noexcept { return Path.data() - 1; }
-
- /// \brief Return a pointer to the first character after the currently
- /// lexed element.
- PosPtr getNextTokenStartPos() const noexcept {
- switch (State) {
- case PS_BeforeBegin:
- return Path.data();
- case PS_InRootName:
- case PS_InRootDir:
- case PS_InFilenames:
- return &RawEntry.back() + 1;
- case PS_InTrailingSep:
- case PS_AtEnd:
- return getAfterBack();
- }
- _LIBCPP_UNREACHABLE();
- }
-
- /// \brief Return a pointer to the first character in the currently lexed
- /// element.
- PosPtr getCurrentTokenStartPos() const noexcept {
- switch (State) {
- case PS_BeforeBegin:
- case PS_InRootName:
- return &Path.front();
- case PS_InRootDir:
- case PS_InFilenames:
- case PS_InTrailingSep:
- return &RawEntry.front();
- case PS_AtEnd:
- return &Path.back() + 1;
- }
- _LIBCPP_UNREACHABLE();
- }
-
- PosPtr consumeSeparator(PosPtr P, PosPtr End) const noexcept {
- if (P == End || *P != '/')
- return nullptr;
- const int Inc = P < End ? 1 : -1;
- P += Inc;
- while (P != End && *P == '/')
- P += Inc;
- return P;
- }
-
- PosPtr consumeName(PosPtr P, PosPtr End) const noexcept {
- if (P == End || *P == '/')
- return nullptr;
- const int Inc = P < End ? 1 : -1;
- P += Inc;
- while (P != End && *P != '/')
- P += Inc;
- return P;
- }
-};
-
-string_view_pair separate_filename(string_view_t const& s) {
- if (s == "." || s == ".." || s.empty())
- return string_view_pair{s, ""};
- auto pos = s.find_last_of('.');
- if (pos == string_view_t::npos || pos == 0)
- return string_view_pair{s, string_view_t{}};
- return string_view_pair{s.substr(0, pos), s.substr(pos)};
-}
-
-string_view_t createView(PosPtr S, PosPtr E) noexcept {
- return {S, static_cast<size_t>(E - S) + 1};
-}
-
-} // namespace parser
-} // namespace
-
-// POSIX HELPERS
-
-namespace detail {
-namespace {
-
-using value_type = path::value_type;
-using string_type = path::string_type;
-
-struct FileDescriptor {
- const path& name;
- int fd = -1;
- StatT m_stat;
- file_status m_status;
-
- template <class... Args>
- static FileDescriptor create(const path* p, error_code& ec, Args... args) {
- ec.clear();
- int fd;
- if ((fd = ::open(p->c_str(), args...)) == -1) {
- ec = capture_errno();
- return FileDescriptor{p};
- }
- return FileDescriptor(p, fd);
- }
-
- template <class... Args>
- static FileDescriptor create_with_status(const path* p, error_code& ec,
- Args... args) {
- FileDescriptor fd = create(p, ec, args...);
- if (!ec)
- fd.refresh_status(ec);
-
- return fd;
- }
-
- file_status get_status() const { return m_status; }
- StatT const& get_stat() const { return m_stat; }
-
- bool status_known() const { return _VSTD_FS::status_known(m_status); }
-
- file_status refresh_status(error_code& ec);
-
- void close() noexcept {
- if (fd != -1)
- ::close(fd);
- fd = -1;
- }
-
- FileDescriptor(FileDescriptor&& other)
- : name(other.name), fd(other.fd), m_stat(other.m_stat),
- m_status(other.m_status) {
- other.fd = -1;
- other.m_status = file_status{};
- }
-
- ~FileDescriptor() { close(); }
-
- FileDescriptor(FileDescriptor const&) = delete;
- FileDescriptor& operator=(FileDescriptor const&) = delete;
-
-private:
- explicit FileDescriptor(const path* p, int fd = -1) : name(*p), fd(fd) {}
-};
-
-perms posix_get_perms(const StatT& st) noexcept {
- return static_cast<perms>(st.st_mode) & perms::mask;
-}
-
-::mode_t posix_convert_perms(perms prms) {
- return static_cast< ::mode_t>(prms & perms::mask);
-}
-
-file_status create_file_status(error_code& m_ec, path const& p,
- const StatT& path_stat, error_code* ec) {
- if (ec)
- *ec = m_ec;
- if (m_ec && (m_ec.value() == ENOENT || m_ec.value() == ENOTDIR)) {
- return file_status(file_type::not_found);
- } else if (m_ec) {
- ErrorHandler<void> err("posix_stat", ec, &p);
- err.report(m_ec, "failed to determine attributes for the specified path");
- return file_status(file_type::none);
- }
- // else
-
- file_status fs_tmp;
- auto const mode = path_stat.st_mode;
- if (S_ISLNK(mode))
- fs_tmp.type(file_type::symlink);
- else if (S_ISREG(mode))
- fs_tmp.type(file_type::regular);
- else if (S_ISDIR(mode))
- fs_tmp.type(file_type::directory);
- else if (S_ISBLK(mode))
- fs_tmp.type(file_type::block);
- else if (S_ISCHR(mode))
- fs_tmp.type(file_type::character);
- else if (S_ISFIFO(mode))
- fs_tmp.type(file_type::fifo);
- else if (S_ISSOCK(mode))
- fs_tmp.type(file_type::socket);
- else
- fs_tmp.type(file_type::unknown);
-
- fs_tmp.permissions(detail::posix_get_perms(path_stat));
- return fs_tmp;
-}
-
-file_status posix_stat(path const& p, StatT& path_stat, error_code* ec) {
- error_code m_ec;
- if (::stat(p.c_str(), &path_stat) == -1)
- m_ec = detail::capture_errno();
- return create_file_status(m_ec, p, path_stat, ec);
-}
-
-file_status posix_stat(path const& p, error_code* ec) {
- StatT path_stat;
- return posix_stat(p, path_stat, ec);
-}
-
-file_status posix_lstat(path const& p, StatT& path_stat, error_code* ec) {
- error_code m_ec;
- if (::lstat(p.c_str(), &path_stat) == -1)
- m_ec = detail::capture_errno();
- return create_file_status(m_ec, p, path_stat, ec);
-}
-
-file_status posix_lstat(path const& p, error_code* ec) {
- StatT path_stat;
- return posix_lstat(p, path_stat, ec);
-}
-
-bool posix_ftruncate(const FileDescriptor& fd, size_t to_size, error_code& ec) {
- if (::ftruncate(fd.fd, to_size) == -1) {
- ec = capture_errno();
- return true;
- }
- ec.clear();
- return false;
-}
-
-bool posix_fchmod(const FileDescriptor& fd, const StatT& st, error_code& ec) {
- if (::fchmod(fd.fd, st.st_mode) == -1) {
- ec = capture_errno();
- return true;
- }
- ec.clear();
- return false;
-}
-
-bool stat_equivalent(const StatT& st1, const StatT& st2) {
- return (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
-}
-
-file_status FileDescriptor::refresh_status(error_code& ec) {
- // FD must be open and good.
- m_status = file_status{};
- m_stat = {};
- error_code m_ec;
- if (::fstat(fd, &m_stat) == -1)
- m_ec = capture_errno();
- m_status = create_file_status(m_ec, name, m_stat, &ec);
- return m_status;
-}
-} // namespace
-} // end namespace detail
-
-using detail::capture_errno;
-using detail::ErrorHandler;
-using detail::StatT;
-using detail::TimeSpec;
-using parser::createView;
-using parser::PathParser;
-using parser::string_view_t;
-
-const bool _FilesystemClock::is_steady;
-
-_FilesystemClock::time_point _FilesystemClock::now() noexcept {
- typedef chrono::duration<rep> __secs;
-#if defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
- typedef chrono::duration<rep, nano> __nsecs;
- struct timespec tp;
- if (0 != clock_gettime(CLOCK_REALTIME, &tp))
- __throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed");
- return time_point(__secs(tp.tv_sec) +
- chrono::duration_cast<duration>(__nsecs(tp.tv_nsec)));
-#else
- typedef chrono::duration<rep, micro> __microsecs;
- timeval tv;
- gettimeofday(&tv, 0);
- return time_point(__secs(tv.tv_sec) + __microsecs(tv.tv_usec));
-#endif // _LIBCPP_USE_CLOCK_GETTIME && CLOCK_REALTIME
-}
-
-filesystem_error::~filesystem_error() {}
-
-void filesystem_error::__create_what(int __num_paths) {
- const char* derived_what = system_error::what();
- __storage_->__what_ = [&]() -> string {
- const char* p1 = path1().native().empty() ? "\"\"" : path1().c_str();
- const char* p2 = path2().native().empty() ? "\"\"" : path2().c_str();
- switch (__num_paths) {
- default:
- return detail::format_string("filesystem error: %s", derived_what);
- case 1:
- return detail::format_string("filesystem error: %s [%s]", derived_what,
- p1);
- case 2:
- return detail::format_string("filesystem error: %s [%s] [%s]",
- derived_what, p1, p2);
- }
- }();
-}
-
-static path __do_absolute(const path& p, path* cwd, error_code* ec) {
- if (ec)
- ec->clear();
- if (p.is_absolute())
- return p;
- *cwd = __current_path(ec);
- if (ec && *ec)
- return {};
- return (*cwd) / p;
-}
-
-path __absolute(const path& p, error_code* ec) {
- path cwd;
- return __do_absolute(p, &cwd, ec);
-}
-
-path __canonical(path const& orig_p, error_code* ec) {
- path cwd;
- ErrorHandler<path> err("canonical", ec, &orig_p, &cwd);
-
- path p = __do_absolute(orig_p, &cwd, ec);
- char buff[PATH_MAX + 1];
- char* ret;
- if ((ret = ::realpath(p.c_str(), buff)) == nullptr)
- return err.report(capture_errno());
- return {ret};
-}
-
-void __copy(const path& from, const path& to, copy_options options,
- error_code* ec) {
- ErrorHandler<void> err("copy", ec, &from, &to);
-
- const bool sym_status = bool(
- options & (copy_options::create_symlinks | copy_options::skip_symlinks));
-
- const bool sym_status2 = bool(options & copy_options::copy_symlinks);
-
- error_code m_ec1;
- StatT f_st = {};
- const file_status f = sym_status || sym_status2
- ? detail::posix_lstat(from, f_st, &m_ec1)
- : detail::posix_stat(from, f_st, &m_ec1);
- if (m_ec1)
- return err.report(m_ec1);
-
- StatT t_st = {};
- const file_status t = sym_status ? detail::posix_lstat(to, t_st, &m_ec1)
- : detail::posix_stat(to, t_st, &m_ec1);
-
- if (not status_known(t))
- return err.report(m_ec1);
-
- if (!exists(f) || is_other(f) || is_other(t) ||
- (is_directory(f) && is_regular_file(t)) ||
- detail::stat_equivalent(f_st, t_st)) {
- return err.report(errc::function_not_supported);
- }
-
- if (ec)
- ec->clear();
-
- if (is_symlink(f)) {
- if (bool(copy_options::skip_symlinks & options)) {
- // do nothing
- } else if (not exists(t)) {
- __copy_symlink(from, to, ec);
- } else {
- return err.report(errc::file_exists);
- }
- return;
- } else if (is_regular_file(f)) {
- if (bool(copy_options::directories_only & options)) {
- // do nothing
- } else if (bool(copy_options::create_symlinks & options)) {
- __create_symlink(from, to, ec);
- } else if (bool(copy_options::create_hard_links & options)) {
- __create_hard_link(from, to, ec);
- } else if (is_directory(t)) {
- __copy_file(from, to / from.filename(), options, ec);
- } else {
- __copy_file(from, to, options, ec);
- }
- return;
- } else if (is_directory(f) && bool(copy_options::create_symlinks & options)) {
- return err.report(errc::is_a_directory);
- } else if (is_directory(f) && (bool(copy_options::recursive & options) ||
- copy_options::none == options)) {
-
- if (!exists(t)) {
- // create directory to with attributes from 'from'.
- __create_directory(to, from, ec);
- if (ec && *ec) {
- return;
- }
- }
- directory_iterator it =
- ec ? directory_iterator(from, *ec) : directory_iterator(from);
- if (ec && *ec) {
- return;
- }
- error_code m_ec2;
- for (; it != directory_iterator(); it.increment(m_ec2)) {
- if (m_ec2) {
- return err.report(m_ec2);
- }
- __copy(it->path(), to / it->path().filename(),
- options | copy_options::__in_recursive_copy, ec);
- if (ec && *ec) {
- return;
- }
- }
- }
-}
-
-namespace detail {
-namespace {
-
-#ifdef _LIBCPP_USE_SENDFILE
-bool copy_file_impl_sendfile(FileDescriptor& read_fd, FileDescriptor& write_fd,
- error_code& ec) {
-
- size_t count = read_fd.get_stat().st_size;
- do {
- ssize_t res;
- if ((res = ::sendfile(write_fd.fd, read_fd.fd, nullptr, count)) == -1) {
- ec = capture_errno();
- return false;
- }
- count -= res;
- } while (count > 0);
-
- ec.clear();
-
- return true;
-}
-#elif defined(_LIBCPP_USE_COPYFILE)
-bool copy_file_impl_copyfile(FileDescriptor& read_fd, FileDescriptor& write_fd,
- error_code& ec) {
- struct CopyFileState {
- copyfile_state_t state;
- CopyFileState() { state = copyfile_state_alloc(); }
- ~CopyFileState() { copyfile_state_free(state); }
-
- private:
- CopyFileState(CopyFileState const&) = delete;
- CopyFileState& operator=(CopyFileState const&) = delete;
- };
-
- CopyFileState cfs;
- if (fcopyfile(read_fd.fd, write_fd.fd, cfs.state, COPYFILE_DATA) < 0) {
- ec = capture_errno();
- return false;
- }
-
- ec.clear();
- return true;
-}
-#endif
-
-// Note: This function isn't guarded by ifdef's even though it may be unused
-// in order to assure it still compiles.
-__attribute__((unused)) bool copy_file_impl_default(FileDescriptor& read_fd,
- FileDescriptor& write_fd,
- error_code& ec) {
- ifstream in;
- in.__open(read_fd.fd, ios::binary);
- if (!in.is_open()) {
- // This assumes that __open didn't reset the error code.
- ec = capture_errno();
- return false;
- }
- ofstream out;
- out.__open(write_fd.fd, ios::binary);
- if (!out.is_open()) {
- ec = capture_errno();
- return false;
- }
-
- if (in.good() && out.good()) {
- using InIt = istreambuf_iterator<char>;
- using OutIt = ostreambuf_iterator<char>;
- InIt bin(in);
- InIt ein;
- OutIt bout(out);
- copy(bin, ein, bout);
- }
- if (out.fail() || in.fail()) {
- ec = make_error_code(errc::io_error);
- return false;
- }
-
- ec.clear();
- return true;
-}
-
-bool copy_file_impl(FileDescriptor& from, FileDescriptor& to, error_code& ec) {
-#if defined(_LIBCPP_USE_SENDFILE)
- return copy_file_impl_sendfile(from, to, ec);
-#elif defined(_LIBCPP_USE_COPYFILE)
- return copy_file_impl_copyfile(from, to, ec);
-#else
- return copy_file_impl_default(from, to, ec);
-#endif
-}
-
-} // namespace
-} // namespace detail
-
-bool __copy_file(const path& from, const path& to, copy_options options,
- error_code* ec) {
- using detail::FileDescriptor;
- ErrorHandler<bool> err("copy_file", ec, &to, &from);
-
- error_code m_ec;
- FileDescriptor from_fd =
- FileDescriptor::create_with_status(&from, m_ec, O_RDONLY | O_NONBLOCK);
- if (m_ec)
- return err.report(m_ec);
-
- auto from_st = from_fd.get_status();
- StatT const& from_stat = from_fd.get_stat();
- if (!is_regular_file(from_st)) {
- if (not m_ec)
- m_ec = make_error_code(errc::not_supported);
- return err.report(m_ec);
- }
-
- const bool skip_existing = bool(copy_options::skip_existing & options);
- const bool update_existing = bool(copy_options::update_existing & options);
- const bool overwrite_existing =
- bool(copy_options::overwrite_existing & options);
-
- StatT to_stat_path;
- file_status to_st = detail::posix_stat(to, to_stat_path, &m_ec);
- if (!status_known(to_st))
- return err.report(m_ec);
-
- const bool to_exists = exists(to_st);
- if (to_exists && !is_regular_file(to_st))
- return err.report(errc::not_supported);
-
- if (to_exists && detail::stat_equivalent(from_stat, to_stat_path))
- return err.report(errc::file_exists);
-
- if (to_exists && skip_existing)
- return false;
-
- bool ShouldCopy = [&]() {
- if (to_exists && update_existing) {
- auto from_time = detail::extract_mtime(from_stat);
- auto to_time = detail::extract_mtime(to_stat_path);
- if (from_time.tv_sec < to_time.tv_sec)
- return false;
- if (from_time.tv_sec == to_time.tv_sec &&
- from_time.tv_nsec <= to_time.tv_nsec)
- return false;
- return true;
- }
- if (!to_exists || overwrite_existing)
- return true;
- return err.report(errc::file_exists);
- }();
- if (!ShouldCopy)
- return false;
-
- // Don't truncate right away. We may not be opening the file we originally
- // looked at; we'll check this later.
- int to_open_flags = O_WRONLY;
- if (!to_exists)
- to_open_flags |= O_CREAT;
- FileDescriptor to_fd = FileDescriptor::create_with_status(
- &to, m_ec, to_open_flags, from_stat.st_mode);
- if (m_ec)
- return err.report(m_ec);
-
- if (to_exists) {
- // Check that the file we initially stat'ed is equivalent to the one
- // we opened.
- // FIXME: report this better.
- if (!detail::stat_equivalent(to_stat_path, to_fd.get_stat()))
- return err.report(errc::bad_file_descriptor);
-
- // Set the permissions and truncate the file we opened.
- if (detail::posix_fchmod(to_fd, from_stat, m_ec))
- return err.report(m_ec);
- if (detail::posix_ftruncate(to_fd, 0, m_ec))
- return err.report(m_ec);
- }
-
- if (!copy_file_impl(from_fd, to_fd, m_ec)) {
- // FIXME: Remove the dest file if we failed, and it didn't exist previously.
- return err.report(m_ec);
- }
-
- return true;
-}
-
-void __copy_symlink(const path& existing_symlink, const path& new_symlink,
- error_code* ec) {
- const path real_path(__read_symlink(existing_symlink, ec));
- if (ec && *ec) {
- return;
- }
- // NOTE: proposal says you should detect if you should call
- // create_symlink or create_directory_symlink. I don't think this
- // is needed with POSIX
- __create_symlink(real_path, new_symlink, ec);
-}
-
-bool __create_directories(const path& p, error_code* ec) {
- ErrorHandler<bool> err("create_directories", ec, &p);
-
- error_code m_ec;
- auto const st = detail::posix_stat(p, &m_ec);
- if (!status_known(st))
- return err.report(m_ec);
- else if (is_directory(st))
- return false;
- else if (exists(st))
- return err.report(errc::file_exists);
-
- const path parent = p.parent_path();
- if (!parent.empty()) {
- const file_status parent_st = status(parent, m_ec);
- if (not status_known(parent_st))
- return err.report(m_ec);
- if (not exists(parent_st)) {
- __create_directories(parent, ec);
- if (ec && *ec) {
- return false;
- }
- }
- }
- return __create_directory(p, ec);
-}
-
-bool __create_directory(const path& p, error_code* ec) {
- ErrorHandler<bool> err("create_directory", ec, &p);
-
- if (::mkdir(p.c_str(), static_cast<int>(perms::all)) == 0)
- return true;
- if (errno != EEXIST)
- err.report(capture_errno());
- return false;
-}
-
-bool __create_directory(path const& p, path const& attributes, error_code* ec) {
- ErrorHandler<bool> err("create_directory", ec, &p, &attributes);
-
- StatT attr_stat;
- error_code mec;
- auto st = detail::posix_stat(attributes, attr_stat, &mec);
- if (!status_known(st))
- return err.report(mec);
- if (!is_directory(st))
- return err.report(errc::not_a_directory,
- "the specified attribute path is invalid");
-
- if (::mkdir(p.c_str(), attr_stat.st_mode) == 0)
- return true;
- if (errno != EEXIST)
- err.report(capture_errno());
- return false;
-}
-
-void __create_directory_symlink(path const& from, path const& to,
- error_code* ec) {
- ErrorHandler<void> err("create_directory_symlink", ec, &from, &to);
- if (::symlink(from.c_str(), to.c_str()) != 0)
- return err.report(capture_errno());
-}
-
-void __create_hard_link(const path& from, const path& to, error_code* ec) {
- ErrorHandler<void> err("create_hard_link", ec, &from, &to);
- if (::link(from.c_str(), to.c_str()) == -1)
- return err.report(capture_errno());
-}
-
-void __create_symlink(path const& from, path const& to, error_code* ec) {
- ErrorHandler<void> err("create_symlink", ec, &from, &to);
- if (::symlink(from.c_str(), to.c_str()) == -1)
- return err.report(capture_errno());
-}
-
-path __current_path(error_code* ec) {
- ErrorHandler<path> err("current_path", ec);
-
- auto size = ::pathconf(".", _PC_PATH_MAX);
- _LIBCPP_ASSERT(size >= 0, "pathconf returned a 0 as max size");
-
- auto buff = unique_ptr<char[]>(new char[size + 1]);
- char* ret;
- if ((ret = ::getcwd(buff.get(), static_cast<size_t>(size))) == nullptr)
- return err.report(capture_errno(), "call to getcwd failed");
-
- return {buff.get()};
-}
-
-void __current_path(const path& p, error_code* ec) {
- ErrorHandler<void> err("current_path", ec, &p);
- if (::chdir(p.c_str()) == -1)
- err.report(capture_errno());
-}
-
-bool __equivalent(const path& p1, const path& p2, error_code* ec) {
- ErrorHandler<bool> err("equivalent", ec, &p1, &p2);
-
- error_code ec1, ec2;
- StatT st1 = {}, st2 = {};
- auto s1 = detail::posix_stat(p1.native(), st1, &ec1);
- if (!exists(s1))
- return err.report(errc::not_supported);
- auto s2 = detail::posix_stat(p2.native(), st2, &ec2);
- if (!exists(s2))
- return err.report(errc::not_supported);
-
- return detail::stat_equivalent(st1, st2);
-}
-
-uintmax_t __file_size(const path& p, error_code* ec) {
- ErrorHandler<uintmax_t> err("file_size", ec, &p);
-
- error_code m_ec;
- StatT st;
- file_status fst = detail::posix_stat(p, st, &m_ec);
- if (!exists(fst) || !is_regular_file(fst)) {
- errc error_kind =
- is_directory(fst) ? errc::is_a_directory : errc::not_supported;
- if (!m_ec)
- m_ec = make_error_code(error_kind);
- return err.report(m_ec);
- }
- // is_regular_file(p) == true
- return static_cast<uintmax_t>(st.st_size);
-}
-
-uintmax_t __hard_link_count(const path& p, error_code* ec) {
- ErrorHandler<uintmax_t> err("hard_link_count", ec, &p);
-
- error_code m_ec;
- StatT st;
- detail::posix_stat(p, st, &m_ec);
- if (m_ec)
- return err.report(m_ec);
- return static_cast<uintmax_t>(st.st_nlink);
-}
-
-bool __fs_is_empty(const path& p, error_code* ec) {
- ErrorHandler<bool> err("is_empty", ec, &p);
-
- error_code m_ec;
- StatT pst;
- auto st = detail::posix_stat(p, pst, &m_ec);
- if (m_ec)
- return err.report(m_ec);
- else if (!is_directory(st) && !is_regular_file(st))
- return err.report(errc::not_supported);
- else if (is_directory(st)) {
- auto it = ec ? directory_iterator(p, *ec) : directory_iterator(p);
- if (ec && *ec)
- return false;
- return it == directory_iterator{};
- } else if (is_regular_file(st))
- return static_cast<uintmax_t>(pst.st_size) == 0;
-
- _LIBCPP_UNREACHABLE();
-}
-
-static file_time_type __extract_last_write_time(const path& p, const StatT& st,
- error_code* ec) {
- using detail::fs_time;
- ErrorHandler<file_time_type> err("last_write_time", ec, &p);
-
- auto ts = detail::extract_mtime(st);
- if (!fs_time::is_representable(ts))
- return err.report(errc::value_too_large);
-
- return fs_time::convert_from_timespec(ts);
-}
-
-file_time_type __last_write_time(const path& p, error_code* ec) {
- using namespace chrono;
- ErrorHandler<file_time_type> err("last_write_time", ec, &p);
-
- error_code m_ec;
- StatT st;
- detail::posix_stat(p, st, &m_ec);
- if (m_ec)
- return err.report(m_ec);
- return __extract_last_write_time(p, st, ec);
-}
-
-void __last_write_time(const path& p, file_time_type new_time, error_code* ec) {
- using detail::fs_time;
- ErrorHandler<void> err("last_write_time", ec, &p);
-
- error_code m_ec;
- array<TimeSpec, 2> tbuf;
-#if !defined(_LIBCPP_USE_UTIMENSAT)
- // This implementation has a race condition between determining the
- // last access time and attempting to set it to the same value using
- // ::utimes
- StatT st;
- file_status fst = detail::posix_stat(p, st, &m_ec);
- if (m_ec)
- return err.report(m_ec);
- tbuf[0] = detail::extract_atime(st);
-#else
- tbuf[0].tv_sec = 0;
- tbuf[0].tv_nsec = UTIME_OMIT;
-#endif
- if (!fs_time::convert_to_timespec(tbuf[1], new_time))
- return err.report(errc::value_too_large);
-
- detail::set_file_times(p, tbuf, m_ec);
- if (m_ec)
- return err.report(m_ec);
-}
-
-void __permissions(const path& p, perms prms, perm_options opts,
- error_code* ec) {
- ErrorHandler<void> err("permissions", ec, &p);
-
- auto has_opt = [&](perm_options o) { return bool(o & opts); };
- const bool resolve_symlinks = !has_opt(perm_options::nofollow);
- const bool add_perms = has_opt(perm_options::add);
- const bool remove_perms = has_opt(perm_options::remove);
- _LIBCPP_ASSERT(
- (add_perms + remove_perms + has_opt(perm_options::replace)) == 1,
- "One and only one of the perm_options constants replace, add, or remove "
- "is present in opts");
-
- bool set_sym_perms = false;
- prms &= perms::mask;
- if (!resolve_symlinks || (add_perms || remove_perms)) {
- error_code m_ec;
- file_status st = resolve_symlinks ? detail::posix_stat(p, &m_ec)
- : detail::posix_lstat(p, &m_ec);
- set_sym_perms = is_symlink(st);
- if (m_ec)
- return err.report(m_ec);
- _LIBCPP_ASSERT(st.permissions() != perms::unknown,
- "Permissions unexpectedly unknown");
- if (add_perms)
- prms |= st.permissions();
- else if (remove_perms)
- prms = st.permissions() & ~prms;
- }
- const auto real_perms = detail::posix_convert_perms(prms);
-
-#if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_FDCWD)
- const int flags = set_sym_perms ? AT_SYMLINK_NOFOLLOW : 0;
- if (::fchmodat(AT_FDCWD, p.c_str(), real_perms, flags) == -1) {
- return err.report(capture_errno());
- }
-#else
- if (set_sym_perms)
- return err.report(errc::operation_not_supported);
- if (::chmod(p.c_str(), real_perms) == -1) {
- return err.report(capture_errno());
- }
-#endif
-}
-
-path __read_symlink(const path& p, error_code* ec) {
- ErrorHandler<path> err("read_symlink", ec, &p);
-
- char buff[PATH_MAX + 1];
- error_code m_ec;
- ::ssize_t ret;
- if ((ret = ::readlink(p.c_str(), buff, PATH_MAX)) == -1) {
- return err.report(capture_errno());
- }
- _LIBCPP_ASSERT(ret <= PATH_MAX, "TODO");
- _LIBCPP_ASSERT(ret > 0, "TODO");
- buff[ret] = 0;
- return {buff};
-}
-
-bool __remove(const path& p, error_code* ec) {
- ErrorHandler<bool> err("remove", ec, &p);
- if (::remove(p.c_str()) == -1) {
- if (errno != ENOENT)
- err.report(capture_errno());
- return false;
- }
- return true;
-}
-
-namespace {
-
-uintmax_t remove_all_impl(path const& p, error_code& ec) {
- const auto npos = static_cast<uintmax_t>(-1);
- const file_status st = __symlink_status(p, &ec);
- if (ec)
- return npos;
- uintmax_t count = 1;
- if (is_directory(st)) {
- for (directory_iterator it(p, ec); !ec && it != directory_iterator();
- it.increment(ec)) {
- auto other_count = remove_all_impl(it->path(), ec);
- if (ec)
- return npos;
- count += other_count;
- }
- if (ec)
- return npos;
- }
- if (!__remove(p, &ec))
- return npos;
- return count;
-}
-
-} // end namespace
-
-uintmax_t __remove_all(const path& p, error_code* ec) {
- ErrorHandler<uintmax_t> err("remove_all", ec, &p);
-
- error_code mec;
- auto count = remove_all_impl(p, mec);
- if (mec) {
- if (mec == errc::no_such_file_or_directory)
- return 0;
- return err.report(mec);
- }
- return count;
-}
-
-void __rename(const path& from, const path& to, error_code* ec) {
- ErrorHandler<void> err("rename", ec, &from, &to);
- if (::rename(from.c_str(), to.c_str()) == -1)
- err.report(capture_errno());
-}
-
-void __resize_file(const path& p, uintmax_t size, error_code* ec) {
- ErrorHandler<void> err("resize_file", ec, &p);
- if (::truncate(p.c_str(), static_cast< ::off_t>(size)) == -1)
- return err.report(capture_errno());
-}
-
-space_info __space(const path& p, error_code* ec) {
- ErrorHandler<void> err("space", ec, &p);
- space_info si;
- struct statvfs m_svfs = {};
- if (::statvfs(p.c_str(), &m_svfs) == -1) {
- err.report(capture_errno());
- si.capacity = si.free = si.available = static_cast<uintmax_t>(-1);
- return si;
- }
- // Multiply with overflow checking.
- auto do_mult = [&](uintmax_t& out, uintmax_t other) {
- out = other * m_svfs.f_frsize;
- if (other == 0 || out / other != m_svfs.f_frsize)
- out = static_cast<uintmax_t>(-1);
- };
- do_mult(si.capacity, m_svfs.f_blocks);
- do_mult(si.free, m_svfs.f_bfree);
- do_mult(si.available, m_svfs.f_bavail);
- return si;
-}
-
-file_status __status(const path& p, error_code* ec) {
- return detail::posix_stat(p, ec);
-}
-
-file_status __symlink_status(const path& p, error_code* ec) {
- return detail::posix_lstat(p, ec);
-}
-
-path __temp_directory_path(error_code* ec) {
- ErrorHandler<path> err("temp_directory_path", ec);
-
- const char* env_paths[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"};
- const char* ret = nullptr;
-
- for (auto& ep : env_paths)
- if ((ret = getenv(ep)))
- break;
- if (ret == nullptr)
- ret = "/tmp";
-
- path p(ret);
- error_code m_ec;
- file_status st = detail::posix_stat(p, &m_ec);
- if (!status_known(st))
- return err.report(m_ec, "cannot access path \"%s\"", p);
-
- if (!exists(st) || !is_directory(st))
- return err.report(errc::not_a_directory, "path \"%s\" is not a directory",
- p);
-
- return p;
-}
-
-path __weakly_canonical(const path& p, error_code* ec) {
- ErrorHandler<path> err("weakly_canonical", ec, &p);
-
- if (p.empty())
- return __canonical("", ec);
-
- path result;
- path tmp;
- tmp.__reserve(p.native().size());
- auto PP = PathParser::CreateEnd(p.native());
- --PP;
- vector<string_view_t> DNEParts;
-
- while (PP.State != PathParser::PS_BeforeBegin) {
- tmp.assign(createView(p.native().data(), &PP.RawEntry.back()));
- error_code m_ec;
- file_status st = __status(tmp, &m_ec);
- if (!status_known(st)) {
- return err.report(m_ec);
- } else if (exists(st)) {
- result = __canonical(tmp, ec);
- break;
- }
- DNEParts.push_back(*PP);
- --PP;
- }
- if (PP.State == PathParser::PS_BeforeBegin)
- result = __canonical("", ec);
- if (ec)
- ec->clear();
- if (DNEParts.empty())
- return result;
- for (auto It = DNEParts.rbegin(); It != DNEParts.rend(); ++It)
- result /= *It;
- return result.lexically_normal();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// path definitions
-///////////////////////////////////////////////////////////////////////////////
-
-constexpr path::value_type path::preferred_separator;
-
-path& path::replace_extension(path const& replacement) {
- path p = extension();
- if (not p.empty()) {
- __pn_.erase(__pn_.size() - p.native().size());
- }
- if (!replacement.empty()) {
- if (replacement.native()[0] != '.') {
- __pn_ += ".";
- }
- __pn_.append(replacement.__pn_);
- }
- return *this;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// path.decompose
-
-string_view_t path::__root_name() const {
- auto PP = PathParser::CreateBegin(__pn_);
- if (PP.State == PathParser::PS_InRootName)
- return *PP;
- return {};
-}
-
-string_view_t path::__root_directory() const {
- auto PP = PathParser::CreateBegin(__pn_);
- if (PP.State == PathParser::PS_InRootName)
- ++PP;
- if (PP.State == PathParser::PS_InRootDir)
- return *PP;
- return {};
-}
-
-string_view_t path::__root_path_raw() const {
- auto PP = PathParser::CreateBegin(__pn_);
- if (PP.State == PathParser::PS_InRootName) {
- auto NextCh = PP.peek();
- if (NextCh && *NextCh == '/') {
- ++PP;
- return createView(__pn_.data(), &PP.RawEntry.back());
- }
- return PP.RawEntry;
- }
- if (PP.State == PathParser::PS_InRootDir)
- return *PP;
- return {};
-}
-
-static bool ConsumeRootName(PathParser *PP) {
- static_assert(PathParser::PS_BeforeBegin == 1 &&
- PathParser::PS_InRootName == 2,
- "Values for enums are incorrect");
- while (PP->State <= PathParser::PS_InRootName)
- ++(*PP);
- return PP->State == PathParser::PS_AtEnd;
-}
-
-static bool ConsumeRootDir(PathParser* PP) {
- static_assert(PathParser::PS_BeforeBegin == 1 &&
- PathParser::PS_InRootName == 2 &&
- PathParser::PS_InRootDir == 3, "Values for enums are incorrect");
- while (PP->State <= PathParser::PS_InRootDir)
- ++(*PP);
- return PP->State == PathParser::PS_AtEnd;
-}
-
-string_view_t path::__relative_path() const {
- auto PP = PathParser::CreateBegin(__pn_);
- if (ConsumeRootDir(&PP))
- return {};
- return createView(PP.RawEntry.data(), &__pn_.back());
-}
-
-string_view_t path::__parent_path() const {
- if (empty())
- return {};
- // Determine if we have a root path but not a relative path. In that case
- // return *this.
- {
- auto PP = PathParser::CreateBegin(__pn_);
- if (ConsumeRootDir(&PP))
- return __pn_;
- }
- // Otherwise remove a single element from the end of the path, and return
- // a string representing that path
- {
- auto PP = PathParser::CreateEnd(__pn_);
- --PP;
- if (PP.RawEntry.data() == __pn_.data())
- return {};
- --PP;
- return createView(__pn_.data(), &PP.RawEntry.back());
- }
-}
-
-string_view_t path::__filename() const {
- if (empty())
- return {};
- {
- PathParser PP = PathParser::CreateBegin(__pn_);
- if (ConsumeRootDir(&PP))
- return {};
- }
- return *(--PathParser::CreateEnd(__pn_));
-}
-
-string_view_t path::__stem() const {
- return parser::separate_filename(__filename()).first;
-}
-
-string_view_t path::__extension() const {
- return parser::separate_filename(__filename()).second;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// path.gen
-
-enum PathPartKind : unsigned char {
- PK_None,
- PK_RootSep,
- PK_Filename,
- PK_Dot,
- PK_DotDot,
- PK_TrailingSep
-};
-
-static PathPartKind ClassifyPathPart(string_view_t Part) {
- if (Part.empty())
- return PK_TrailingSep;
- if (Part == ".")
- return PK_Dot;
- if (Part == "..")
- return PK_DotDot;
- if (Part == "/")
- return PK_RootSep;
- return PK_Filename;
-}
-
-path path::lexically_normal() const {
- if (__pn_.empty())
- return *this;
-
- using PartKindPair = pair<string_view_t, PathPartKind>;
- vector<PartKindPair> Parts;
- // Guess as to how many elements the path has to avoid reallocating.
- Parts.reserve(32);
-
- // Track the total size of the parts as we collect them. This allows the
- // resulting path to reserve the correct amount of memory.
- size_t NewPathSize = 0;
- auto AddPart = [&](PathPartKind K, string_view_t P) {
- NewPathSize += P.size();
- Parts.emplace_back(P, K);
- };
- auto LastPartKind = [&]() {
- if (Parts.empty())
- return PK_None;
- return Parts.back().second;
- };
-
- bool MaybeNeedTrailingSep = false;
- // Build a stack containing the remaining elements of the path, popping off
- // elements which occur before a '..' entry.
- for (auto PP = PathParser::CreateBegin(__pn_); PP; ++PP) {
- auto Part = *PP;
- PathPartKind Kind = ClassifyPathPart(Part);
- switch (Kind) {
- case PK_Filename:
- case PK_RootSep: {
- // Add all non-dot and non-dot-dot elements to the stack of elements.
- AddPart(Kind, Part);
- MaybeNeedTrailingSep = false;
- break;
- }
- case PK_DotDot: {
- // Only push a ".." element if there are no elements preceding the "..",
- // or if the preceding element is itself "..".
- auto LastKind = LastPartKind();
- if (LastKind == PK_Filename) {
- NewPathSize -= Parts.back().first.size();
- Parts.pop_back();
- } else if (LastKind != PK_RootSep)
- AddPart(PK_DotDot, "..");
- MaybeNeedTrailingSep = LastKind == PK_Filename;
- break;
- }
- case PK_Dot:
- case PK_TrailingSep: {
- MaybeNeedTrailingSep = true;
- break;
- }
- case PK_None:
- _LIBCPP_UNREACHABLE();
- }
- }
- // [fs.path.generic]p6.8: If the path is empty, add a dot.
- if (Parts.empty())
- return ".";
-
- // [fs.path.generic]p6.7: If the last filename is dot-dot, remove any
- // trailing directory-separator.
- bool NeedTrailingSep = MaybeNeedTrailingSep && LastPartKind() == PK_Filename;
-
- path Result;
- Result.__pn_.reserve(Parts.size() + NewPathSize + NeedTrailingSep);
- for (auto& PK : Parts)
- Result /= PK.first;
-
- if (NeedTrailingSep)
- Result /= "";
-
- return Result;
-}
-
-static int DetermineLexicalElementCount(PathParser PP) {
- int Count = 0;
- for (; PP; ++PP) {
- auto Elem = *PP;
- if (Elem == "..")
- --Count;
- else if (Elem != "." && Elem != "")
- ++Count;
- }
- return Count;
-}
-
-path path::lexically_relative(const path& base) const {
- { // perform root-name/root-directory mismatch checks
- auto PP = PathParser::CreateBegin(__pn_);
- auto PPBase = PathParser::CreateBegin(base.__pn_);
- auto CheckIterMismatchAtBase = [&]() {
- return PP.State != PPBase.State &&
- (PP.inRootPath() || PPBase.inRootPath());
- };
- if (PP.inRootName() && PPBase.inRootName()) {
- if (*PP != *PPBase)
- return {};
- } else if (CheckIterMismatchAtBase())
- return {};
-
- if (PP.inRootPath())
- ++PP;
- if (PPBase.inRootPath())
- ++PPBase;
- if (CheckIterMismatchAtBase())
- return {};
- }
-
- // Find the first mismatching element
- auto PP = PathParser::CreateBegin(__pn_);
- auto PPBase = PathParser::CreateBegin(base.__pn_);
- while (PP && PPBase && PP.State == PPBase.State && *PP == *PPBase) {
- ++PP;
- ++PPBase;
- }
-
- // If there is no mismatch, return ".".
- if (!PP && !PPBase)
- return ".";
-
- // Otherwise, determine the number of elements, 'n', which are not dot or
- // dot-dot minus the number of dot-dot elements.
- int ElemCount = DetermineLexicalElementCount(PPBase);
- if (ElemCount < 0)
- return {};
-
- // if n == 0 and (a == end() || a->empty()), returns path("."); otherwise
- if (ElemCount == 0 && (PP.atEnd() || *PP == ""))
- return ".";
-
- // return a path constructed with 'n' dot-dot elements, followed by the
- // elements of '*this' after the mismatch.
- path Result;
- // FIXME: Reserve enough room in Result that it won't have to re-allocate.
- while (ElemCount--)
- Result /= "..";
- for (; PP; ++PP)
- Result /= *PP;
- return Result;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// path.comparisons
-static int CompareRootName(PathParser *LHS, PathParser *RHS) {
- if (!LHS->inRootName() && !RHS->inRootName())
- return 0;
-
- auto GetRootName = [](PathParser *Parser) -> string_view_t {
- return Parser->inRootName() ? **Parser : "";
- };
- int res = GetRootName(LHS).compare(GetRootName(RHS));
- ConsumeRootName(LHS);
- ConsumeRootName(RHS);
- return res;
-}
-
-static int CompareRootDir(PathParser *LHS, PathParser *RHS) {
- if (!LHS->inRootDir() && RHS->inRootDir())
- return -1;
- else if (LHS->inRootDir() && !RHS->inRootDir())
- return 1;
- else {
- ConsumeRootDir(LHS);
- ConsumeRootDir(RHS);
- return 0;
- }
-}
-
-static int CompareRelative(PathParser *LHSPtr, PathParser *RHSPtr) {
- auto &LHS = *LHSPtr;
- auto &RHS = *RHSPtr;
-
- int res;
- while (LHS && RHS) {
- if ((res = (*LHS).compare(*RHS)) != 0)
- return res;
- ++LHS;
- ++RHS;
- }
- return 0;
-}
-
-static int CompareEndState(PathParser *LHS, PathParser *RHS) {
- if (LHS->atEnd() && !RHS->atEnd())
- return -1;
- else if (!LHS->atEnd() && RHS->atEnd())
- return 1;
- return 0;
-}
-
-int path::__compare(string_view_t __s) const {
- auto LHS = PathParser::CreateBegin(__pn_);
- auto RHS = PathParser::CreateBegin(__s);
- int res;
-
- if ((res = CompareRootName(&LHS, &RHS)) != 0)
- return res;
-
- if ((res = CompareRootDir(&LHS, &RHS)) != 0)
- return res;
-
- if ((res = CompareRelative(&LHS, &RHS)) != 0)
- return res;
-
- return CompareEndState(&LHS, &RHS);
-}
-
-////////////////////////////////////////////////////////////////////////////
-// path.nonmembers
-size_t hash_value(const path& __p) noexcept {
- auto PP = PathParser::CreateBegin(__p.native());
- size_t hash_value = 0;
- hash<string_view_t> hasher;
- while (PP) {
- hash_value = __hash_combine(hash_value, hasher(*PP));
- ++PP;
- }
- return hash_value;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// path.itr
-path::iterator path::begin() const {
- auto PP = PathParser::CreateBegin(__pn_);
- iterator it;
- it.__path_ptr_ = this;
- it.__state_ = static_cast<path::iterator::_ParserState>(PP.State);
- it.__entry_ = PP.RawEntry;
- it.__stashed_elem_.__assign_view(*PP);
- return it;
-}
-
-path::iterator path::end() const {
- iterator it{};
- it.__state_ = path::iterator::_AtEnd;
- it.__path_ptr_ = this;
- return it;
-}
-
-path::iterator& path::iterator::__increment() {
- PathParser PP(__path_ptr_->native(), __entry_, __state_);
- ++PP;
- __state_ = static_cast<_ParserState>(PP.State);
- __entry_ = PP.RawEntry;
- __stashed_elem_.__assign_view(*PP);
- return *this;
-}
-
-path::iterator& path::iterator::__decrement() {
- PathParser PP(__path_ptr_->native(), __entry_, __state_);
- --PP;
- __state_ = static_cast<_ParserState>(PP.State);
- __entry_ = PP.RawEntry;
- __stashed_elem_.__assign_view(*PP);
- return *this;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// directory entry definitions
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef _LIBCPP_WIN32API
-error_code directory_entry::__do_refresh() noexcept {
- __data_.__reset();
- error_code failure_ec;
-
- StatT full_st;
- file_status st = detail::posix_lstat(__p_, full_st, &failure_ec);
- if (!status_known(st)) {
- __data_.__reset();
- return failure_ec;
- }
-
- if (!_VSTD_FS::exists(st) || !_VSTD_FS::is_symlink(st)) {
- __data_.__cache_type_ = directory_entry::_RefreshNonSymlink;
- __data_.__type_ = st.type();
- __data_.__non_sym_perms_ = st.permissions();
- } else { // we have a symlink
- __data_.__sym_perms_ = st.permissions();
- // Get the information about the linked entity.
- // Ignore errors from stat, since we don't want errors regarding symlink
- // resolution to be reported to the user.
- error_code ignored_ec;
- st = detail::posix_stat(__p_, full_st, &ignored_ec);
-
- __data_.__type_ = st.type();
- __data_.__non_sym_perms_ = st.permissions();
-
- // If we failed to resolve the link, then only partially populate the
- // cache.
- if (!status_known(st)) {
- __data_.__cache_type_ = directory_entry::_RefreshSymlinkUnresolved;
- return error_code{};
- }
- // Otherwise, we resolved the link, potentially as not existing.
- // That's OK.
- __data_.__cache_type_ = directory_entry::_RefreshSymlink;
- }
-
- if (_VSTD_FS::is_regular_file(st))
- __data_.__size_ = static_cast<uintmax_t>(full_st.st_size);
-
- if (_VSTD_FS::exists(st)) {
- __data_.__nlink_ = static_cast<uintmax_t>(full_st.st_nlink);
-
- // Attempt to extract the mtime, and fail if it's not representable using
- // file_time_type. For now we ignore the error, as we'll report it when
- // the value is actually used.
- error_code ignored_ec;
- __data_.__write_time_ =
- __extract_last_write_time(__p_, full_st, &ignored_ec);
- }
-
- return failure_ec;
-}
-#else
-error_code directory_entry::__do_refresh() noexcept {
- __data_.__reset();
- error_code failure_ec;
-
- file_status st = _VSTD_FS::symlink_status(__p_, failure_ec);
- if (!status_known(st)) {
- __data_.__reset();
- return failure_ec;
- }
-
- if (!_VSTD_FS::exists(st) || !_VSTD_FS::is_symlink(st)) {
- __data_.__cache_type_ = directory_entry::_RefreshNonSymlink;
- __data_.__type_ = st.type();
- __data_.__non_sym_perms_ = st.permissions();
- } else { // we have a symlink
- __data_.__sym_perms_ = st.permissions();
- // Get the information about the linked entity.
- // Ignore errors from stat, since we don't want errors regarding symlink
- // resolution to be reported to the user.
- error_code ignored_ec;
- st = _VSTD_FS::status(__p_, ignored_ec);
-
- __data_.__type_ = st.type();
- __data_.__non_sym_perms_ = st.permissions();
-
- // If we failed to resolve the link, then only partially populate the
- // cache.
- if (!status_known(st)) {
- __data_.__cache_type_ = directory_entry::_RefreshSymlinkUnresolved;
- return error_code{};
- }
- __data_.__cache_type_ = directory_entry::_RefreshSymlink;
- }
-
- // FIXME: This is currently broken, and the implementation only a placeholder.
- // We need to cache last_write_time, file_size, and hard_link_count here before
- // the implementation actually works.
-
- return failure_ec;
-}
-#endif
-
-#ifndef _LIBAUTO_UNDEF_VSTD_FS
-#pragma pop_macro("_VSTD_FS")
-#else
-#undef _VSTD
-#undef _LIBAUTO_UNDEF_VSTD_FS
-#endif
-} // namespace android::hardware::automotive::filesystem
-/* clang-format on */
-
-#endif // defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 8000
diff --git a/automotive/evs/aidl/impl/default/include/EvsVideoEmulatedCamera.h b/automotive/evs/aidl/impl/default/include/EvsVideoEmulatedCamera.h
index a850d65..9d1610a 100644
--- a/automotive/evs/aidl/impl/default/include/EvsVideoEmulatedCamera.h
+++ b/automotive/evs/aidl/impl/default/include/EvsVideoEmulatedCamera.h
@@ -93,6 +93,8 @@
bool initialize();
+ bool initializeMediaCodec();
+
void generateFrames();
void renderOneFrame();
diff --git a/automotive/evs/aidl/impl/default/resources/evs_mock_configuration.xml b/automotive/evs/aidl/impl/default/resources/evs_mock_configuration.xml
index 6cbc18e..af5b354 100644
--- a/automotive/evs/aidl/impl/default/resources/evs_mock_configuration.xml
+++ b/automotive/evs/aidl/impl/default/resources/evs_mock_configuration.xml
@@ -55,6 +55,30 @@
/>
</characteristics>
</device>
+ <device id='/dev/video11' position='front'>
+ <caps>
+ <!-- list of supported controls -->
+ <supported_controls>
+ <control name='BRIGHTNESS' min='0' max='255'/>
+ <control name='CONTRAST' min='0' max='255'/>
+ </supported_controls>
+
+ <stream id='0' width='640' height='360' format='RGBA_8888' framerate='30'/>
+ </caps>
+
+ <!-- list of parameters -->
+ <characteristics>
+ <!-- Camera intrinsic calibration matrix. See
+ https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#LENS_INTRINSIC_CALIBRATION
+ -->
+ <parameter
+ name='LENS_INTRINSIC_CALIBRATION'
+ type='float'
+ size='5'
+ value='0.0,0.0,0.0,0.0,0.0'
+ />
+ </characteristics>
+ </device>
</camera>
<display>
<device id='display0' position='driver'>
diff --git a/automotive/evs/aidl/impl/default/src/EvsCamera.cpp b/automotive/evs/aidl/impl/default/src/EvsCamera.cpp
index bc3bfdd..005c71f 100644
--- a/automotive/evs/aidl/impl/default/src/EvsCamera.cpp
+++ b/automotive/evs/aidl/impl/default/src/EvsCamera.cpp
@@ -198,9 +198,14 @@
auto status = ndk::ScopedAStatus::ok();
{
std::unique_lock lck(mMutex);
+ if (mStreamState != StreamState::RUNNING) {
+ // We're already in the middle of the procedure to stop current data
+ // stream.
+ return status;
+ }
+
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 e3f7b5e..480c28d 100644
--- a/automotive/evs/aidl/impl/default/src/EvsVideoEmulatedCamera.cpp
+++ b/automotive/evs/aidl/impl/default/src/EvsVideoEmulatedCamera.cpp
@@ -81,6 +81,10 @@
}
}
+ return initializeMediaCodec();
+}
+
+bool EvsVideoEmulatedCamera::initializeMediaCodec() {
// Initialize Media Codec and file format.
std::unique_ptr<AMediaFormat, FormatDeleter> format;
const char* mime;
@@ -304,6 +308,13 @@
LOG(ERROR) << __func__
<< ": Received error in releasing output buffer. Error code: " << release_status;
}
+
+ if ((info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) != 0) {
+ LOG(INFO) << "Start video playback from the beginning.";
+ AMediaExtractor_seekTo(mVideoExtractor.get(), /* seekPosUs= */ 0,
+ AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC);
+ AMediaCodec_flush(mVideoCodec.get());
+ }
}
void EvsVideoEmulatedCamera::initializeParameters() {
@@ -337,11 +348,24 @@
std::unique_lock<std::mutex>& /* lck */) {
mStream = receiver;
- const media_status_t status = AMediaCodec_start(mVideoCodec.get());
- if (status != AMEDIA_OK) {
- LOG(ERROR) << __func__ << ": Received error in starting decoder. Error code: " << status
- << ".";
- return false;
+ 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.";
+
+ if (!initializeMediaCodec()) {
+ LOG(ERROR) << __func__ << ": Failed to re-configure the media codec.";
+ return false;
+ }
+
+ AMediaExtractor_seekTo(mVideoExtractor.get(), /* seekPosUs= */ 0,
+ AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC);
+ AMediaCodec_flush(mVideoCodec.get());
+
+ if(auto status = AMediaCodec_start(mVideoCodec.get()); status != AMEDIA_OK) {
+ LOG(ERROR) << __func__ << ": Received error again in starting decoder. "
+ << "Error code: " << status;
+ return false;
+ }
}
mCaptureThread = std::thread([this]() { generateFrames(); });
@@ -364,6 +388,12 @@
if (!Base::postVideoStreamStop_locked(status, lck)) {
return false;
}
+
+ EvsEventDesc event = { .aType = EvsEventType::STREAM_STOPPED, };
+ if (auto result = mStream->notify(event); !result.isOk()) {
+ LOG(WARNING) << "Failed to notify the end of the stream.";
+ }
+
mStream = nullptr;
return true;
}
diff --git a/automotive/remoteaccess/test_grpc_server/impl/src/TestWakeupClientServiceImpl.cpp b/automotive/remoteaccess/test_grpc_server/impl/src/TestWakeupClientServiceImpl.cpp
index 5d33fcb..515dc98 100644
--- a/automotive/remoteaccess/test_grpc_server/impl/src/TestWakeupClientServiceImpl.cpp
+++ b/automotive/remoteaccess/test_grpc_server/impl/src/TestWakeupClientServiceImpl.cpp
@@ -169,7 +169,8 @@
Looper::setForThread(mLooper);
while (true) {
- mLooper->pollAll(/*timeoutMillis=*/-1);
+ // Don't use pollAll since it might swallow wake.
+ mLooper->pollOnce(/*timeoutMillis=*/-1);
if (mServerStopped) {
return;
}
diff --git a/automotive/remoteaccess/test_grpc_server/impl/test/TestWakeupClientServiceImplUnitTest.cpp b/automotive/remoteaccess/test_grpc_server/impl/test/TestWakeupClientServiceImplUnitTest.cpp
index 4bc0086..a7927f5 100644
--- a/automotive/remoteaccess/test_grpc_server/impl/test/TestWakeupClientServiceImplUnitTest.cpp
+++ b/automotive/remoteaccess/test_grpc_server/impl/test/TestWakeupClientServiceImplUnitTest.cpp
@@ -41,7 +41,6 @@
constexpr int32_t kTestCount = 1234;
constexpr int64_t kTestStartTimeInEpochSeconds = 2345;
constexpr int64_t kTestPeriodicInSeconds = 123;
-const std::string kTestGrpcAddr = "localhost:50051";
class MyTestWakeupClientServiceImpl final : public ServiceImpl {
public:
@@ -53,27 +52,41 @@
class TestWakeupClientServiceImplUnitTest : public ::testing::Test {
public:
virtual void SetUp() override {
- mServerThread = std::thread([this] {
+ int selectedPort = 0;
+ mServerStarted = false;
+ mService.reset();
+ mServer.reset();
+ mServerThread = std::thread([this, &selectedPort] {
mService = std::make_unique<MyTestWakeupClientServiceImpl>();
ServerBuilder builder;
- builder.AddListeningPort(kTestGrpcAddr, grpc::InsecureServerCredentials());
+ builder.AddListeningPort("localhost:0", grpc::InsecureServerCredentials(),
+ &selectedPort);
WakeupClientServiceImpl wakeupClientService(mService.get());
builder.RegisterService(&wakeupClientService);
mServer = builder.BuildAndStart();
+ mServerStarted = true;
{
std::unique_lock<std::mutex> lock(mLock);
mServerStartCv.notify_one();
}
- mServer->Wait();
+ if (mServer != nullptr) {
+ mServer->Wait();
+ }
});
{
std::unique_lock<std::mutex> lock(mLock);
- mServerStartCv.wait(lock, [this] {
+ bool serverStarted = mServerStartCv.wait_for(lock, std::chrono::seconds(10), [this] {
ScopedLockAssertion lockAssertion(mLock);
- return mServer != nullptr;
+ return mServerStarted.load();
});
+ ASSERT_TRUE(serverStarted) << "Failed to wait for mServerStarted to be set within 10s";
}
- mChannel = grpc::CreateChannel(kTestGrpcAddr, grpc::InsecureChannelCredentials());
+ if (mServer == nullptr) {
+ GTEST_SKIP() << "Failed to start the test grpc server";
+ }
+ std::string address = "localhost:" + std::to_string(selectedPort);
+ std::cout << "Test grpc server started at: " << address << std::endl;
+ mChannel = grpc::CreateChannel(address, grpc::InsecureChannelCredentials());
mStub = WakeupClient::NewStub(mChannel);
}
@@ -147,6 +160,7 @@
std::thread mServerThread;
std::unique_ptr<MyTestWakeupClientServiceImpl> mService;
std::unique_ptr<Server> mServer;
+ std::atomic<bool> mServerStarted = false;
std::shared_ptr<Channel> mChannel;
std::unique_ptr<WakeupClient::Stub> mStub;
std::vector<GetRemoteTasksResponse> mRemoteTaskResponses;
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index 4846bfb..f021f7b 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -449,7 +449,8 @@
{.config = {.prop = toInt(VehicleProperty::HVAC_MAX_DEFROST_ON),
.access = VehiclePropertyAccess::READ_WRITE,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
+ .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_FRONT_ROW},
+ VehicleAreaConfig{.areaId = HVAC_REAR_ROW}}},
.initialValue = {.int32Values = {0}}},
{.config = {.prop = toInt(VehicleProperty::HVAC_RECIRC_ON),
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h
index f58e09a..e866f70 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h
@@ -50,6 +50,9 @@
VehicleAreaWheel::LEFT_REAR | VehicleAreaWheel::RIGHT_REAR);
constexpr int SEAT_1_LEFT = (int)(VehicleAreaSeat::ROW_1_LEFT);
constexpr int SEAT_1_RIGHT = (int)(VehicleAreaSeat::ROW_1_RIGHT);
+constexpr int HVAC_FRONT_ROW = (int)(VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_1_RIGHT);
+constexpr int HVAC_REAR_ROW = (int)(VehicleAreaSeat::ROW_2_LEFT | VehicleAreaSeat::ROW_2_CENTER |
+ VehicleAreaSeat::ROW_2_RIGHT);
constexpr int HVAC_LEFT = (int)(VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_2_LEFT |
VehicleAreaSeat::ROW_2_CENTER);
constexpr int HVAC_RIGHT = (int)(VehicleAreaSeat::ROW_1_RIGHT | VehicleAreaSeat::ROW_2_RIGHT);
diff --git a/automotive/vehicle/aidl/aidl_test/Android.bp b/automotive/vehicle/aidl/aidl_test/Android.bp
index 2dc9ee1..ea6a710 100644
--- a/automotive/vehicle/aidl/aidl_test/Android.bp
+++ b/automotive/vehicle/aidl/aidl_test/Android.bp
@@ -49,7 +49,7 @@
name: "VehiclePropertyAnnotationJavaTest",
srcs: [
"VehiclePropertyAnnotationJavaTest.java",
- ":IVehicleGeneratedJavaFiles",
+ ":IVehicleGeneratedJavaFiles-V3",
],
static_libs: [
"android.hardware.automotive.vehicle-V3-java",
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl
index 726d419..9387965 100644
--- a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl
@@ -62,7 +62,9 @@
* For example, if a property is defined as READ_WRITE, but the OEM wants to specify certain
* area Ids as READ-only, the corresponding areaIds should have an access set to READ, while the
* others must be set to READ_WRITE. We do not support setting specific area Ids to WRITE-only
- * when the property is READ-WRITE.
+ * when the property is READ-WRITE. If any one area config has access
+ * VehiclePropertyAccess::WRITE, then all VehicleAreaConfig.access values and
+ * VehiclePropConfig.access must be set to WRITE for the property.
*
* VehiclePropConfig.access should be equal the maximal subset of the accesses set in
* VehiclePropConfig.areaConfigs, excluding those with access == VehiclePropertyAccess.NONE. For
@@ -73,6 +75,8 @@
* In the scenario where the OEM actually wants to set VehicleAreaConfig.access =
* VehiclePropertyAccess.NONE, the maximal subset rule should apply with this area config
* included, making the VehiclePropConfig.access = VehiclePropertyAccess.NONE.
+ *
+ * See VehiclePropConfig.access for more information.
*/
VehiclePropertyAccess access = VehiclePropertyAccess.NONE;
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropConfig.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropConfig.aidl
index 3109621..d8304f6 100644
--- a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropConfig.aidl
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropConfig.aidl
@@ -44,6 +44,36 @@
* VehiclePropertyAccess.NONE for a particular area config, the maximal subset rule should apply
* with this area config included, making the VehiclePropConfig.access =
* VehiclePropertyAccess.NONE.
+ *
+ * Currently we do not support scenarios where some areaIds are WRITE while others are
+ * READ_WRITE. See the documentation for VehicleAreaConfig.access for more details.
+ *
+ * Examples:
+ * Suppose we have a property with two areaIds which we will call "LEFT" and "RIGHT". Here
+ * are some scenarios that can describe what the VehiclePropConfig.access value should be for
+ * this property.
+ * 1. LEFT is READ and RIGHT is READ_WRITE. VehiclePropConfig.access must be READ as that is
+ * the maximal common access across all areaIds.
+ * 2. LEFT is READ_WRITE and RIGHT is READ_WRITE. VehiclePropConfig.access must be READ_WRITE
+ * as that is the maximal common access across all areaIds.
+ * 3. LEFT is WRITE and RIGHT is WRITE. VehiclePropConfig.access must be WRITE as that is the
+ * maximal common access across all areaIds.
+ * 4. LEFT is READ_WRITE and RIGHT is not set (i.e. defaults to NONE)/is set to NONE, with the
+ * expectation that RIGHT should be populated with the default access mode of the property.
+ * VehiclePropConfig.access can be set to READ or READ_WRITE, whatever the OEM feels is the
+ * appropriate default access for the property.
+ * 5. LEFT is READ and RIGHT is not set (i.e. defaults to NONE)/is set to NONE, with the
+ * expectation that RIGHT should be populated with the default access mode of the property.
+ * VehiclePropConfig.access must be set to READ because setting to READ_WRITE breaks the
+ * rule of having the global access being the maximal subset of the area config accesses.
+ * If the OEM wants RIGHT to be READ_WRITE in this scenario, the config should be rewritten
+ * such that LEFT is not set/is set to NONE and RIGHT is set to READ_WRITE with
+ * VehiclePropConfig.access set to READ.
+ * 6. LEFT is READ_WRITE and RIGHT is set to NONE with the intention of RIGHT to specifically
+ * have no access. VehiclePropConfig.access must be NONE to support RIGHT maintaining its
+ * NONE access.
+ * 7. LEFT is READ_WRITE and RIGHT is WRITE. This is unsupported behaviour and the config
+ * should not be defined this way.
*/
VehiclePropertyAccess access = VehiclePropertyAccess.NONE;
diff --git a/automotive/vehicle/aidl/emu_metadata/.clang-format b/automotive/vehicle/aidl/emu_metadata/.clang-format
new file mode 100644
index 0000000..e384528
--- /dev/null
+++ b/automotive/vehicle/aidl/emu_metadata/.clang-format
@@ -0,0 +1 @@
+DisableFormat: true
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 c812326..0dea16b 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
@@ -5,23 +5,28 @@
"values": [
{
"name": "VIN of vehicle",
- "value": 286261504
+ "value": 286261504,
+ "description": "VIN of vehicle"
},
{
"name": "Manufacturer of vehicle",
- "value": 286261505
+ "value": 286261505,
+ "description": "Manufacturer of vehicle\nThis property must communicate the vehicle's public brand name."
},
{
"name": "Model of vehicle",
- "value": 286261506
+ "value": 286261506,
+ "description": "Model of vehicle\nThis property must communicate the vehicle's public model name."
},
{
"name": "INFO_MODEL_YEAR",
- "value": 289407235
+ "value": 289407235,
+ "description": "Model year of vehicle in YYYY format based on the Gregorian calendar."
},
{
"name": "INFO_FUEL_CAPACITY",
- "value": 291504388
+ "value": 291504388,
+ "description": "Fuel capacity of the vehicle in milliliters\nThis property must communicate the maximum amount of the fuel that can be stored in the vehicle in milliliters. This property does not apply to electric vehicles. That is, if INFO_FUEL_TYPE only contains FuelType::FUEL_TYPE_ELECTRIC, this property must not be implemented. For EVs, implement INFO_EV_BATTERY_CAPACITY."
},
{
"name": "INFO_FUEL_TYPE",
@@ -29,11 +34,13 @@
"data_enums": [
"FuelType"
],
- "data_enum": "FuelType"
+ "data_enum": "FuelType",
+ "description": "List of fuels the vehicle may use.\nFuelType::FUEL_TYPE_ELECTRIC must only be included if the vehicle is plug in rechargeable. For example: An FHEV (Fully Hybrid Electric Vehicle) must not include FuelType::FUEL_TYPE_ELECTRIC in INFO_FUEL_TYPE's INT32_VEC value. So INFO_FUEL_TYPE can be populated as such: int32Values = { FuelType::FUEL_TYPE_UNLEADED } On the other hand, a PHEV (Plug-in Hybrid Electric Vehicle) is plug in rechargeable, and hence should include FuelType::FUEL_TYPE_ELECTRIC in INFO_FUEL_TYPE's INT32_VEC value. So INFO_FUEL_TYPE can be populated as such: int32Values = { FuelType::FUEL_TYPE_UNLEADED, FuelType::FUEL_TYPE_ELECTRIC }"
},
{
"name": "INFO_EV_BATTERY_CAPACITY",
- "value": 291504390
+ "value": 291504390,
+ "description": "Nominal usable battery capacity for EV or hybrid vehicle\nReturns the nominal battery capacity, if EV or hybrid. This is the total usable battery capacity when the vehicle is new. This value might be different from EV_CURRENT_BATTERY_CAPACITY because EV_CURRENT_BATTERY_CAPACITY returns the real-time usable battery capacity taking into account factors such as battery aging and temperature dependency."
},
{
"name": "INFO_EV_CONNECTOR_TYPE",
@@ -41,7 +48,8 @@
"data_enums": [
"EvConnectorType"
],
- "data_enum": "EvConnectorType"
+ "data_enum": "EvConnectorType",
+ "description": "List of connectors this EV may use\nIf the vehicle has multiple charging ports, this property must return all possible connector types that can be used by at least one charging port on the vehicle."
},
{
"name": "Fuel door location",
@@ -49,7 +57,8 @@
"data_enums": [
"PortLocationType"
],
- "data_enum": "PortLocationType"
+ "data_enum": "PortLocationType",
+ "description": "Fuel door location\nThis property must communicate the location of the fuel door on the vehicle. This property does not apply to electric vehicles. That is, if INFO_FUEL_TYPE only contains FuelType::FUEL_TYPE_ELECTRIC, this property must not be implemented. For EVs, implement INFO_EV_PORT_LOCATION or INFO_MULTI_EV_PORT_LOCATIONS."
},
{
"name": "EV port location",
@@ -57,7 +66,8 @@
"data_enums": [
"PortLocationType"
],
- "data_enum": "PortLocationType"
+ "data_enum": "PortLocationType",
+ "description": "EV port location\nThis property must communicate the location of the charging port on the EV using the PortLocationType enum. If there are multiple ports available on the vehicle, this property must return the port that allows the fastest charging. To communicate all port locations, use INFO_MULTI_EV_PORT_LOCATIONS."
},
{
"name": "INFO_DRIVER_SEAT",
@@ -65,11 +75,13 @@
"data_enums": [
"VehicleAreaSeat"
],
- "data_enum": "VehicleAreaSeat"
+ "data_enum": "VehicleAreaSeat",
+ "description": "Driver's seat location VHAL implementations must ignore the areaId. Use VehicleArea:GLOBAL."
},
{
"name": "INFO_EXTERIOR_DIMENSIONS",
- "value": 289472779
+ "value": 289472779,
+ "description": "Exterior dimensions of vehicle.\nint32Values[0] = height int32Values[1] = length int32Values[2] = width int32Values[3] = width including mirrors int32Values[4] = wheel base int32Values[5] = track width front int32Values[6] = track width rear int32Values[7] = curb to curb turning diameter"
},
{
"name": "Multiple EV port locations",
@@ -77,31 +89,38 @@
"data_enums": [
"PortLocationType"
],
- "data_enum": "PortLocationType"
+ "data_enum": "PortLocationType",
+ "description": "Multiple EV port locations\nImplement this property if the vehicle has multiple EV ports. Port locations are defined in PortLocationType. For example, a car has one port in front left and one port in rear left: int32Values[0] = PortLocationType::FRONT_LEFT int32Values[1] = PortLocationType::REAR_LEFT\nIf only one port exists on the vehicle, this property's value should list just one element. See INFO_EV_PORT_LOCATION for describing just one port location."
},
{
"name": "PERF_ODOMETER",
- "value": 291504644
+ "value": 291504644,
+ "description": "Current odometer value of the vehicle"
},
{
"name": "Speed of the vehicle",
- "value": 291504647
+ "value": 291504647,
+ "description": "Speed of the vehicle\nThe value must be positive when the vehicle is moving forward and negative when the vehicle is moving backward. This value is independent of gear value (CURRENT_GEAR or GEAR_SELECTION), for example, if GEAR_SELECTION is GEAR_NEUTRAL, PERF_VEHICLE_SPEED is positive when the vehicle is moving forward, negative when moving backward, and zero when not moving."
},
{
"name": "PERF_VEHICLE_SPEED_DISPLAY",
- "value": 291504648
+ "value": 291504648,
+ "description": "Speed of the vehicle for displays\nSome cars display a slightly slower speed than the actual speed. This is usually displayed on the speedometer."
},
{
"name": "PERF_STEERING_ANGLE",
- "value": 291504649
+ "value": 291504649,
+ "description": "Front 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 front wheels with respect to the vehicle, not the angle of the steering wheel."
},
{
"name": "PERF_REAR_STEERING_ANGLE",
- "value": 291504656
+ "value": 291504656,
+ "description": "Rear bicycle model steering angle for vehicle\nAngle is in degrees. Left is negative.\nThis property is independent of the angle of the steering wheel. This property must communicate the angle of the rear wheels with respect to the vehicle, not the angle of the steering wheel."
},
{
"name": "Temperature of engine coolant",
- "value": 291504897
+ "value": 291504897,
+ "description": "Temperature of engine coolant"
},
{
"name": "Engine oil level",
@@ -109,67 +128,83 @@
"data_enums": [
"VehicleOilLevel"
],
- "data_enum": "VehicleOilLevel"
+ "data_enum": "VehicleOilLevel",
+ "description": "Engine oil level"
},
{
"name": "Temperature of engine oil",
- "value": 291504900
+ "value": 291504900,
+ "description": "Temperature of engine oil"
},
{
"name": "Engine rpm",
- "value": 291504901
+ "value": 291504901,
+ "description": "Engine rpm"
},
{
"name": "Reports wheel ticks",
- "value": 290521862
+ "value": 290521862,
+ "description": "Reports wheel ticks\nThe first element in the vector is a reset count. A reset indicates previous tick counts are not comparable with this and future ones. Some sort of discontinuity in tick counting has occurred.\nThe next four elements represent ticks for individual wheels in the following order: front left, front right, rear right, rear left. All tick counts are cumulative. Tick counts increment when the vehicle moves forward, and decrement when vehicles moves in reverse. The ticks should be reset to 0 when the vehicle is started by the user.\nint64Values[0] = reset count int64Values[1] = front left ticks int64Values[2] = front right ticks int64Values[3] = rear right ticks int64Values[4] = rear left ticks\nconfigArray is used to indicate the micrometers-per-wheel-tick value and which wheels are supported. configArray is set as follows:\nconfigArray[0], bits [0:3] = supported wheels. Uses enum Wheel. For example, if all wheels are supported, then configArray[0] = VehicleAreaWheel::LEFT_FRONT | VehicleAreaWheel::RIGHT_FRONT | VehicleAreaWheel::LEFT_REAR | VehicleAreaWheel::RIGHT_REAR configArray[1] = micrometers per front left wheel tick configArray[2] = micrometers per front right wheel tick configArray[3] = micrometers per rear right wheel tick configArray[4] = micrometers per rear left wheel tick\nNOTE: If a wheel is not supported, its value shall always be set to 0.\nVehiclePropValue.timestamp must be correctly filled in."
},
{
- "name": "FUEL_LEVEL",
- "value": 291504903
+ "name": "Fuel level in milliliters",
+ "value": 291504903,
+ "description": "Fuel level in milliliters\nThis property must communicate the current amount of fuel remaining in the vehicle in milliliters. This property does not apply to electric vehicles. That is, if INFO_FUEL_TYPE only contains FuelType::FUEL_TYPE_ELECTRIC, this property must not be implemented. For EVs, implement EV_BATTERY_LEVEL.\nValue may not exceed INFO_FUEL_CAPACITY."
},
{
"name": "Fuel door open",
- "value": 287310600
+ "value": 287310600,
+ "description": "Fuel door open\nThis property must communicate whether the fuel door on the vehicle is open or not. This property does not apply to electric vehicles. That is, if INFO_FUEL_TYPE only contains FuelType::FUEL_TYPE_ELECTRIC, this property must not be implemented. For EVs, implement EV_CHARGE_PORT_OPEN.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "EV_BATTERY_LEVEL",
- "value": 291504905
+ "value": 291504905,
+ "description": "Battery level for EV or hybrid vehicle\nReturns the current battery level, if EV or hybrid. This value will not exceed EV_CURRENT_BATTERY_CAPACITY. To calculate the battery percentage, use: (EV_BATTERY_LEVEL\/EV_CURRENT_BATTERY_CAPACITY)*100."
},
{
"name": "EV_CURRENT_BATTERY_CAPACITY",
- "value": 291504909
+ "value": 291504909,
+ "description": "Current usable battery capacity for EV or hybrid vehicle\nReturns the actual value of battery capacity, if EV or hybrid. This property captures the real-time usable battery capacity taking into account factors such as battery aging and temperature dependency. Therefore, this value might be different from INFO_EV_BATTERY_CAPACITY because INFO_EV_BATTERY_CAPACITY returns the nominal battery capacity from when the vehicle was new."
},
{
"name": "EV charge port open",
- "value": 287310602
+ "value": 287310602,
+ "description": "EV charge port open\nIf the vehicle has multiple charging ports, this property must return true if any of the charge ports are open.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "EV charge port connected",
- "value": 287310603
+ "value": 287310603,
+ "description": "EV charge port connected\nIf the vehicle has multiple charging ports, this property must return true if any of the charge ports are connected."
},
{
"name": "EV_BATTERY_INSTANTANEOUS_CHARGE_RATE",
- "value": 291504908
+ "value": 291504908,
+ "description": "EV instantaneous charge rate in milliwatts\nPositive value indicates battery is being charged. Negative value indicates battery being discharged."
},
{
"name": "Range remaining",
- "value": 291504904
+ "value": 291504904,
+ "description": "Range remaining\nMeters remaining of fuel and charge. Range remaining shall account for all energy sources in a vehicle. For example, a hybrid car's range will be the sum of the ranges based on fuel and battery.\nThis property is defined as VehiclePropertyAccess.READ_WRITE because a navigation app could update the range if it has a more accurate estimate based on the upcoming route. However, this property can be implemented as VehiclePropertyAccess.READ only at the OEM's discretion."
},
{
"name": "EV battery average temperature",
- "value": 291504910
+ "value": 291504910,
+ "description": "EV battery average temperature\nExposes the temperature of the battery in an EV. If multiple batteries exist in the EV, or multiple temperature sensors exist, this property should be set to the mean or a meaningful weighted average that best represents the overall temperature of the battery system."
},
{
"name": "Tire pressure",
- "value": 392168201
+ "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, } },"
},
{
"name": "Critically low tire pressure",
- "value": 392168202
+ "value": 392168202,
+ "description": "Critically low tire pressure\nThis property indicates the critically low pressure threshold for each tire. It indicates when it is time for tires to be replaced or fixed. The value must be less than or equal to minFloatValue in TIRE_PRESSURE. Minimum and maximum property values (that is, minFloatValue, maxFloatValue) are not applicable to this property."
},
{
"name": "ENGINE_IDLE_AUTO_STOP_ENABLED",
- "value": 287310624
+ "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."
},
{
"name": "Impact detected.",
@@ -177,7 +212,8 @@
"data_enums": [
"ImpactSensorLocation"
],
- "data_enum": "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."
},
{
"name": "Currently selected gear",
@@ -185,7 +221,8 @@
"data_enums": [
"VehicleGear"
],
- "data_enum": "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."
},
{
"name": "CURRENT_GEAR",
@@ -193,27 +230,33 @@
"data_enums": [
"VehicleGear"
],
- "data_enum": "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."
},
{
"name": "Parking brake state.",
- "value": 287310850
+ "value": 287310850,
+ "description": "Parking brake state.\nThis property is true indicates that the car's parking brake is currently engaged. False implies that the car's parking brake is currently disengaged."
},
{
"name": "Auto-apply parking brake.",
- "value": 287310851
+ "value": 287310851,
+ "description": "Auto-apply parking brake.\nThis property is true indicates that the car's automatic parking brake feature is currently enabled. False indicates that the car's automatic parking brake feature is currently disabled.\nThis property is often confused with PARKING_BRAKE_ON. The difference is that PARKING_BRAKE_ON describes whether the actual parking brake is currently on\/off, whereas PARKING_BRAKE_AUTO_APPLY describes whether the feature of automatic parking brake is enabled\/ disabled, and does not describe the current state of the actual parking brake."
},
{
"name": "EV_BRAKE_REGENERATION_LEVEL",
- "value": 289408012
+ "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."
},
{
"name": "Warning for fuel low level.",
- "value": 287310853
+ "value": 287310853,
+ "description": "Warning for fuel low level.\nThis property corresponds to the low fuel warning on the dashboard. Once FUEL_LEVEL_LOW is set, it should not be cleared until more fuel is added to the vehicle. This property may take into account all fuel sources for a vehicle - for example:\nFor a gas powered vehicle, this property is based soley on gas level. For a battery powered vehicle, this property is based solely on battery level. For a hybrid vehicle, this property may be based on the combination of gas and battery levels, at the OEM's discretion."
},
{
"name": "Night mode",
- "value": 287310855
+ "value": 287310855,
+ "description": "Night mode\nTrue indicates that the night mode sensor has detected that the car cabin environment has low light. The platform could use this, for example, to enable appropriate UI for better viewing in dark or low light environments."
},
{
"name": "TURN_SIGNAL_STATE",
@@ -221,7 +264,8 @@
"data_enums": [
"VehicleTurnSignal"
],
- "data_enum": "VehicleTurnSignal"
+ "data_enum": "VehicleTurnSignal",
+ "description": "State of the vehicles turn signals"
},
{
"name": "Represents ignition state",
@@ -229,15 +273,18 @@
"data_enums": [
"VehicleIgnitionState"
],
- "data_enum": "VehicleIgnitionState"
+ "data_enum": "VehicleIgnitionState",
+ "description": "Represents ignition state"
},
{
"name": "ABS is active",
- "value": 287310858
+ "value": 287310858,
+ "description": "ABS is active\nSet to true when ABS is active. Reset to false when ABS is off. This property may be intermittently set (pulsing) based on the real-time state of the ABS system."
},
{
"name": "Traction Control is active",
- "value": 287310859
+ "value": 287310859,
+ "description": "Traction Control is active\nSet to true when traction control (TC) is active. Reset to false when TC is off. This property may be intermittently set (pulsing) based on the real-time state of the TC system."
},
{
"name": "EV_STOPPING_MODE",
@@ -245,11 +292,13 @@
"data_enums": [
"EvStoppingMode"
],
- "data_enum": "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."
},
{
"name": "ELECTRONIC_STABILITY_CONTROL_ENABLED",
- "value": 287310862
+ "value": 287310862,
+ "description": "Enable or disable Electronic Stability Control (ESC).\nSet true to enable ESC and false to disable ESC. When ESC is enabled, a system in the vehicle should be controlling the tires during instances with high risk of skidding to actively prevent the same from happening.\nIn general, ELECTRONIC_STABILITY_CONTROL_ENABLED should always return true or false. If the feature is not available due to some temporary state, such as the vehicle speed being too high, that information must be conveyed through the ErrorState values in the ELECTRONIC_STABILITY_CONTROL_STATE property.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "ELECTRONIC_STABILITY_CONTROL_STATE",
@@ -258,11 +307,13 @@
"ElectronicStabilityControlState",
"ErrorState"
],
- "data_enum": "ElectronicStabilityControlState"
+ "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."
},
{
"name": "Fan speed setting",
- "value": 356517120
+ "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."
},
{
"name": "Fan direction setting",
@@ -270,55 +321,68 @@
"data_enums": [
"VehicleHvacFanDirection"
],
- "data_enum": "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."
},
{
"name": "HVAC current temperature.",
- "value": 358614274
+ "value": 358614274,
+ "description": "HVAC current temperature."
},
{
- "name": "HVAC, target temperature set.",
- "value": 358614275
+ "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."
},
{
"name": "HVAC_DEFROSTER",
- "value": 320865540
+ "value": 320865540,
+ "description": "Fan-based defrost for designated window.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "HVAC_AC_ON",
- "value": 354419973
+ "value": 354419973,
+ "description": "On\/off AC for designated areaId\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "On\/off max AC",
- "value": 354419974
+ "value": 354419974,
+ "description": "On\/off max AC\nWhen MAX AC is on, the ECU may adjust the vent position, fan speed, temperature, etc as necessary to cool the vehicle as quickly as possible. Any parameters modified as a side effect of turning on\/off the MAX AC parameter shall generate onPropertyEvent() callbacks to the VHAL.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "On\/off max defrost",
- "value": 354419975
+ "value": 354419975,
+ "description": "On\/off max defrost\nWhen MAX DEFROST is on, the ECU may adjust the vent position, fan speed, temperature, etc as necessary to defrost the windows as quickly as possible. Any parameters modified as a side effect of turning on\/off the MAX DEFROST parameter shall generate onPropertyEvent() callbacks to the VHAL. The AreaIDs for HVAC_MAX_DEFROST_ON indicate MAX DEFROST can be controlled in the area. For example: areaConfig.areaId = {ROW_1_LEFT | ROW_1_RIGHT} indicates HVAC_MAX_DEFROST_ON only can be controlled for the front rows.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Recirculation on\/off",
- "value": 354419976
+ "value": 354419976,
+ "description": "Recirculation on\/off\nControls the supply of exterior air to the cabin. Recirc “on” means the majority of the airflow into the cabin is originating in the cabin. Recirc “off” means the majority of the airflow into the cabin is coming from outside the car.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "HVAC_DUAL_ON",
- "value": 354419977
+ "value": 354419977,
+ "description": "Enable temperature coupling between areas.\nThe AreaIDs for HVAC_DUAL_ON property shall contain a combination of HVAC_TEMPERATURE_SET AreaIDs that can be coupled together. If HVAC_TEMPERATURE_SET is mapped to AreaIDs [a_1, a_2, ..., a_n], and if HVAC_DUAL_ON can be enabled to couple a_i and a_j, then HVAC_DUAL_ON property must be mapped to [a_i | a_j]. Further, if a_k and a_l can also be coupled together separately then HVAC_DUAL_ON must be mapped to [a_i | a_j, a_k | a_l].\nExample: A car has two front seats (ROW_1_LEFT, ROW_1_RIGHT) and three back seats (ROW_2_LEFT, ROW_2_CENTER, ROW_2_RIGHT). There are two temperature control units -- driver side and passenger side -- which can be optionally synchronized. This may be expressed in the AreaIDs this way: - HVAC_TEMPERATURE_SET->[ROW_1_LEFT | ROW_2_LEFT, ROW_1_RIGHT | ROW_2_CENTER | ROW_2_RIGHT] - HVAC_DUAL_ON->[ROW_1_LEFT | ROW_2_LEFT | ROW_1_RIGHT | ROW_2_CENTER | ROW_2_RIGHT]\nWhen the property is enabled, the ECU must synchronize the temperature for the affected areas. Any parameters modified as a side effect of turning on\/off the DUAL_ON parameter shall generate onPropertyEvent() callbacks to the VHAL. In addition, if setting a temperature (i.e. driver's temperature) changes another temperature (i.e. front passenger's temperature), then the appropriate onPropertyEvent() callbacks must be generated. If a user changes a temperature that breaks the coupling (e.g. setting the passenger temperature independently) then the VHAL must send the appropriate onPropertyEvent() callbacks (i.e. HVAC_DUAL_ON = false, HVAC_TEMPERATURE_SET[AreaID] = xxx, etc).\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "HVAC_AUTO_ON",
- "value": 354419978
+ "value": 354419978,
+ "description": "On\/off automatic climate control.\nIf true, automatic climate control is on. If false, automatic climate control is off.\nIf the vehicle does not support directly turning off automatic climate control, then OEMs should add logic in their VHAL implementation so that setting HVAC_AUTO_ON to false would change the necessary HVAC settings to indirectly turn off HVAC_AUTO_ON. Ideally, this should not be disruptive to the user, so OEMs should change back to the previous state any settings that were modified once automatic climate control is off. That way the only outcome should be that HVAC_AUTO_ON is off. If restoring the HVAC settings to its previous settings is not possible, then the OEM should choose the least disruptive change and implement that.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Seat heating\/cooling",
- "value": 356517131
+ "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."
},
{
"name": "Side Mirror Heat",
- "value": 339739916
+ "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."
},
{
"name": "Steering Wheel Heating\/Cooling",
- "value": 289408269
+ "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."
},
{
"name": "Temperature units for display",
@@ -326,15 +390,18 @@
"data_enums": [
"VehicleUnit"
],
- "data_enum": "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."
},
{
"name": "Actual fan speed",
- "value": 356517135
+ "value": 356517135,
+ "description": "Actual fan speed"
},
{
"name": "HVAC_POWER_ON",
- "value": 354419984
+ "value": 354419984,
+ "description": "Represents global power state for HVAC. Setting this property to false MAY mark some properties that control individual HVAC features\/subsystems to UNAVAILABLE state. Setting this property to true MAY mark some properties that control individual HVAC features\/subsystems to AVAILABLE state (unless any\/all of them are UNAVAILABLE on their own individual merits).\n[Definition] HvacPower_DependentProperties: Properties that need HVAC to be powered on in order to enable their functionality. For example, in some cars, in order to turn on the AC, HVAC must be powered on first.\nHvacPower_DependentProperties list must be set in the VehiclePropConfig.configArray. HvacPower_DependentProperties must only contain properties that are associated with VehicleArea:SEAT. Properties that are not associated with VehicleArea:SEAT, for example, HVAC_DEFROSTER, must never depend on HVAC_POWER_ON property and must never be part of HvacPower_DependentProperties list.\nAreaID mapping for HVAC_POWER_ON property must contain all AreaIDs that HvacPower_DependentProperties are mapped to.\nExample 1: A car has two front seats (ROW_1_LEFT, ROW_1_RIGHT) and three back seats (ROW_2_LEFT, ROW_2_CENTER, ROW_2_RIGHT). If the HVAC features (AC, Temperature etc.) throughout the car are dependent on a single HVAC power controller then HVAC_POWER_ON must be mapped to [ROW_1_LEFT | ROW_1_RIGHT | ROW_2_LEFT | ROW_2_CENTER | ROW_2_RIGHT].\nExample 2: A car has two seats in the front row (ROW_1_LEFT, ROW_1_RIGHT) and three seats in the second (ROW_2_LEFT, ROW_2_CENTER, ROW_2_RIGHT) and third rows (ROW_3_LEFT, ROW_3_CENTER, ROW_3_RIGHT). If the car has temperature controllers in the front row which can operate entirely independently of temperature controllers in the back of the vehicle, then HVAC_POWER_ON must be mapped to a two element array: - ROW_1_LEFT | ROW_1_RIGHT - ROW_2_LEFT | ROW_2_CENTER | ROW_2_RIGHT | ROW_3_LEFT | ROW_3_CENTER | ROW_3_RIGHT\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Fan Positions Available",
@@ -342,23 +409,28 @@
"data_enums": [
"VehicleHvacFanDirection"
],
- "data_enum": "VehicleHvacFanDirection"
+ "data_enum": "VehicleHvacFanDirection",
+ "description": "Fan Positions Available\nThis is a bit mask of fan positions available for the zone. Each available fan direction is denoted by a separate entry in the vector. A fan direction may have multiple bits from vehicle_hvac_fan_direction set. For instance, a typical car may have the following fan positions: - FAN_DIRECTION_FACE (0x1) - FAN_DIRECTION_FLOOR (0x2) - FAN_DIRECTION_FACE | FAN_DIRECTION_FLOOR (0x3) - FAN_DIRECTION_DEFROST (0x4) - FAN_DIRECTION_FLOOR | FAN_DIRECTION_DEFROST (0x6)"
},
{
"name": "Automatic recirculation on\/off",
- "value": 354419986
+ "value": 354419986,
+ "description": "Automatic recirculation on\/off\nWhen automatic recirculation is ON, the HVAC system may automatically switch to recirculation mode if the vehicle detects poor incoming air quality.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Seat ventilation",
- "value": 356517139
+ "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."
},
{
"name": "Electric defrosters' status",
- "value": 320865556
+ "value": 320865556,
+ "description": "Electric defrosters' status\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "HVAC_TEMPERATURE_VALUE_SUGGESTION",
- "value": 291570965
+ "value": 291570965,
+ "description": "Suggested values for setting HVAC temperature.\nImplement the property to help applications understand the closest supported temperature value in Celsius or Fahrenheit.\nfloatValues[0] = the requested value that an application wants to set a temperature to. floatValues[1] = the unit for floatValues[0]. It should be one of {VehicleUnit.CELSIUS, VehicleUnit.FAHRENHEIT}. floatValues[2] = the value OEMs suggested in CELSIUS. This value is not included in the request. floatValues[3] = the value OEMs suggested in FAHRENHEIT. This value is not included in the request.\nAn application calls set(VehiclePropValue propValue) with the requested value and unit for the value. OEMs need to return the suggested values in floatValues[2] and floatValues[3] by onPropertyEvent() callbacks. The suggested values must conform to the values that can be derived from the HVAC_TEMPERATURE_SET configArray. In other words, the suggested values and the table of values from the configArray should be the same. It is recommended for the OEM to add custom logic in their VHAL implementation in order to avoid making requests to the HVAC ECU.\nThe logic can be as follows: For converting the temperature from celsius to fahrenheit use the following: \/\/ Given tempC and the configArray float minTempC = configArray[0] \/ 10.0; float temperatureIncrementCelsius = configArray[2] \/ 10.0; float minTempF = configArray[3] \/ 10.0; float temperatureIncrementFahrenheit = configArray[5] \/ 10.0; \/\/ Round to the closest increment int numIncrements = round((tempC - minTempC) \/ temperatureIncrementCelsius); tempF = temperatureIncrementFahrenheit * numIncrements + minTempF;\nFor example, when a user uses the voice assistant to set HVAC temperature to 66.2 in Fahrenheit. First, an application will set this property with the value [66.2, (float)VehicleUnit.FAHRENHEIT,0,0]. If OEMs suggest to set 19.0 in Celsius or 66.5 in Fahrenheit for user's request, then VHAL must generate a callback with property value [66.2, (float)VehicleUnit.FAHRENHEIT, 19.0, 66.5]. After the voice assistant gets the callback, it will inform the user and set HVAC temperature to the suggested value.\nAnother example, an application receives 21 Celsius as the current temperature value by querying HVC_TEMPERATURE_SET. But the application wants to know what value is displayed on the car's UI in Fahrenheit. For this, the application sets the property to [21, (float)VehicleUnit.CELSIUS, 0, 0]. If the suggested value by the OEM for 21 Celsius is 70 Fahrenheit, then VHAL must generate a callback with property value [21, (float)VehicleUnit.CELSIUS, 21.0, 70.0]. In this case, the application can know that the value is 70.0 Fahrenheit in the car’s UI."
},
{
"name": "Distance units for display",
@@ -366,7 +438,8 @@
"data_enums": [
"VehicleUnit"
],
- "data_enum": "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."
},
{
"name": "Fuel volume units for display",
@@ -374,7 +447,8 @@
"data_enums": [
"VehicleUnit"
],
- "data_enum": "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."
},
{
"name": "TIRE_PRESSURE_DISPLAY_UNITS",
@@ -382,7 +456,8 @@
"data_enums": [
"VehicleUnit"
],
- "data_enum": "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."
},
{
"name": "EV battery units for display",
@@ -390,71 +465,88 @@
"data_enums": [
"VehicleUnit"
],
- "data_enum": "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."
},
{
"name": "FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME",
- "value": 287311364
+ "value": 287311364,
+ "description": "Fuel consumption units for display\nIndicates type of units the car is using to display fuel consumption information to user True indicates units are distance over volume such as MPG. False indicates units are volume over distance such as L\/100KM.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Speed units for display",
- "value": 289408517
+ "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."
},
{
"name": "EXTERNAL_CAR_TIME",
- "value": 290457096
+ "value": 290457096,
+ "description": "Current date and time suggestion for the Car, encoded as Epoch time (in milliseconds). This value denotes the number of milliseconds seconds that have elapsed since 1\/1\/1970 UTC.\nThis property signals a change in CarTime to Android. If the property is supported, VHAL must report the most accurate current CarTime when this property is read, and publish a change to this property when the CarTime value has changed. An on-change event for this property must be published when CarTime changes for any reason other than the natural elapse of time (time delta smaller than 500ms should not trigger an on change event). Android will read and subscribe to this property to fetch time from VHAL. This can be useful to synchronize Android's time with other vehicle systems (dash clock etc). int64Values[0] = provided Epoch time (in milliseconds)\nWhenever a new Value for the property is received, AAOS will create and send an \"ExternalTimeSuggestion\" to the \"TimeDetectorService\". If other sources do not have a higher priority, Android will use this to set the system time. For information on how to adjust time source priorities and how time suggestions are handled (including how Android handles gitter, drift, and minimum resolution) see Time Detector Service documentation.\nNote that the property may take >0 ms to get propagated through the stack and, having a timestamped property helps reduce any time drift. So, for all reads to the property, the timestamp can be used to negate this drift: drift = elapsedTime - PropValue.timestamp effectiveTime = PropValue.value.int64Values[0] + drift\nIt is strongly recommended that this property must not be used to retrieve time from ECUs using protocols (GNSS, NTP, Telephony etc). Since these protocols are already supported by Android, it is recommended to use Android’s own systems for them instead of wiring those through the VHAL using this property.\nWARNING: The value available through this property should not be dependent on value written by Android to ANDROID_EPOCH_TIME property in any way."
},
{
"name": "ANDROID_EPOCH_TIME",
- "value": 290457094
+ "value": 290457094,
+ "description": "Current date and time, encoded as Epoch time (in milliseconds). This value denotes the number of milliseconds seconds that have elapsed since 1\/1\/1970 UTC.\nCarServices will write to this value to give VHAL the Android system's time, if the VHAL supports this property. This can be useful to synchronize other vehicle systems (dash clock etc) with Android's time.\nAAOS writes to this property once during boot, and will thereafter write only when some time-source changes are propagated. AAOS will fill in VehiclePropValue.timestamp correctly. Note that AAOS will not send updates for natural elapse of time. int64Values[0] = provided Unix time (in milliseconds)\nNote that the property may take >0 ms to get propagated through the stack and, having a timestamped property helps reduce any time drift. So, for all writes to the property, the timestamp can be used to negate this drift: drift = elapsedTime - PropValue.timestamp effectiveTime = PropValue.value.int64Values[0] + drift"
},
{
"name": "STORAGE_ENCRYPTION_BINDING_SEED",
- "value": 292554247
+ "value": 292554247,
+ "description": "External encryption binding seed.\nThis value is mixed with the local key storage encryption key. This property holds 16 bytes, and is expected to be persisted on an ECU separate from the IVI. The property is initially set by AAOS, who generates it using a CSRNG. AAOS will then read the property on subsequent boots. The binding seed is expected to be reliably persisted. Any loss of the seed results in a factory reset of the IVI."
},
{
"name": "Outside temperature",
- "value": 291505923
+ "value": 291505923,
+ "description": "Outside temperature\nThis property must communicate the temperature reading of the environment outside the vehicle. If there are multiple sensors for measuring the outside temperature, this property should be populated with the mean or a meaningful weighted average of the readings that will best represent the temperature of the outside environment."
},
{
"name": "AP_POWER_STATE_REQ",
- "value": 289475072
+ "value": 289475072,
+ "description": "Property to control power state of application processor\nIt is assumed that AP's power state is controlled by a separate power controller.\nFor configuration information, VehiclePropConfig.configArray must have bit flag combining values in VehicleApPowerStateConfigFlag.\nint32Values[0] : VehicleApPowerStateReq enum value int32Values[1] : additional parameter relevant for each state, 0 if not used."
},
{
"name": "AP_POWER_STATE_REPORT",
- "value": 289475073
+ "value": 289475073,
+ "description": "Property to report power state of application processor\nIt is assumed that AP's power state is controller by separate power controller.\nint32Values[0] : VehicleApPowerStateReport enum value int32Values[1] : Time in ms to wake up, if necessary. Otherwise 0."
},
{
"name": "AP_POWER_BOOTUP_REASON",
- "value": 289409538
+ "value": 289409538,
+ "description": "Property to report bootup reason for the current power on. This is a static property that will not change for the whole duration until power off. For example, even if user presses power on button after automatic power on with door unlock, bootup reason must stay with VehicleApPowerBootupReason#USER_UNLOCK.\nint32Values[0] must be VehicleApPowerBootupReason."
},
{
"name": "DISPLAY_BRIGHTNESS",
- "value": 289409539
+ "value": 289409539,
+ "description": "Property to represent brightness of the display.\nSome cars have single control for the brightness of all displays and this property is to share change in that control. In cars which have displays whose brightness is controlled separately, they must use PER_DISPLAY_BRIGHTNESS.\nOnly one of DISPLAY_BRIGHTNESS and PER_DISPLAY_BRIGHTNESS should be implemented. If both are available, PER_DISPLAY_BRIGHTNESS is used by AAOS.\nIf this is writable, android side can set this value when user changes display brightness from Settings. If this is read only, user may still change display brightness from Settings, but that must not be reflected to other displays.\nIf this is writable, writing this property must cause an on property change event even if the new display brightness is the same as the current value."
},
{
"name": "PER_DISPLAY_BRIGHTNESS",
- "value": 289475076
+ "value": 289475076,
+ "description": "Property to represent brightness of the displays which are controlled separately.\nSome cars have one or more displays whose brightness is controlled separately and this property is to inform the brightness of each passenger display. In cars where all displays' brightness is controlled together, they must use DISPLAY_BRIGHTNESS.\nOnly one of DISPLAY_BRIGHTNESS and PER_DISPLAY_BRIGHTNESS should be implemented. If both are available, PER_DISPLAY_BRIGHTNESS is used by AAOS.\nThe display port uniquely identifies a physical connector on the device for display output, ranging from 0 to 255.\nWriting this property must cause an on property change event that contains the same [display port, brightness] tuple even if the new display brightness is the same as the current value.\nTo get the display brightness for a specific display port, the GetValueRequest must contain a VehiclePropValue, which contains one int32Value: displayPort. Getting this property without specifying the the display port is undefined behavior.\nint32Values[0] : display port int32Values[1] : brightness"
},
{
"name": "Valet mode enabled",
- "value": 287312389
+ "value": 287312389,
+ "description": "Valet mode enabled\nThis property allows the user to enable\/disable valet mode in their vehicle. Valet mode is a privacy and security setting that prevents an untrusted driver to access more private areas in the vehicle, such as the glove box or the trunk(s).\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Head up display (HUD) enabled",
- "value": 354421254
+ "value": 354421254,
+ "description": "Head up display (HUD) enabled\nThis property allows the user to turn on\/off the HUD for their seat.\nEach HUD in the vehicle should be assigned to the seat that is intended to use it. For example, if there is a single HUD in the vehicle that is used by the driver so that they no longer need to continuously look at the instrument cluster, then this property should be defined with a single area ID equal to the driver's seat area value."
},
{
"name": "HW_KEY_INPUT",
- "value": 289475088
+ "value": 289475088,
+ "description": "Property to feed H\/W input events to android\nint32Values[0] : action defined by VehicleHwKeyInputAction int32Values[1] : key code, must use standard android key code int32Values[2] : target display defined in VehicleDisplay. Events not tied to specific display must be sent to VehicleDisplay#MAIN. int32Values[3] : [optional] Number of ticks. The value must be equal or greater than 1. When omitted, Android will default to 1."
},
{
"name": "HW_KEY_INPUT_V2",
- "value": 367004177
+ "value": 367004177,
+ "description": "Property to feed H\/W input events to android\nint32array[0]: target display defined by VehicleDisplay like VehicleDisplay::MAIN, VehicleDisplay::INSTRUMENT_CLUSTER, VehicleDisplay::AUX int32array[1]: key code, must use standard android key code like KEYCODE_HOME, KEYCODE_BACK int32array[2]: action defined in VehicleHwKeyInputAction like VehicleHwKeyInputAction::ACTION_UP, VehicleHwKeyInputAction::ACTION_UP int32array[3]: repeat count of the event. For key down events, this is the repeat count with the first down starting at 0 and counting up from there. For key up events, this is always equal to 0\nint64array[0]: down time, elapsed nanoseconds since boot. Denotes the time of the most recent key down event. For the down event, it will be the event time of the down event itself"
},
{
"name": "HW_MOTION_INPUT",
- "value": 367004178
+ "value": 367004178,
+ "description": "Property to feed H\/W input events to android\nint32array[0]: target display defined by VehicleDisplay like VehicleDisplay::MAIN, VehicleDisplay::INSTRUMENT_CLUSTER, VehicleDisplay::AUX int32array[1]: input type defined in VehicleHwMotionInputSource like VehicleHwMotionInputSource::SOURCE_KEYBOARD, VehicleHwMotionInputSource::SOURCE_DPAD int32array[2]: action code defined in VehicleHwMotionInputAction like VehicleHwMotionInputAction::ACTION_UP, VehicleHwMotionInputAction::ACTION_DOWN int32array[3]: button state flag defined in VehicleHwMotionButtonStateFlag like VehicleHwMotionButtonStateFlag::BUTTON_PRIMARY, VehicleHwMotionButtonStateFlag::BUTTON_SECONDARY int32array[4]: pointer events count, N. N must be a positive integer int32array[5:5+N-1]: pointer id, length N int32array[5+N:5+2*N-1] : tool type, length N. As defined in VehicleHwMotionToolType like VehicleHwMotionToolType::TOOL_TYPE_FINGER, VehicleHwMotionToolType::TOOL_TYPE_STYLUS\nfloatArray[0:N-1] : x data, length N floatArray[N:2*N-1] : y data, length N floatArray[2*N:3*N-1] : pressure data, length N floatArray[3*N:4*N-1] : size data, length N\nint64array[0]: down time, elapsed nanoseconds since boot. Denotes the time when the user originally pressed down to start a stream of position events. For the down event, it will be the event time of the down event itself"
},
{
"name": "HW_ROTARY_INPUT",
@@ -462,7 +554,8 @@
"data_enums": [
"RotaryInputType"
],
- "data_enum": "RotaryInputType"
+ "data_enum": "RotaryInputType",
+ "description": "Property to feed H\/W rotary events to android\nint32Values[0] : RotaryInputType identifying which rotary knob rotated int32Values[1] : number of detents (clicks), positive for clockwise, negative for counterclockwise int32Values[2] : target display defined in VehicleDisplay. Events not tied to specific display must be sent to VehicleDisplay#MAIN. int32values[3 .. 3 + abs(number of detents) - 2]: nanosecond deltas between pairs of consecutive detents, if the number of detents is > 1 or < -1\nVehiclePropValue.timestamp: when the rotation occurred. If the number of detents is > 1 or < -1, this is when the first detent of rotation occurred."
},
{
"name": "HW_CUSTOM_INPUT",
@@ -470,167 +563,208 @@
"data_enums": [
"CustomInputType"
],
- "data_enum": "CustomInputType"
+ "data_enum": "CustomInputType",
+ "description": "Defines a custom OEM partner input event.\nThis input event must be used by OEM partners who wish to propagate events not supported by Android. It is composed by an array of int32 values only.\nThe Android properties are:\nint32Values[0] : Input code identifying the function representing this event. Valid event types are defined by CustomInputType.CUSTOM_EVENT_F1 up to CustomInputType.CUSTOM_EVENT_F10. They represent the custom event to be defined by OEM partners. int32Values[1] : target display type defined in VehicleDisplay. Events not tied to specific display must be sent to VehicleDisplay#MAIN. int32Values[2] : repeat counter, if 0 then event is not repeated. Values 1 or above means how many times this event repeated."
},
{
"name": "Door position",
- "value": 373295872
+ "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."
},
{
"name": "Door move",
- "value": 373295873
+ "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."
},
{
"name": "Door lock",
- "value": 371198722
+ "value": 371198722,
+ "description": "Door lock\n'true' indicates door is locked\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "DOOR_CHILD_LOCK_ENABLED",
- "value": 371198723
+ "value": 371198723,
+ "description": "Door child lock feature enabled\nReturns true if the door child lock feature is enabled and false if it is disabled.\nIf enabled, the door is unable to be opened from the inside.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Mirror Z Position",
- "value": 339741504
+ "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."
},
{
"name": "Mirror Z Move",
- "value": 339741505
+ "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."
},
{
"name": "Mirror Y Position",
- "value": 339741506
+ "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."
},
{
"name": "Mirror Y Move",
- "value": 339741507
+ "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."
},
{
"name": "Mirror Lock",
- "value": 287312708
+ "value": 287312708,
+ "description": "Mirror Lock\nTrue indicates mirror positions are locked and not changeable\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Mirror Fold",
- "value": 287312709
+ "value": 287312709,
+ "description": "Mirror Fold\nTrue indicates mirrors are folded\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "MIRROR_AUTO_FOLD_ENABLED",
- "value": 337644358
+ "value": 337644358,
+ "description": "Represents property for Mirror Auto Fold feature.\nThis property is true when the feature for automatically folding the vehicle's side mirrors (for example, when the mirrors fold inward automatically when one exits and locks the vehicle) is enabled.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "MIRROR_AUTO_TILT_ENABLED",
- "value": 337644359
+ "value": 337644359,
+ "description": "Represents property for Mirror Auto Tilt feature.\nThis property is true when the feature for automatically tilting the vehicle's side mirrors (for example, when the mirrors tilt downward automatically when one reverses the vehicle) is enabled.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Seat memory select",
- "value": 356518784
+ "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."
},
{
"name": "Seat memory set",
- "value": 356518785
+ "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."
},
{
"name": "Seatbelt buckled",
- "value": 354421634
+ "value": 354421634,
+ "description": "Seatbelt buckled\nTrue indicates belt is buckled.\nWrite access indicates automatic seat buckling capabilities. There are no known cars at this time, but you never know...\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Seatbelt height position",
- "value": 356518787
+ "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."
},
{
"name": "Seatbelt height move",
- "value": 356518788
+ "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."
},
{
"name": "Seat fore\/aft position",
- "value": 356518789
+ "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."
},
{
"name": "Seat fore\/aft move",
- "value": 356518790
+ "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."
},
{
"name": "Seat backrest angle 1 position",
- "value": 356518791
+ "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."
},
{
"name": "Seat backrest angle 1 move",
- "value": 356518792
+ "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."
},
{
"name": "Seat backrest angle 2 position",
- "value": 356518793
+ "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."
},
{
"name": "Seat backrest angle 2 move",
- "value": 356518794
+ "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."
},
{
"name": "Seat height position",
- "value": 356518795
+ "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."
},
{
"name": "Seat height move",
- "value": 356518796
+ "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."
},
{
"name": "Seat depth position",
- "value": 356518797
+ "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."
},
{
"name": "Seat depth move",
- "value": 356518798
+ "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."
},
{
"name": "Seat tilt position",
- "value": 356518799
+ "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."
},
{
"name": "Seat tilt move",
- "value": 356518800
+ "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."
},
{
"name": "Lumber fore\/aft position",
- "value": 356518801
+ "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."
},
{
"name": "Lumbar fore\/aft move",
- "value": 356518802
+ "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."
},
{
"name": "Lumbar side support position",
- "value": 356518803
+ "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."
},
{
"name": "Lumbar side support move",
- "value": 356518804
+ "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."
},
{
"name": "SEAT_HEADREST_HEIGHT_POS",
- "value": 289409941
+ "value": 289409941,
+ "description": "(Deprecated) Headrest height position\nThis property is deprecated because it is defined as type VehicleArea:GLOBAL, which means all seats use the same value. Use SEAT_HEADREST_HEIGHT_POS_V2 instead which fixes this issue by being defined as type VehicleArea:SEAT.\nSets the headrest height. Max value indicates tallest setting. Min value indicates shortest setting.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Headrest height position",
- "value": 356518820
+ "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."
},
{
"name": "Headrest height move",
- "value": 356518806
+ "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."
},
{
"name": "Headrest angle position",
- "value": 356518807
+ "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."
},
{
"name": "Headrest angle move",
- "value": 356518808
+ "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."
},
{
"name": "Headrest fore\/aft position",
- "value": 356518809
+ "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."
},
{
"name": "Headrest fore\/aft move",
- "value": 356518810
+ "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."
},
{
"name": "SEAT_FOOTWELL_LIGHTS_STATE",
@@ -638,7 +772,8 @@
"data_enums": [
"VehicleLightState"
],
- "data_enum": "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."
},
{
"name": "SEAT_FOOTWELL_LIGHTS_SWITCH",
@@ -646,15 +781,18 @@
"data_enums": [
"VehicleLightSwitch"
],
- "data_enum": "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."
},
{
"name": "SEAT_EASY_ACCESS_ENABLED",
- "value": 354421661
+ "value": 354421661,
+ "description": "Represents property for Seat easy access feature.\nIf true, the seat will automatically adjust to make it easier for the occupant to enter and exit the vehicle. Each area ID must map to the seat that the user is trying to enter\/exit with the help of the easy access feature.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "SEAT_AIRBAG_ENABLED",
- "value": 354421662
+ "value": 354421662,
+ "description": "Represents feature to enable\/disable a seat's ability to deploy airbag(s) when triggered (e.g. by a crash).\nIf true, it means the seat's airbags are enabled, and if triggered (e.g. by a crash), they will deploy. If false, it means the seat's airbags are disabled, and they will not deploy under any circumstance. This property does not indicate if the airbags are deployed or not.\nThis property can be set to VehiclePropertyAccess.READ read only for the sake of regulation or safety concerns.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Seat airbags deployed",
@@ -662,31 +800,38 @@
"data_enums": [
"VehicleAirbagLocation"
],
- "data_enum": "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)."
},
{
"name": "SEAT_CUSHION_SIDE_SUPPORT_POS",
- "value": 356518815
+ "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."
},
{
"name": "SEAT_CUSHION_SIDE_SUPPORT_MOVE",
- "value": 356518816
+ "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."
},
{
"name": "SEAT_LUMBAR_VERTICAL_POS",
- "value": 356518817
+ "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."
},
{
"name": "SEAT_LUMBAR_VERTICAL_MOVE",
- "value": 356518818
+ "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."
},
{
"name": "SEAT_WALK_IN_POS",
- "value": 356518819
+ "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."
},
{
"name": "SEAT_BELT_PRETENSIONER_DEPLOYED",
- "value": 354421670
+ "value": 354421670,
+ "description": "Seat belt pretensioner deployed.\nProperty to relay information on whether the seat belt pretensioner has been deployed for a particular seat due to a collision. This is different from the regular seat belt tightening system that continuously adds tension to the seat belts so that they fit snugly around the person sitting in the seat, nor is it the seat belt retractor system that locks the seat belt in place during sudden brakes or when the user jerks the seat belt.\nIf this property is dependant on the state of other properties, and those properties are currently in the state that doesn't support this property, this should return StatusCode#NOT_AVAILABLE"
},
{
"name": "Seat Occupancy",
@@ -694,23 +839,28 @@
"data_enums": [
"VehicleSeatOccupancyState"
],
- "data_enum": "VehicleSeatOccupancyState"
+ "data_enum": "VehicleSeatOccupancyState",
+ "description": "Seat Occupancy\nIndicates whether a particular seat is occupied or not, to the best of the car's ability to determine. Valid values are from the VehicleSeatOccupancyState enum."
},
{
"name": "Window Position",
- "value": 322964416
+ "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."
},
{
"name": "Window Move",
- "value": 322964417
+ "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."
},
{
- "name": "Window Lock",
- "value": 320867268
+ "name": "Window Child Lock",
+ "value": 320867268,
+ "description": "Window Child Lock\nTrue indicates the window is child-locked.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "WINDSHIELD_WIPERS_PERIOD",
- "value": 322964421
+ "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."
},
{
"name": "Windshield wipers state.",
@@ -718,7 +868,8 @@
"data_enums": [
"WindshieldWipersState"
],
- "data_enum": "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)."
},
{
"name": "Windshield wipers switch.",
@@ -726,91 +877,113 @@
"data_enums": [
"WindshieldWipersSwitch"
],
- "data_enum": "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."
},
{
"name": "Steering wheel depth position",
- "value": 289410016
+ "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."
},
{
"name": "Steering wheel depth movement",
- "value": 289410017
+ "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."
},
{
"name": "Steering wheel height position",
- "value": 289410018
+ "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."
},
{
"name": "Steering wheel height movement",
- "value": 289410019
+ "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."
},
{
"name": "STEERING_WHEEL_THEFT_LOCK_ENABLED",
- "value": 287312868
+ "value": 287312868,
+ "description": "Steering wheel theft lock feature enabled\nIf true, the steering wheel will lock automatically to prevent theft in certain situations.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Steering wheel locked",
- "value": 287312869
+ "value": 287312869,
+ "description": "Steering wheel locked\nIf true, the steering wheel's position is locked and not changeable.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "STEERING_WHEEL_EASY_ACCESS_ENABLED",
- "value": 287312870
+ "value": 287312870,
+ "description": "Steering wheel easy access feature enabled\nIf true, the driver’s steering wheel will automatically adjust to make it easier for the driver to enter and exit the vehicle.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "GLOVE_BOX_DOOR_POS",
- "value": 356518896
+ "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."
},
{
"name": "Lock or unlock the glove box.",
- "value": 354421745
+ "value": 354421745,
+ "description": "Lock or unlock the glove box.\nIf true, the glove box is locked. If false, the glove box is unlocked.\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 VehicleAreaSeat#ROW_1_RIGHT).\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "VEHICLE_MAP_SERVICE",
- "value": 299895808
+ "value": 299895808,
+ "description": "Vehicle Maps Service (VMS) message\nThis property uses MIXED data to communicate vms messages.\nIts contents are to be interpreted as follows: the indices defined in VmsMessageIntegerValuesIndex are to be used to read from int32Values; bytes is a serialized VMS message as defined in the vms protocol which is opaque to the framework;\nIVehicle#get must always return StatusCode::NOT_AVAILABLE."
},
{
"name": "LOCATION_CHARACTERIZATION",
- "value": 289410064
+ "value": 289410064,
+ "description": "Characterization of inputs used for computing location.\nThis property must indicate what (if any) data and sensor inputs are considered by the system when computing the vehicle's location that is shared with Android through the GNSS HAL.\nThe value must return a collection of bit flags. The bit flags are defined in LocationCharacterization. The value must also include exactly one of DEAD_RECKONED or RAW_GNSS_ONLY among its collection of bit flags.\nWhen this property is not supported, it is assumed that no additional sensor inputs are fused into the GNSS updates provided through the GNSS HAL. That is unless otherwise specified through the GNSS HAL interfaces."
},
{
"name": "ULTRASONICS_SENSOR_POSITION",
- "value": 406916128
+ "value": 406916128,
+ "description": "Static data for the position of each ultrasonic sensor installed on the vehicle.\nEach individual sensor is identified by its unique VehicleAreaConfig#areaId and returns the sensor's position formatted as [x, y, z] where:\nint32Values[0] = x, the position of the sensor along the x-axis relative to the origin of the Android Automotive sensor coordinate frame in millimeters int32Values[1] = y, the position of the sensor along the y-axis relative to the origin of the Android Automotive sensor coordinate frame in millimeters. int32Values[2] = z, the position of the sensor along the z-axis relative to the origin of the Android Automotive sensor coordinate frame in millimeters.\nIf the data is aggregated by another ECU, then OEMs have the option of reporting the same reading across all included sensors or reporting a virtual representation of all the included sensors as if they were one sensor."
},
{
"name": "ULTRASONICS_SENSOR_ORIENTATION",
- "value": 409013281
+ "value": 409013281,
+ "description": "Static data for the orientation of each ultrasonic sensor installed on the vehicle.\nEach individual sensor is identified by its VehicleAreaConfig#areaId and returns the sensor's orientation formatted as [qw, qx, qy, qz] where:\nint32Values[0] = qw, the quaternion coefficient w within the quaterinion (w + xi + yj + zk) describing the rotation of the sensor relative to the Android Automotive sensor coordinate frame. int32Values[1] = qx, the quaternion coefficient x within the quaterinion (w + xi + yj + zk) describing the rotation of the sensor relative to the Android Automotive sensor coordinate frame. int32Values[2] = qy, the quaternion coefficient y within the quaterinion (w + xi + yj + zk) describing the rotation of the sensor relative to the Android Automotive sensor coordinate frame. int32Values[3] = qz, the quaternion coefficient z within the quaterinion (w + xi + yj + zk) describing the rotation of the sensor relative to the Android Automotive sensor coordinate frame.\nThis assumes each sensor uses the same axes conventions as Android Automotive.\nIf the data is aggregated by another ECU, then OEMs have the option of reporting the same reading across all included sensors or reporting a virtual representation of all the included sensors as if they were one sensor."
},
{
"name": "ULTRASONICS_SENSOR_FIELD_OF_VIEW",
- "value": 406916130
+ "value": 406916130,
+ "description": "Static data for the field of view of each ultrasonic sensor in degrees.\nEach individual sensor is identified by its VehicleAreaConfig#areaId and returns the sensor's field of view formatted as [horizontal, vertical] where:\nint32Values[0] = horizontal, the horizontal field of view for the specified ultrasonic sensor in degrees. int32Values[1] = vertical, the vertical field of view for the associated specified ultrasonic sensor in degrees.\nThis assumes each sensor uses the same axes conventions as Android Automotive.\nIf the data is aggregated by another ECU, then OEMs have the option of reporting the same reading across all included sensors or reporting a virtual representation of all the included sensors as if they were one sensor."
},
{
"name": "ULTRASONICS_SENSOR_DETECTION_RANGE",
- "value": 406916131
+ "value": 406916131,
+ "description": "Static data for the detection range of each ultrasonic sensor in millimeters.\nEach individual sensor is identified by its VehicleAreaConfig#areaId and returns the sensor's detection range formatted as [minimum, maximum] where:\nint32Values[0] = minimum, the minimum range detectable by the ultrasonic sensor in millimeters. int32Values[1] = maximum, the maximum range detectable by the ultrasonic sensor in millimeters.\nIf the data is aggregated by another ECU, then OEMs have the option of reporting the same reading across all included sensors or reporting a virtual representation of all the included sensors as if they were one sensor."
},
{
"name": "ULTRASONICS_SENSOR_SUPPORTED_RANGES",
- "value": 406916132
+ "value": 406916132,
+ "description": "Static data for the supported ranges of each ultrasonic sensor in millimeters.\nFor ultrasonic sensors that only support readings within a specific range. For example, if an ultrasonic sensor detects an object at 700mm, but can only report that an object has been detected between 500mm and 1000mm.\nEach individual sensor is identified by its VehicleAreaConfig#areaId and returns the sensor's supported ranges formatted as [range_min_1, range_max_1, range_min_2, range_max_2, ...] where:\nint32Values[0] = range_min_1, the minimum of one supported range by the specified sensor in millimeters, inclusive. int32Values[1] = range_max_1, the maximum of one supported range by the specified sensor in millimeters, inclusive. int32Values[2] = range_min_2, the minimum of another supported range by the specified sensor in millimeters, inclusive. int32Values[3] = range_max_2, the maximum of another supported range by the specified sensor in millimeters, inclusive.\nExample: - Ultrasonic sensor supports the following ranges: - 150mm to 499mm - 500mm to 999mm - 1000mm to 1500mm - The associated supported ranges should be formatted as: - int32Values[0] = 150 - int32Values[1] = 499 - int32Values[2] = 500 - int32Values[3] = 999 - int32Values[4] = 1000 - int32Values[5] = 1500\nIf this property is not defined, all the values within the ULTRASONICS_SENSOR_DETECTION_RANGE for the specified sensor are assumed to be supported.\nIf the data is aggregated by another ECU, then OEMs have the option of reporting the same reading across all included sensors or reporting a virtual representation of all the included sensors as if they were one sensor."
},
{
"name": "ULTRASONICS_SENSOR_MEASURED_DISTANCE",
- "value": 406916133
+ "value": 406916133,
+ "description": "The distance reading of the nearest detected object per sensor in millimeters.\nEach individual sensor is identified by its VehicleAreaConfig#areaId and returns the sensor's measured distance formatted as [distance, distance_error] where:\nint32Values[0] = distance, the measured distance of the nearest object in millimeters. If only a range is supported, this value must be set to the minimum supported distance in the detected range as specified in ULTRASONICS_SENSOR_SUPPORTED_RANGES. int32Values[1] = distance_error, the error of the measured distance value in millimeters.\nIf no object is detected, an empty vector must be returned. If distance_error is not available then an array of only the measured distance must be returned.\nIf the data is aggregated by another ECU, then OEMs have the option of reporting the same reading across all included sensors or reporting a virtual representation of all the included sensors as if they were one sensor."
},
{
"name": "OBD2 Live Sensor Data",
- "value": 299896064
+ "value": 299896064,
+ "description": "OBD2 Live Sensor Data\nReports a snapshot of the current (live) values of the OBD2 sensors available.\nThe configArray is set as follows: configArray[0] = number of vendor-specific integer-valued sensors configArray[1] = number of vendor-specific float-valued sensors\nThe values of this property are to be interpreted as in the following example. Considering a configArray = {2,3} int32Values must be a vector containing Obd2IntegerSensorIndex.LAST_SYSTEM_INDEX + 2 elements (that is, 33 elements); floatValues must be a vector containing Obd2FloatSensorIndex.LAST_SYSTEM_INDEX + 3 elements (that is, 73 elements);\nIt is possible for each frame to contain a different subset of sensor values, both system provided sensors, and vendor-specific ones. In order to support that, the bytes element of the property value is used as a bitmask,.\nbytes must have a sufficient number of bytes to represent the total number of possible sensors (in this case, 14 bytes to represent 106 possible values); it is to be read as a contiguous bitmask such that each bit indicates the presence or absence of a sensor from the frame, starting with as many bits as the size of int32Values, immediately followed by as many bits as the size of floatValues.\nFor example, should bytes[0] = 0x4C (0b01001100) it would mean that: int32Values[0 and 1] are not valid sensor values int32Values[2 and 3] are valid sensor values int32Values[4 and 5] are not valid sensor values int32Values[6] is a valid sensor value int32Values[7] is not a valid sensor value Should bytes[5] = 0x61 (0b01100001) it would mean that: int32Values[32] is a valid sensor value floatValues[0 thru 3] are not valid sensor values floatValues[4 and 5] are valid sensor values floatValues[6] is not a valid sensor value"
},
{
"name": "OBD2 Freeze Frame Sensor Data",
- "value": 299896065
+ "value": 299896065,
+ "description": "OBD2 Freeze Frame Sensor Data\nReports a snapshot of the value of the OBD2 sensors available at the time that a fault occurred and was detected.\nA configArray must be provided with the same meaning as defined for OBD2_LIVE_FRAME.\nThe values of this property are to be interpreted in a similar fashion as those for OBD2_LIVE_FRAME, with the exception that the stringValue field may contain a non-empty diagnostic troubleshooting code (DTC).\nA IVehicle#get request of this property must provide a value for int64Values[0]. This will be interpreted as the timestamp of the freeze frame to retrieve. A list of timestamps can be obtained by a IVehicle#get of OBD2_FREEZE_FRAME_INFO.\nShould no freeze frame be available at the given timestamp, a response of NOT_AVAILABLE must be returned by the implementation. Because vehicles may have limited storage for freeze frames, it is possible for a frame request to respond with NOT_AVAILABLE even if the associated timestamp has been recently obtained via OBD2_FREEZE_FRAME_INFO."
},
{
"name": "OBD2 Freeze Frame Information",
- "value": 299896066
+ "value": 299896066,
+ "description": "OBD2 Freeze Frame Information\nThis property describes the current freeze frames stored in vehicle memory and available for retrieval via OBD2_FREEZE_FRAME.\nThe values are to be interpreted as follows: each element of int64Values must be the timestamp at which a a fault code has been detected and the corresponding freeze frame stored, and each such element can be used as the key to OBD2_FREEZE_FRAME to retrieve the corresponding freeze frame."
},
{
"name": "OBD2 Freeze Frame Clear",
- "value": 299896067
+ "value": 299896067,
+ "description": "OBD2 Freeze Frame Clear\nThis property allows deletion of any of the freeze frames stored in vehicle memory, as described by OBD2_FREEZE_FRAME_INFO.\nThe configArray is set as follows: configArray[0] = 1 if the implementation is able to clear individual freeze frames by timestamp, 0 otherwise\nIVehicle#set of this property is to be interpreted as follows: if int64Values contains no elements, then all frames stored must be cleared; if int64Values contains one or more elements, then frames at the timestamps stored in int64Values must be cleared, and the others not cleared. Should the vehicle not support selective clearing of freeze frames, this latter mode must return NOT_AVAILABLE."
},
{
"name": "Headlights State",
@@ -818,7 +991,8 @@
"data_enums": [
"VehicleLightState"
],
- "data_enum": "VehicleLightState"
+ "data_enum": "VehicleLightState",
+ "description": "Headlights State\nReturn the current state of headlights."
},
{
"name": "High beam lights state",
@@ -826,7 +1000,8 @@
"data_enums": [
"VehicleLightState"
],
- "data_enum": "VehicleLightState"
+ "data_enum": "VehicleLightState",
+ "description": "High beam lights state\nReturn the current state of high beam lights."
},
{
"name": "Fog light state",
@@ -834,7 +1009,8 @@
"data_enums": [
"VehicleLightState"
],
- "data_enum": "VehicleLightState"
+ "data_enum": "VehicleLightState",
+ "description": "Fog light state\nReturn the current state of fog lights.\nIf the car has both front and rear fog lights: If front and rear fog lights can only be controlled together: FOG_LIGHTS_STATE must be implemented. FRONT_FOG_LIGHTS_STATE and REAR_FOG_LIGHTS_STATE must not be implemented.\nIf the front and rear fog lights can only be controlled independently: FOG_LIGHTS_STATE must not be implemented. FRONT_FOG_LIGHTS_STATE and REAR_FOG_LIGHTS_STATE must be implemented.\nIf the car has only front fog lights: Only one of FOG_LIGHTS_STATE or FRONT_FOG_LIGHTS_STATE must be implemented and not both. REAR_FOG_LIGHTS_STATE must not be implemented.\nIf the car has only rear fog lights: Only one of FOG_LIGHTS_STATE or REAR_FOG_LIGHTS_STATE must be implemented and not both. FRONT_FOG_LIGHTS_STATE must not be implemented."
},
{
"name": "Hazard light status",
@@ -842,7 +1018,8 @@
"data_enums": [
"VehicleLightState"
],
- "data_enum": "VehicleLightState"
+ "data_enum": "VehicleLightState",
+ "description": "Hazard light status\nReturn the current status of hazard lights."
},
{
"name": "Headlight switch",
@@ -850,7 +1027,8 @@
"data_enums": [
"VehicleLightSwitch"
],
- "data_enum": "VehicleLightSwitch"
+ "data_enum": "VehicleLightSwitch",
+ "description": "Headlight switch\nThe setting that the user wants.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "High beam light switch",
@@ -858,7 +1036,8 @@
"data_enums": [
"VehicleLightSwitch"
],
- "data_enum": "VehicleLightSwitch"
+ "data_enum": "VehicleLightSwitch",
+ "description": "High beam light switch\nThe setting that the user wants.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Fog light switch",
@@ -866,7 +1045,8 @@
"data_enums": [
"VehicleLightSwitch"
],
- "data_enum": "VehicleLightSwitch"
+ "data_enum": "VehicleLightSwitch",
+ "description": "Fog light switch\nThe setting that the user wants.\nIf the car has both front and rear fog lights: If front and rear fog lights can only be controlled together: FOG_LIGHTS_SWITCH must be implemented. FRONT_FOG_LIGHTS_SWITCH and REAR_FOG_LIGHTS_SWITCH must not be implemented.\nIf the front and rear fog lights can only be controlled independently: FOG_LIGHTS_SWITCH must not be implemented. FRONT_FOG_LIGHTS_SWITCH and REAR_FOG_LIGHTS_SWITCH must be implemented.\nIf the car has only front fog lights: Only one of FOG_LIGHTS_SWITCH or FRONT_FOG_LIGHTS_SWITCH must be implemented and not both. REAR_FOG_LIGHTS_SWITCH must not be implemented.\nIf the car has only rear fog lights: Only one of FOG_LIGHTS_SWITCH or REAR_FOG_LIGHTS_SWITCH must be implemented and not both. FRONT_FOG_LIGHTS_SWITCH must not be implemented.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Hazard light switch",
@@ -874,7 +1054,8 @@
"data_enums": [
"VehicleLightSwitch"
],
- "data_enum": "VehicleLightSwitch"
+ "data_enum": "VehicleLightSwitch",
+ "description": "Hazard light switch\nThe setting that the user wants.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Cabin lights",
@@ -882,7 +1063,8 @@
"data_enums": [
"VehicleLightState"
],
- "data_enum": "VehicleLightState"
+ "data_enum": "VehicleLightState",
+ "description": "Cabin lights\nReturn current status of cabin lights."
},
{
"name": "Cabin lights switch",
@@ -890,7 +1072,8 @@
"data_enums": [
"VehicleLightSwitch"
],
- "data_enum": "VehicleLightSwitch"
+ "data_enum": "VehicleLightSwitch",
+ "description": "Cabin lights switch\nThe position of the physical switch which controls the cabin lights. This might be different than the CABIN_LIGHTS_STATE if the lights are on because a door is open or because of a voice command. For example, while the switch is in the \"off\" or \"automatic\" position.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Reading lights",
@@ -898,7 +1081,8 @@
"data_enums": [
"VehicleLightState"
],
- "data_enum": "VehicleLightState"
+ "data_enum": "VehicleLightState",
+ "description": "Reading lights\nReturn current status of reading lights."
},
{
"name": "Reading lights switch",
@@ -906,7 +1090,8 @@
"data_enums": [
"VehicleLightSwitch"
],
- "data_enum": "VehicleLightSwitch"
+ "data_enum": "VehicleLightSwitch",
+ "description": "Reading lights switch\nThe position of the physical switch which controls the reading lights. This might be different than the READING_LIGHTS_STATE if the lights are on because a door is open or because of a voice command. For example, while the switch is in the \"off\" or \"automatic\" position.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Steering wheel lights state",
@@ -914,7 +1099,8 @@
"data_enums": [
"VehicleLightState"
],
- "data_enum": "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."
},
{
"name": "Steering wheel lights switch",
@@ -922,83 +1108,103 @@
"data_enums": [
"VehicleLightSwitch"
],
- "data_enum": "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."
},
{
"name": "SUPPORT_CUSTOMIZE_VENDOR_PERMISSION",
- "value": 287313669
+ "value": 287313669,
+ "description": "Support customize permissions for vendor properties\nImplement this property if vehicle hal support customize vendor permissions feature. VehiclePropConfig.configArray is used to indicate vendor properties and permissions which selected for this vendor property. The permission must be one of enum in VehicleVendorPermission. The configArray is set as follows: configArray[n] = propId : property ID for the vendor property configArray[n+1] = one of enums in VehicleVendorPermission. It indicates the permission for reading value of the property. configArray[n+2] = one of enums in VehicleVendorPermission. It indicates the permission for writing value of the property.\nFor example: configArray = { vendor_prop_1, PERMISSION_VENDOR_SEAT_READ, PERMISSION_VENDOR_SEAT_WRITE, vendor_prop_2, PERMISSION_VENDOR_INFO, PERMISSION_NOT_ACCESSIBLE, } If vendor properties are not in this array, they will have the default vendor permission. If vendor chose PERMISSION_NOT_ACCESSIBLE, android will not have access to the property. In the example, Android can not write value for vendor_prop_2."
},
{
"name": "DISABLED_OPTIONAL_FEATURES",
- "value": 286265094
+ "value": 286265094,
+ "description": "Allow disabling optional featurs from vhal.\nThis property reports optional features that should be disabled. All allowed optional features for the system is declared in Car service overlay, config_allowed_optional_car_features. This property allows disabling features defined in the overlay. Without this property, all the features declared in the overlay will be enabled.\nValue read should include all features disabled with ',' separation. ex) \"com.android.car.user.CarUserNoticeService,storage_monitoring\""
},
{
"name": "INITIAL_USER_INFO",
- "value": 299896583
+ "value": 299896583,
+ "description": "Defines the initial Android user to be used during initialization.\nThis property is called by the Android system when it initializes and it lets the HAL define which Android user should be started.\nThis request is made by setting a VehiclePropValue (defined by InitialUserInfoRequest), and the HAL must respond with a property change event (defined by InitialUserInfoResponse). If the HAL doesn't respond after some time (defined by the Android system), the Android system will proceed as if HAL returned a response of action InitialUserInfoResponseAction:DEFAULT.\nFor example, on first boot, the request could be:\nint32[0]: 42 \/\/ request id (arbitrary number set by Android system) int32[1]: 1 \/\/ InitialUserInfoRequestType::FIRST_BOOT int32[2]: 0 \/\/ id of current user (usersInfo.currentUser.userId) int32[3]: 1 \/\/ flag of current user (usersInfo.currentUser.flags = SYSTEM) int32[4]: 1 \/\/ number of existing users (usersInfo.numberUsers); int32[5]: 0 \/\/ user #0 (usersInfo.existingUsers[0].userId) int32[6]: 1 \/\/ flags of user #0 (usersInfo.existingUsers[0].flags)\nAnd if the HAL want to respond with the creation of an admin user called \"Owner\", the response would be:\nint32[0]: 42 \/\/ must match the request id from the request int32[1]: 2 \/\/ action = InitialUserInfoResponseAction::CREATE int32[2]: -10000 \/\/ userToSwitchOrCreate.userId (not used as user will be created) int32[3]: 8 \/\/ userToSwitchOrCreate.flags = ADMIN string: \"||Owner\" \/\/ userLocales + separator + userNameToCreate\nNotice the string value represents multiple values, separated by ||. The first value is the (optional) system locales for the user to be created (in this case, it's empty, meaning it will use Android's default value), while the second value is the (also optional) name of the to user to be created (when the type of response is InitialUserInfoResponseAction:CREATE). For example, to create the same \"Owner\" user with \"en-US\" and \"pt-BR\" locales, the string value of the response would be \"en-US,pt-BR||Owner\". As such, neither the locale nor the name can have || on it, although a single | is fine.\nNOTE: if the HAL doesn't support user management, then it should not define this property, which in turn would disable the other user-related properties (for example, the Android system would never issue them and user-related requests from the HAL layer would be ignored by the Android System). But if it supports user management, then it must support all core user-related properties (INITIAL_USER_INFO, SWITCH_USER, CREATE_USER, and REMOVE_USER)."
},
{
"name": "SWITCH_USER",
- "value": 299896584
+ "value": 299896584,
+ "description": "Defines a request to switch the foreground Android user.\nThis property is used primarily by the Android System to inform the HAL that the current foreground Android user is switching, but it could also be used by the HAL to request the Android system to switch users - the\nWhen the request is made by Android, it sets a VehiclePropValue and the HAL must responde with a property change event; when the HAL is making the request, it must also do it through a property change event (the main difference is that the request id will be positive in the former case, and negative in the latter; the SwitchUserMessageType will also be different).\nThe format of both request is defined by SwitchUserRequest and the format of the response (when needed) is defined by SwitchUserResponse. How the HAL (or Android System) should proceed depends on the message type (which is defined by the SwitchUserMessageType parameter), as defined below.\n1.LEGACY_ANDROID_SWITCH -----------------------\nCalled by the Android System to indicate the Android user is about to change, when the change request was made in a way that is not integrated with the HAL (for example, through adb shell am switch-user).\nThe HAL can switch its internal user once it receives this request, but it doesn't need to reply back to the Android System. If its internal user cannot be changed for some reason, then it must wait for the SWITCH_USER(type=ANDROID_POST_SWITCH) call to recover (for example, it could issue a SWITCH_USER(type=VEHICLE_REQUEST) to switch back to the previous user), but ideally it should never fail (as switching back could result in a confusing experience for the end user).\nFor example, if the system have users (0, 10, 11) and it's switching from 0 to 11 (where none of them have any special flag), the request would be:\nint32[0]: 42 \/\/ request id int32[1]: 1 \/\/ SwitchUserMessageType::LEGACY_ANDROID_SWITCH int32[2]: 11 \/\/ target user id int32[3]: 0 \/\/ target user flags (none) int32[4]: 10 \/\/ current user int32[5]: 0 \/\/ current user flags (none) int32[6]: 3 \/\/ number of users int32[7]: 0 \/\/ user #0 (Android user id 0) int32[8]: 0 \/\/ flags of user #0 (none) int32[9]: 10 \/\/ user #1 (Android user id 10) int32[10]: 0 \/\/ flags of user #1 (none) int32[11]: 11 \/\/ user #2 (Android user id 11) int32[12]: 0 \/\/ flags of user #2 (none)\n2.ANDROID_SWITCH ---------------- Called by the Android System to indicate the Android user is about to change, but Android will wait for the HAL's response (up to some time) before proceeding.\nThe HAL must switch its internal user once it receives this request, then respond back to Android with a SWITCH_USER(type=VEHICLE_RESPONSE) indicating whether its internal user was switched or not (through the SwitchUserStatus enum).\nFor example, if Android has users (0, 10, 11) and it's switching from 10 to 11 (where none of them have any special flag), the request would be:\nint32[0]: 42 \/\/ request id int32[1]: 2 \/\/ SwitchUserMessageType::ANDROID_SWITCH int32[2]: 11 \/\/ target user id int32[3]: 0 \/\/ target user flags (none) int32[4]: 10 \/\/ current user int32[5]: 0 \/\/ current user flags (none) int32[6]: 3 \/\/ number of users int32[7]: 0 \/\/ 1st user (user 0) int32[8]: 1 \/\/ 1st user flags (SYSTEM) int32[9]: 10 \/\/ 2nd user (user 10) int32[10]: 0 \/\/ 2nd user flags (none) int32[11]: 11 \/\/ 3rd user (user 11) int32[12]: 0 \/\/ 3rd user flags (none)\nIf the request succeeded, the HAL must update the property with:\nint32[0]: 42 \/\/ request id int32[1]: 3 \/\/ messageType = SwitchUserMessageType::VEHICLE_RESPONSE int32[2]: 1 \/\/ status = SwitchUserStatus::SUCCESS\nBut if it failed, the response would be something like:\nint32[0]: 42 \/\/ request id int32[1]: 3 \/\/ messageType = SwitchUserMessageType::VEHICLE_RESPONSE int32[2]: 2 \/\/ status = SwitchUserStatus::FAILURE string: \"108-D'OH!\" \/\/ OEM-specific error message\n3.VEHICLE_RESPONSE ------------------ Called by the HAL to indicate whether a request of type ANDROID_SWITCH should proceed or abort - see the ANDROID_SWITCH section above for more info.\n4.VEHICLE_REQUEST ------------------ Called by the HAL to request that the current foreground Android user is switched.\nThis is useful in situations where Android started as one user, but the vehicle identified the driver as another user. For example, user A unlocked the car using the key fob of user B; the INITIAL_USER_INFO request returned user B, but then a face recognition subsubsystem identified the user as A.\nThe HAL makes this request by a property change event (passing a negative request id), and the Android system will response by issue an ANDROID_POST_SWITCH call which the same request id.\nFor example, if the current foreground Android user is 10 and the HAL asked it to switch to 11, the request would be:\nint32[0]: -108 \/\/ request id int32[1]: 4 \/\/ messageType = SwitchUserMessageType::VEHICLE_REQUEST int32[2]: 11 \/\/ Android user id\nIf the request succeeded and Android has 3 users (0, 10, 11), the response would be:\nint32[0]: -108 \/\/ request id int32[1]: 5 \/\/ messageType = SwitchUserMessageType::ANDROID_POST_SWITCH int32[2]: 11 \/\/ target user id int32[3]: 0 \/\/ target user id flags (none) int32[4]: 11 \/\/ current user int32[5]: 0 \/\/ current user flags (none) int32[6]: 3 \/\/ number of users int32[7]: 0 \/\/ 1st user (user 0) int32[8]: 0 \/\/ 1st user flags (none) int32[9]: 10 \/\/ 2nd user (user 10) int32[10]: 4 \/\/ 2nd user flags (none) int32[11]: 11 \/\/ 3rd user (user 11) int32[12]: 3 \/\/ 3rd user flags (none)\nNotice that both the current and target user ids are the same - if the request failed, then they would be different (i.e, target user would be 11, but current user would still be 10).\n5.ANDROID_POST_SWITCH --------------------- Called by the Android System after a request to switch a user was made.\nThis property is called after switch requests of any type (i.e., LEGACY_ANDROID_SWITCH, ANDROID_SWITCH, or VEHICLE_REQUEST) and can be used to determine if the request succeeded or failed:\n1. When it succeeded, it's called when the Android user is in the unlocked state and the value of the current and target users ids in the response are the same. This would be equivalent to receiving an Intent.ACTION_USER_UNLOCKED in an Android app. 2. When it failed it's called right away and the value of the current and target users ids in the response are different (as the current user didn't change to the target). 3. If a new switch request is made before the HAL responded to the previous one or before the user was unlocked, then the ANDROID_POST_SWITCH request is not made. For example, the driver could accidentally switch to the wrong user which has lock credentials, then switch to the right one before entering the credentials.\nThe HAL can update its internal state once it receives this request, but it doesn't need to reply back to the Android System.\nRequest: the first N values as defined by INITIAL_USER_INFO (where the request-specific value at index 1 is SwitchUserMessageType::ANDROID_POST_SWITCH), then 2 more values for the target user id (i.e., the Android user id that was requested to be switched to) and its flags (as defined by UserFlags).\nResponse: none.\nExample: see VEHICLE_REQUEST section above."
},
{
"name": "CREATE_USER",
- "value": 299896585
+ "value": 299896585,
+ "description": "Called by the Android System after an Android user was created.\nThe HAL can use this property to create its equivalent user.\nThis is an async request: Android makes the request by setting a VehiclePropValue, and HAL must respond with a property change indicating whether the request succeeded or failed. If it failed, the Android system will remove the user.\nThe format of the request is defined by CreateUserRequest and the format of the response by CreateUserResponse.\nFor example, if system had 2 users (0 and 10) and a 3rd one (which is an ephemeral guest) was created, the request would be:\nint32[0]: 42 \/\/ request id int32[1]: 11 \/\/ Android id of the created user int32[2]: 6 \/\/ Android flags (ephemeral guest) of the created user int32[3]: 10 \/\/ current user int32[4]: 0 \/\/ current user flags (none) int32[5]: 3 \/\/ number of users int32[6]: 0 \/\/ 1st user (user 0) int32[7]: 0 \/\/ 1st user flags (none) int32[8]: 10 \/\/ 2nd user (user 10) int32[9]: 0 \/\/ 2nd user flags (none) int32[19]: 11 \/\/ 3rd user (user 11) int32[11]: 6 \/\/ 3rd user flags (ephemeral guest) string: \"ElGuesto\" \/\/ name of the new user\nThen if the request succeeded, the HAL would return:\nint32[0]: 42 \/\/ request id int32[1]: 1 \/\/ CreateUserStatus::SUCCESS\nBut if it failed:\nint32[0]: 42 \/\/ request id int32[1]: 2 \/\/ CreateUserStatus::FAILURE string: \"D'OH!\" \/\/ The meaning is a blackbox - it's passed to the caller (like Settings UI), \/\/ which in turn can take the proper action."
},
{
"name": "REMOVE_USER",
- "value": 299896586
+ "value": 299896586,
+ "description": "Called by the Android System after an Android user was removed.\nThe HAL can use this property to remove its equivalent user.\nThis is write-only call - the Android System is not expecting a reply from the HAL. Hence, this request should not fail - if the equivalent HAL user cannot be removed, then HAL should mark it as inactive or recover in some other way.\nThe request is made by setting the VehiclePropValue with the contents defined by RemoveUserRequest.\nFor example, if system had 3 users (0, 10, and 11) and user 11 was removed, the request would be:\nint32[0]: 42 \/\/ request id int32[1]: 11 \/\/ (Android user id of the removed user) int32[2]: 0 \/\/ (Android user flags of the removed user) int32[3]: 10 \/\/ current user int32[4]: 0 \/\/ current user flags (none) int32[5]: 2 \/\/ number of users int32[6]: 0 \/\/ 1st user (user 0) int32[7]: 0 \/\/ 1st user flags (none) int32[8]: 10 \/\/ 2nd user (user 10) int32[9]: 0 \/\/ 2nd user flags (none)"
},
{
"name": "USER_IDENTIFICATION_ASSOCIATION",
- "value": 299896587
+ "value": 299896587,
+ "description": "Property used to associate (or query the association) the current user with vehicle-specific identification mechanisms (such as key FOB).\nThis is an optional user management property - the OEM could still support user management without defining it. In fact, this property could be used without supporting the core user-related functions described on INITIAL_USER_INFO.\nTo query the association, the Android system gets the property, passing a VehiclePropValue containing the types of associations are being queried, as defined by UserIdentificationGetRequest. The HAL must return right away, returning a VehiclePropValue with a UserIdentificationResponse. Notice that user identification should have already happened while system is booting up and the VHAL implementation should only return the already identified association (like the key FOB used to unlock the car), instead of starting a new association from the get call.\nTo associate types, the Android system sets the property, passing a VehiclePropValue containing the types and values of associations being set, as defined by the UserIdentificationSetRequest. The HAL will then use a property change event (whose VehiclePropValue is defined by UserIdentificationResponse) indicating the current status of the types after the request.\nFor example, to query if the current user (10) is associated with the FOB that unlocked the car and a custom mechanism provided by the OEM, the request would be:\nint32[0]: 42 \/\/ request id int32[1]: 10 (Android user id) int32[2]: 0 (Android user flags) int32[3]: 2 (number of types queried) int32[4]: 1 (1st type queried, UserIdentificationAssociationType::KEY_FOB) int32[5]: 101 (2nd type queried, UserIdentificationAssociationType::CUSTOM_1)\nIf the user is associated with the FOB but not with the custom mechanism, the response would be:\nint32[0]: 42 \/\/ request id int32[1]: 2 (number of associations in the response) int32[2]: 1 (1st type: UserIdentificationAssociationType::KEY_FOB) int32[3]: 2 (1st value: UserIdentificationAssociationValue::ASSOCIATED_CURRENT_USER) int32[4]: 101 (2st type: UserIdentificationAssociationType::CUSTOM_1) int32[5]: 4 (2nd value: UserIdentificationAssociationValue::NOT_ASSOCIATED_ANY_USER)\nThen to associate the user with the custom mechanism, a set request would be made:\nint32[0]: 43 \/\/ request id int32[1]: 10 (Android user id) int32[2]: 0 (Android user flags) int32[3]: 1 (number of associations being set) int32[4]: 101 (1st type: UserIdentificationAssociationType::CUSTOM_1) int32[5]: 1 (1st value: UserIdentificationAssociationSetValue::ASSOCIATE_CURRENT_USER)\nIf the request succeeded, the response would be simply:\nint32[0]: 43 \/\/ request id int32[1]: 1 (number of associations in the response) int32[2]: 101 (1st type: UserIdentificationAssociationType::CUSTOM_1) int32[3]: 1 (1st value: UserIdentificationAssociationValue::ASSOCIATED_CURRENT_USER)\nNotice that the set request adds associations, but doesn't remove the existing ones. In the example above, the end state would be 2 associations (FOB and CUSTOM_1). If we wanted to associate the user with just CUSTOM_1 but not FOB, then the request should have been:\nint32[0]: 43 \/\/ request id int32[1]: 10 (Android user id) int32[2]: 2 (number of types set) int32[3]: 1 (1st type: UserIdentificationAssociationType::KEY_FOB) int32[4]: 2 (1st value: UserIdentificationAssociationValue::DISASSOCIATE_CURRENT_USER) int32[5]: 101 (2nd type: UserIdentificationAssociationType::CUSTOM_1) int32[6]: 1 (2nd value: UserIdentificationAssociationValue::ASSOCIATE_CURRENT_USER)"
},
{
"name": "Enable\/request an EVS service.",
- "value": 289476368
+ "value": 289476368,
+ "description": "Enable\/request an EVS service.\nThe property provides a generalized way to trigger EVS services. VHAL should use this property to request Android to start or stop EVS service.\nint32Values[0] = a type of the EVS service. The value must be one of enums in EvsServiceType. int32Values[1] = the state of the EVS service. The value must be one of enums in EvsServiceState.\nFor example, to enable rear view EVS service, android side can set the property value as [EvsServiceType::REAR_VIEW, EvsServiceState::ON]."
},
{
"name": "POWER_POLICY_REQ",
- "value": 286265121
+ "value": 286265121,
+ "description": "Defines a request to apply power policy.\nVHAL sets this property to change car power policy. Car power policy service subscribes to this property and actually changes the power policy. The request is made by setting the VehiclePropValue with the ID of a power policy which is defined at \/vendor\/etc\/automotive\/power_policy.xml. If the given ID is not defined, car power policy service ignores the request and the current power policy is maintained.\nstring: \"sample_policy_id\" \/\/ power policy ID"
},
{
"name": "POWER_POLICY_GROUP_REQ",
- "value": 286265122
+ "value": 286265122,
+ "description": "Defines a request to set the power polic group used to decide a default power policy per power status transition.\nVHAL sets this property with the ID of a power policy group in order to set the default power policy applied at power status transition. Power policy groups are defined at \/vendor\/etc\/power_policy.xml. If the given ID is not defined, car power policy service ignores the request. Car power policy service subscribes to this property and sets the power policy group. The actual application of power policy takes place when the system power status changes and there is a valid mapped power policy for the new power status.\nstring: \"sample_policy_group_id\" \/\/ power policy group ID"
},
{
"name": "CURRENT_POWER_POLICY",
- "value": 286265123
+ "value": 286265123,
+ "description": "Notifies the current power policy to VHAL layer.\nCar power policy service sets this property when the current power policy is changed.\nstring: \"sample_policy_id\" \/\/ power policy ID"
},
{
"name": "WATCHDOG_ALIVE",
- "value": 290459441
+ "value": 290459441,
+ "description": "Defines an event that car watchdog updates to tell it's alive.\nCar watchdog sets this property to system uptime in milliseconds at every 3 second. During the boot, the update may take longer time."
},
{
"name": "WATCHDOG_TERMINATED_PROCESS",
- "value": 299896626
+ "value": 299896626,
+ "description": "Defines a process terminated by car watchdog and the reason of termination.\nint32Values[0]: 1 \/\/ ProcessTerminationReason showing why a process is terminated. string: \"\/system\/bin\/log\" \/\/ Process execution command."
},
{
"name": "VHAL_HEARTBEAT",
- "value": 290459443
+ "value": 290459443,
+ "description": "Defines an event that VHAL signals to car watchdog as a heartbeat.\nIf VHAL supports this property, VHAL should write system uptime to this property at every 3 second. Car watchdog subscribes to this property and checks if the property is updated at every 3 second. With the buffer time of 3 second, car watchdog waits for a heart beat to be signaled up to 6 seconds from the last heart beat. If it isn’t, car watchdog considers VHAL unhealthy and terminates it. If this property is not supported by VHAL, car watchdog doesn't check VHAL health status."
},
{
"name": "CLUSTER_SWITCH_UI",
- "value": 289410868
+ "value": 289410868,
+ "description": "Starts the ClusterUI in cluster display.\nint32: the type of ClusterUI to show 0 indicates ClusterHome, that is a home screen of cluster display, and provides the default UI and a kind of launcher functionality for cluster display. the other values are followed by OEM's definition."
},
{
"name": "CLUSTER_DISPLAY_STATE",
- "value": 289476405
+ "value": 289476405,
+ "description": "Changes the state of the cluster display.\nBounds: the area to render the cluster Activity. Inset: the area which Activity should avoid from placing any important information.\nint32[0]: on\/off: 0 - off, 1 - on, -1 - don't care int32[1]: Bounds - left: positive number - left position in pixels -1 - don't care (should set all Bounds fields) int32[2]: Bounds - top: same format with 'left' int32[3]: Bounds - right: same format with 'left' int32[4]: Bounds - bottom: same format with 'left' int32[5]: Inset - left: positive number - actual left inset value in pixels -1 - don't care (should set \"don't care\" all Inset fields) int32[6]: Inset - top: same format with 'left' int32[7]: Inset - right: same format with 'left' int32[8]: Inset - bottom: same format with 'left'"
},
{
"name": "CLUSTER_REPORT_STATE",
- "value": 299896630
+ "value": 299896630,
+ "description": "Reports the current display state and ClusterUI state.\nClusterHome will send this message when it handles CLUSTER_SWITCH_UI, CLUSTER_DISPLAY_STATE.\nIn addition, ClusterHome should send this message when it starts for the first time. When ClusterOS receives this message and if the internal expectation is different with the received message, then it should send CLUSTER_SWITCH_UI, CLUSTER_DISPLAY_STATE again to match the state.\nint32[0]: on\/off: 0 - off, 1 - on int32[1]: Bounds - left int32[2]: Bounds - top int32[3]: Bounds - right int32[4]: Bounds - bottom int32[5]: Inset - left int32[6]: Inset - top int32[7]: Inset - right int32[8]: Inset - bottom int32[9]: the type of ClusterUI in the fullscreen or main screen. 0 indicates ClusterHome. the other values are followed by OEM's definition. int32[10]: the type of ClusterUI in sub screen if the currently two UIs are shown. -1 indicates the area isn't used any more. bytes: the array to represent the availability of ClusterUI. 0 indicates non-available and 1 indicates available. For example, let's assume a car supports 3 OEM defined ClusterUI like HOME, MAPS, CALL, and it only supports CALL UI only when the cellular network is available. Then, if the nework is avaibale, it'll send [1 1 1], and if it's out of network, it'll send [1 1 0]."
},
{
"name": "CLUSTER_REQUEST_DISPLAY",
- "value": 289410871
+ "value": 289410871,
+ "description": "Requests to change the cluster display state to show some ClusterUI.\nWhen the current display state is off and ClusterHome sends this message to ClusterOS to request to turn the display on to show some specific ClusterUI. ClusterOS should response this with CLUSTER_DISPLAY_STATE.\nint32: the type of ClusterUI to show"
},
{
"name": "CLUSTER_NAVIGATION_STATE",
- "value": 292556600
+ "value": 292556600,
+ "description": "Informs the current navigation state.\nbytes: the serialized message of NavigationStateProto."
},
{
"name": "ELECTRONIC_TOLL_COLLECTION_CARD_TYPE",
@@ -1006,7 +1212,8 @@
"data_enums": [
"ElectronicTollCollectionCardType"
],
- "data_enum": "ElectronicTollCollectionCardType"
+ "data_enum": "ElectronicTollCollectionCardType",
+ "description": "Electronic Toll Collection card type.\nThis property indicates the type of ETC card in this vehicle. If the head unit is aware of an ETC card attached to the vehicle, this property should return the type of card attached; otherwise, this property should be UNAVAILABLE."
},
{
"name": "ELECTRONIC_TOLL_COLLECTION_CARD_STATUS",
@@ -1014,7 +1221,8 @@
"data_enums": [
"ElectronicTollCollectionCardStatus"
],
- "data_enum": "ElectronicTollCollectionCardStatus"
+ "data_enum": "ElectronicTollCollectionCardStatus",
+ "description": "Electronic Toll Collection card status.\nThis property indicates the status of ETC card in this vehicle. If the head unit is aware of an ETC card attached to the vehicle, ELECTRONIC_TOLL_COLLECTION_CARD_TYPE gives that status of the card; otherwise, this property should be UNAVAILABLE."
},
{
"name": "Front fog lights state",
@@ -1022,7 +1230,8 @@
"data_enums": [
"VehicleLightState"
],
- "data_enum": "VehicleLightState"
+ "data_enum": "VehicleLightState",
+ "description": "Front fog lights state\nReturn the current state of the front fog lights. Only one of FOG_LIGHTS_STATE or FRONT_FOG_LIGHTS_STATE must be implemented. Please refer to the documentation on FOG_LIGHTS_STATE for more information."
},
{
"name": "Front fog lights switch",
@@ -1030,7 +1239,8 @@
"data_enums": [
"VehicleLightSwitch"
],
- "data_enum": "VehicleLightSwitch"
+ "data_enum": "VehicleLightSwitch",
+ "description": "Front fog lights switch\nThe setting that the user wants. Only one of FOG_LIGHTS_SWITCH or FRONT_FOG_LIGHTS_SWITCH must be implemented. Please refer to the documentation on FOG_LIGHTS_SWITCH for more information.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Rear fog lights state",
@@ -1038,7 +1248,8 @@
"data_enums": [
"VehicleLightState"
],
- "data_enum": "VehicleLightState"
+ "data_enum": "VehicleLightState",
+ "description": "Rear fog lights state\nReturn the current state of the rear fog lights. Only one of FOG_LIGHTS_STATE or REAR_FOG_LIGHTS_STATE must be implemented. Please refer to the documentation on FOG_LIGHTS_STATE for more information."
},
{
"name": "Rear fog lights switch",
@@ -1046,15 +1257,18 @@
"data_enums": [
"VehicleLightSwitch"
],
- "data_enum": "VehicleLightSwitch"
+ "data_enum": "VehicleLightSwitch",
+ "description": "Rear fog lights switch\nThe setting that the user wants. Only one of FOG_LIGHTS_SWITCH or REAR_FOG_LIGHTS_SWITCH must be implemented. Please refer to the documentation on FOG_LIGHTS_SWITCH for more information.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "EV_CHARGE_CURRENT_DRAW_LIMIT",
- "value": 291508031
+ "value": 291508031,
+ "description": "Indicates the maximum current draw threshold for charging set by the user\nconfigArray[0] is used to specify the max current draw allowed by the vehicle in Amperes.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "EV_CHARGE_PERCENT_LIMIT",
- "value": 291508032
+ "value": 291508032,
+ "description": "Indicates the maximum charge percent threshold set by the user\nReturns a float value from 0 to 100.\nconfigArray is used to specify the valid values. For example, if the vehicle supports the following charge percent limit values: [20, 40, 60, 80, 100] then the configArray should be {20, 40, 60, 80, 100} If the configArray is empty then all values from 0 to 100 must be valid.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Charging state of the car",
@@ -1062,15 +1276,18 @@
"data_enums": [
"EvChargeState"
],
- "data_enum": "EvChargeState"
+ "data_enum": "EvChargeState",
+ "description": "Charging state of the car\nReturns the current charging state of the car.\nIf the vehicle has a target charge percentage other than 100, this property must return EvChargeState::STATE_FULLY_CHARGED when the battery charge level has reached the target level. See EV_CHARGE_PERCENT_LIMIT for more context."
},
{
"name": "EV_CHARGE_SWITCH",
- "value": 287313730
+ "value": 287313730,
+ "description": "Start or stop charging the EV battery\nThe setting that the user wants. Setting this property to true starts the battery charging and setting to false stops charging.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "EV_CHARGE_TIME_REMAINING",
- "value": 289410883
+ "value": 289410883,
+ "description": "Estimated charge time remaining in seconds\nReturns 0 if the vehicle is not charging."
},
{
"name": "EV_REGENERATIVE_BRAKING_STATE",
@@ -1078,7 +1295,8 @@
"data_enums": [
"EvRegenerativeBrakingState"
],
- "data_enum": "EvRegenerativeBrakingState"
+ "data_enum": "EvRegenerativeBrakingState",
+ "description": "Regenerative braking or one-pedal drive setting of the car\nReturns the current setting associated with the regenerative braking setting in the car\nIf the OEM requires more setting than those provided in EvRegenerativeBrakingState, the EV_BRAKE_REGENERATION_LEVEL property can be used instead, which provides a more granular way of providing the same information."
},
{
"name": "TRAILER_PRESENT",
@@ -1086,11 +1304,13 @@
"data_enums": [
"TrailerState"
],
- "data_enum": "TrailerState"
+ "data_enum": "TrailerState",
+ "description": "Indicates if there is a trailer present or not.\nReturns the trailer state of the car."
},
{
"name": "VEHICLE_CURB_WEIGHT",
- "value": 289410886
+ "value": 289410886,
+ "description": "Vehicle’s curb weight in kilograms.\nReturns the vehicle's curb weight in kilograms. Curb weight is the total weight of the vehicle with standard equipment and all necessary operating consumables such as motor oil,transmission oil, brake fluid, coolant, air conditioning refrigerant, and weight of fuel at nominal tank capacity, while not loaded with either passengers or cargo.\nconfigArray[0] is used to specify the vehicle’s gross weight in kilograms. The vehicle’s gross weight is the maximum operating weight of the vehicle as specified by the manufacturer including the vehicle's chassis, body, engine, engine fluids, fuel, accessories, driver, passengers and cargo but excluding that of any trailers."
},
{
"name": "GENERAL_SAFETY_REGULATION_COMPLIANCE_REQUIREMENT",
@@ -1098,11 +1318,13 @@
"data_enums": [
"GsrComplianceRequirementType"
],
- "data_enum": "GsrComplianceRequirementType"
+ "data_enum": "GsrComplianceRequirementType",
+ "description": "EU's General security regulation compliance requirement.\nReturns whether general security regulation compliance is required, if so, what type of requirement."
},
{
"name": "SUPPORTED_PROPERTY_IDS",
- "value": 289476424
+ "value": 289476424,
+ "description": "(Deprecated) List of all supported property IDs.\nA list of all supported property IDs (including this property). This property is required for HIDL VHAL to work with large amount of vehicle prop configs where the getAllPropConfigs payload exceeds the binder limitation. This issue is fixed in AIDL version using LargeParcelable in getAllPropConfigs, so this property is deprecated.\nIn HIDL VHAL implementation, if the amount of data returned in getAllPropConfigs exceeds the binder limitation, vendor must support this property and return all the supported property IDs. Car service will divide this list into smaller sub lists and use getPropConfigs([ids]) to query the sub lists. The results will be merged together in Car Service.\nThe config array for this property must contain one int element which is the number of configs per getPropConfigs request by Car Service. This number must be small enough so that each getPropConfigs payload will not exceed binder limitation, however, a smaller number will cause more requests, which increase overhead to fetch all the configs."
},
{
"name": "SHUTDOWN_REQUEST",
@@ -1110,15 +1332,18 @@
"data_enums": [
"VehicleApPowerStateShutdownParam"
],
- "data_enum": "VehicleApPowerStateShutdownParam"
+ "data_enum": "VehicleApPowerStateShutdownParam",
+ "description": "Request the head unit to be shutdown.\n<p>This is required for executing a task when the head unit is powered off (remote task feature). After the head unit is powered-on to execute the task, the head unit should be shutdown. The head unit will send this message once the task is finished.\n<p>This is not for the case when a user wants to shutdown the head unit.\n<p>This usually involves telling a separate system outside the head unit (e.g. a power controller) to prepare shutting down the head unit.\n<p>Note that the external system must validate whether this request is valid by checking whether the vehicle is currently in use. If a user enters the vehicle after a SHUTDOWN_REQUEST is sent, then the system must ignore this request. It is recommended to store a VehicleInUse property in the power controller and exposes it through VEHICLE_IN_USE property. A shutdown request must be ignored if VehicleInUse is true.\n<p>If allowed, the external system will start sending a shutdown signal to the head unit, which will cause VHAL to send SHUTDOWN_PREPARE message to Android. Android will then start the shut down process by handling the message.\n<p>This property is only for issuing a request and only supports writing. Every time this property value is set, the request to shutdown will be issued no matter what the current property value is. The current property value is meaningless.\n<p>Since this property is write-only, subscribing is not allowed and no property change event will be generated.\n<p>The value to set indicates the shutdown option, it must be one of {@code VehicleApPowerStateShutdownParam}, e.g., VehicleApPowerStateShutdownParam.SLEEP_IMMEDIATELY. This shutdown option might not be honored if the system doesn't support such option. In such case, an error will not be returned.\n<p>For configuration information, VehiclePropConfig.configArray must have bit flag combining values in {@code VehicleApPowerStateConfigFlag} to indicate which shutdown options are supported.\n<p>Returns error if failed to send the shutdown request to the other system."
},
{
"name": "VEHICLE_IN_USE",
- "value": 287313738
+ "value": 287313738,
+ "description": "Whether the vehicle is currently in use.\n<p>In-use means a human user is present and is intended to use the vehicle. This doesn't necessarily means the human user is in the vehicle. For example, if the human user unlocks the vehicle remotely, the vehicle is considered in use.\n<p>If this property is supported:\n<p>Each time user powers on the vehicle or the system detects the user is present, VEHICLE_IN_USE must be set to true. Each time user powers off the vehicle or the system detects the user is not present, VEHICLE_IN_USE must be set to false.\n<p>This property is different than AP_POWER_BOOTUP_REASON in the sense that AP_POWER_BOOTUP_REASON is only set once during the system bootup. However, this property might change multiple times during a system bootup cycle.\n<p>For example, a device is currently not in use. The system bootup to execute a remote task. VEHICLE_IN_USE is false. While the remote task is executing, the user enters the vehicle and powers on the vehicle. VEHICLE_IN_USE is set to true. After a driving session, user powers off the vehicle, VEHICLE_IN_USE is set to false.\n<p>This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "CLUSTER_HEARTBEAT",
- "value": 299896651
+ "value": 299896651,
+ "description": "Sends the heartbeat signal to ClusterOS.\nint64[0]: epochTimeNs int64[1]: the visibility of ClusterUI, 0 - invisible, 1 - visible bytes: the app specific metadata, this can be empty when ClusterHomeService use the heartbeat to deliver the change of the visibility."
},
{
"name": "VEHICLE_DRIVING_AUTOMATION_CURRENT_LEVEL",
@@ -1126,7 +1351,8 @@
"data_enums": [
"VehicleAutonomousState"
],
- "data_enum": "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."
},
{
"name": "CAMERA_SERVICE_CURRENT_STATE",
@@ -1134,11 +1360,13 @@
"data_enums": [
"CameraServiceState"
],
- "data_enum": "CameraServiceState"
+ "data_enum": "CameraServiceState",
+ "description": "Reports current state of CarEvsService types.\nInforms other components of current state of each CarEvsService service type with values defined in CameraServiceState. CarEvsService will update this property whenever a service type transitions into a new state.\nint32[0]: Current state of REARVIEW service type. int32[1]: Current state of SURROUNDVIEW service type. int32[2]: Current state of FRONTVIEW service type. int32[3]: Current state of LEFTVIEW service type. int32[4]: Current state of RIGHTVIEW service type. int32[5]: Current state of DRIVERVIEW service type. int32[6]: Current state of FRONT_PASSENGERVIEW service type. int32[7]: Current state of REAR_PASSENGERVIEW service type."
},
{
"name": "AUTOMATIC_EMERGENCY_BRAKING_ENABLED",
- "value": 287313920
+ "value": 287313920,
+ "description": "Enable or disable Automatic Emergency Braking (AEB).\nSet true to enable AEB and false to disable AEB. When AEB is enabled, the ADAS system in the vehicle should be turned on and monitoring to avoid potential collisions. This property should apply for higher speed applications only. For enabling low speed automatic emergency braking, LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED should be used.\nIn general, AUTOMATIC_EMERGENCY_BRAKING_ENABLED should always return true or false. If the feature is not available due to some temporary state, such as the vehicle speed being too low, that information must be conveyed through the ErrorState values in the AUTOMATIC_EMERGENCY_BRAKING_STATE property.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "AUTOMATIC_EMERGENCY_BRAKING_STATE",
@@ -1147,11 +1375,13 @@
"AutomaticEmergencyBrakingState",
"ErrorState"
],
- "data_enum": "AutomaticEmergencyBrakingState"
+ "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."
},
{
"name": "FORWARD_COLLISION_WARNING_ENABLED",
- "value": 287313922
+ "value": 287313922,
+ "description": "Enable or disable Forward Collision Warning (FCW).\nSet true to enable FCW and false to disable FCW. When FCW is enabled, the ADAS system in the vehicle should be turned on and monitoring for potential collisions.\nIn general, FORWARD_COLLISION_WARNING_ENABLED should always return true or false. If the feature is not available due to some temporary state, such as the vehicle speed being too low, that information must be conveyed through the ErrorState values in the FORWARD_COLLISION_WARNING_STATE property.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "FORWARD_COLLISION_WARNING_STATE",
@@ -1160,11 +1390,13 @@
"ForwardCollisionWarningState",
"ErrorState"
],
- "data_enum": "ForwardCollisionWarningState"
+ "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."
},
{
"name": "BLIND_SPOT_WARNING_ENABLED",
- "value": 287313924
+ "value": 287313924,
+ "description": "Enable and disable Blind Spot Warning (BSW).\nSet true to enable BSW and false to disable BSW. When BSW is enabled, the ADAS system in the vehicle should be turned on and monitoring for objects in the vehicle’s blind spots.\nIn general, BLIND_SPOT_WARNING_ENABLED should always return true or false. If the feature is not available due to some temporary state, such as the vehicle speed being too low, that information must be conveyed through the ErrorState values in the BLIND_SPOT_WARNING_STATE property.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "BLIND_SPOT_WARNING_STATE",
@@ -1173,11 +1405,13 @@
"BlindSpotWarningState",
"ErrorState"
],
- "data_enum": "BlindSpotWarningState"
+ "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."
},
{
"name": "LANE_DEPARTURE_WARNING_ENABLED",
- "value": 287313926
+ "value": 287313926,
+ "description": "Enable or disable Lane Departure Warning (LDW).\nSet true to enable LDW and false to disable LDW. When LDW is enabled, the ADAS system in the vehicle should be turned on and monitoring if the vehicle is approaching or crossing lane lines, in which case a warning will be given.\nIn general, LANE_DEPARTURE_WARNING_ENABLED should always return true or false. If the feature is not available due to some temporary state, such as the vehicle speed being too low or too high, that information must be conveyed through the ErrorState values in the LANE_DEPARTURE_WARNING_STATE property.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "LANE_DEPARTURE_WARNING_STATE",
@@ -1186,11 +1420,13 @@
"LaneDepartureWarningState",
"ErrorState"
],
- "data_enum": "LaneDepartureWarningState"
+ "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."
},
{
"name": "LANE_KEEP_ASSIST_ENABLED",
- "value": 287313928
+ "value": 287313928,
+ "description": "Enable or disable Lane Keep Assist (LKA).\nSet true to enable LKA and false to disable LKA. When LKA is enabled, the ADAS system in the vehicle should be turned on and monitoring if the driver unintentionally drifts toward or over the lane marking. If an unintentional lane departure is detected, the system applies steering control to return the vehicle into the current lane.\nThis is different from Lane Centering Assist (LCA) which, when activated, applies continuous steering control to keep the vehicle centered in the current lane.\nIn general, LANE_KEEP_ASSIST_ENABLED should always return true or false. If the feature is not available due to some temporary state, such as the vehicle speed being too low or too high, that information must be conveyed through the ErrorState values in the LANE_KEEP_ASSIST_STATE property.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Lane Keep Assist (LKA) state.",
@@ -1199,11 +1435,13 @@
"LaneKeepAssistState",
"ErrorState"
],
- "data_enum": "LaneKeepAssistState"
+ "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."
},
{
"name": "LANE_CENTERING_ASSIST_ENABLED",
- "value": 287313930
+ "value": 287313930,
+ "description": "Enable or disable Lane Centering Assist (LCA).\nSet true to enable LCA and false to disable LCA. When LCA is enabled, the ADAS system in the vehicle should be turned on and waiting for an activation signal from the driver. Once the feature is activated, the ADAS system should be steering the vehicle to keep it centered in its current lane.\nThis is different from Lane Keep Assist (LKA) which monitors if the driver unintentionally drifts toward or over the lane marking. If an unintentional lane departure is detected, the system applies steering control to return the vehicle into the current lane.\nIn general, LANE_CENTERING_ASSIST_ENABLED should always return true or false. If the feature is not available due to some temporary state, such as the vehicle speed being too low or too high, that information must be conveyed through the ErrorState values in the LANE_CENTERING_ASSIST_STATE property.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "LANE_CENTERING_ASSIST_COMMAND",
@@ -1211,7 +1449,8 @@
"data_enums": [
"LaneCenteringAssistCommand"
],
- "data_enum": "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."
},
{
"name": "LANE_CENTERING_ASSIST_STATE",
@@ -1220,11 +1459,13 @@
"LaneCenteringAssistState",
"ErrorState"
],
- "data_enum": "LaneCenteringAssistState"
+ "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."
},
{
"name": "EMERGENCY_LANE_KEEP_ASSIST_ENABLED",
- "value": 287313933
+ "value": 287313933,
+ "description": "Enable or disable Emergency Lane Keep Assist (ELKA).\nSet true to enable ELKA and false to disable ELKA. When ELKA is enabled, the ADAS system in the vehicle should be on and monitoring for unsafe lane changes by the driver. When an unsafe maneuver is detected, ELKA alerts the driver and applies steering corrections to keep the vehicle in its original lane.\nIn general, EMERGENCY_LANE_KEEP_ASSIST_ENABLED should always return true or false. If the feature is not available due to some temporary state, such as the vehicle speed being too low, that information must be conveyed through the ErrorState values in the EMERGENCY_LANE_KEEP_ASSIST_STATE property.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "EMERGENCY_LANE_KEEP_ASSIST_STATE",
@@ -1233,11 +1474,13 @@
"EmergencyLaneKeepAssistState",
"ErrorState"
],
- "data_enum": "EmergencyLaneKeepAssistState"
+ "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."
},
{
"name": "CRUISE_CONTROL_ENABLED",
- "value": 287313935
+ "value": 287313935,
+ "description": "Enable or disable cruise control (CC).\nSet true to enable CC and false to disable CC. This property is shared by all forms of CruiseControlType(s).\nWhen CC is enabled, the ADAS system in the vehicle should be turned on and responding to commands.\nIn general, CRUISE_CONTROL_ENABLED should always return true or false. If the feature is not available due to some temporary state, such as the vehicle speed being too low, that information must be conveyed through the ErrorState values in the CRUISE_CONTROL_STATE property.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "CRUISE_CONTROL_TYPE",
@@ -1246,7 +1489,8 @@
"CruiseControlType",
"ErrorState"
],
- "data_enum": "CruiseControlType"
+ "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."
},
{
"name": "CRUISE_CONTROL_STATE",
@@ -1255,7 +1499,8 @@
"CruiseControlState",
"ErrorState"
],
- "data_enum": "CruiseControlState"
+ "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."
},
{
"name": "CRUISE_CONTROL_COMMAND",
@@ -1263,23 +1508,28 @@
"data_enums": [
"CruiseControlCommand"
],
- "data_enum": "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."
},
{
"name": "CRUISE_CONTROL_TARGET_SPEED",
- "value": 291508243
+ "value": 291508243,
+ "description": "Current target speed for Cruise Control (CC).\nOEMs should set the minFloatValue and maxFloatValue values for this property to define the min and max target speed values. These values must be non-negative.\nThe maxFloatValue represents the upper bound of the target speed. The minFloatValue represents the lower bound of the target speed.\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": "ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP",
- "value": 289411092
+ "value": 289411092,
+ "description": "Current target time gap for Adaptive Cruise Control (ACC) or Predictive Cruise Control in milliseconds.\nThis property should specify the target time gap to a leading vehicle. This gap is defined as the time to travel the distance between the leading vehicle's rear-most point to the ACC vehicle's front-most point. The actual time gap from a leading vehicle can be above or below this value.\nThe possible values to set for the target time gap should be specified in configArray in ascending order. All values must be positive. If the property is writable, all values must be writable.\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.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "ADAPTIVE_CRUISE_CONTROL_LEAD_VEHICLE_MEASURED_DISTANCE",
- "value": 289411093
+ "value": 289411093,
+ "description": "Measured distance from leading vehicle when using Adaptive Cruise Control (ACC) or Predictive Cruise Control.\nReturns the measured distance in millimeters between the rear-most point of the leading vehicle and the front-most point of the ACC vehicle.\nThe maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. The minInt32Value should be 0. The maxInt32Value should be populated with the maximum range the distance sensor can support. This value should be non-negative.\nWhen no lead vehicle is detected (that is, when there is no leading vehicle or the leading vehicle is too far away for the sensor to detect), this property should return StatusCode.NOT_AVAILABLE.\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": "HANDS_ON_DETECTION_ENABLED",
- "value": 287313942
+ "value": 287313942,
+ "description": "Enable or disable Hands On Detection (HOD).\nSet true to enable HOD and false to disable HOD. When HOD is enabled, a system inside the vehicle should be monitoring the presence of the driver's hands on the steering wheel and send a warning if it detects that the driver's hands are no longer on the steering wheel.\nIn general, HANDS_ON_DETECTION_ENABLED should always return true or false. If the feature is not available due to some temporary state, that information must be conveyed through the ErrorState values in the HANDS_ON_DETECTION_STATE property.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "HANDS_ON_DETECTION_DRIVER_STATE",
@@ -1288,7 +1538,8 @@
"HandsOnDetectionDriverState",
"ErrorState"
],
- "data_enum": "HandsOnDetectionDriverState"
+ "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."
},
{
"name": "HANDS_ON_DETECTION_WARNING",
@@ -1297,11 +1548,13 @@
"HandsOnDetectionWarning",
"ErrorState"
],
- "data_enum": "HandsOnDetectionWarning"
+ "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."
},
{
"name": "DRIVER_DROWSINESS_ATTENTION_SYSTEM_ENABLED",
- "value": 287313945
+ "value": 287313945,
+ "description": "Enable or disable driver drowsiness and attention monitoring.\nSet true to enable driver drowsiness and attention monitoring and false to disable driver drowsiness and attention monitoring. When driver drowsiness and attention monitoring is enabled, a system inside the vehicle should be monitoring the drowsiness and attention level of the driver and warn the driver if needed.\nIn general, DRIVER_DROWSINESS_ATTENTION_SYSTEM_ENABLED should always return true or false. If the feature is not available due to some temporary state, that information must be conveyed through the ErrorState values in the DRIVER_DROWSINESS_ATTENTION_STATE property.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "DRIVER_DROWSINESS_ATTENTION_STATE",
@@ -1310,11 +1563,13 @@
"DriverDrowsinessAttentionState",
"ErrorState"
],
- "data_enum": "DriverDrowsinessAttentionState"
+ "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."
},
{
"name": "DRIVER_DROWSINESS_ATTENTION_WARNING_ENABLED",
- "value": 287313947
+ "value": 287313947,
+ "description": "Enable or disable driver drowsiness and attention warnings.\nSet true to enable driver drowsiness and attention warnings and false to disable driver drowsiness and attention warnings.\nWhen driver drowsiness and attention warnings are enabled, the driver drowsiness and attention monitoring system inside the vehicle should warn the driver when it detects the driver is drowsy or not attentive.\nIn general, DRIVER_DROWSINESS_ATTENTION_WARNING_ENABLED should always return true or false. If the feature is not available due to some temporary state, that information must be conveyed through the ErrorState values in the DRIVER_DROWSINESS_ATTENTION_WARNING property.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "DRIVER_DROWSINESS_ATTENTION_WARNING",
@@ -1323,11 +1578,13 @@
"DriverDrowsinessAttentionWarning",
"ErrorState"
],
- "data_enum": "DriverDrowsinessAttentionWarning"
+ "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."
},
{
"name": "DRIVER_DISTRACTION_SYSTEM_ENABLED",
- "value": 287313949
+ "value": 287313949,
+ "description": "Enable or disable driver distraction monitoring.\nSet true to enable driver distraction monitoring and false to disable driver distraction monitoring. When driver distraction monitoring is enabled, a system inside the vehicle should be monitoring the distraction level of the driver and warn the driver if needed.\nIn general, DRIVER_DISTRACTION_SYSTEM_ENABLED should always return true or false. If the feature is not available due to some temporary state, that information must be conveyed through the ErrorState values in the DRIVER_DISTRACTION_STATE property.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Driver distraction state.",
@@ -1336,11 +1593,13 @@
"DriverDistractionState",
"ErrorState"
],
- "data_enum": "DriverDistractionState"
+ "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."
},
{
"name": "DRIVER_DISTRACTION_WARNING_ENABLED",
- "value": 287313951
+ "value": 287313951,
+ "description": "Enable or disable driver distraction warnings.\nSet true to enable driver distraction warnings and false to disable driver distraction warnings.\nWhen driver distraction warnings are enabled, the driver distraction monitoring system inside the vehicle should warn the driver when it detects the driver is distracted.\nIn general, DRIVER_DISTRACTION_WARNING_ENABLED should always return true or false. If the feature is not available due to some temporary state, that information must be conveyed through the ErrorState values in the DRIVER_DISTRACTION_WARNING property.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "Driver distraction warning.",
@@ -1349,11 +1608,13 @@
"DriverDistractionWarning",
"ErrorState"
],
- "data_enum": "DriverDistractionWarning"
+ "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."
},
{
"name": "LOW_SPEED_COLLISION_WARNING_ENABLED",
- "value": 287313953
+ "value": 287313953,
+ "description": "Enable or disable Low Speed Collision Warning.\nSet true to enable low speed collision warning and false to disable low speed collision warning. When low speed collision warning is enabled, the ADAS system in the vehicle should warn the driver of potential collisions at low speeds. This property is different from the pre-existing FORWARD_COLLISION_WARNING_ENABLED, 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.\nIn general, LOW_SPEED_COLLISION_WARNING_ENABLED should always return true or false. If the feature is not available due to some temporary state, such as the vehicle speed being too high, that information must be conveyed through the ErrorState values in the LOW_SPEED_COLLISION_WARNING_STATE property.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "LOW_SPEED_COLLISION_WARNING_STATE",
@@ -1362,11 +1623,13 @@
"LowSpeedCollisionWarningState",
"ErrorState"
],
- "data_enum": "LowSpeedCollisionWarningState"
+ "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."
},
{
"name": "CROSS_TRAFFIC_MONITORING_ENABLED",
- "value": 287313955
+ "value": 287313955,
+ "description": "Enable or disable Cross Traffic Monitoring.\nSet true to enable Cross Traffic Monitoring and false to disable Cross Traffic Monitoring. When Cross Traffic Monitoring is enabled, the ADAS system in the vehicle should be turned on and monitoring for potential sideways collisions.\nIn general, CROSS_TRAFFIC_MONITORING_ENABLED should always return true or false. If the feature is not available due to some temporary state, such as the vehicle speed being too high, that information must be conveyed through the ErrorState values in the CROSS_TRAFFIC_MONITORING_STATE property.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "CROSS_TRAFFIC_MONITORING_WARNING_STATE",
@@ -1375,11 +1638,13 @@
"CrossTrafficMonitoringWarningState",
"ErrorState"
],
- "data_enum": "CrossTrafficMonitoringWarningState"
+ "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."
},
{
"name": "LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED",
- "value": 287313957
+ "value": 287313957,
+ "description": "Enable or disable Low Speed Automatic Emergency Braking.\nSet true to enable Low Speed Automatic Emergency Braking or false to disable Low Speed Automatic Emergency Braking. When Low Speed Automatic Emergency Braking is enabled, the ADAS system in the vehicle should be turned on and monitoring to avoid potential collisions in low speed conditions. This property is different from the pre-existing AUTOMATIC_EMERGENCY_BRAKING_ENABLED, 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.\nIn general, LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED should always return true or false. If the feature is not available due to some temporary state, such as the vehicle speed being too low, that information must be conveyed through the ErrorState values in the LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE property.\nThis property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to implement it as VehiclePropertyAccess.READ only."
},
{
"name": "LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE",
@@ -1388,12 +1653,13 @@
"LowSpeedAutomaticEmergencyBrakingState",
"ErrorState"
],
- "data_enum": "LowSpeedAutomaticEmergencyBrakingState"
+ "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."
}
]
},
{
- "name": "LaneDepartureWarningState",
+ "name": "AutomaticEmergencyBrakingState",
"package": "android.hardware.automotive.vehicle",
"values": [
{
@@ -1401,21 +1667,21 @@
"value": 0
},
{
- "name": "NO_WARNING",
+ "name": "ENABLED",
"value": 1
},
{
- "name": "WARNING_LEFT",
+ "name": "ACTIVATED",
"value": 2
},
{
- "name": "WARNING_RIGHT",
+ "name": "USER_OVERRIDE",
"value": 3
}
]
},
{
- "name": "HandsOnDetectionWarning",
+ "name": "BlindSpotWarningState",
"package": "android.hardware.automotive.vehicle",
"values": [
{
@@ -1433,6 +1699,194 @@
]
},
{
+ "name": "CameraServiceState",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "UNAVAILABLE",
+ "value": 0
+ },
+ {
+ "name": "INACTIVE",
+ "value": 1
+ },
+ {
+ "name": "REQUESTED",
+ "value": 2
+ },
+ {
+ "name": "ACTIVE",
+ "value": 3
+ }
+ ]
+ },
+ {
+ "name": "CrossTrafficMonitoringWarningState",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "OTHER",
+ "value": 0
+ },
+ {
+ "name": "NO_WARNING",
+ "value": 1
+ },
+ {
+ "name": "WARNING_FRONT_LEFT",
+ "value": 2
+ },
+ {
+ "name": "WARNING_FRONT_RIGHT",
+ "value": 3
+ },
+ {
+ "name": "WARNING_FRONT_BOTH",
+ "value": 4
+ },
+ {
+ "name": "WARNING_REAR_LEFT",
+ "value": 5
+ },
+ {
+ "name": "WARNING_REAR_RIGHT",
+ "value": 6
+ },
+ {
+ "name": "WARNING_REAR_BOTH",
+ "value": 7
+ }
+ ]
+ },
+ {
+ "name": "CruiseControlCommand",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "ACTIVATE",
+ "value": 1
+ },
+ {
+ "name": "SUSPEND",
+ "value": 2
+ },
+ {
+ "name": "INCREASE_TARGET_SPEED",
+ "value": 3
+ },
+ {
+ "name": "DECREASE_TARGET_SPEED",
+ "value": 4
+ },
+ {
+ "name": "INCREASE_TARGET_TIME_GAP",
+ "value": 5
+ },
+ {
+ "name": "DECREASE_TARGET_TIME_GAP",
+ "value": 6
+ }
+ ]
+ },
+ {
+ "name": "CruiseControlState",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "OTHER",
+ "value": 0
+ },
+ {
+ "name": "ENABLED",
+ "value": 1
+ },
+ {
+ "name": "ACTIVATED",
+ "value": 2
+ },
+ {
+ "name": "USER_OVERRIDE",
+ "value": 3
+ },
+ {
+ "name": "SUSPENDED",
+ "value": 4
+ },
+ {
+ "name": "FORCED_DEACTIVATION_WARNING",
+ "value": 5
+ }
+ ]
+ },
+ {
+ "name": "CruiseControlType",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "OTHER",
+ "value": 0
+ },
+ {
+ "name": "STANDARD",
+ "value": 1
+ },
+ {
+ "name": "ADAPTIVE",
+ "value": 2
+ },
+ {
+ "name": "PREDICTIVE",
+ "value": 3
+ }
+ ]
+ },
+ {
+ "name": "CustomInputType",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "CUSTOM_EVENT_F1",
+ "value": 1001
+ },
+ {
+ "name": "CUSTOM_EVENT_F2",
+ "value": 1002
+ },
+ {
+ "name": "CUSTOM_EVENT_F3",
+ "value": 1003
+ },
+ {
+ "name": "CUSTOM_EVENT_F4",
+ "value": 1004
+ },
+ {
+ "name": "CUSTOM_EVENT_F5",
+ "value": 1005
+ },
+ {
+ "name": "CUSTOM_EVENT_F6",
+ "value": 1006
+ },
+ {
+ "name": "CUSTOM_EVENT_F7",
+ "value": 1007
+ },
+ {
+ "name": "CUSTOM_EVENT_F8",
+ "value": 1008
+ },
+ {
+ "name": "CUSTOM_EVENT_F9",
+ "value": 1009
+ },
+ {
+ "name": "CUSTOM_EVENT_F10",
+ "value": 1010
+ }
+ ]
+ },
+ {
"name": "DriverDistractionState",
"package": "android.hardware.automotive.vehicle",
"values": [
@@ -1451,34 +1905,312 @@
]
},
{
- "name": "VehicleTurnSignal",
+ "name": "DriverDistractionWarning",
"package": "android.hardware.automotive.vehicle",
"values": [
{
- "name": "NONE",
+ "name": "OTHER",
"value": 0
},
{
- "name": "RIGHT",
+ "name": "NO_WARNING",
"value": 1
},
{
- "name": "LEFT",
+ "name": "WARNING",
"value": 2
}
]
},
{
- "name": "RotaryInputType",
+ "name": "DriverDrowsinessAttentionState",
"package": "android.hardware.automotive.vehicle",
"values": [
{
- "name": "ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION",
+ "name": "OTHER",
"value": 0
},
{
- "name": "ROTARY_INPUT_TYPE_AUDIO_VOLUME",
+ "name": "KSS_RATING_1_EXTREMELY_ALERT",
"value": 1
+ },
+ {
+ "name": "KSS_RATING_2_VERY_ALERT",
+ "value": 2
+ },
+ {
+ "name": "KSS_RATING_3_ALERT",
+ "value": 3
+ },
+ {
+ "name": "KSS_RATING_4_RATHER_ALERT",
+ "value": 4
+ },
+ {
+ "name": "KSS_RATING_5_NEITHER_ALERT_NOR_SLEEPY",
+ "value": 5
+ },
+ {
+ "name": "KSS_RATING_6_SOME_SLEEPINESS",
+ "value": 6
+ },
+ {
+ "name": "KSS_RATING_7_SLEEPY_NO_EFFORT",
+ "value": 7
+ },
+ {
+ "name": "KSS_RATING_8_SLEEPY_SOME_EFFORT",
+ "value": 8
+ },
+ {
+ "name": "KSS_RATING_9_VERY_SLEEPY",
+ "value": 9
+ }
+ ]
+ },
+ {
+ "name": "DriverDrowsinessAttentionWarning",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "OTHER",
+ "value": 0
+ },
+ {
+ "name": "NO_WARNING",
+ "value": 1
+ },
+ {
+ "name": "WARNING",
+ "value": 2
+ }
+ ]
+ },
+ {
+ "name": "ElectronicStabilityControlState",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "OTHER",
+ "value": 0
+ },
+ {
+ "name": "ENABLED",
+ "value": 1
+ },
+ {
+ "name": "ACTIVATED",
+ "value": 2
+ }
+ ]
+ },
+ {
+ "name": "ElectronicTollCollectionCardStatus",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "UNKNOWN",
+ "value": 0
+ },
+ {
+ "name": "ELECTRONIC_TOLL_COLLECTION_CARD_VALID",
+ "value": 1
+ },
+ {
+ "name": "ELECTRONIC_TOLL_COLLECTION_CARD_INVALID",
+ "value": 2
+ },
+ {
+ "name": "ELECTRONIC_TOLL_COLLECTION_CARD_NOT_INSERTED",
+ "value": 3
+ }
+ ]
+ },
+ {
+ "name": "ElectronicTollCollectionCardType",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "UNKNOWN",
+ "value": 0
+ },
+ {
+ "name": "JP_ELECTRONIC_TOLL_COLLECTION_CARD",
+ "value": 1
+ },
+ {
+ "name": "JP_ELECTRONIC_TOLL_COLLECTION_CARD_V2",
+ "value": 2
+ }
+ ]
+ },
+ {
+ "name": "EmergencyLaneKeepAssistState",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "OTHER",
+ "value": 0
+ },
+ {
+ "name": "ENABLED",
+ "value": 1
+ },
+ {
+ "name": "WARNING_LEFT",
+ "value": 2
+ },
+ {
+ "name": "WARNING_RIGHT",
+ "value": 3
+ },
+ {
+ "name": "ACTIVATED_STEER_LEFT",
+ "value": 4
+ },
+ {
+ "name": "ACTIVATED_STEER_RIGHT",
+ "value": 5
+ },
+ {
+ "name": "USER_OVERRIDE",
+ "value": 6
+ }
+ ]
+ },
+ {
+ "name": "ErrorState",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "OTHER_ERROR_STATE",
+ "value": -1
+ },
+ {
+ "name": "NOT_AVAILABLE_DISABLED",
+ "value": -2
+ },
+ {
+ "name": "NOT_AVAILABLE_SPEED_LOW",
+ "value": -3
+ },
+ {
+ "name": "NOT_AVAILABLE_SPEED_HIGH",
+ "value": -4
+ },
+ {
+ "name": "NOT_AVAILABLE_POOR_VISIBILITY",
+ "value": -5
+ },
+ {
+ "name": "NOT_AVAILABLE_SAFETY",
+ "value": -6
+ }
+ ]
+ },
+ {
+ "name": "EvChargeState",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "UNKNOWN",
+ "value": 0
+ },
+ {
+ "name": "CHARGING",
+ "value": 1
+ },
+ {
+ "name": "FULLY_CHARGED",
+ "value": 2
+ },
+ {
+ "name": "NOT_CHARGING",
+ "value": 3
+ },
+ {
+ "name": "ERROR",
+ "value": 4
+ }
+ ]
+ },
+ {
+ "name": "EvConnectorType",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "UNKNOWN",
+ "value": 0
+ },
+ {
+ "name": "IEC_TYPE_1_AC",
+ "value": 1
+ },
+ {
+ "name": "IEC_TYPE_2_AC",
+ "value": 2
+ },
+ {
+ "name": "IEC_TYPE_3_AC",
+ "value": 3
+ },
+ {
+ "name": "IEC_TYPE_4_DC",
+ "value": 4
+ },
+ {
+ "name": "IEC_TYPE_1_CCS_DC",
+ "value": 5
+ },
+ {
+ "name": "IEC_TYPE_2_CCS_DC",
+ "value": 6
+ },
+ {
+ "name": "TESLA_ROADSTER",
+ "value": 7
+ },
+ {
+ "name": "TESLA_HPWC",
+ "value": 8
+ },
+ {
+ "name": "TESLA_SUPERCHARGER",
+ "value": 9
+ },
+ {
+ "name": "GBT_AC",
+ "value": 10
+ },
+ {
+ "name": "GBT_DC",
+ "value": 11
+ },
+ {
+ "name": "OTHER",
+ "value": 101
+ }
+ ]
+ },
+ {
+ "name": "EvRegenerativeBrakingState",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "UNKNOWN",
+ "value": 0
+ },
+ {
+ "name": "DISABLED",
+ "value": 1
+ },
+ {
+ "name": "PARTIALLY_ENABLED",
+ "value": 2
+ },
+ {
+ "name": "FULLY_ENABLED",
+ "value": 3
}
]
},
@@ -1505,19 +2237,19 @@
]
},
{
- "name": "VehicleLightState",
+ "name": "ForwardCollisionWarningState",
"package": "android.hardware.automotive.vehicle",
"values": [
{
- "name": "OFF",
+ "name": "OTHER",
"value": 0
},
{
- "name": "ON",
+ "name": "NO_WARNING",
"value": 1
},
{
- "name": "DAYTIME_RUNNING",
+ "name": "WARNING",
"value": 2
}
]
@@ -1581,37 +2313,223 @@
]
},
{
- "name": "VehicleIgnitionState",
+ "name": "GsrComplianceRequirementType",
"package": "android.hardware.automotive.vehicle",
"values": [
{
- "name": "UNDEFINED",
+ "name": "GSR_COMPLIANCE_NOT_REQUIRED",
"value": 0
},
{
- "name": "LOCK",
+ "name": "GSR_COMPLIANCE_REQUIRED_V1",
+ "value": 1
+ }
+ ]
+ },
+ {
+ "name": "HandsOnDetectionDriverState",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "OTHER",
+ "value": 0
+ },
+ {
+ "name": "HANDS_ON",
"value": 1
},
{
- "name": "OFF",
+ "name": "HANDS_OFF",
+ "value": 2
+ }
+ ]
+ },
+ {
+ "name": "HandsOnDetectionWarning",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "OTHER",
+ "value": 0
+ },
+ {
+ "name": "NO_WARNING",
+ "value": 1
+ },
+ {
+ "name": "WARNING",
+ "value": 2
+ }
+ ]
+ },
+ {
+ "name": "ImpactSensorLocation",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "OTHER",
+ "value": 1
+ },
+ {
+ "name": "FRONT",
"value": 2
},
{
- "name": "ACC",
- "value": 3
- },
- {
- "name": "ON",
+ "name": "FRONT_LEFT_DOOR_SIDE",
"value": 4
},
{
- "name": "START",
+ "name": "FRONT_RIGHT_DOOR_SIDE",
+ "value": 8
+ },
+ {
+ "name": "REAR_LEFT_DOOR_SIDE",
+ "value": 16
+ },
+ {
+ "name": "REAR_RIGHT_DOOR_SIDE",
+ "value": 32
+ },
+ {
+ "name": "REAR",
+ "value": 64
+ }
+ ]
+ },
+ {
+ "name": "LaneCenteringAssistCommand",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "ACTIVATE",
+ "value": 1
+ },
+ {
+ "name": "DEACTIVATE",
+ "value": 2
+ }
+ ]
+ },
+ {
+ "name": "LaneCenteringAssistState",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "OTHER",
+ "value": 0
+ },
+ {
+ "name": "ENABLED",
+ "value": 1
+ },
+ {
+ "name": "ACTIVATION_REQUESTED",
+ "value": 2
+ },
+ {
+ "name": "ACTIVATED",
+ "value": 3
+ },
+ {
+ "name": "USER_OVERRIDE",
+ "value": 4
+ },
+ {
+ "name": "FORCED_DEACTIVATION_WARNING",
"value": 5
}
]
},
{
- "name": "EvConnectorType",
+ "name": "LaneDepartureWarningState",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "OTHER",
+ "value": 0
+ },
+ {
+ "name": "NO_WARNING",
+ "value": 1
+ },
+ {
+ "name": "WARNING_LEFT",
+ "value": 2
+ },
+ {
+ "name": "WARNING_RIGHT",
+ "value": 3
+ }
+ ]
+ },
+ {
+ "name": "LaneKeepAssistState",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "OTHER",
+ "value": 0
+ },
+ {
+ "name": "ENABLED",
+ "value": 1
+ },
+ {
+ "name": "ACTIVATED_STEER_LEFT",
+ "value": 2
+ },
+ {
+ "name": "ACTIVATED_STEER_RIGHT",
+ "value": 3
+ },
+ {
+ "name": "USER_OVERRIDE",
+ "value": 4
+ }
+ ]
+ },
+ {
+ "name": "LowSpeedAutomaticEmergencyBrakingState",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "OTHER",
+ "value": 0
+ },
+ {
+ "name": "ENABLED",
+ "value": 1
+ },
+ {
+ "name": "ACTIVATED",
+ "value": 2
+ },
+ {
+ "name": "USER_OVERRIDE",
+ "value": 3
+ }
+ ]
+ },
+ {
+ "name": "LowSpeedCollisionWarningState",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "OTHER",
+ "value": 0
+ },
+ {
+ "name": "NO_WARNING",
+ "value": 1
+ },
+ {
+ "name": "WARNING",
+ "value": 2
+ }
+ ]
+ },
+ {
+ "name": "PortLocationType",
"package": "android.hardware.automotive.vehicle",
"values": [
{
@@ -1619,52 +2537,42 @@
"value": 0
},
{
- "name": "IEC_TYPE_1_AC",
+ "name": "FRONT_LEFT",
"value": 1
},
{
- "name": "IEC_TYPE_2_AC",
+ "name": "FRONT_RIGHT",
"value": 2
},
{
- "name": "IEC_TYPE_3_AC",
+ "name": "REAR_RIGHT",
"value": 3
},
{
- "name": "IEC_TYPE_4_DC",
+ "name": "REAR_LEFT",
"value": 4
},
{
- "name": "IEC_TYPE_1_CCS_DC",
+ "name": "FRONT",
"value": 5
},
{
- "name": "IEC_TYPE_2_CCS_DC",
+ "name": "REAR",
"value": 6
+ }
+ ]
+ },
+ {
+ "name": "RotaryInputType",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION",
+ "value": 0
},
{
- "name": "TESLA_ROADSTER",
- "value": 7
- },
- {
- "name": "TESLA_HPWC",
- "value": 8
- },
- {
- "name": "TESLA_SUPERCHARGER",
- "value": 9
- },
- {
- "name": "GBT_AC",
- "value": 10
- },
- {
- "name": "GBT_DC",
- "value": 11
- },
- {
- "name": "OTHER",
- "value": 101
+ "name": "ROTARY_INPUT_TYPE_AUDIO_VOLUME",
+ "value": 1
}
]
},
@@ -1691,66 +2599,66 @@
]
},
{
- "name": "DriverDrowsinessAttentionState",
+ "name": "VehicleAirbagLocation",
"package": "android.hardware.automotive.vehicle",
"values": [
{
"name": "OTHER",
- "value": 0
- },
- {
- "name": "KSS_RATING_1_EXTREMELY_ALERT",
"value": 1
},
{
- "name": "KSS_RATING_2_VERY_ALERT",
+ "name": "FRONT",
"value": 2
},
{
- "name": "KSS_RATING_3_ALERT",
- "value": 3
- },
- {
- "name": "KSS_RATING_4_RATHER_ALERT",
+ "name": "KNEE",
"value": 4
},
{
- "name": "KSS_RATING_5_NEITHER_ALERT_NOR_SLEEPY",
- "value": 5
- },
- {
- "name": "KSS_RATING_6_SOME_SLEEPINESS",
- "value": 6
- },
- {
- "name": "KSS_RATING_7_SLEEPY_NO_EFFORT",
- "value": 7
- },
- {
- "name": "KSS_RATING_8_SLEEPY_SOME_EFFORT",
+ "name": "LEFT_SIDE",
"value": 8
},
{
- "name": "KSS_RATING_9_VERY_SLEEPY",
- "value": 9
+ "name": "RIGHT_SIDE",
+ "value": 16
+ },
+ {
+ "name": "CURTAIN",
+ "value": 32
}
]
},
{
- "name": "DriverDistractionWarning",
+ "name": "VehicleApPowerStateShutdownParam",
"package": "android.hardware.automotive.vehicle",
"values": [
{
- "name": "OTHER",
- "value": 0
- },
- {
- "name": "NO_WARNING",
+ "name": "SHUTDOWN_IMMEDIATELY",
"value": 1
},
{
- "name": "WARNING",
+ "name": "CAN_SLEEP",
"value": 2
+ },
+ {
+ "name": "SHUTDOWN_ONLY",
+ "value": 3
+ },
+ {
+ "name": "SLEEP_IMMEDIATELY",
+ "value": 4
+ },
+ {
+ "name": "HIBERNATE_IMMEDIATELY",
+ "value": 5
+ },
+ {
+ "name": "CAN_HIBERNATE",
+ "value": 6
+ },
+ {
+ "name": "EMERGENCY_SHUTDOWN",
+ "value": 7
}
]
},
@@ -1801,6 +2709,176 @@
]
},
{
+ "name": "VehicleAutonomousState",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "LEVEL_0",
+ "value": 0
+ },
+ {
+ "name": "LEVEL_1",
+ "value": 1
+ },
+ {
+ "name": "LEVEL_2",
+ "value": 2
+ },
+ {
+ "name": "LEVEL_3",
+ "value": 3
+ },
+ {
+ "name": "LEVEL_4",
+ "value": 4
+ },
+ {
+ "name": "LEVEL_5",
+ "value": 5
+ }
+ ]
+ },
+ {
+ "name": "VehicleGear",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "GEAR_UNKNOWN",
+ "value": 0
+ },
+ {
+ "name": "GEAR_NEUTRAL",
+ "value": 1
+ },
+ {
+ "name": "GEAR_REVERSE",
+ "value": 2
+ },
+ {
+ "name": "GEAR_PARK",
+ "value": 4
+ },
+ {
+ "name": "GEAR_DRIVE",
+ "value": 8
+ },
+ {
+ "name": "GEAR_1",
+ "value": 16
+ },
+ {
+ "name": "GEAR_2",
+ "value": 32
+ },
+ {
+ "name": "GEAR_3",
+ "value": 64
+ },
+ {
+ "name": "GEAR_4",
+ "value": 128
+ },
+ {
+ "name": "GEAR_5",
+ "value": 256
+ },
+ {
+ "name": "GEAR_6",
+ "value": 512
+ },
+ {
+ "name": "GEAR_7",
+ "value": 1024
+ },
+ {
+ "name": "GEAR_8",
+ "value": 2048
+ },
+ {
+ "name": "GEAR_9",
+ "value": 4096
+ }
+ ]
+ },
+ {
+ "name": "VehicleHvacFanDirection",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "UNKNOWN",
+ "value": 0
+ },
+ {
+ "name": "FACE",
+ "value": 1
+ },
+ {
+ "name": "FLOOR",
+ "value": 2
+ },
+ {
+ "name": "FACE_AND_FLOOR",
+ "value": 3
+ },
+ {
+ "name": "DEFROST",
+ "value": 4
+ },
+ {
+ "name": "DEFROST_AND_FLOOR",
+ "value": 6
+ }
+ ]
+ },
+ {
+ "name": "VehicleIgnitionState",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "UNDEFINED",
+ "value": 0
+ },
+ {
+ "name": "LOCK",
+ "value": 1
+ },
+ {
+ "name": "OFF",
+ "value": 2
+ },
+ {
+ "name": "ACC",
+ "value": 3
+ },
+ {
+ "name": "ON",
+ "value": 4
+ },
+ {
+ "name": "START",
+ "value": 5
+ }
+ ]
+ },
+ {
+ "name": "VehicleLightState",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "OFF",
+ "value": 0
+ },
+ {
+ "name": "ON",
+ "value": 1
+ },
+ {
+ "name": "DAYTIME_RUNNING",
+ "value": 2
+ }
+ ]
+ },
+ {
"name": "VehicleLightSwitch",
"package": "android.hardware.automotive.vehicle",
"values": [
@@ -1823,260 +2901,6 @@
]
},
{
- "name": "WindshieldWipersSwitch",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "OTHER",
- "value": 0
- },
- {
- "name": "OFF",
- "value": 1
- },
- {
- "name": "MIST",
- "value": 2
- },
- {
- "name": "INTERMITTENT_LEVEL_1",
- "value": 3
- },
- {
- "name": "INTERMITTENT_LEVEL_2",
- "value": 4
- },
- {
- "name": "INTERMITTENT_LEVEL_3",
- "value": 5
- },
- {
- "name": "INTERMITTENT_LEVEL_4",
- "value": 6
- },
- {
- "name": "INTERMITTENT_LEVEL_5",
- "value": 7
- },
- {
- "name": "CONTINUOUS_LEVEL_1",
- "value": 8
- },
- {
- "name": "CONTINUOUS_LEVEL_2",
- "value": 9
- },
- {
- "name": "CONTINUOUS_LEVEL_3",
- "value": 10
- },
- {
- "name": "CONTINUOUS_LEVEL_4",
- "value": 11
- },
- {
- "name": "CONTINUOUS_LEVEL_5",
- "value": 12
- },
- {
- "name": "AUTO",
- "value": 13
- },
- {
- "name": "SERVICE",
- "value": 14
- }
- ]
- },
- {
- "name": "CrossTrafficMonitoringWarningState",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "OTHER",
- "value": 0
- },
- {
- "name": "NO_WARNING",
- "value": 1
- },
- {
- "name": "WARNING_FRONT_LEFT",
- "value": 2
- },
- {
- "name": "WARNING_FRONT_RIGHT",
- "value": 3
- },
- {
- "name": "WARNING_FRONT_BOTH",
- "value": 4
- },
- {
- "name": "WARNING_REAR_LEFT",
- "value": 5
- },
- {
- "name": "WARNING_REAR_RIGHT",
- "value": 6
- },
- {
- "name": "WARNING_REAR_BOTH",
- "value": 7
- }
- ]
- },
- {
- "name": "LaneCenteringAssistCommand",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "ACTIVATE",
- "value": 1
- },
- {
- "name": "DEACTIVATE",
- "value": 2
- }
- ]
- },
- {
- "name": "VehicleSeatOccupancyState",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "UNKNOWN",
- "value": 0
- },
- {
- "name": "VACANT",
- "value": 1
- },
- {
- "name": "OCCUPIED",
- "value": 2
- }
- ]
- },
- {
- "name": "ErrorState",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "OTHER_ERROR_STATE",
- "value": -1
- },
- {
- "name": "NOT_AVAILABLE_DISABLED",
- "value": -2
- },
- {
- "name": "NOT_AVAILABLE_SPEED_LOW",
- "value": -3
- },
- {
- "name": "NOT_AVAILABLE_SPEED_HIGH",
- "value": -4
- },
- {
- "name": "NOT_AVAILABLE_POOR_VISIBILITY",
- "value": -5
- },
- {
- "name": "NOT_AVAILABLE_SAFETY",
- "value": -6
- }
- ]
- },
- {
- "name": "BlindSpotWarningState",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "OTHER",
- "value": 0
- },
- {
- "name": "NO_WARNING",
- "value": 1
- },
- {
- "name": "WARNING",
- "value": 2
- }
- ]
- },
- {
- "name": "WindshieldWipersState",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "OTHER",
- "value": 0
- },
- {
- "name": "OFF",
- "value": 1
- },
- {
- "name": "ON",
- "value": 2
- },
- {
- "name": "SERVICE",
- "value": 3
- }
- ]
- },
- {
- "name": "VehicleAirbagLocation",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "OTHER",
- "value": 1
- },
- {
- "name": "FRONT",
- "value": 2
- },
- {
- "name": "KNEE",
- "value": 4
- },
- {
- "name": "LEFT_SIDE",
- "value": 8
- },
- {
- "name": "RIGHT_SIDE",
- "value": 16
- },
- {
- "name": "CURTAIN",
- "value": 32
- }
- ]
- },
- {
- "name": "DriverDrowsinessAttentionWarning",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "OTHER",
- "value": 0
- },
- {
- "name": "NO_WARNING",
- "value": 1
- },
- {
- "name": "WARNING",
- "value": 2
- }
- ]
- },
- {
"name": "VehicleOilLevel",
"package": "android.hardware.automotive.vehicle",
"values": [
@@ -2103,19 +2927,37 @@
]
},
{
- "name": "ForwardCollisionWarningState",
+ "name": "VehicleSeatOccupancyState",
"package": "android.hardware.automotive.vehicle",
"values": [
{
- "name": "OTHER",
+ "name": "UNKNOWN",
"value": 0
},
{
- "name": "NO_WARNING",
+ "name": "VACANT",
"value": 1
},
{
- "name": "WARNING",
+ "name": "OCCUPIED",
+ "value": 2
+ }
+ ]
+ },
+ {
+ "name": "VehicleTurnSignal",
+ "package": "android.hardware.automotive.vehicle",
+ "values": [
+ {
+ "name": "NONE",
+ "value": 0
+ },
+ {
+ "name": "RIGHT",
+ "value": 1
+ },
+ {
+ "name": "LEFT",
"value": 2
}
]
@@ -2263,37 +3105,7 @@
]
},
{
- "name": "VehicleHvacFanDirection",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "UNKNOWN",
- "value": 0
- },
- {
- "name": "FACE",
- "value": 1
- },
- {
- "name": "FLOOR",
- "value": 2
- },
- {
- "name": "FACE_AND_FLOOR",
- "value": 3
- },
- {
- "name": "DEFROST",
- "value": 4
- },
- {
- "name": "DEFROST_AND_FLOOR",
- "value": 6
- }
- ]
- },
- {
- "name": "LowSpeedCollisionWarningState",
+ "name": "WindshieldWipersState",
"package": "android.hardware.automotive.vehicle",
"values": [
{
@@ -2301,628 +3113,82 @@
"value": 0
},
{
- "name": "NO_WARNING",
+ "name": "OFF",
"value": 1
},
{
- "name": "WARNING",
+ "name": "ON",
"value": 2
+ },
+ {
+ "name": "SERVICE",
+ "value": 3
}
]
},
{
- "name": "CruiseControlCommand",
+ "name": "WindshieldWipersSwitch",
"package": "android.hardware.automotive.vehicle",
"values": [
{
- "name": "ACTIVATE",
+ "name": "OTHER",
+ "value": 0
+ },
+ {
+ "name": "OFF",
"value": 1
},
{
- "name": "SUSPEND",
+ "name": "MIST",
"value": 2
},
{
- "name": "INCREASE_TARGET_SPEED",
+ "name": "INTERMITTENT_LEVEL_1",
"value": 3
},
{
- "name": "DECREASE_TARGET_SPEED",
+ "name": "INTERMITTENT_LEVEL_2",
"value": 4
},
{
- "name": "INCREASE_TARGET_TIME_GAP",
+ "name": "INTERMITTENT_LEVEL_3",
"value": 5
},
{
- "name": "DECREASE_TARGET_TIME_GAP",
- "value": 6
- }
- ]
- },
- {
- "name": "ElectronicStabilityControlState",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "OTHER",
- "value": 0
- },
- {
- "name": "ENABLED",
- "value": 1
- },
- {
- "name": "ACTIVATED",
- "value": 2
- }
- ]
- },
- {
- "name": "EvRegenerativeBrakingState",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "UNKNOWN",
- "value": 0
- },
- {
- "name": "DISABLED",
- "value": 1
- },
- {
- "name": "PARTIALLY_ENABLED",
- "value": 2
- },
- {
- "name": "FULLY_ENABLED",
- "value": 3
- }
- ]
- },
- {
- "name": "LowSpeedAutomaticEmergencyBrakingState",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "OTHER",
- "value": 0
- },
- {
- "name": "ENABLED",
- "value": 1
- },
- {
- "name": "ACTIVATED",
- "value": 2
- },
- {
- "name": "USER_OVERRIDE",
- "value": 3
- }
- ]
- },
- {
- "name": "LaneCenteringAssistState",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "OTHER",
- "value": 0
- },
- {
- "name": "ENABLED",
- "value": 1
- },
- {
- "name": "ACTIVATION_REQUESTED",
- "value": 2
- },
- {
- "name": "ACTIVATED",
- "value": 3
- },
- {
- "name": "USER_OVERRIDE",
- "value": 4
- },
- {
- "name": "FORCED_DEACTIVATION_WARNING",
- "value": 5
- }
- ]
- },
- {
- "name": "VehicleGear",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "GEAR_UNKNOWN",
- "value": 0
- },
- {
- "name": "GEAR_NEUTRAL",
- "value": 1
- },
- {
- "name": "GEAR_REVERSE",
- "value": 2
- },
- {
- "name": "GEAR_PARK",
- "value": 4
- },
- {
- "name": "GEAR_DRIVE",
- "value": 8
- },
- {
- "name": "GEAR_1",
- "value": 16
- },
- {
- "name": "GEAR_2",
- "value": 32
- },
- {
- "name": "GEAR_3",
- "value": 64
- },
- {
- "name": "GEAR_4",
- "value": 128
- },
- {
- "name": "GEAR_5",
- "value": 256
- },
- {
- "name": "GEAR_6",
- "value": 512
- },
- {
- "name": "GEAR_7",
- "value": 1024
- },
- {
- "name": "GEAR_8",
- "value": 2048
- },
- {
- "name": "GEAR_9",
- "value": 4096
- }
- ]
- },
- {
- "name": "ElectronicTollCollectionCardType",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "UNKNOWN",
- "value": 0
- },
- {
- "name": "JP_ELECTRONIC_TOLL_COLLECTION_CARD",
- "value": 1
- },
- {
- "name": "JP_ELECTRONIC_TOLL_COLLECTION_CARD_V2",
- "value": 2
- }
- ]
- },
- {
- "name": "VehicleApPowerStateShutdownParam",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "SHUTDOWN_IMMEDIATELY",
- "value": 1
- },
- {
- "name": "CAN_SLEEP",
- "value": 2
- },
- {
- "name": "SHUTDOWN_ONLY",
- "value": 3
- },
- {
- "name": "SLEEP_IMMEDIATELY",
- "value": 4
- },
- {
- "name": "HIBERNATE_IMMEDIATELY",
- "value": 5
- },
- {
- "name": "CAN_HIBERNATE",
+ "name": "INTERMITTENT_LEVEL_4",
"value": 6
},
{
- "name": "EMERGENCY_SHUTDOWN",
+ "name": "INTERMITTENT_LEVEL_5",
"value": 7
- }
- ]
- },
- {
- "name": "AutomaticEmergencyBrakingState",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "OTHER",
- "value": 0
},
{
- "name": "ENABLED",
- "value": 1
- },
- {
- "name": "ACTIVATED",
- "value": 2
- },
- {
- "name": "USER_OVERRIDE",
- "value": 3
- }
- ]
- },
- {
- "name": "ImpactSensorLocation",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "OTHER",
- "value": 1
- },
- {
- "name": "FRONT",
- "value": 2
- },
- {
- "name": "FRONT_LEFT_DOOR_SIDE",
- "value": 4
- },
- {
- "name": "FRONT_RIGHT_DOOR_SIDE",
+ "name": "CONTINUOUS_LEVEL_1",
"value": 8
},
{
- "name": "REAR_LEFT_DOOR_SIDE",
- "value": 16
+ "name": "CONTINUOUS_LEVEL_2",
+ "value": 9
},
{
- "name": "REAR_RIGHT_DOOR_SIDE",
- "value": 32
+ "name": "CONTINUOUS_LEVEL_3",
+ "value": 10
},
{
- "name": "REAR",
- "value": 64
- }
- ]
- },
- {
- "name": "CruiseControlType",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "OTHER",
- "value": 0
+ "name": "CONTINUOUS_LEVEL_4",
+ "value": 11
},
{
- "name": "STANDARD",
- "value": 1
+ "name": "CONTINUOUS_LEVEL_5",
+ "value": 12
},
{
- "name": "ADAPTIVE",
- "value": 2
+ "name": "AUTO",
+ "value": 13
},
{
- "name": "PREDICTIVE",
- "value": 3
- }
- ]
- },
- {
- "name": "LaneKeepAssistState",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "OTHER",
- "value": 0
- },
- {
- "name": "ENABLED",
- "value": 1
- },
- {
- "name": "ACTIVATED_STEER_LEFT",
- "value": 2
- },
- {
- "name": "ACTIVATED_STEER_RIGHT",
- "value": 3
- },
- {
- "name": "USER_OVERRIDE",
- "value": 4
- }
- ]
- },
- {
- "name": "CustomInputType",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "CUSTOM_EVENT_F1",
- "value": 1001
- },
- {
- "name": "CUSTOM_EVENT_F2",
- "value": 1002
- },
- {
- "name": "CUSTOM_EVENT_F3",
- "value": 1003
- },
- {
- "name": "CUSTOM_EVENT_F4",
- "value": 1004
- },
- {
- "name": "CUSTOM_EVENT_F5",
- "value": 1005
- },
- {
- "name": "CUSTOM_EVENT_F6",
- "value": 1006
- },
- {
- "name": "CUSTOM_EVENT_F7",
- "value": 1007
- },
- {
- "name": "CUSTOM_EVENT_F8",
- "value": 1008
- },
- {
- "name": "CUSTOM_EVENT_F9",
- "value": 1009
- },
- {
- "name": "CUSTOM_EVENT_F10",
- "value": 1010
- }
- ]
- },
- {
- "name": "ElectronicTollCollectionCardStatus",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "UNKNOWN",
- "value": 0
- },
- {
- "name": "ELECTRONIC_TOLL_COLLECTION_CARD_VALID",
- "value": 1
- },
- {
- "name": "ELECTRONIC_TOLL_COLLECTION_CARD_INVALID",
- "value": 2
- },
- {
- "name": "ELECTRONIC_TOLL_COLLECTION_CARD_NOT_INSERTED",
- "value": 3
- }
- ]
- },
- {
- "name": "HandsOnDetectionDriverState",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "OTHER",
- "value": 0
- },
- {
- "name": "HANDS_ON",
- "value": 1
- },
- {
- "name": "HANDS_OFF",
- "value": 2
- }
- ]
- },
- {
- "name": "EmergencyLaneKeepAssistState",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "OTHER",
- "value": 0
- },
- {
- "name": "ENABLED",
- "value": 1
- },
- {
- "name": "WARNING_LEFT",
- "value": 2
- },
- {
- "name": "WARNING_RIGHT",
- "value": 3
- },
- {
- "name": "ACTIVATED_STEER_LEFT",
- "value": 4
- },
- {
- "name": "ACTIVATED_STEER_RIGHT",
- "value": 5
- },
- {
- "name": "USER_OVERRIDE",
- "value": 6
- }
- ]
- },
- {
- "name": "VehicleAutonomousState",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "LEVEL_0",
- "value": 0
- },
- {
- "name": "LEVEL_1",
- "value": 1
- },
- {
- "name": "LEVEL_2",
- "value": 2
- },
- {
- "name": "LEVEL_3",
- "value": 3
- },
- {
- "name": "LEVEL_4",
- "value": 4
- },
- {
- "name": "LEVEL_5",
- "value": 5
- }
- ]
- },
- {
- "name": "EvChargeState",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "UNKNOWN",
- "value": 0
- },
- {
- "name": "CHARGING",
- "value": 1
- },
- {
- "name": "FULLY_CHARGED",
- "value": 2
- },
- {
- "name": "NOT_CHARGING",
- "value": 3
- },
- {
- "name": "ERROR",
- "value": 4
- }
- ]
- },
- {
- "name": "CameraServiceState",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "UNAVAILABLE",
- "value": 0
- },
- {
- "name": "INACTIVE",
- "value": 1
- },
- {
- "name": "REQUESTED",
- "value": 2
- },
- {
- "name": "ACTIVE",
- "value": 3
- }
- ]
- },
- {
- "name": "GsrComplianceRequirementType",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "GSR_COMPLIANCE_NOT_REQUIRED",
- "value": 0
- },
- {
- "name": "GSR_COMPLIANCE_REQUIRED_V1",
- "value": 1
- }
- ]
- },
- {
- "name": "PortLocationType",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "UNKNOWN",
- "value": 0
- },
- {
- "name": "FRONT_LEFT",
- "value": 1
- },
- {
- "name": "FRONT_RIGHT",
- "value": 2
- },
- {
- "name": "REAR_RIGHT",
- "value": 3
- },
- {
- "name": "REAR_LEFT",
- "value": 4
- },
- {
- "name": "FRONT",
- "value": 5
- },
- {
- "name": "REAR",
- "value": 6
- }
- ]
- },
- {
- "name": "CruiseControlState",
- "package": "android.hardware.automotive.vehicle",
- "values": [
- {
- "name": "OTHER",
- "value": 0
- },
- {
- "name": "ENABLED",
- "value": 1
- },
- {
- "name": "ACTIVATED",
- "value": 2
- },
- {
- "name": "USER_OVERRIDE",
- "value": 3
- },
- {
- "name": "SUSPENDED",
- "value": 4
- },
- {
- "name": "FORCED_DEACTIVATION_WARNING",
- "value": 5
+ "name": "SERVICE",
+ "value": 14
}
]
}
diff --git a/automotive/vehicle/aidl/generated_lib/cpp/AccessForVehicleProperty.h b/automotive/vehicle/aidl/generated_lib/3/cpp/AccessForVehicleProperty.h
similarity index 100%
rename from automotive/vehicle/aidl/generated_lib/cpp/AccessForVehicleProperty.h
rename to automotive/vehicle/aidl/generated_lib/3/cpp/AccessForVehicleProperty.h
diff --git a/automotive/vehicle/aidl/generated_lib/cpp/Android.bp b/automotive/vehicle/aidl/generated_lib/3/cpp/Android.bp
similarity index 95%
rename from automotive/vehicle/aidl/generated_lib/cpp/Android.bp
rename to automotive/vehicle/aidl/generated_lib/3/cpp/Android.bp
index d14cbc2..7ff27a4 100644
--- a/automotive/vehicle/aidl/generated_lib/cpp/Android.bp
+++ b/automotive/vehicle/aidl/generated_lib/3/cpp/Android.bp
@@ -19,7 +19,7 @@
}
cc_library_headers {
- name: "IVehicleGeneratedHeaders",
+ name: "IVehicleGeneratedHeaders-V3",
vendor_available: true,
local_include_dirs: ["."],
export_include_dirs: ["."],
diff --git a/automotive/vehicle/aidl/generated_lib/cpp/ChangeModeForVehicleProperty.h b/automotive/vehicle/aidl/generated_lib/3/cpp/ChangeModeForVehicleProperty.h
similarity index 100%
rename from automotive/vehicle/aidl/generated_lib/cpp/ChangeModeForVehicleProperty.h
rename to automotive/vehicle/aidl/generated_lib/3/cpp/ChangeModeForVehicleProperty.h
diff --git a/automotive/vehicle/aidl/generated_lib/cpp/VersionForVehicleProperty.h b/automotive/vehicle/aidl/generated_lib/3/cpp/VersionForVehicleProperty.h
similarity index 98%
rename from automotive/vehicle/aidl/generated_lib/cpp/VersionForVehicleProperty.h
rename to automotive/vehicle/aidl/generated_lib/3/cpp/VersionForVehicleProperty.h
index 1c1035d..0e80bd8 100644
--- a/automotive/vehicle/aidl/generated_lib/cpp/VersionForVehicleProperty.h
+++ b/automotive/vehicle/aidl/generated_lib/3/cpp/VersionForVehicleProperty.h
@@ -84,7 +84,7 @@
{VehicleProperty::TRACTION_CONTROL_ACTIVE, 2},
{VehicleProperty::EV_STOPPING_MODE, 2},
{VehicleProperty::ELECTRONIC_STABILITY_CONTROL_ENABLED, 3},
- {VehicleProperty::ELECTRONIC_STABILITY_CONTROL_STATE, 2},
+ {VehicleProperty::ELECTRONIC_STABILITY_CONTROL_STATE, 3},
{VehicleProperty::HVAC_FAN_SPEED, 2},
{VehicleProperty::HVAC_FAN_DIRECTION, 2},
{VehicleProperty::HVAC_TEMPERATURE_CURRENT, 2},
@@ -172,8 +172,8 @@
{VehicleProperty::SEAT_FOOTWELL_LIGHTS_STATE, 2},
{VehicleProperty::SEAT_FOOTWELL_LIGHTS_SWITCH, 2},
{VehicleProperty::SEAT_EASY_ACCESS_ENABLED, 2},
- {VehicleProperty::SEAT_AIRBAG_ENABLED, 3},
- {VehicleProperty::SEAT_AIRBAGS_DEPLOYED, 2},
+ {VehicleProperty::SEAT_AIRBAG_ENABLED, 2},
+ {VehicleProperty::SEAT_AIRBAGS_DEPLOYED, 3},
{VehicleProperty::SEAT_CUSHION_SIDE_SUPPORT_POS, 2},
{VehicleProperty::SEAT_CUSHION_SIDE_SUPPORT_MOVE, 2},
{VehicleProperty::SEAT_LUMBAR_VERTICAL_POS, 2},
@@ -293,7 +293,7 @@
{VehicleProperty::DRIVER_DROWSINESS_ATTENTION_WARNING, 3},
{VehicleProperty::DRIVER_DISTRACTION_SYSTEM_ENABLED, 3},
{VehicleProperty::DRIVER_DISTRACTION_STATE, 3},
- {VehicleProperty::DRIVER_DISTRACTION_WARNING_ENABLED, 2},
+ {VehicleProperty::DRIVER_DISTRACTION_WARNING_ENABLED, 3},
{VehicleProperty::DRIVER_DISTRACTION_WARNING, 3},
{VehicleProperty::LOW_SPEED_COLLISION_WARNING_ENABLED, 3},
{VehicleProperty::LOW_SPEED_COLLISION_WARNING_STATE, 3},
diff --git a/automotive/vehicle/aidl/generated_lib/java/AccessForVehicleProperty.java b/automotive/vehicle/aidl/generated_lib/3/java/AccessForVehicleProperty.java
similarity index 100%
rename from automotive/vehicle/aidl/generated_lib/java/AccessForVehicleProperty.java
rename to automotive/vehicle/aidl/generated_lib/3/java/AccessForVehicleProperty.java
diff --git a/automotive/vehicle/aidl/generated_lib/java/Android.bp b/automotive/vehicle/aidl/generated_lib/3/java/Android.bp
similarity index 94%
rename from automotive/vehicle/aidl/generated_lib/java/Android.bp
rename to automotive/vehicle/aidl/generated_lib/3/java/Android.bp
index 1d612e8..b98fcbd 100644
--- a/automotive/vehicle/aidl/generated_lib/java/Android.bp
+++ b/automotive/vehicle/aidl/generated_lib/3/java/Android.bp
@@ -19,7 +19,7 @@
}
filegroup {
- name: "IVehicleGeneratedJavaFiles",
+ name: "IVehicleGeneratedJavaFiles-V3",
srcs: [
"*.java",
],
diff --git a/automotive/vehicle/aidl/generated_lib/java/ChangeModeForVehicleProperty.java b/automotive/vehicle/aidl/generated_lib/3/java/ChangeModeForVehicleProperty.java
similarity index 100%
rename from automotive/vehicle/aidl/generated_lib/java/ChangeModeForVehicleProperty.java
rename to automotive/vehicle/aidl/generated_lib/3/java/ChangeModeForVehicleProperty.java
diff --git a/automotive/vehicle/aidl/generated_lib/java/EnumForVehicleProperty.java b/automotive/vehicle/aidl/generated_lib/3/java/EnumForVehicleProperty.java
similarity index 100%
rename from automotive/vehicle/aidl/generated_lib/java/EnumForVehicleProperty.java
rename to automotive/vehicle/aidl/generated_lib/3/java/EnumForVehicleProperty.java
diff --git a/automotive/vehicle/aidl/generated_lib/java/UnitsForVehicleProperty.java b/automotive/vehicle/aidl/generated_lib/3/java/UnitsForVehicleProperty.java
similarity index 100%
rename from automotive/vehicle/aidl/generated_lib/java/UnitsForVehicleProperty.java
rename to automotive/vehicle/aidl/generated_lib/3/java/UnitsForVehicleProperty.java
diff --git a/automotive/vehicle/aidl/generated_lib/cpp/AccessForVehicleProperty.h b/automotive/vehicle/aidl/generated_lib/4/cpp/AccessForVehicleProperty.h
similarity index 100%
copy from automotive/vehicle/aidl/generated_lib/cpp/AccessForVehicleProperty.h
copy to automotive/vehicle/aidl/generated_lib/4/cpp/AccessForVehicleProperty.h
diff --git a/automotive/vehicle/aidl/generated_lib/cpp/Android.bp b/automotive/vehicle/aidl/generated_lib/4/cpp/Android.bp
similarity index 79%
copy from automotive/vehicle/aidl/generated_lib/cpp/Android.bp
copy to automotive/vehicle/aidl/generated_lib/4/cpp/Android.bp
index d14cbc2..5bee849 100644
--- a/automotive/vehicle/aidl/generated_lib/cpp/Android.bp
+++ b/automotive/vehicle/aidl/generated_lib/4/cpp/Android.bp
@@ -26,3 +26,12 @@
defaults: ["VehicleHalInterfaceDefaults"],
host_supported: true,
}
+
+cc_library_headers {
+ name: "IVehicleGeneratedHeaders-V4",
+ vendor_available: true,
+ local_include_dirs: ["."],
+ export_include_dirs: ["."],
+ defaults: ["VehicleHalInterfaceDefaults"],
+ host_supported: true,
+}
diff --git a/automotive/vehicle/aidl/generated_lib/cpp/ChangeModeForVehicleProperty.h b/automotive/vehicle/aidl/generated_lib/4/cpp/ChangeModeForVehicleProperty.h
similarity index 100%
copy from automotive/vehicle/aidl/generated_lib/cpp/ChangeModeForVehicleProperty.h
copy to automotive/vehicle/aidl/generated_lib/4/cpp/ChangeModeForVehicleProperty.h
diff --git a/automotive/vehicle/aidl/generated_lib/cpp/VersionForVehicleProperty.h b/automotive/vehicle/aidl/generated_lib/4/cpp/VersionForVehicleProperty.h
similarity index 98%
copy from automotive/vehicle/aidl/generated_lib/cpp/VersionForVehicleProperty.h
copy to automotive/vehicle/aidl/generated_lib/4/cpp/VersionForVehicleProperty.h
index 1c1035d..0e80bd8 100644
--- a/automotive/vehicle/aidl/generated_lib/cpp/VersionForVehicleProperty.h
+++ b/automotive/vehicle/aidl/generated_lib/4/cpp/VersionForVehicleProperty.h
@@ -84,7 +84,7 @@
{VehicleProperty::TRACTION_CONTROL_ACTIVE, 2},
{VehicleProperty::EV_STOPPING_MODE, 2},
{VehicleProperty::ELECTRONIC_STABILITY_CONTROL_ENABLED, 3},
- {VehicleProperty::ELECTRONIC_STABILITY_CONTROL_STATE, 2},
+ {VehicleProperty::ELECTRONIC_STABILITY_CONTROL_STATE, 3},
{VehicleProperty::HVAC_FAN_SPEED, 2},
{VehicleProperty::HVAC_FAN_DIRECTION, 2},
{VehicleProperty::HVAC_TEMPERATURE_CURRENT, 2},
@@ -172,8 +172,8 @@
{VehicleProperty::SEAT_FOOTWELL_LIGHTS_STATE, 2},
{VehicleProperty::SEAT_FOOTWELL_LIGHTS_SWITCH, 2},
{VehicleProperty::SEAT_EASY_ACCESS_ENABLED, 2},
- {VehicleProperty::SEAT_AIRBAG_ENABLED, 3},
- {VehicleProperty::SEAT_AIRBAGS_DEPLOYED, 2},
+ {VehicleProperty::SEAT_AIRBAG_ENABLED, 2},
+ {VehicleProperty::SEAT_AIRBAGS_DEPLOYED, 3},
{VehicleProperty::SEAT_CUSHION_SIDE_SUPPORT_POS, 2},
{VehicleProperty::SEAT_CUSHION_SIDE_SUPPORT_MOVE, 2},
{VehicleProperty::SEAT_LUMBAR_VERTICAL_POS, 2},
@@ -293,7 +293,7 @@
{VehicleProperty::DRIVER_DROWSINESS_ATTENTION_WARNING, 3},
{VehicleProperty::DRIVER_DISTRACTION_SYSTEM_ENABLED, 3},
{VehicleProperty::DRIVER_DISTRACTION_STATE, 3},
- {VehicleProperty::DRIVER_DISTRACTION_WARNING_ENABLED, 2},
+ {VehicleProperty::DRIVER_DISTRACTION_WARNING_ENABLED, 3},
{VehicleProperty::DRIVER_DISTRACTION_WARNING, 3},
{VehicleProperty::LOW_SPEED_COLLISION_WARNING_ENABLED, 3},
{VehicleProperty::LOW_SPEED_COLLISION_WARNING_STATE, 3},
diff --git a/automotive/vehicle/aidl/generated_lib/java/AccessForVehicleProperty.java b/automotive/vehicle/aidl/generated_lib/4/java/AccessForVehicleProperty.java
similarity index 100%
copy from automotive/vehicle/aidl/generated_lib/java/AccessForVehicleProperty.java
copy to automotive/vehicle/aidl/generated_lib/4/java/AccessForVehicleProperty.java
diff --git a/automotive/vehicle/aidl/generated_lib/java/Android.bp b/automotive/vehicle/aidl/generated_lib/4/java/Android.bp
similarity index 89%
copy from automotive/vehicle/aidl/generated_lib/java/Android.bp
copy to automotive/vehicle/aidl/generated_lib/4/java/Android.bp
index 1d612e8..f3c96f5 100644
--- a/automotive/vehicle/aidl/generated_lib/java/Android.bp
+++ b/automotive/vehicle/aidl/generated_lib/4/java/Android.bp
@@ -24,3 +24,10 @@
"*.java",
],
}
+
+filegroup {
+ name: "IVehicleGeneratedJavaFiles-V4",
+ srcs: [
+ "*.java",
+ ],
+}
diff --git a/automotive/vehicle/aidl/generated_lib/java/ChangeModeForVehicleProperty.java b/automotive/vehicle/aidl/generated_lib/4/java/ChangeModeForVehicleProperty.java
similarity index 100%
copy from automotive/vehicle/aidl/generated_lib/java/ChangeModeForVehicleProperty.java
copy to automotive/vehicle/aidl/generated_lib/4/java/ChangeModeForVehicleProperty.java
diff --git a/automotive/vehicle/aidl/generated_lib/java/EnumForVehicleProperty.java b/automotive/vehicle/aidl/generated_lib/4/java/EnumForVehicleProperty.java
similarity index 100%
copy from automotive/vehicle/aidl/generated_lib/java/EnumForVehicleProperty.java
copy to automotive/vehicle/aidl/generated_lib/4/java/EnumForVehicleProperty.java
diff --git a/automotive/vehicle/aidl/generated_lib/java/UnitsForVehicleProperty.java b/automotive/vehicle/aidl/generated_lib/4/java/UnitsForVehicleProperty.java
similarity index 100%
copy from automotive/vehicle/aidl/generated_lib/java/UnitsForVehicleProperty.java
copy to automotive/vehicle/aidl/generated_lib/4/java/UnitsForVehicleProperty.java
diff --git a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/Android.bp b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/Android.bp
index d1974ac..28c95ce 100644
--- a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/Android.bp
+++ b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/Android.bp
@@ -27,7 +27,7 @@
defaults: ["VehicleHalDefaults"],
static_libs: ["VehicleHalUtils"],
header_libs: [
- "IVehicleGeneratedHeaders",
+ "IVehicleGeneratedHeaders-V3",
],
shared_libs: ["libjsoncpp"],
}
@@ -44,7 +44,7 @@
defaults: ["VehicleHalDefaults"],
static_libs: ["VehicleHalUtils"],
header_libs: [
- "IVehicleGeneratedHeaders",
+ "IVehicleGeneratedHeaders-V3",
"libbinder_headers",
],
cflags: ["-DENABLE_VEHICLE_HAL_TEST_PROPERTIES"],
@@ -60,7 +60,7 @@
defaults: ["VehicleHalDefaults"],
static_libs: ["VehicleHalUtils"],
header_libs: [
- "IVehicleGeneratedHeaders",
+ "IVehicleGeneratedHeaders-V3",
],
shared_libs: ["libjsoncpp"],
}
diff --git a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp
index ea1437e..57af04c 100644
--- a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp
+++ b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp
@@ -104,6 +104,8 @@
{"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},
diff --git a/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json b/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
index 0a859af..2d1e9ab 100644
--- a/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
+++ b/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
@@ -2033,19 +2033,10 @@
},
"areas": [
{
- "areaId": "Constants::SEAT_1_LEFT"
+ "areaId": "Constants::HVAC_FRONT_ROW"
},
{
- "areaId": "Constants::SEAT_1_RIGHT"
- },
- {
- "areaId": "Constants::SEAT_2_LEFT"
- },
- {
- "areaId": "Constants::SEAT_2_RIGHT"
- },
- {
- "areaId": "Constants::SEAT_2_CENTER"
+ "areaId": "Constants::HVAC_REAR_ROW"
}
]
},
diff --git a/automotive/vehicle/aidl/impl/default_config/test/Android.bp b/automotive/vehicle/aidl/impl/default_config/test/Android.bp
index 651ed90..70933be 100644
--- a/automotive/vehicle/aidl/impl/default_config/test/Android.bp
+++ b/automotive/vehicle/aidl/impl/default_config/test/Android.bp
@@ -31,7 +31,7 @@
"libgtest",
],
header_libs: [
- "IVehicleGeneratedHeaders",
+ "IVehicleGeneratedHeaders-V3",
],
shared_libs: [
"libjsoncpp",
@@ -57,7 +57,7 @@
"-DENABLE_VEHICLE_HAL_TEST_PROPERTIES",
],
header_libs: [
- "IVehicleGeneratedHeaders",
+ "IVehicleGeneratedHeaders-V3",
],
shared_libs: [
"libjsoncpp",
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
index 583e40b..79d3e77 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
@@ -269,16 +269,6 @@
std::string dumpInjectEvent(const std::vector<std::string>& options);
std::string dumpSubscriptions();
- template <typename T>
- 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;
- }
- android::base::Result<float> safelyParseFloat(int index, const std::string& s);
std::vector<std::string> getOptionValues(const std::vector<std::string>& options,
size_t* index);
android::base::Result<aidl::android::hardware::automotive::vehicle::VehiclePropValue>
@@ -325,6 +315,18 @@
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);
};
} // namespace fake
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
index 9b880cd..4f060e2 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
@@ -281,6 +281,19 @@
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) {
@@ -1770,19 +1783,26 @@
return "Usage: \n\n"
"[no args]: dumps (id and value) all supported properties \n"
"--help: shows this help\n"
- "--list: lists the ids of all supported properties\n"
- "--get <PROP1> [PROP2] [PROPN]: dumps the value of specific properties. \n"
- "--getWithArg <PROP> [ValueArguments]: gets the value for a specific property with "
- "arguments. \n"
- "--set <PROP> [ValueArguments]: sets the value of property PROP. \n"
- "--save-prop <prop> [-a AREA_ID]: saves the current value for PROP, integration test"
- " that modifies prop value must call this before test and restore-prop after test. \n"
- "--restore-prop <prop> [-a AREA_ID]: restores a previously saved property value. \n"
- "--inject-event <PROP> [ValueArguments]: inject a property update event from car\n\n"
- "ValueArguments are in the format of [-i INT_VALUE [INT_VALUE ...]] "
- "[-i64 INT64_VALUE [INT64_VALUE ...]] [-f FLOAT_VALUE [FLOAT_VALUE ...]] [-s STR_VALUE] "
- "[-b BYTES_VALUE] [-a AREA_ID].\n"
- "Notice that the string, bytes and area value can be set just once, while the other can"
+ "--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();
@@ -1848,11 +1868,18 @@
return "no properties to list\n";
}
int rowNumber = 1;
- std::string msg = StringPrintf("listing %zu properties\n", configs.size());
+ std::stringstream ss;
+ ss << "listing " << configs.size() << " properties" << std::endl;
for (const auto& config : configs) {
- msg += StringPrintf("%d: %s\n", rowNumber++, PROP_ID_TO_CSTR(config.prop));
+ 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 msg;
+ return ss.str();
}
Result<void> FakeVehicleHardware::checkArgumentsSize(const std::vector<std::string>& options,
@@ -1865,6 +1892,16 @@
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);
+}
+
std::string FakeVehicleHardware::dumpSpecificProperty(const std::vector<std::string>& options) {
if (auto result = checkArgumentsSize(options, /*minSize=*/2); !result.ok()) {
return getErrorMsg(result);
@@ -1875,7 +1912,7 @@
size_t size = options.size();
std::string msg = "";
for (size_t i = 1; i < size; ++i) {
- auto propResult = safelyParseInt<int32_t>(i, options[i]);
+ auto propResult = parsePropId(options, i);
if (!propResult.ok()) {
msg += getErrorMsg(propResult);
continue;
@@ -1911,9 +1948,9 @@
// --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 = safelyParseInt<int32_t>(optionIndex, options[optionIndex]);
+ auto result = parsePropId(options, optionIndex);
if (!result.ok()) {
- return Error() << StringPrintf("Property value: \"%s\" is not a valid int: %s\n",
+ return Error() << StringPrintf("Property ID/Name: \"%s\" is not valid: %s\n",
options[optionIndex].c_str(), getErrorMsg(result).c_str());
}
VehiclePropValue prop = {};
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
index cab33e1..0924360 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
@@ -2613,6 +2613,23 @@
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");
@@ -2766,6 +2783,7 @@
std::string infoMakeProperty = std::to_string(toInt(VehicleProperty::INFO_MAKE));
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},
@@ -2790,10 +2808,7 @@
false,
"No values specified"},
{"fail_unknown_options", {"--set", infoMakeProperty, "-abcd"}, false, "Unknown option"},
- {"fail_invalid_property",
- {"--set", "not valid", "-s", CAR_MAKE},
- false,
- "not a valid int"},
+ {"fail_invalid_property", {"--set", "not_valid", "-s", CAR_MAKE}, false, "not valid"},
{"fail_duplicate_string",
{"--set", infoMakeProperty, "-s", CAR_MAKE, "-s", CAR_MAKE},
false,
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h b/automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h
index 78b61f7..f2327e1 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h
@@ -97,6 +97,8 @@
constexpr int HVAC_LEFT = SEAT_1_LEFT | SEAT_2_LEFT | SEAT_2_CENTER;
constexpr int HVAC_RIGHT = SEAT_1_RIGHT | SEAT_2_RIGHT;
constexpr int HVAC_ALL = HVAC_LEFT | HVAC_RIGHT;
+constexpr int HVAC_FRONT_ROW = SEAT_1_LEFT | SEAT_1_RIGHT;
+constexpr int HVAC_REAR_ROW = SEAT_2_LEFT | SEAT_2_CENTER | SEAT_2_RIGHT;
} // namespace vehicle
} // namespace automotive
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
index aca725d..f48bb2a 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
@@ -328,11 +328,15 @@
}
};
+// This is for debug purpose only.
inline std::string propIdToString(int32_t propId) {
return toString(
static_cast<aidl::android::hardware::automotive::vehicle::VehicleProperty>(propId));
}
+// This is for debug purpose only.
+android::base::Result<int32_t> stringToPropId(const std::string& propName);
+
template <typename T>
void roundToNearestResolution(std::vector<T>& arrayToSanitize, float resolution) {
if (resolution == 0) {
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp b/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
index 3d0a524..a7caeb1 100644
--- a/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
@@ -153,10 +153,9 @@
propValue->status = oldStatus;
}
+ // areaId and propId must be the same between valueToUpdate and propValue.
valueUpdated = (valueToUpdate->value != propValue->value ||
- valueToUpdate->status != propValue->status ||
- valueToUpdate->prop != propValue->prop ||
- valueToUpdate->areaId != propValue->areaId);
+ valueToUpdate->status != propValue->status);
} else if (!updateStatus) {
propValue->status = VehiclePropertyStatus::AVAILABLE;
}
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/VehicleUtils.cpp b/automotive/vehicle/aidl/impl/utils/common/src/VehicleUtils.cpp
index f85728d..4d06e4e 100644
--- a/automotive/vehicle/aidl/impl/utils/common/src/VehicleUtils.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/src/VehicleUtils.cpp
@@ -16,14 +16,18 @@
#include "VehicleUtils.h"
+#include <unordered_map>
+
namespace android {
namespace hardware {
namespace automotive {
namespace vehicle {
using ::aidl::android::hardware::automotive::vehicle::StatusCode;
+using ::aidl::android::hardware::automotive::vehicle::toString;
using ::aidl::android::hardware::automotive::vehicle::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;
@@ -31,6 +35,39 @@
using ::android::base::Result;
using ::ndk::ScopedAStatus;
+namespace {
+
+class PropertyIdByNameSingleton {
+ public:
+ static PropertyIdByNameSingleton& getInstance() {
+ static PropertyIdByNameSingleton instance;
+ return instance;
+ }
+
+ Result<int32_t> getPropertyId(const std::string& name) {
+ auto it = mPropertyIdByName.find(name);
+ if (it == mPropertyIdByName.end()) {
+ return Error();
+ }
+ return it->second;
+ }
+
+ PropertyIdByNameSingleton(PropertyIdByNameSingleton const&) = delete;
+ void operator=(PropertyIdByNameSingleton const&) = delete;
+
+ private:
+ std::unordered_map<std::string, int32_t> mPropertyIdByName;
+
+ PropertyIdByNameSingleton() {
+ constexpr auto values = ndk::internal::enum_values<VehicleProperty>;
+ for (unsigned int i = 0; i < values.size(); i++) {
+ mPropertyIdByName.emplace(toString(values[i]), toInt(values[i]));
+ }
+ }
+};
+
+} // namespace
+
Result<void> checkPropValue(const VehiclePropValue& value, const VehiclePropConfig* config) {
int32_t property = value.prop;
VehiclePropertyType type = getPropType(property);
@@ -213,6 +250,10 @@
return aidl::android::hardware::automotive::vehicle::toString(mCode);
}
+Result<int32_t> stringToPropId(const std::string& propName) {
+ return PropertyIdByNameSingleton::getInstance().getPropertyId(propName);
+}
+
} // namespace vehicle
} // namespace automotive
} // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp b/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp
index 9abb2a2..1048877 100644
--- a/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp
@@ -770,6 +770,23 @@
ASSERT_EQ(result.error().message(), "error message: INVALID_ARG");
}
+TEST(VehicleUtilsTest, testPropIdToString) {
+ ASSERT_EQ(propIdToString(toInt(VehicleProperty::PERF_VEHICLE_SPEED)), "PERF_VEHICLE_SPEED");
+}
+
+TEST(VehicleUtilsTest, testStringToPropId) {
+ auto result = stringToPropId("PERF_VEHICLE_SPEED");
+
+ ASSERT_TRUE(result.ok());
+ ASSERT_EQ(result.value(), toInt(VehicleProperty::PERF_VEHICLE_SPEED));
+}
+
+TEST(VehicleUtilsTest, testStringToPropId_InvalidName) {
+ auto result = stringToPropId("PERF_VEHICLE_SPEED12345");
+
+ ASSERT_FALSE(result.ok());
+}
+
class InvalidPropValueTest : public testing::TestWithParam<InvalidPropValueTestCase> {};
INSTANTIATE_TEST_SUITE_P(InvalidPropValueTests, InvalidPropValueTest,
diff --git a/automotive/vehicle/aidl/impl/vhal/Android.bp b/automotive/vehicle/aidl/impl/vhal/Android.bp
index ae1102f..5cc071d 100644
--- a/automotive/vehicle/aidl/impl/vhal/Android.bp
+++ b/automotive/vehicle/aidl/impl/vhal/Android.bp
@@ -66,7 +66,7 @@
],
header_libs: [
"IVehicleHardware",
- "IVehicleGeneratedHeaders",
+ "IVehicleGeneratedHeaders-V3",
],
shared_libs: [
"libbinder_ndk",
diff --git a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
index 250b30c..fa2a310 100644
--- a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
+++ b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
@@ -42,10 +42,11 @@
namespace automotive {
namespace vehicle {
-class DefaultVehicleHal final : public aidl::android::hardware::automotive::vehicle::BnVehicle {
+namespace aidlvhal = ::aidl::android::hardware::automotive::vehicle;
+
+class DefaultVehicleHal final : public aidlvhal::BnVehicle {
public:
- using CallbackType =
- std::shared_ptr<aidl::android::hardware::automotive::vehicle::IVehicleCallback>;
+ using CallbackType = std::shared_ptr<aidlvhal::IVehicleCallback>;
explicit DefaultVehicleHal(std::unique_ptr<IVehicleHardware> hardware);
@@ -54,26 +55,16 @@
~DefaultVehicleHal();
- ndk::ScopedAStatus getAllPropConfigs(
- aidl::android::hardware::automotive::vehicle::VehiclePropConfigs* returnConfigs)
- override;
- ndk::ScopedAStatus getValues(
- const CallbackType& callback,
- const aidl::android::hardware::automotive::vehicle::GetValueRequests& requests)
- override;
- ndk::ScopedAStatus setValues(
- const CallbackType& callback,
- const aidl::android::hardware::automotive::vehicle::SetValueRequests& requests)
- override;
- ndk::ScopedAStatus getPropConfigs(
- const std::vector<int32_t>& props,
- aidl::android::hardware::automotive::vehicle::VehiclePropConfigs* returnConfigs)
- override;
- ndk::ScopedAStatus subscribe(
- const CallbackType& callback,
- const std::vector<aidl::android::hardware::automotive::vehicle::SubscribeOptions>&
- options,
- int32_t maxSharedMemoryFileCount) override;
+ 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,
@@ -86,12 +77,8 @@
// friend class for unit testing.
friend class DefaultVehicleHalTest;
- using GetValuesClient =
- GetSetValuesClient<aidl::android::hardware::automotive::vehicle::GetValueResult,
- aidl::android::hardware::automotive::vehicle::GetValueResults>;
- using SetValuesClient =
- GetSetValuesClient<aidl::android::hardware::automotive::vehicle::SetValueResult,
- aidl::android::hardware::automotive::vehicle::SetValueResults>;
+ 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 {
@@ -137,28 +124,27 @@
bool mShouldRefreshPropertyConfigs;
std::unique_ptr<IVehicleHardware> mVehicleHardware;
- // mConfigsByPropId and mConfigFile are only modified during initialization, so no need to
- // lock guard them.
- std::unordered_map<int32_t, aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
- mConfigsByPropId;
- // Only modified in constructor, so thread-safe.
- std::unique_ptr<ndk::ScopedFileDescriptor> mConfigFile;
// 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<aidl::android::hardware::automotive::vehicle::VehiclePropValue>>
- mBatchedEventQueue;
+ std::shared_ptr<ConcurrentQueue<aidlvhal::VehiclePropValue>> mBatchedEventQueue;
// BatchingConsumer is thread-safe.
- std::shared_ptr<
- BatchingConsumer<aidl::android::hardware::automotive::vehicle::VehiclePropValue>>
+ std::shared_ptr<BatchingConsumer<aidlvhal::VehiclePropValue>>
mPropertyChangeEventsBatchingConsumer;
// Only set once during initialization.
std::chrono::nanoseconds mEventBatchingWindow;
// Only used for testing.
int32_t mTestInterfaceVersion = 0;
+ // mConfigsByPropId and mConfigFile is lazy initialized.
+ mutable std::mutex mConfigInitLock;
+ mutable bool mConfigInit GUARDED_BY(mConfigInitLock) = false;
+ mutable std::unordered_map<int32_t, aidlvhal::VehiclePropConfig> mConfigsByPropId
+ GUARDED_BY(mConfigInitLock);
+ mutable std::unique_ptr<ndk::ScopedFileDescriptor> mConfigFile GUARDED_BY(mConfigInitLock);
+
std::mutex mLock;
std::unordered_map<const AIBinder*, std::unique_ptr<OnBinderDiedContext>> mOnBinderDiedContexts
GUARDED_BY(mLock);
@@ -182,32 +168,23 @@
// A thread to handle onBinderDied or onBinderUnlinked event.
std::thread mOnBinderDiedUnlinkedHandlerThread;
- android::base::Result<void> checkProperty(
- const aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue);
+ android::base::Result<void> checkProperty(const aidlvhal::VehiclePropValue& propValue);
android::base::Result<std::vector<int64_t>> checkDuplicateRequests(
- const std::vector<aidl::android::hardware::automotive::vehicle::GetValueRequest>&
- requests);
+ const std::vector<aidlvhal::GetValueRequest>& requests);
android::base::Result<std::vector<int64_t>> checkDuplicateRequests(
- const std::vector<aidl::android::hardware::automotive::vehicle::SetValueRequest>&
- requests);
- VhalResult<void> checkSubscribeOptions(
- const std::vector<aidl::android::hardware::automotive::vehicle::SubscribeOptions>&
- options);
+ const std::vector<aidlvhal::SetValueRequest>& requests);
+ VhalResult<void> checkSubscribeOptions(const std::vector<aidlvhal::SubscribeOptions>& options);
- VhalResult<void> checkPermissionHelper(
- const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value,
- aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess accessToTest) const;
+ VhalResult<void> checkPermissionHelper(const aidlvhal::VehiclePropValue& value,
+ aidlvhal::VehiclePropertyAccess accessToTest) const;
- VhalResult<void> checkReadPermission(
- const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const;
+ VhalResult<void> checkReadPermission(const aidlvhal::VehiclePropValue& value) const;
- VhalResult<void> checkWritePermission(
- const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const;
+ VhalResult<void> checkWritePermission(const aidlvhal::VehiclePropValue& value) const;
- android::base::Result<const aidl::android::hardware::automotive::vehicle::VehiclePropConfig*>
- getConfig(int32_t propId) const;
+ android::base::Result<const aidlvhal::VehiclePropConfig*> getConfig(int32_t propId) const;
void onBinderDiedWithContext(const AIBinder* clientId);
@@ -219,7 +196,7 @@
bool checkDumpPermission();
- bool getAllPropConfigsFromHardware();
+ bool getAllPropConfigsFromHardwareLocked() const REQUIRES(mConfigInitLock);
// The looping handler function to process all onBinderDied or onBinderUnlinked events in
// mBinderEvents.
@@ -228,19 +205,19 @@
size_t countSubscribeClients();
// Handles the property change events in batch.
- void handleBatchedPropertyEvents(
- std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>&&
- batchedEvents);
+ void handleBatchedPropertyEvents(std::vector<aidlvhal::VehiclePropValue>&& batchedEvents);
- int32_t getVhalInterfaceVersion();
+ int32_t getVhalInterfaceVersion() const;
+
+ // Gets mConfigsByPropId, lazy init it if necessary.
+ const std::unordered_map<int32_t, aidlvhal::VehiclePropConfig>& getConfigsByPropId() const;
+ // Gets mConfigFile, lazy init it if necessary.
+ const ndk::ScopedFileDescriptor* getConfigFile() const;
// Puts the property change events into a queue so that they can handled in batch.
static void batchPropertyChangeEvent(
- const std::weak_ptr<ConcurrentQueue<
- aidl::android::hardware::automotive::vehicle::VehiclePropValue>>&
- batchedEventQueue,
- std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>&&
- updatedValues);
+ 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>
@@ -248,10 +225,8 @@
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<aidl::android::hardware::automotive::vehicle::VehiclePropValue>&&
- updatedValues);
+ static void onPropertyChangeEvent(const std::weak_ptr<SubscriptionManager>& subscriptionManager,
+ std::vector<aidlvhal::VehiclePropValue>&& updatedValues);
static void onPropertySetErrorEvent(
const std::weak_ptr<SubscriptionManager>& subscriptionManager,
diff --git a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
index a29861f..9dc039d 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
@@ -24,6 +24,7 @@
#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>
@@ -71,6 +72,7 @@
using ::ndk::ScopedAIBinder_DeathRecipient;
using ::ndk::ScopedAStatus;
+using ::ndk::ScopedFileDescriptor;
std::string toString(const std::unordered_set<int64_t>& values) {
std::string str = "";
@@ -103,10 +105,7 @@
: mVehicleHardware(std::move(vehicleHardware)),
mPendingRequestPool(std::make_shared<PendingRequestPool>(TIMEOUT_IN_NANO)),
mTestInterfaceVersion(testInterfaceVersion) {
- if (!getAllPropConfigsFromHardware()) {
- return;
- }
-
+ ALOGD("DefaultVehicleHal init");
IVehicleHardware* vehicleHardwarePtr = mVehicleHardware.get();
mSubscriptionManager = std::make_shared<SubscriptionManager>(vehicleHardwarePtr);
mEventBatchingWindow = mVehicleHardware->getPropertyOnChangeEventBatchingWindow();
@@ -319,16 +318,18 @@
mPendingRequestPool = std::make_unique<PendingRequestPool>(timeoutInNano);
}
-int32_t DefaultVehicleHal::getVhalInterfaceVersion() {
+int32_t DefaultVehicleHal::getVhalInterfaceVersion() const {
if (mTestInterfaceVersion != 0) {
return mTestInterfaceVersion;
}
int32_t myVersion = 0;
- getInterfaceVersion(&myVersion);
+ // getInterfaceVersion is in-reality a const method.
+ const_cast<DefaultVehicleHal*>(this)->getInterfaceVersion(&myVersion);
return myVersion;
}
-bool DefaultVehicleHal::getAllPropConfigsFromHardware() {
+bool DefaultVehicleHal::getAllPropConfigsFromHardwareLocked() const {
+ ALOGD("Get all property configs from hardware");
auto configs = mVehicleHardware->getAllPropertyConfigs();
std::vector<VehiclePropConfig> filteredConfigs;
int32_t myVersion = getVhalInterfaceVersion();
@@ -373,22 +374,46 @@
return true;
}
+const ScopedFileDescriptor* DefaultVehicleHal::getConfigFile() const {
+ std::scoped_lock lockGuard(mConfigInitLock);
+ if (!mConfigInit) {
+ CHECK(getAllPropConfigsFromHardwareLocked())
+ << "Failed to get property configs from hardware";
+ mConfigInit = true;
+ }
+ return mConfigFile.get();
+}
+
+const std::unordered_map<int32_t, VehiclePropConfig>& DefaultVehicleHal::getConfigsByPropId()
+ const {
+ std::scoped_lock lockGuard(mConfigInitLock);
+ if (!mConfigInit) {
+ CHECK(getAllPropConfigsFromHardwareLocked())
+ << "Failed to get property configs from hardware";
+ mConfigInit = true;
+ }
+ return mConfigsByPropId;
+}
+
ScopedAStatus DefaultVehicleHal::getAllPropConfigs(VehiclePropConfigs* output) {
- if (mConfigFile != nullptr) {
+ const ScopedFileDescriptor* configFile = getConfigFile();
+ const auto& configsByPropId = getConfigsByPropId();
+ if (configFile != nullptr) {
output->payloads.clear();
- output->sharedMemoryFd.set(dup(mConfigFile->get()));
+ output->sharedMemoryFd.set(dup(configFile->get()));
return ScopedAStatus::ok();
}
- output->payloads.reserve(mConfigsByPropId.size());
- for (const auto& [_, config] : mConfigsByPropId) {
+ output->payloads.reserve(configsByPropId.size());
+ for (const auto& [_, config] : configsByPropId) {
output->payloads.push_back(config);
}
return ScopedAStatus::ok();
}
Result<const VehiclePropConfig*> DefaultVehicleHal::getConfig(int32_t propId) const {
- auto it = mConfigsByPropId.find(propId);
- if (it == mConfigsByPropId.end()) {
+ const auto& configsByPropId = getConfigsByPropId();
+ auto it = configsByPropId.find(propId);
+ if (it == configsByPropId.end()) {
return Error() << "no config for property, ID: " << propId;
}
return &(it->second);
@@ -634,9 +659,11 @@
ScopedAStatus DefaultVehicleHal::getPropConfigs(const std::vector<int32_t>& props,
VehiclePropConfigs* output) {
std::vector<VehiclePropConfig> configs;
+ const auto& configsByPropId = getConfigsByPropId();
for (int32_t prop : props) {
- if (mConfigsByPropId.find(prop) != mConfigsByPropId.end()) {
- configs.push_back(mConfigsByPropId[prop]);
+ auto it = configsByPropId.find(prop);
+ if (it != configsByPropId.end()) {
+ configs.push_back(it->second);
} else {
return ScopedAStatus::fromServiceSpecificErrorWithMessage(
toInt(StatusCode::INVALID_ARG),
@@ -665,13 +692,15 @@
VhalResult<void> DefaultVehicleHal::checkSubscribeOptions(
const std::vector<SubscribeOptions>& options) {
+ const auto& configsByPropId = getConfigsByPropId();
for (const auto& option : options) {
int32_t propId = option.propId;
- if (mConfigsByPropId.find(propId) == mConfigsByPropId.end()) {
+ 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 = mConfigsByPropId[propId];
+ const VehiclePropConfig& config = it->second;
std::vector<VehicleAreaConfig> areaConfigs;
if (option.areaIds.empty()) {
areaConfigs = config.areaConfigs;
@@ -744,10 +773,11 @@
}
std::vector<SubscribeOptions> onChangeSubscriptions;
std::vector<SubscribeOptions> continuousSubscriptions;
+ const auto& configsByPropId = getConfigsByPropId();
for (const auto& option : options) {
int32_t propId = option.propId;
// We have already validate config exists.
- const VehiclePropConfig& config = mConfigsByPropId[propId];
+ const VehiclePropConfig& config = configsByPropId.at(propId);
SubscribeOptions optionCopy = option;
// If areaIds is empty, subscribe to all areas.
@@ -871,7 +901,7 @@
(areaConfig == nullptr || !hasRequiredAccess(areaConfig->access, accessToTest))) {
return StatusError(StatusCode::ACCESS_DENIED)
<< StringPrintf("Property %" PRId32 " does not have the following access: %" PRId32,
- propId, accessToTest);
+ propId, static_cast<int32_t>(accessToTest));
}
return {};
}
@@ -936,17 +966,19 @@
}
DumpResult result = mVehicleHardware->dump(options);
if (result.refreshPropertyConfigs) {
- getAllPropConfigsFromHardware();
+ std::scoped_lock lockGuard(mConfigInitLock);
+ getAllPropConfigsFromHardwareLocked();
}
dprintf(fd, "%s", (result.buffer + "\n").c_str());
if (!result.callerShouldDumpState) {
return STATUS_OK;
}
dprintf(fd, "Vehicle HAL State: \n");
+ const auto& configsByPropId = getConfigsByPropId();
{
std::scoped_lock<std::mutex> lockGuard(mLock);
dprintf(fd, "Interface version: %" PRId32 "\n", getVhalInterfaceVersion());
- dprintf(fd, "Containing %zu property configs\n", mConfigsByPropId.size());
+ dprintf(fd, "Containing %zu property configs\n", configsByPropId.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());
diff --git a/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp b/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp
index f1106ee..14ee707 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp
@@ -40,6 +40,7 @@
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,
@@ -88,7 +89,7 @@
}
float log = std::log10(resolution);
- return log == (int)log;
+ return std::abs(log - std::round(log)) < EPSILON;
}
void ContSubConfigs::refreshCombinedConfig() {
@@ -433,6 +434,9 @@
}
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.
diff --git a/automotive/vehicle/aidl/impl/vhal/test/SubscriptionManagerTest.cpp b/automotive/vehicle/aidl/impl/vhal/test/SubscriptionManagerTest.cpp
index f377202..440a9f9 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/SubscriptionManagerTest.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/test/SubscriptionManagerTest.cpp
@@ -521,6 +521,8 @@
}
TEST_F(SubscriptionManagerTest, testCheckResolutionValid) {
+ ASSERT_TRUE(SubscriptionManager::checkResolution(0.0));
+ ASSERT_TRUE(SubscriptionManager::checkResolution(0.1));
ASSERT_TRUE(SubscriptionManager::checkResolution(1.0));
}
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 6e77f53..7891dd9 100644
--- a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/EvConnectorType.aidl
+++ b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/EvConnectorType.aidl
@@ -28,16 +28,65 @@
* type.
*/
UNKNOWN = 0,
+ /**
+ * IEC 62196 Type 1 connector
+ *
+ * Also known as the "Yazaki connector" or "J1772 connector".
+ */
IEC_TYPE_1_AC = 1,
+ /**
+ * IEC 62196 Type 2 connector
+ *
+ * Also known as the "Mennekes connector".
+ */
IEC_TYPE_2_AC = 2,
+ /**
+ * IEC 62196 Type 3 connector
+ *
+ * Also known as the "Scame connector".
+ */
IEC_TYPE_3_AC = 3,
+ /**
+ * IEC 62196 Type AA connector
+ *
+ * Also known as the "Chademo connector".
+ */
IEC_TYPE_4_DC = 4,
+ /**
+ * IEC 62196 Type EE connector
+ *
+ * Also known as the “CCS1 connector” or “Combo1 connector".
+ */
IEC_TYPE_1_CCS_DC = 5,
+ /**
+ * IEC 62196 Type EE connector
+ *
+ * Also known as the “CCS2 connector” or “Combo2 connector”.
+ */
IEC_TYPE_2_CCS_DC = 6,
+ /**
+ * DO NOT USE
+ *
+ * Connector of Tesla Roadster.
+ */
TESLA_ROADSTER = 7,
+ /**
+ * DO NOT USE
+ * Use TESLA_SUPERCHARGER instead.
+ *
+ * High Power Wall Charger of Tesla.
+ */
TESLA_HPWC = 8,
+ /**
+ * SAE J3400 connector
+ *
+ * Also known as the "North American Charging Standard" (NACS)
+ * or the "Tesla charging standard" connector.
+ */
TESLA_SUPERCHARGER = 9,
+ /** GBT_AC Fast Charging Standard */
GBT_AC = 10,
+ /** GBT_DC Fast Charging Standard */
GBT_DC = 11,
/**
* Connector type to use when no other types apply. Before using this
diff --git a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleIgnitionState.aidl b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleIgnitionState.aidl
index 4de97f6..2338008 100644
--- a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleIgnitionState.aidl
+++ b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleIgnitionState.aidl
@@ -28,6 +28,10 @@
* Steering wheel is not locked, engine and all accessories are OFF. If
* car can be in LOCK and OFF state at the same time than HAL must report
* LOCK state.
+ *
+ * If IGNITION_STATE is implemented on a BEV, then this state must
+ * communicate that the BEV's High Voltage battery is disconnected and thus
+ * the vehicle is OFF.
*/
OFF,
/**
@@ -38,6 +42,10 @@
/**
* Ignition is in state ON. Accessories and instrument cluster available,
* engine might be running or ready to be started.
+ *
+ * If IGNITION_STATE is implemented on a BEV, then this state must
+ * communicate that the BEV's High Voltage battery is connected and thus the
+ * vehicle is ON.
*/
ON,
/**
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 6f5c0c1..e54c179 100644
--- a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl
+++ b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl
@@ -59,6 +59,8 @@
/**
* Manufacturer of vehicle
*
+ * This property must communicate the vehicle's public brand name.
+ *
* @change_mode VehiclePropertyChangeMode.STATIC
* @access VehiclePropertyAccess.READ
* @version 2
@@ -68,6 +70,8 @@
/**
* Model of vehicle
*
+ * This property must communicate the vehicle's public model name.
+ *
* @change_mode VehiclePropertyChangeMode.STATIC
* @access VehiclePropertyAccess.READ
* @version 2
@@ -87,6 +91,11 @@
/**
* Fuel capacity of the vehicle in milliliters
*
+ * This property must communicate the maximum amount of the fuel that can be stored in the
+ * vehicle in milliliters. This property does not apply to electric vehicles. That is, if
+ * INFO_FUEL_TYPE only contains FuelType::FUEL_TYPE_ELECTRIC, this property must not be
+ * implemented. For EVs, implement INFO_EV_BATTERY_CAPACITY.
+ *
* @change_mode VehiclePropertyChangeMode.STATIC
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit.MILLILITER
@@ -102,7 +111,7 @@
* An FHEV (Fully Hybrid Electric Vehicle) must not include FuelType::FUEL_TYPE_ELECTRIC in
* INFO_FUEL_TYPE's INT32_VEC value. So INFO_FUEL_TYPE can be populated as such:
* int32Values = { FuelType::FUEL_TYPE_UNLEADED }
- * On the other hand, a PHEV (Partially Hybrid Electric Vehicle) is plug in rechargeable, and
+ * On the other hand, a PHEV (Plug-in Hybrid Electric Vehicle) is plug in rechargeable, and
* hence should include FuelType::FUEL_TYPE_ELECTRIC in INFO_FUEL_TYPE's INT32_VEC value. So
* INFO_FUEL_TYPE can be populated as such:
* int32Values = { FuelType::FUEL_TYPE_UNLEADED, FuelType::FUEL_TYPE_ELECTRIC }
@@ -115,12 +124,13 @@
INFO_FUEL_TYPE = 0x0105 + 0x10000000 + 0x01000000
+ 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
/**
- * Nominal battery capacity for EV or hybrid vehicle
+ * Nominal usable battery capacity for EV or hybrid vehicle
*
- * Returns the nominal battery capacity, if EV or hybrid. This is the battery capacity when the
- * vehicle is new. This value might be different from EV_CURRENT_BATTERY_CAPACITY because
- * EV_CURRENT_BATTERY_CAPACITY returns the real-time battery capacity taking into account
- * factors such as battery aging and temperature dependency.
+ * Returns the nominal battery capacity, if EV or hybrid. This is the total usable battery
+ * capacity when the vehicle is new. This value might be different from
+ * EV_CURRENT_BATTERY_CAPACITY because EV_CURRENT_BATTERY_CAPACITY returns the real-time usable
+ * battery capacity taking into account factors such as battery aging and temperature
+ * dependency.
*
* @change_mode VehiclePropertyChangeMode.STATIC
* @access VehiclePropertyAccess.READ
@@ -132,6 +142,9 @@
/**
* List of connectors this EV may use
*
+ * If the vehicle has multiple charging ports, this property must return all possible connector
+ * types that can be used by at least one charging port on the vehicle.
+ *
* @change_mode VehiclePropertyChangeMode.STATIC
* @data_enum EvConnectorType
* @access VehiclePropertyAccess.READ
@@ -142,6 +155,11 @@
/**
* Fuel door location
*
+ * This property must communicate the location of the fuel door on the vehicle. This property
+ * does not apply to electric vehicles. That is, if INFO_FUEL_TYPE only contains
+ * FuelType::FUEL_TYPE_ELECTRIC, this property must not be implemented. For EVs, implement
+ * INFO_EV_PORT_LOCATION or INFO_MULTI_EV_PORT_LOCATIONS.
+ *
* @change_mode VehiclePropertyChangeMode.STATIC
* @data_enum PortLocationType
* @access VehiclePropertyAccess.READ
@@ -152,6 +170,11 @@
/**
* EV port location
*
+ * This property must communicate the location of the charging port on the EV using the
+ * PortLocationType enum. If there are multiple ports available on the vehicle, this property
+ * must return the port that allows the fastest charging. To communicate all port locations,
+ * use INFO_MULTI_EV_PORT_LOCATIONS.
+ *
* @change_mode VehiclePropertyChangeMode.STATIC
* @access VehiclePropertyAccess.READ
* @data_enum PortLocationType
@@ -196,7 +219,10 @@
* 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[0] = PortLocationType::REAR_LEFT
+ * int32Values[1] = PortLocationType::REAR_LEFT
+ *
+ * If 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.
*
* @change_mode VehiclePropertyChangeMode.STATIC
* @access VehiclePropertyAccess.READ
@@ -249,6 +275,10 @@
*
* Angle is in degrees. Left is negative.
*
+ * This property is independent of the angle of the steering wheel. This property must
+ * communicate the angle of the front wheels with respect to the vehicle, not the angle of the
+ * steering wheel.
+ *
* @change_mode VehiclePropertyChangeMode.CONTINUOUS
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit.DEGREES
@@ -261,6 +291,10 @@
*
* Angle is in degrees. Left is negative.
*
+ * This 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.
+ *
* @change_mode VehiclePropertyChangeMode.CONTINUOUS
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit.DEGREES
@@ -350,9 +384,14 @@
WHEEL_TICK = 0x0306 + 0x10000000 + 0x01000000
+ 0x00510000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT64_VEC
/**
- * Fuel remaining in the vehicle, in milliliters
+ * Fuel level in milliliters
*
- * Value may not exceed INFO_FUEL_CAPACITY
+ * This property must communicate the current amount of fuel remaining in the vehicle in
+ * milliliters. This property does not apply to electric vehicles. That is, if INFO_FUEL_TYPE
+ * only contains FuelType::FUEL_TYPE_ELECTRIC, this property must not be implemented. For EVs,
+ * implement EV_BATTERY_LEVEL.
+ *
+ * Value may not exceed INFO_FUEL_CAPACITY.
*
* @change_mode VehiclePropertyChangeMode.CONTINUOUS
* @access VehiclePropertyAccess.READ
@@ -364,6 +403,11 @@
/**
* Fuel door open
*
+ * This property must communicate whether the fuel door on the vehicle is open or not. This
+ * property does not apply to electric vehicles. That is, if INFO_FUEL_TYPE only contains
+ * FuelType::FUEL_TYPE_ELECTRIC, this property must not be implemented. For EVs, implement
+ * EV_CHARGE_PORT_OPEN.
+ *
* This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
* implement it as VehiclePropertyAccess.READ only.
*
@@ -389,12 +433,13 @@
EV_BATTERY_LEVEL = 0x0309 + 0x10000000 + 0x01000000
+ 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
/**
- * Current battery capacity for EV or hybrid vehicle
+ * Current usable battery capacity for EV or hybrid vehicle
*
* Returns the actual value of battery capacity, if EV or hybrid. This property captures the
- * real-time battery capacity taking into account factors such as battery aging and temperature
- * dependency. Therefore, this value might be different from INFO_EV_BATTERY_CAPACITY because
- * INFO_EV_BATTERY_CAPACITY returns the nominal battery capacity from when the vehicle was new.
+ * real-time usable battery capacity taking into account factors such as battery aging and
+ * temperature dependency. Therefore, this value might be different from
+ * INFO_EV_BATTERY_CAPACITY because INFO_EV_BATTERY_CAPACITY returns the nominal battery
+ * capacity from when the vehicle was new.
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
@@ -406,6 +451,9 @@
/**
* EV charge port open
*
+ * If the vehicle has multiple charging ports, this property must return true if any of the
+ * charge ports are open.
+ *
* This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
* implement it as VehiclePropertyAccess.READ only.
*
@@ -419,6 +467,9 @@
/**
* EV charge port connected
*
+ * If the vehicle has multiple charging ports, this property must return true if any of the
+ * charge ports are connected.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @version 2
@@ -625,8 +676,12 @@
* The maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All values between
* minInt32Value and maxInt32Value must be supported. The minInt32Value must be 0.
*
- * The maxInt32Value indicates the maximum amount of energy regenerated from braking. The
- * minInt32Value indicates no regenerative braking.
+ * The maxInt32Value indicates the setting for the maximum amount of energy regenerated from
+ * braking. The minInt32Value indicates the setting for no regenerative braking.
+ *
+ * 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
+ * are not granular enough for the OEM.
*
* This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
* implement it as VehiclePropertyAccess.READ only.
@@ -772,7 +827,7 @@
* @access VehiclePropertyAccess.READ
* @data_enum ElectronicStabilityControlState
* @data_enum ErrorState
- * @version 2
+ * @version 3
*/
ELECTRONIC_STABILITY_CONTROL_STATE =
0x040F + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -868,10 +923,18 @@
HVAC_TEMPERATURE_CURRENT = 0x0502 + 0x10000000 + 0x05000000
+ 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:FLOAT
/**
- * HVAC, target temperature set.
+ * HVAC target temperature set in Celsius.
*
- * The configArray is used to indicate the valid values for HVAC in Fahrenheit and Celsius.
- * Android might use it in the HVAC app UI.
+ * 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
+ * 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.
+ *
* The 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.
@@ -879,14 +942,35 @@
* 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.
+ *
+ * The minFloatValue and maxFloatValue in VehicleAreaConfig must be equal to configArray[0] and
+ * configArray[1] respectively.
+ *
* For example, if the vehicle supports temperature values as:
* [16.0, 16.5, 17.0 ,..., 28.0] in Celsius
- * [60.5, 61.5, 62.5 ,..., 85.5] in Fahrenheit.
- * The configArray should be configArray = {160, 280, 5, 605, 825, 10}.
+ * [60.5, 61.5, 62.5 ,..., 84.5] in Fahrenheit
+ * The configArray should be configArray = {160, 280, 5, 605, 845, 10}.
*
- * If the vehicle supports HVAC_TEMPERATURE_VALUE_SUGGESTION, the application can use
- * that property to get the suggested value before setting HVAC_TEMPERATURE_SET. Otherwise,
- * the application may choose the value in HVAC_TEMPERATURE_SET configArray by itself.
+ * Ideally, 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.
+ *
+ * There 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.
+ *
+ * For 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.
+ *
+ * Any value set in between a valid value should be rounded to the closest valid value.
+ *
+ * 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
+ * Fahrenheit.
*
* This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
* implement it as VehiclePropertyAccess.READ only.
@@ -1295,7 +1379,22 @@
*
* An application calls set(VehiclePropValue propValue) with the requested value and unit for
* the value. OEMs need to return the suggested values in floatValues[2] and floatValues[3] by
- * onPropertyEvent() callbacks.
+ * onPropertyEvent() callbacks. The suggested values must conform to the values that can be
+ * derived from the HVAC_TEMPERATURE_SET configArray. In other words, the suggested values and
+ * the table of values from the configArray should be the same. It is recommended for the OEM to
+ * add custom logic in their VHAL implementation in order to avoid making requests to the HVAC
+ * ECU.
+ *
+ * The logic can be as follows:
+ * For converting the temperature from celsius to fahrenheit use the following:
+ * // Given tempC and the configArray
+ * float minTempC = configArray[0] / 10.0;
+ * float temperatureIncrementCelsius = configArray[2] / 10.0;
+ * float minTempF = configArray[3] / 10.0;
+ * float temperatureIncrementFahrenheit = configArray[5] / 10.0;
+ * // Round to the closest increment
+ * int numIncrements = round((tempC - minTempC) / temperatureIncrementCelsius);
+ * tempF = temperatureIncrementFahrenheit * numIncrements + minTempF;
*
* For example, when a user uses the voice assistant to set HVAC temperature to 66.2 in
* Fahrenheit.
@@ -1557,6 +1656,11 @@
/**
* Outside temperature
*
+ * This property must communicate the temperature reading of the environment outside the
+ * vehicle. If there are multiple sensors for measuring the outside temperature, this property
+ * should be populated with the mean or a meaningful weighted average of the readings that will
+ * best represent the temperature of the outside environment.
+ *
* @change_mode VehiclePropertyChangeMode.CONTINUOUS
* @access VehiclePropertyAccess.READ
* @unit VehicleUnit.CELSIUS
@@ -1630,8 +1734,13 @@
* change display brightness from Settings, but that must not be reflected
* to other displays.
*
+ * If this is writable, writing this property must cause an on property
+ * change event even if the new display brightness is the same as the
+ * current value.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
+ * @access VehiclePropertyAccess.READ
* @version 2
*/
DISPLAY_BRIGHTNESS = 0x0A03 + 0x10000000 + 0x01000000
@@ -1651,6 +1760,15 @@
* The display port uniquely identifies a physical connector on the device
* for display output, ranging from 0 to 255.
*
+ * Writing this property must cause an on property change event that
+ * contains the same [display port, brightness] tuple even if the new
+ * display brightness is the same as the current value.
+ *
+ * To get the display brightness for a specific display port, the
+ * GetValueRequest must contain a VehiclePropValue, which contains one
+ * int32Value: displayPort. Getting this property without specifying the
+ * the display port is undefined behavior.
+ *
* int32Values[0] : display port
* int32Values[1] : brightness
*
@@ -2909,7 +3027,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
- * @version 3
+ * @version 2
*/
SEAT_AIRBAG_ENABLED =
0x0B9E + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.BOOLEAN,
@@ -2932,7 +3050,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum VehicleAirbagLocation
- * @version 2
+ * @version 3
*/
SEAT_AIRBAGS_DEPLOYED =
0x0BA5 + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.INT32,
@@ -3182,9 +3300,9 @@
WINDOW_MOVE = 0x0BC1 + 0x10000000 + 0x03000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:INT32
/**
- * Window Lock
+ * Window Child Lock
*
- * True indicates windows are locked and can't be moved.
+ * True indicates the window is child-locked.
*
* This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
* implement it as VehiclePropertyAccess.READ only.
@@ -4822,6 +4940,10 @@
*
* Returns the current charging state of the car.
*
+ * If the vehicle has a target charge percentage other than 100, this property must return
+ * EvChargeState::STATE_FULLY_CHARGED when the battery charge level has reached the target
+ * level. See EV_CHARGE_PERCENT_LIMIT for more context.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
* @data_enum EvChargeState
@@ -4861,10 +4983,13 @@
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
/**
- * Regenerative braking or one-pedal drive state of the car
+ * Regenerative braking or one-pedal drive setting of the car
*
- * Returns the current state associated with the regenerative braking
- * setting in the car
+ * Returns the current setting associated with the regenerative braking setting in the car
+ *
+ * If the OEM requires more setting than those provided in EvRegenerativeBrakingState, the
+ * EV_BRAKE_REGENERATION_LEVEL property can be used instead, which provides a more granular
+ * way of providing the same information.
*
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
@@ -5868,7 +5993,7 @@
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ_WRITE
* @access VehiclePropertyAccess.READ
- * @version 2
+ * @version 3
*/
DRIVER_DISTRACTION_WARNING_ENABLED =
0x101F + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
diff --git a/automotive/vehicle/tools/generate_annotation_enums.py b/automotive/vehicle/tools/generate_annotation_enums.py
index f279767..460e9f9 100755
--- a/automotive/vehicle/tools/generate_annotation_enums.py
+++ b/automotive/vehicle/tools/generate_annotation_enums.py
@@ -17,9 +17,9 @@
"""A script to generate Java files and CPP header files based on annotations in VehicleProperty.aidl
Need ANDROID_BUILD_TOP environmental variable to be set. This script will update
- ChangeModeForVehicleProperty.h and AccessForVehicleProperty.h under generated_lib/cpp and
+ ChangeModeForVehicleProperty.h and AccessForVehicleProperty.h under generated_lib/version/cpp and
ChangeModeForVehicleProperty.java, AccessForVehicleProperty.java, EnumForVehicleProperty.java
- UnitsForVehicleProperty.java under generated_lib/java.
+ UnitsForVehicleProperty.java under generated_lib/version/java.
Usage:
$ python generate_annotation_enums.py
@@ -31,22 +31,20 @@
import sys
import tempfile
+# Keep this updated with the latest in-development property version.
+PROPERTY_VERSION = '4'
+
PROP_AIDL_FILE_PATH = ('hardware/interfaces/automotive/vehicle/aidl_property/android/hardware/' +
'automotive/vehicle/VehicleProperty.aidl')
-CHANGE_MODE_CPP_FILE_PATH = ('hardware/interfaces/automotive/vehicle/aidl/generated_lib/cpp/' +
- 'ChangeModeForVehicleProperty.h')
-ACCESS_CPP_FILE_PATH = ('hardware/interfaces/automotive/vehicle/aidl/generated_lib/cpp/' +
- 'AccessForVehicleProperty.h')
-CHANGE_MODE_JAVA_FILE_PATH = ('hardware/interfaces/automotive/vehicle/aidl/generated_lib/java/' +
- 'ChangeModeForVehicleProperty.java')
-ACCESS_JAVA_FILE_PATH = ('hardware/interfaces/automotive/vehicle/aidl/generated_lib/java/' +
- 'AccessForVehicleProperty.java')
-ENUM_JAVA_FILE_PATH = ('hardware/interfaces/automotive/vehicle/aidl/generated_lib/java/' +
- 'EnumForVehicleProperty.java')
-UNITS_JAVA_FILE_PATH = ('hardware/interfaces/automotive/vehicle/aidl/generated_lib/java/' +
- 'UnitsForVehicleProperty.java')
-VERSION_CPP_FILE_PATH = ('hardware/interfaces/automotive/vehicle/aidl/generated_lib/cpp/' +
- 'VersionForVehicleProperty.h')
+GENERATED_LIB = ('hardware/interfaces/automotive/vehicle/aidl/generated_lib/' + PROPERTY_VERSION +
+ '/')
+CHANGE_MODE_CPP_FILE_PATH = GENERATED_LIB + '/cpp/ChangeModeForVehicleProperty.h'
+ACCESS_CPP_FILE_PATH = GENERATED_LIB + '/cpp/AccessForVehicleProperty.h'
+CHANGE_MODE_JAVA_FILE_PATH = GENERATED_LIB + '/java/ChangeModeForVehicleProperty.java'
+ACCESS_JAVA_FILE_PATH = GENERATED_LIB + '/java/AccessForVehicleProperty.java'
+ENUM_JAVA_FILE_PATH = GENERATED_LIB + '/java/EnumForVehicleProperty.java'
+UNITS_JAVA_FILE_PATH = GENERATED_LIB + '/java/UnitsForVehicleProperty.java'
+VERSION_CPP_FILE_PATH = GENERATED_LIB + '/cpp/VersionForVehicleProperty.h'
SCRIPT_PATH = 'hardware/interfaces/automotive/vehicle/tools/generate_annotation_enums.py'
TAB = ' '
diff --git a/automotive/vehicle/tools/generate_emu_metadata/src/com/android/car/tool/EmuMetadataGenerator.java b/automotive/vehicle/tools/generate_emu_metadata/src/com/android/car/tool/EmuMetadataGenerator.java
index 8e12f67..bea5951 100644
--- a/automotive/vehicle/tools/generate_emu_metadata/src/com/android/car/tool/EmuMetadataGenerator.java
+++ b/automotive/vehicle/tools/generate_emu_metadata/src/com/android/car/tool/EmuMetadataGenerator.java
@@ -47,7 +47,9 @@
import java.io.FileOutputStream;
import java.io.FileReader;
import java.lang.reflect.Field;
+import java.text.Collator;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
@@ -93,6 +95,8 @@
private static final String CHECK_FILE_PATH =
"${ANDROID_BUILD_TOP}/hardware/interfaces/automotive/vehicle/aidl/emu_metadata/"
+ "android.hardware.automotive.vehicle-types-meta.json";
+ private static final List<String> ANNOTATIONS =
+ List.of("@change_mode", "@access", "@version", "@data_enum", "@unit");
// Emulator can display at least this many characters before cutting characters.
private static final int MAX_PROPERTY_NAME_LENGTH = 30;
@@ -139,6 +143,7 @@
public String name;
public Integer value;
public final List<String> dataEnums = new ArrayList<>();
+ public String description = "";
ValueField(String name, Integer value) {
this.name = name;
@@ -311,17 +316,38 @@
int propertyId = parseIntEnumField(propertyDef);
// We use the first paragraph as the property's name
- String propertyDescription = doc.getDescription().toText().split("\n\n")[0];
- String name = propertyDescription;
- if (propertyDescription.indexOf("\n") != -1
- || propertyDescription.length() > MAX_PROPERTY_NAME_LENGTH) {
+ String propertyDescription = doc.getDescription().toText();
+ String firstLine = propertyDescription.split("\n\n")[0];
+ String name = firstLine;
+ if (firstLine.indexOf("\n") != -1 || firstLine.length() > MAX_PROPERTY_NAME_LENGTH) {
// The description is too long, we just use the property name.
name = propertyName;
}
+
ValueField field = new ValueField(name, propertyId);
+ String fieldDescription = "";
+ for (String line : propertyDescription.split("\n")) {
+ String stripped = line.strip();
+ // If this is an empty line, starts a new paragraph.
+ if (stripped.isEmpty()) {
+ fieldDescription += "\n";
+ }
+ // Ignore annotation lines.
+ for (int j = 0; j < ANNOTATIONS.size(); j++) {
+ if (stripped.startsWith(ANNOTATIONS.get(j))) {
+ continue;
+ }
+ }
+ // If this is a new line, we concat it with the previous line with a space.
+ if (!fieldDescription.isEmpty()
+ && fieldDescription.charAt(fieldDescription.length() - 1) != '\n') {
+ fieldDescription += " ";
+ }
+ fieldDescription += stripped;
+ }
+ field.description = fieldDescription.strip();
List<JavadocBlockTag> blockTags = doc.getBlockTags();
- List<Integer> dataEnums = new ArrayList<>();
for (int j = 0; j < blockTags.size(); j++) {
String commentTagName = blockTags.get(j).getTagName();
String commentTagContent = blockTags.get(j).getContent().toText();
@@ -344,6 +370,16 @@
enumTypes.add(dataEnum);
}
+ // Sort the enum types based on their packageName, name.
+ // Make sure VehicleProperty is always at the first.
+ Collections.sort(enumTypes.subList(1, enumTypes.size()), (Enum enum1, Enum enum2) -> {
+ var collator = Collator.getInstance();
+ if (enum1.packageName.equals(enum2.packageName)) {
+ return collator.compare(enum1.name, enum2.name);
+ }
+ return collator.compare(enum1.packageName, enum2.packageName);
+ });
+
// Output enumTypes as JSON to output.
JSONArray jsonEnums = new JSONArray();
for (int i = 0; i < enumTypes.size(); i++) {
@@ -370,6 +406,9 @@
// entry.
jsonValueField.put("data_enum", valueField.dataEnums.get(0));
}
+ if (!valueField.description.isEmpty()) {
+ jsonValueField.put("description", valueField.description);
+ }
values.put(jsonValueField);
}
@@ -379,6 +418,7 @@
try (FileOutputStream outputStream = new FileOutputStream(parsedArgs.output)) {
outputStream.write(jsonEnums.toString(4).getBytes());
}
+
System.out.println("Input at folder: " + parsedArgs.inputDir
+ " successfully parsed. Output at: " + parsedArgs.output);
diff --git a/automotive/vehicle/tools/translate_aidl_enums.py b/automotive/vehicle/tools/translate_aidl_enums.py
index d224f6f..a7c1808 100644
--- a/automotive/vehicle/tools/translate_aidl_enums.py
+++ b/automotive/vehicle/tools/translate_aidl_enums.py
@@ -110,7 +110,7 @@
import static com.google.common.truth.Truth.assertWithMessage;
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -228,4 +228,4 @@
f.write("".join(parser.outputMsgCtsTest))
if __name__ == "__main__":
- main()
\ No newline at end of file
+ main()
diff --git a/automotive/vehicle/vts/Android.bp b/automotive/vehicle/vts/Android.bp
index 67d0d34..40aec59 100644
--- a/automotive/vehicle/vts/Android.bp
+++ b/automotive/vehicle/vts/Android.bp
@@ -43,7 +43,7 @@
"vhalclient_defaults",
],
header_libs: [
- "IVehicleGeneratedHeaders",
+ "IVehicleGeneratedHeaders-V3",
],
test_suites: [
"general-tests",
diff --git a/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp b/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp
index 4ea6dfe..608a328 100644
--- a/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp
+++ b/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp
@@ -603,6 +603,7 @@
<< "skip testing";
}
+ // Subscribe to PERF_VEHICLE_SPEED using the max sample rate.
auto client = mVhalClient->getSubscriptionClient(mCallback);
ASSERT_NE(client, nullptr) << "Failed to get subscription client";
SubscribeOptionsBuilder builder(propId);
@@ -616,18 +617,17 @@
", error: %s",
propId, result.error().message().c_str());
- ASSERT_TRUE(mCallback->waitForExpectedEvents(propId, 1, std::chrono::seconds(2)))
- << "Must get at least 1 events within 2 seconds after subscription for rate: "
- << maxSampleRate;
-
// Sleep for 1 seconds to wait for more possible events to arrive.
std::this_thread::sleep_for(std::chrono::seconds(1));
client->unsubscribe({propId});
auto events = mCallback->getEvents(propId);
- if (events.size() == 1) {
- // We only received one event, the value is not changing so nothing to check here.
+ if (events.size() <= 1) {
+ // We received 0 or 1 event, the value is not changing so nothing to check here.
+ // If all VHAL clients are subscribing to PERF_VEHICLE_SPEED with VUR on, then we
+ // will receive 0 event. If there are other VHAL clients subscribing to PERF_VEHICLE_SPEED
+ // with VUR off, then we will receive 1 event which is the initial value.
return;
}
@@ -752,9 +752,15 @@
}
}
- if (readOnlyPresent && !writeOnlyPresent) {
+ if (readOnlyPresent) {
+ ASSERT_FALSE(writeOnlyPresent) << StringPrintf(
+ "Found both READ_ONLY and WRITE_ONLY access modes in area configs, which is not "
+ "supported");
maximalAreaAccessSubset = toInt(VehiclePropertyAccess::READ);
} else if (writeOnlyPresent) {
+ ASSERT_FALSE(readWritePresent) << StringPrintf(
+ "Found both WRITE_ONLY and READ_WRITE access modes in area configs, which is not "
+ "supported");
maximalAreaAccessSubset = toInt(VehiclePropertyAccess::WRITE);
} else if (readWritePresent) {
maximalAreaAccessSubset = toInt(VehiclePropertyAccess::READ_WRITE);
diff --git a/biometrics/OWNERS b/biometrics/OWNERS
index 58998c1..a0a5e51 100644
--- a/biometrics/OWNERS
+++ b/biometrics/OWNERS
@@ -1,8 +1,10 @@
-ilyamaty@google.com
+# Bug component: 879035
+
+include platform/frameworks/base:/services/core/java/com/android/server/biometrics/OWNERS
+
jeffpu@google.com
jbolinger@google.com
joshmccloskey@google.com
diyab@google.com
austindelgado@google.com
spdonghao@google.com
-wenhuiy@google.com
diff --git a/biometrics/common/TEST_MAPPING b/biometrics/common/TEST_MAPPING
new file mode 100644
index 0000000..06e9c53
--- /dev/null
+++ b/biometrics/common/TEST_MAPPING
@@ -0,0 +1,10 @@
+{
+ "postsubmit": [
+ {
+ "name": "android.hardware.biometrics.common.ConfigTest"
+ },
+ {
+ "name": "android.hardware.biometrics.common.WorkerThreadTest"
+ }
+ ]
+}
diff --git a/biometrics/common/config/Config.cpp b/biometrics/common/config/Config.cpp
index 01ae864..49f7cc8 100644
--- a/biometrics/common/config/Config.cpp
+++ b/biometrics/common/config/Config.cpp
@@ -34,7 +34,7 @@
else if (value == "false")
res.emplace(false);
else
- LOG(ERROR) << "ERROR: invalid bool " << value;
+ LOG(FATAL) << "ERROR: invalid bool " << value;
return res;
}
@@ -48,7 +48,11 @@
OptInt32 res;
if (!value.empty()) {
std::int32_t val;
- if (ParseInt(value, &val)) res.emplace(val);
+ if (ParseInt(value, &val)) {
+ res.emplace(val);
+ } else {
+ LOG(FATAL) << "ERROR: Could not parse " << value << " as Int32";
+ }
}
return res;
}
@@ -59,6 +63,8 @@
std::int64_t val = std::strtoull(value.c_str(), nullptr, 10);
if (val != 0LL or (val == 0LL && value == "0")) {
res.emplace(val);
+ } else {
+ LOG(FATAL) << "ERROR: Could not parse " << value << " as Int64";
}
}
return res;
@@ -87,7 +93,7 @@
bool Config::setParam(const std::string& name, const std::string& value) {
auto it = mMap.find(name);
if (it == mMap.end()) {
- LOG(ERROR) << "ERROR: setParam unknown config name " << name;
+ LOG(FATAL) << "ERROR: setParam unknown config name " << name;
return false;
}
LOG(INFO) << "setParam name=" << name << "=" << value;
@@ -102,7 +108,7 @@
ConfigValue Config::getInternal(const std::string& name) {
ConfigValue res;
- auto data = mMap[name];
+ auto& data = mMap[name];
switch (mSource) {
case ConfigSourceType::SOURCE_SYSPROP:
res = data.getter();
@@ -111,10 +117,10 @@
res = data.value;
break;
case ConfigSourceType::SOURCE_FILE:
- LOG(WARNING) << "Unsupported";
+ UNIMPLEMENTED(ERROR) << " File-based config is not supported yet";
break;
default:
- LOG(ERROR) << " wrong srouce type " << (int)mSource;
+ LOG(FATAL) << "Wrong srouce type " << (int)mSource;
break;
}
@@ -126,8 +132,9 @@
}
bool Config::setInternal(const std::string& name, const ConfigValue& val) {
+ LOG(INFO) << "Config::set " << name << " to " << toString(val);
bool res = false;
- auto data = mMap[name];
+ auto& data = mMap[name];
switch (mSource) {
case ConfigSourceType::SOURCE_SYSPROP:
@@ -138,10 +145,10 @@
res = true;
break;
case ConfigSourceType::SOURCE_FILE:
- LOG(WARNING) << "Unsupported";
+ UNIMPLEMENTED(ERROR) << " File-based config is not supported yet";
break;
default:
- LOG(ERROR) << " wrong srouce type " << (int)mSource;
+ LOG(FATAL) << "Wrong srouce type " << (int)mSource;
break;
}
diff --git a/biometrics/common/config/include/config/Config.h b/biometrics/common/config/include/config/Config.h
index 864e164..0367832 100644
--- a/biometrics/common/config/include/config/Config.h
+++ b/biometrics/common/config/include/config/Config.h
@@ -84,6 +84,33 @@
virtual Config::Data* getConfigData(int* size) = 0;
bool setParam(const std::string& name, const std::string& value);
+ void sourcedFromAidl() { mSource = ConfigSourceType::SOURCE_AIDL; }
+ std::string toString(const ConfigValue& v) const {
+ std::ostringstream os;
+ if (std::holds_alternative<OptInt32>(v)) {
+ OptInt32 ov = std::get<OptInt32>(v);
+ if (ov.has_value()) os << ov.value();
+ } else if (std::holds_alternative<OptInt64>(v)) {
+ OptInt64 ov = std::get<OptInt64>(v);
+ if (ov.has_value()) os << ov.value();
+ } else if (std::holds_alternative<OptBool>(v)) {
+ OptBool ov = std::get<OptBool>(v);
+ if (ov.has_value()) os << ov.value();
+ os << std::get<OptBool>(v).value();
+ } else if (std::holds_alternative<OptIntVec>(v)) {
+ for (auto x : std::get<OptIntVec>(v))
+ if (x.has_value()) os << x.value() << " ";
+ }
+ return os.str();
+ }
+ std::string toString() const {
+ std::ostringstream os;
+ for (auto const& [k, v] : mMap) {
+ os << k << ":" << toString(v.value) << std::endl;
+ }
+ return os.str();
+ }
+
ConfigValue parseBool(const std::string& value);
ConfigValue parseString(const std::string& name);
ConfigValue parseInt32(const std::string& value);
diff --git a/biometrics/common/config/tests/ConfigTest.cpp b/biometrics/common/config/tests/ConfigTest.cpp
index d922040..9794b25 100644
--- a/biometrics/common/config/tests/ConfigTest.cpp
+++ b/biometrics/common/config/tests/ConfigTest.cpp
@@ -115,7 +115,7 @@
void SetUp() override { cfg.init(); }
void TearDown() override {}
- void switch2aidl() { cfg.setParam("astring", "astring"); }
+ void switch2aidl() { cfg.sourcedFromAidl(); }
TestConfig cfg;
};
@@ -129,7 +129,6 @@
{"1234", 1234},
{"0", 0},
{"", defval},
- {"xyz", defval},
};
for (int i = 0; i < sizeof(values) / sizeof(values[0]); i++) {
ASSERT_EQ((std::get<OptInt32>(cfg.parseInt32(values[i].strval))).value_or(defval),
@@ -143,8 +142,10 @@
std::string strval;
std::int64_t expval;
} values[] = {
- {"1234", 1234}, {"12345678909876", 12345678909876}, {"0", 0}, {"", defval},
- {"xyz", defval},
+ {"1234", 1234},
+ {"12345678909876", 12345678909876},
+ {"0", 0},
+ {"", defval},
};
for (int i = 0; i < sizeof(values) / sizeof(values[0]); i++) {
ASSERT_EQ((std::get<OptInt64>(cfg.parseInt64(values[i].strval))).value_or(defval),
@@ -160,8 +161,6 @@
} values[] = {
{"false", false},
{"true", true},
- {"", defval},
- {"xyz", defval},
};
for (int i = 0; i < sizeof(values) / sizeof(values[0]); i++) {
ASSERT_EQ((std::get<OptBool>(cfg.parseBool(values[i].strval))).value_or(defval),
@@ -174,9 +173,7 @@
struct {
std::string strval;
std::vector<std::optional<int>> expval;
- } values[] = {
- {"1", {1}}, {"1,2,3", {1, 2, 3}}, {"1,2,b", defval}, {"", defval}, {"xyz", defval},
- };
+ } values[] = {{"1", {1}}, {"1,2,3", {1, 2, 3}}, {"1,2,b", defval}, {"", defval}};
for (int i = 0; i < sizeof(values) / sizeof(values[0]); i++) {
ASSERT_EQ(std::get<OptIntVec>(cfg.parseIntVec(values[i].strval)), values[i].expval);
}
@@ -255,12 +252,4 @@
EXPECT_EQ(cfg.getopt<OptIntVec>("avector"), val_avector_new);
}
-TEST_F(ConfigTest, setParam) {
- ASSERT_TRUE(cfg.setParam("aint32", "789"));
- ASSERT_EQ(cfg.get<std::int32_t>("aint32"), 789);
- ASSERT_TRUE(cfg.setParam("avector", "7,8,9,10"));
- OptIntVec val_avector_new{7, 8, 9, 10};
- EXPECT_EQ(cfg.getopt<OptIntVec>("avector"), val_avector_new);
- ASSERT_FALSE(cfg.setParam("unknown", "any"));
-}
} // namespace aidl::android::hardware::biometrics
diff --git a/biometrics/face/aidl/TEST_MAPPING b/biometrics/face/aidl/TEST_MAPPING
new file mode 100644
index 0000000..817fd01
--- /dev/null
+++ b/biometrics/face/aidl/TEST_MAPPING
@@ -0,0 +1,13 @@
+{
+ "postsubmit": [
+ {
+ "name": "android.hardware.biometrics.face.FakeFaceEngineTest"
+ },
+ {
+ "name": "android.hardware.biometrics.face.FakeLockoutTrackerTest"
+ },
+ {
+ "name": "VtsHalBiometricsFaceTargetTest"
+ }
+ ]
+}
diff --git a/biometrics/fingerprint/aidl/Android.bp b/biometrics/fingerprint/aidl/Android.bp
index 282a702..a395c01 100644
--- a/biometrics/fingerprint/aidl/Android.bp
+++ b/biometrics/fingerprint/aidl/Android.bp
@@ -57,5 +57,5 @@
},
],
- frozen: true,
+ frozen: false,
}
diff --git a/biometrics/fingerprint/aidl/TEST_MAPPING b/biometrics/fingerprint/aidl/TEST_MAPPING
new file mode 100644
index 0000000..84cca2f
--- /dev/null
+++ b/biometrics/fingerprint/aidl/TEST_MAPPING
@@ -0,0 +1,22 @@
+{
+ "postsubmit": [
+ {
+ "name": "android.hardware.biometrics.fingerprint.FakeFingerprintEngineTest"
+ },
+ {
+ "name": "android.hardware.biometrics.fingerprint.FakeFingerprintEngineUdfpsTest"
+ },
+ {
+ "name": "android.hardware.biometrics.fingerprint.FakeLockoutTrackerTest"
+ },
+ {
+ "name": "android.hardware.biometrics.fingerprint.SessionTest"
+ },
+ {
+ "name": "android.hardware.biometrics.fingerprint.VirtualHalTest"
+ },
+ {
+ "name": "VtsHalBiometricsFingerprintTargetTest"
+ }
+ ]
+}
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
new file mode 100644
index 0000000..c1dc51c
--- /dev/null
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.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.biometrics.fingerprint;
+/* @hide */
+@VintfStability
+union AcquiredInfoAndVendorCode {
+ android.hardware.biometrics.fingerprint.AcquiredInfo acquiredInfo = android.hardware.biometrics.fingerprint.AcquiredInfo.UNKNOWN;
+ int vendorCode;
+}
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl
new file mode 100644
index 0000000..173ac17
--- /dev/null
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.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.biometrics.fingerprint;
+/* @hide */
+@VintfStability
+parcelable EnrollmentProgressStep {
+ int durationMs;
+ android.hardware.biometrics.fingerprint.AcquiredInfoAndVendorCode[] acquiredInfoAndVendorCodes;
+}
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IVirtualHal.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IVirtualHal.aidl
new file mode 100644
index 0000000..33ae83c
--- /dev/null
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IVirtualHal.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make 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.biometrics.fingerprint;
+/* @hide */
+@VintfStability
+interface IVirtualHal {
+ oneway void setEnrollments(in int[] id);
+ oneway void setEnrollmentHit(in int hit_id);
+ oneway void setNextEnrollment(in android.hardware.biometrics.fingerprint.NextEnrollment next_enrollment);
+ oneway void setAuthenticatorId(in long id);
+ oneway void setChallenge(in long challenge);
+ oneway void setOperationAuthenticateFails(in boolean fail);
+ oneway void setOperationAuthenticateLatency(in int[] latencyMs);
+ oneway void setOperationAuthenticateDuration(in int durationMs);
+ oneway void setOperationAuthenticateError(in int error);
+ oneway void setOperationAuthenticateAcquired(in android.hardware.biometrics.fingerprint.AcquiredInfoAndVendorCode[] acquired);
+ oneway void setOperationEnrollError(in int error);
+ oneway void setOperationEnrollLatency(in int[] latencyMs);
+ oneway void setOperationDetectInteractionLatency(in int[] latencyMs);
+ oneway void setOperationDetectInteractionError(in int error);
+ oneway void setOperationDetectInteractionDuration(in int durationMs);
+ oneway void setOperationDetectInteractionAcquired(in android.hardware.biometrics.fingerprint.AcquiredInfoAndVendorCode[] acquired);
+ oneway void setLockout(in boolean lockout);
+ oneway void setLockoutEnable(in boolean enable);
+ oneway void setLockoutTimedThreshold(in int threshold);
+ oneway void setLockoutTimedDuration(in int durationMs);
+ oneway void setLockoutPermanentThreshold(in int threshold);
+ oneway void resetConfigurations();
+ oneway void setType(in android.hardware.biometrics.fingerprint.FingerprintSensorType type);
+ oneway void setSensorId(in int id);
+ oneway void setSensorStrength(in android.hardware.biometrics.common.SensorStrength strength);
+ oneway void setMaxEnrollmentPerUser(in int max);
+ oneway void setSensorLocation(in android.hardware.biometrics.fingerprint.SensorLocation loc);
+ oneway void setNavigationGuesture(in boolean v);
+ oneway void setDetectInteraction(in boolean v);
+ oneway void setDisplayTouch(in boolean v);
+ oneway void setControlIllumination(in boolean v);
+ const int STATUS_INVALID_PARAMETER = 1;
+}
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/NextEnrollment.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/NextEnrollment.aidl
new file mode 100644
index 0000000..75ed070
--- /dev/null
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/NextEnrollment.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.biometrics.fingerprint;
+/* @hide */
+@VintfStability
+parcelable NextEnrollment {
+ int id;
+ android.hardware.biometrics.fingerprint.EnrollmentProgressStep[] progressSteps;
+ boolean result = true;
+}
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
new file mode 100644
index 0000000..c7be950
--- /dev/null
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.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.biometrics.fingerprint;
+
+import android.hardware.biometrics.fingerprint.AcquiredInfo;
+
+/**
+ * @hide
+ */
+@VintfStability
+union AcquiredInfoAndVendorCode {
+ /**
+ * Acquired info as specified in AcqauiredInfo.aidl
+ */
+ AcquiredInfo acquiredInfo = AcquiredInfo.UNKNOWN;
+
+ /**
+ * Vendor specific code
+ */
+ int vendorCode;
+}
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl
new file mode 100644
index 0000000..bf038f6
--- /dev/null
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.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.biometrics.fingerprint;
+
+import android.hardware.biometrics.fingerprint.AcquiredInfoAndVendorCode;
+
+/**
+ * @hide
+ */
+@VintfStability
+parcelable EnrollmentProgressStep {
+ /**
+ * The duration of the enrollment step in milli-seconds
+ */
+ int durationMs;
+
+ /**
+ * The sequence of acquired info and vendor code to be issued by HAL during the step.
+ * The codes are evenly spreaded over the duration
+ */
+ AcquiredInfoAndVendorCode[] acquiredInfoAndVendorCodes;
+}
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IVirtualHal.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IVirtualHal.aidl
new file mode 100644
index 0000000..cb9135e
--- /dev/null
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IVirtualHal.aidl
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.biometrics.fingerprint;
+
+import android.hardware.biometrics.common.SensorStrength;
+import android.hardware.biometrics.fingerprint.AcquiredInfoAndVendorCode;
+import android.hardware.biometrics.fingerprint.FingerprintSensorType;
+import android.hardware.biometrics.fingerprint.NextEnrollment;
+import android.hardware.biometrics.fingerprint.SensorLocation;
+
+/**
+ * @hide
+ */
+@VintfStability
+oneway interface IVirtualHal {
+ /**
+ * The operation failed due to invalid input parameters, the error messages should
+ * gives more details
+ */
+ const int STATUS_INVALID_PARAMETER = 1;
+
+ /**
+ * Set Fingerprint Virtual HAL behavior parameters
+ */
+
+ /**
+ * setEnrollments
+ *
+ * Set the ids of the fingerprints that were currently enrolled in the Virtual HAL,
+ *
+ * @param ids ids can contain 1 or more ids, each must be larger than 0
+ */
+ void setEnrollments(in int[] id);
+
+ /**
+ * setEnrollmentHit
+ *
+ * Set current fingerprint enrollment ids in Fingerprint Virtual HAL,
+ *
+ * @param ids ids can contain 1 or more ids, each must be larger than 0
+ */
+ void setEnrollmentHit(in int hit_id);
+
+ /**
+ * setNextEnrollment
+ *
+ * Set the next enrollment behavior
+ *
+ * @param next_enrollment specifies enrollment id, progress stages and final result
+ */
+ void setNextEnrollment(in NextEnrollment next_enrollment);
+
+ /**
+ * setAuthenticatorId
+ *
+ * Set authenticator id in virtual HAL, the id is returned in ISession#getAuthenticatorId() call
+ *
+ * @param id authenticator id value, only applied to the sensor with SensorStrength::STRONG.
+ */
+ void setAuthenticatorId(in long id);
+
+ /**
+ * setChallenge
+ *
+ * Set the challenge generated by the virtual HAL, which is returned in
+ * ISessionCallback#onChallengeGenerated()
+ *
+ * @param challenge
+ */
+ void setChallenge(in long challenge);
+
+ /**
+ * setOperationAuthenticateFails
+ *
+ * Set whether to force authentication to fail. If true, the virtual hal will report failure on
+ * authentication attempt until it is set to false
+ *
+ * @param fail if true, then the next authentication will fail
+ */
+ void setOperationAuthenticateFails(in boolean fail);
+
+ /**
+ * setOperationAuthenticateLatency
+ *
+ * Set authentication latency in the virtual hal in a fixed value (single element) or random
+ * values (two elements representing the bound values)
+ * The latency simulates the delay from the time framework requesting HAL to authetication to
+ * the time when HAL is ready to perform authentication operations.
+ *
+ * This method fails with STATUS_INVALID_PARAMETERS if the passed-in array falls in any of
+ * the following conditions
+ * 1. the array contains no element
+ * 2. the array contains more than two elements
+ * 3. the array contains any negative value
+ * The accompanying error message gives more detail
+ *
+ * @param latencyMs[] value(s) are in milli-seconds
+ */
+ void setOperationAuthenticateLatency(in int[] latencyMs);
+
+ /**
+ * setOperationAuthenticateDuration
+ *
+ * Set authentication duration covering the HAL authetication from start to end, including
+ * fingerprint capturing, and matching, acquired info reporting. In case a sequence of acquired
+ * info code are specified via setOperationAuthenticateAcquired(), the reporting is evenly
+ * distributed over the duration.
+ *
+ * This method fails with STATUS_INVALID_PARAMETERS if the passed-in value is negative
+ *
+ * @param duration value is in milli-seconds
+ */
+ void setOperationAuthenticateDuration(in int durationMs);
+
+ /**
+ * setOperationAuthenticateError
+ *
+ * Force authentication to error out for non-zero error
+ * Check hardware/interfaces/biometrics/fingerprint/aidl/default/README.md for valid error codes
+ *
+ * @param error if error < 1000
+ * non-vendor error
+ * else
+ * vendor error
+ */
+ void setOperationAuthenticateError(in int error);
+
+ /**
+ * setOperationAuthenticateAcquired
+ *
+ * Set one of more acquired info codes for the virtual hal to report during authentication
+ * Check hardware/interfaces/biometrics/fingerprint/aidl/default/README.md for valid acquired
+ * info codes
+ *
+ * @param acquired[], one or more acquired info codes
+ */
+ void setOperationAuthenticateAcquired(in AcquiredInfoAndVendorCode[] acquired);
+
+ /**
+ * setOperationEnrollError
+ *
+ * Force enrollment operation to error out for non-zero error
+ * Check hardware/interfaces/biometrics/fingerprint/aidl/default/README.md for valid error codes
+ *
+ * @param error if error < 1000
+ * non-vendor error
+ * else
+ * vendor error
+ */
+ void setOperationEnrollError(in int error);
+
+ /**
+ * setOperationEnrollLatency
+ *
+ * Set enrollment latency in the virtual hal in a fixed value (single element) or random
+ * values (two elements representing the bound values)
+ * The latency simulates the delay from the time framework requesting HAL to enroll to the
+ * time when HAL is ready to perform enrollment operations.
+ *
+ * This method fails with STATUS_INVALID_PARAMETERS if the passed-in array falls in any of
+ * the following conditions
+ * 1. the array contains no element
+ * 2. the array contains more than two elements
+ * 3. the array contains any negative value
+ * The accompanying error message gives more detail
+ *
+ * @param latencyMs[] value(s) are in milli-seconds
+ */
+ void setOperationEnrollLatency(in int[] latencyMs);
+
+ /**
+ * setOperationDetectInteractionLatency
+ *
+ * Set detect interaction latency in the virtual hal in a fixed value (single element) or random
+ * values (two elements representing the bound values)
+ * The latency simulates the delay from the time framework requesting HAL to detect interaction
+ * to the time when HAL is ready to perform detect interaction operations.
+ *
+ * This method fails with STATUS_INVALID_PARAMETERS if the passed-in array falls in any of
+ * the following conditions
+ * 1. the array contains no element
+ * 2. the array contains more than two elements
+ * 3. the array contains any negative value
+ * The accompanying error message gives more detail
+ *
+ * @param latencyMs[] value(s) are in milli-seconds
+ */
+ void setOperationDetectInteractionLatency(in int[] latencyMs);
+
+ /**
+ * setOperationDetectInteractionError
+ *
+ * Force detect interaction operation to error out for non-zero error
+ * Check hardware/interfaces/biometrics/fingerprint/aidl/default/README.md for valid error codes
+ *
+ * @param error if error < 1000
+ * non-vendor error
+ * else
+ * vendor error
+ */
+ void setOperationDetectInteractionError(in int error);
+
+ /**
+ * setOperationDetectInteractionDuration
+ *
+ * Set detect interaction duration covering the HAL authetication from start to end, including
+ * fingerprint detect and acquired info reporting. In case a sequence of acquired info code are
+ * specified via setOperationDetectInteractionAcquired(), the reporting is evenly distributed
+ * over the duration.
+ *
+ * This method fails with STATUS_INVALID_PARAMETERS if the passed-in value is negative
+ *
+ * @param duration value is in milli-seconds
+ */
+ void setOperationDetectInteractionDuration(in int durationMs);
+
+ /**
+ * setOperationDetectInteractionAcquired
+ *
+ * Set one of more acquired info codes for the virtual hal to report during detect interaction
+ * Check hardware/interfaces/biometrics/fingerprint/aidl/default/README.md for valid acquired
+ * info codes
+ *
+ * @param acquired[], one or more acquired info codes
+ */
+ void setOperationDetectInteractionAcquired(in AcquiredInfoAndVendorCode[] acquired);
+
+ /**
+ * setLockout
+ *
+ * Whether to force to lockout on authentcation operation. If true, the virtual hal will report
+ * permanent lockout in processing authentication requrest, regardless of whether
+ * setLockoutEnable(true) is called or not.
+ *
+ * @param lockout, set to true if lockout is desired
+ */
+ void setLockout(in boolean lockout);
+
+ /**
+ * setLockoutEnable
+ *
+ * Whether to enable authentication-fail-based lockout tracking or not. The lock tracking
+ * includes both timed-based (aka temporary) lockout and permanent lockout.
+ *
+ * @param enable, set true to enable the lockout tracking
+ */
+ void setLockoutEnable(in boolean enable);
+
+ /**
+ * setLockoutTimedThreshold
+ *
+ * Set the number of consecutive authentication failures that triggers the timed-based lock to
+ * occur
+ *
+ * This method fails with STATUS_INVALID_PARAMETERS if the passed-in value is negative
+ *
+ * @param threshold, the number of consecutive failures
+ */
+ void setLockoutTimedThreshold(in int threshold);
+
+ /**
+ * setLockoutTimedDuration
+ *
+ * Set the duration to expire timed-based lock during which there is no authentication failure
+ *
+ * This method fails with STATUS_INVALID_PARAMETERS if the passed-in value is negative
+ *
+ * @param duration, in milli-seconds
+ */
+ void setLockoutTimedDuration(in int durationMs);
+
+ /**
+ * setLockoutPermanentThreshold
+ *
+ * Set the number of consecutive authentication failures that triggers the permanent lock to
+ * occur
+ *
+ * This method fails with STATUS_INVALID_PARAMETERS if the passed-in value is negative
+ *
+ * @param threshold, the number of consecutive failures
+ */
+ void setLockoutPermanentThreshold(in int threshold);
+
+ /**
+ * resetConfigurations
+ *
+ * Reset all virtual hal configurations to default values
+ */
+ void resetConfigurations();
+
+ /**
+ * The following functions are used to configure Fingerprint Virtual HAL sensor properties
+ * refer to SensorProps.aidl and CommonProps.aidl for details of each property
+ */
+ void setType(in FingerprintSensorType type);
+ void setSensorId(in int id);
+ void setSensorStrength(in SensorStrength strength);
+ void setMaxEnrollmentPerUser(in int max);
+ void setSensorLocation(in SensorLocation loc);
+ void setNavigationGuesture(in boolean v);
+ void setDetectInteraction(in boolean v);
+ void setDisplayTouch(in boolean v);
+ void setControlIllumination(in boolean v);
+}
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/NextEnrollment.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/NextEnrollment.aidl
new file mode 100644
index 0000000..4b50850
--- /dev/null
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/NextEnrollment.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.biometrics.fingerprint;
+
+/**
+ * @hide
+ */
+@VintfStability
+parcelable NextEnrollment {
+ /**
+ * Identifier of the next enrollment if successful
+ */
+ int id;
+
+ /**
+ * Specification of the progress steps of the next enrollment, each step consists of duration
+ * and sequence of acquired info codes to be generated by HAL.
+ * See EnrollmentProgressStep.aidl for more details
+ */
+ android.hardware.biometrics.fingerprint.EnrollmentProgressStep[] progressSteps;
+
+ /**
+ * Success or failure of the next enrollment
+ */
+ boolean result = true;
+}
diff --git a/biometrics/fingerprint/aidl/default/Android.bp b/biometrics/fingerprint/aidl/default/Android.bp
index 2a73f5d..9b72c87 100644
--- a/biometrics/fingerprint/aidl/default/Android.bp
+++ b/biometrics/fingerprint/aidl/default/Android.bp
@@ -22,6 +22,7 @@
"Fingerprint.cpp",
"Session.cpp",
"FingerprintConfig.cpp",
+ "VirtualHal.cpp",
"main.cpp",
],
stl: "c++_static",
@@ -32,7 +33,7 @@
static_libs: [
"libandroid.hardware.biometrics.fingerprint.VirtualProps",
"libbase",
- "android.hardware.biometrics.fingerprint-V4-ndk",
+ "android.hardware.biometrics.fingerprint-V5-ndk",
"android.hardware.biometrics.common-V4-ndk",
"android.hardware.biometrics.common.thread",
"android.hardware.biometrics.common.util",
@@ -62,7 +63,7 @@
],
static_libs: [
"libandroid.hardware.biometrics.fingerprint.VirtualProps",
- "android.hardware.biometrics.fingerprint-V4-ndk",
+ "android.hardware.biometrics.fingerprint-V5-ndk",
"android.hardware.biometrics.common-V4-ndk",
"android.hardware.keymaster-V4-ndk",
"android.hardware.biometrics.common.util",
@@ -90,7 +91,7 @@
],
static_libs: [
"libandroid.hardware.biometrics.fingerprint.VirtualProps",
- "android.hardware.biometrics.fingerprint-V4-ndk",
+ "android.hardware.biometrics.fingerprint-V5-ndk",
"android.hardware.biometrics.common-V4-ndk",
"android.hardware.keymaster-V4-ndk",
"android.hardware.biometrics.common.util",
@@ -116,7 +117,7 @@
],
static_libs: [
"libandroid.hardware.biometrics.fingerprint.VirtualProps",
- "android.hardware.biometrics.fingerprint-V4-ndk",
+ "android.hardware.biometrics.fingerprint-V5-ndk",
"android.hardware.biometrics.common-V4-ndk",
"android.hardware.keymaster-V4-ndk",
"android.hardware.biometrics.common.util",
@@ -144,7 +145,7 @@
],
static_libs: [
"libandroid.hardware.biometrics.fingerprint.VirtualProps",
- "android.hardware.biometrics.fingerprint-V4-ndk",
+ "android.hardware.biometrics.fingerprint-V5-ndk",
"android.hardware.biometrics.common-V4-ndk",
"android.hardware.keymaster-V4-ndk",
"android.hardware.biometrics.common.util",
@@ -156,6 +157,44 @@
require_root: true,
}
+cc_test {
+ name: "android.hardware.biometrics.fingerprint.VirtualHalTest",
+ local_include_dirs: ["include"],
+ srcs: [
+ "tests/VirtualHalTest.cpp",
+ "Session.cpp",
+ "VirtualHal.cpp",
+ "FakeFingerprintEngineRear.cpp",
+ "FakeFingerprintEngineUdfps.cpp",
+ "FakeFingerprintEngineSide.cpp",
+ "FakeFingerprintEngine.cpp",
+ "FakeLockoutTracker.cpp",
+ "Fingerprint.cpp",
+ "FingerprintConfig.cpp",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ ],
+ static_libs: [
+ "libandroid.hardware.biometrics.fingerprint.VirtualProps",
+ "android.hardware.biometrics.fingerprint-V5-ndk",
+ "android.hardware.biometrics.common-V4-ndk",
+ "android.hardware.keymaster-V4-ndk",
+ "android.hardware.biometrics.common.util",
+ "android.hardware.biometrics.common.thread",
+ "android.hardware.biometrics.common.config",
+ ],
+ product_variables: {
+ debuggable: {
+ cflags: ["-DFPS_DEBUGGABLE"],
+ },
+ },
+ vendor: true,
+ test_suites: ["general-tests"],
+ require_root: true,
+}
+
sysprop_library {
name: "android.hardware.biometrics.fingerprint.VirtualProps",
srcs: ["fingerprint.sysprop"],
diff --git a/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp b/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
index 8b8d046..67eb837 100644
--- a/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
+++ b/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
@@ -544,6 +544,10 @@
void FakeFingerprintEngine::waitForFingerDown(ISessionCallback* cb,
const std::future<void>& cancel) {
+ if (mFingerIsDown) {
+ LOG(WARNING) << "waitForFingerDown: mFingerIsDown==true already!";
+ }
+
while (!mFingerIsDown) {
if (shouldCancel(cancel)) {
LOG(ERROR) << "waitForFingerDown, Fail: cancel";
diff --git a/biometrics/fingerprint/aidl/default/Fingerprint.cpp b/biometrics/fingerprint/aidl/default/Fingerprint.cpp
index dded54b..3055da1 100644
--- a/biometrics/fingerprint/aidl/default/Fingerprint.cpp
+++ b/biometrics/fingerprint/aidl/default/Fingerprint.cpp
@@ -125,6 +125,8 @@
}
::android::base::WriteStringToFd(mEngine->toString(), fd);
+ ::android::base::WriteStringToFd(Fingerprint::cfg().toString(), fd);
+
fsync(fd);
return STATUS_OK;
}
@@ -171,7 +173,7 @@
}
void Fingerprint::clearConfigSysprop() {
- LOG(INFO) << __func__ << ": clear all systprop configuration";
+ LOG(INFO) << __func__ << ": clear all sysprop configuration";
#define RESET_CONFIG_O(__NAME__) \
if (FingerprintHalProperties::__NAME__()) FingerprintHalProperties::__NAME__(std::nullopt)
#define RESET_CONFIG_V(__NAME__) \
@@ -209,4 +211,19 @@
RESET_CONFIG_O(lockout_permanent_threshold);
}
+const char* Fingerprint::type2String(FingerprintSensorType type) {
+ switch (type) {
+ case FingerprintSensorType::REAR:
+ return "rear";
+ case FingerprintSensorType::POWER_BUTTON:
+ return "side";
+ case FingerprintSensorType::UNDER_DISPLAY_OPTICAL:
+ return "udfps";
+ case FingerprintSensorType::UNDER_DISPLAY_ULTRASONIC:
+ return "udfps";
+ default:
+ return "unknown";
+ }
+}
+
} // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/VirtualHal.cpp b/biometrics/fingerprint/aidl/default/VirtualHal.cpp
new file mode 100644
index 0000000..e107d2f
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/VirtualHal.cpp
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <unordered_map>
+
+#include "VirtualHal.h"
+
+#include <android-base/logging.h>
+
+#include "util/CancellationSignal.h"
+
+#undef LOG_TAG
+#define LOG_TAG "FingerprintVirtualHalAidl"
+
+namespace aidl::android::hardware::biometrics::fingerprint {
+
+using Tag = AcquiredInfoAndVendorCode::Tag;
+
+::ndk::ScopedAStatus VirtualHal::setEnrollments(const std::vector<int32_t>& enrollments) {
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().setopt<OptIntVec>("enrollments", intVec2OptIntVec(enrollments));
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setEnrollmentHit(int32_t enrollment_hit) {
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().set<std::int32_t>("enrollment_hit", enrollment_hit);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setNextEnrollment(
+ const ::aidl::android::hardware::biometrics::fingerprint::NextEnrollment& next_enrollment) {
+ Fingerprint::cfg().sourcedFromAidl();
+ std::ostringstream os;
+ os << next_enrollment.id << ":";
+
+ int stepSize = next_enrollment.progressSteps.size();
+ for (int i = 0; i < stepSize; i++) {
+ auto& step = next_enrollment.progressSteps[i];
+ os << step.durationMs;
+ int acSize = step.acquiredInfoAndVendorCodes.size();
+ for (int j = 0; j < acSize; j++) {
+ if (j == 0) os << "-[";
+ auto& acquiredInfoAndVendorCode = step.acquiredInfoAndVendorCodes[j];
+ if (acquiredInfoAndVendorCode.getTag() == AcquiredInfoAndVendorCode::vendorCode)
+ os << acquiredInfoAndVendorCode.get<Tag::vendorCode>();
+ else if (acquiredInfoAndVendorCode.getTag() == AcquiredInfoAndVendorCode::acquiredInfo)
+ os << (int)acquiredInfoAndVendorCode.get<Tag::acquiredInfo>();
+ else
+ LOG(FATAL) << "ERROR: wrong AcquiredInfoAndVendorCode union tag";
+ if (j == acSize - 1)
+ os << "]";
+ else
+ os << ",";
+ }
+ if (i == stepSize - 1)
+ os << ":";
+ else
+ os << ",";
+ }
+
+ os << (next_enrollment.result ? "true" : "false");
+ Fingerprint::cfg().set<std::string>("next_enrollment", os.str());
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setAuthenticatorId(int64_t in_id) {
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().set<int64_t>("authenticator_id", in_id);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setChallenge(int64_t in_challenge) {
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().set<int64_t>("challenge", in_challenge);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateFails(bool in_fail) {
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().set<bool>("operation_authenticate_fails", in_fail);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateLatency(
+ const std::vector<int32_t>& in_latency) {
+ ndk::ScopedAStatus status = sanityCheckLatency(in_latency);
+ if (!status.isOk()) {
+ return status;
+ }
+
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().setopt<OptIntVec>("operation_authenticate_latency",
+ intVec2OptIntVec(in_latency));
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateDuration(int32_t in_duration) {
+ if (in_duration < 0) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IVirtualHal::STATUS_INVALID_PARAMETER, "Error: duration can not be negative"));
+ }
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().set<int32_t>("operation_authenticate_duration", in_duration);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateError(int32_t in_error) {
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().set<int32_t>("operation_authenticate_error", in_error);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateAcquired(
+ const std::vector<AcquiredInfoAndVendorCode>& in_acquired) {
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().setopt<OptIntVec>("operation_authenticate_acquired",
+ acquiredInfoVec2OptIntVec(in_acquired));
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setOperationEnrollError(int32_t in_error) {
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().set<int32_t>("operation_enroll_error", in_error);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setOperationEnrollLatency(const std::vector<int32_t>& in_latency) {
+ ndk::ScopedAStatus status = sanityCheckLatency(in_latency);
+ if (!status.isOk()) {
+ return status;
+ }
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().setopt<OptIntVec>("operation_enroll_latency", intVec2OptIntVec(in_latency));
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setOperationDetectInteractionLatency(
+ const std::vector<int32_t>& in_latency) {
+ ndk::ScopedAStatus status = sanityCheckLatency(in_latency);
+ if (!status.isOk()) {
+ return status;
+ }
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().setopt<OptIntVec>("operation_detect_interact_latency",
+ intVec2OptIntVec(in_latency));
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setOperationDetectInteractionError(int32_t in_error) {
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().set<int32_t>("operation_detect_interaction_error", in_error);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setOperationDetectInteractionDuration(int32_t in_duration) {
+ if (in_duration < 0) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IVirtualHal::STATUS_INVALID_PARAMETER, "Error: duration can not be negative"));
+ }
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().set<int32_t>("operation_detect_interaction_duration", in_duration);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setOperationDetectInteractionAcquired(
+ const std::vector<AcquiredInfoAndVendorCode>& in_acquired) {
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().setopt<OptIntVec>("operation_detect_interaction_acquired",
+ acquiredInfoVec2OptIntVec(in_acquired));
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setLockout(bool in_lockout) {
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().set<bool>("lockout", in_lockout);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setLockoutEnable(bool in_enable) {
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().set<bool>("lockout_enable", in_enable);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setLockoutTimedThreshold(int32_t in_threshold) {
+ if (in_threshold < 0) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IVirtualHal::STATUS_INVALID_PARAMETER, "Error: threshold can not be negative"));
+ }
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().set<int32_t>("lockout_timed_threshold", in_threshold);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setLockoutTimedDuration(int32_t in_duration) {
+ if (in_duration < 0) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IVirtualHal::STATUS_INVALID_PARAMETER, "Error: duration can not be negative"));
+ }
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().set<int32_t>("lockout_timed_duration", in_duration);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setLockoutPermanentThreshold(int32_t in_threshold) {
+ if (in_threshold < 0) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IVirtualHal::STATUS_INVALID_PARAMETER, "Error: threshold can not be negative"));
+ }
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().set<int32_t>("lockout_permanent_threshold", in_threshold);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::resetConfigurations() {
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().init();
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setType(
+ ::aidl::android::hardware::biometrics::fingerprint::FingerprintSensorType in_type) {
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().set<std::string>("type", Fingerprint::type2String(in_type));
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setSensorId(int32_t in_id) {
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().set<int32_t>("sensor_id", in_id);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setSensorStrength(SensorStrength in_strength) {
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().set<int32_t>("sensor_strength", (int32_t)in_strength);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setMaxEnrollmentPerUser(int32_t in_max) {
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().set<int32_t>("max_enrollments", in_max);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setSensorLocation(const SensorLocation& in_loc) {
+ std::string str = std::to_string(in_loc.sensorLocationX) + ":" +
+ std::to_string(in_loc.sensorLocationY) + ":" +
+ std::to_string(in_loc.sensorRadius);
+ ;
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().set<std::string>("sensor_location", str);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setNavigationGuesture(bool in_v) {
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().set<bool>("navigation_guesture", in_v);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setDetectInteraction(bool in_v) {
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().set<bool>("detect_interaction", in_v);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setDisplayTouch(bool in_v) {
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().set<bool>("display_touch", in_v);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setControlIllumination(bool in_v) {
+ Fingerprint::cfg().sourcedFromAidl();
+ Fingerprint::cfg().set<bool>("control_illumination", in_v);
+ return ndk::ScopedAStatus::ok();
+}
+
+OptIntVec VirtualHal::intVec2OptIntVec(const std::vector<int32_t>& in_vec) {
+ OptIntVec optIntVec;
+ std::transform(in_vec.begin(), in_vec.end(), std::back_inserter(optIntVec),
+ [](int value) { return std::optional<int>(value); });
+ return optIntVec;
+}
+
+OptIntVec VirtualHal::acquiredInfoVec2OptIntVec(
+ const std::vector<AcquiredInfoAndVendorCode>& in_vec) {
+ OptIntVec optIntVec;
+ std::transform(in_vec.begin(), in_vec.end(), std::back_inserter(optIntVec),
+ [](AcquiredInfoAndVendorCode ac) {
+ int value;
+ if (ac.getTag() == AcquiredInfoAndVendorCode::acquiredInfo)
+ value = (int)ac.get<Tag::acquiredInfo>();
+ else if (ac.getTag() == AcquiredInfoAndVendorCode::vendorCode)
+ value = ac.get<Tag::vendorCode>();
+ else
+ LOG(FATAL) << "ERROR: wrong AcquiredInfoAndVendorCode tag";
+ return std::optional<int>(value);
+ });
+ return optIntVec;
+}
+
+::ndk::ScopedAStatus VirtualHal::sanityCheckLatency(const std::vector<int32_t>& in_latency) {
+ if (in_latency.size() == 0 || in_latency.size() > 2) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IVirtualHal::STATUS_INVALID_PARAMETER,
+ "Error: input input array must contain 1 or 2 elements"));
+ }
+
+ for (auto x : in_latency) {
+ if (x < 0) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IVirtualHal::STATUS_INVALID_PARAMETER,
+ "Error: input data must not be negative"));
+ }
+ }
+
+ return ndk::ScopedAStatus::ok();
+}
+
+} // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/fingerprint-example.xml b/biometrics/fingerprint/aidl/default/fingerprint-example.xml
index 827813f..ee529e9 100644
--- a/biometrics/fingerprint/aidl/default/fingerprint-example.xml
+++ b/biometrics/fingerprint/aidl/default/fingerprint-example.xml
@@ -1,7 +1,7 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.biometrics.fingerprint</name>
- <version>4</version>
+ <version>5</version>
<fqname>IFingerprint/virtual</fqname>
</hal>
</manifest>
diff --git a/biometrics/fingerprint/aidl/default/include/Fingerprint.h b/biometrics/fingerprint/aidl/default/include/Fingerprint.h
index 1576f07..90f89cb 100644
--- a/biometrics/fingerprint/aidl/default/include/Fingerprint.h
+++ b/biometrics/fingerprint/aidl/default/include/Fingerprint.h
@@ -40,6 +40,7 @@
std::shared_ptr<ISession>* out) override;
binder_status_t dump(int fd, const char** args, uint32_t numArgs);
binder_status_t handleShellCommand(int in, int out, int err, const char** argv, uint32_t argc);
+ bool connected() { return mEngine != nullptr; }
static FingerprintConfig& cfg() {
static FingerprintConfig* cfg = nullptr;
@@ -49,9 +50,10 @@
}
return *cfg;
}
+ void resetConfigToDefault();
+ static const char* type2String(FingerprintSensorType type);
private:
- void resetConfigToDefault();
void onHelp(int);
void onSimFingerDown();
void clearConfigSysprop();
diff --git a/biometrics/fingerprint/aidl/default/include/VirtualHal.h b/biometrics/fingerprint/aidl/default/include/VirtualHal.h
new file mode 100644
index 0000000..e5f62fc
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/include/VirtualHal.h
@@ -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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/biometrics/fingerprint/BnVirtualHal.h>
+
+#include "Fingerprint.h"
+
+namespace aidl::android::hardware::biometrics::fingerprint {
+
+class VirtualHal : public BnVirtualHal {
+ public:
+ VirtualHal(Fingerprint* fp) : mFp(fp) {}
+
+ ::ndk::ScopedAStatus setEnrollments(const std::vector<int32_t>& in_id) override;
+ ::ndk::ScopedAStatus setEnrollmentHit(int32_t in_hit_id) override;
+ ::ndk::ScopedAStatus setNextEnrollment(
+ const ::aidl::android::hardware::biometrics::fingerprint::NextEnrollment&
+ in_next_enrollment) override;
+ ::ndk::ScopedAStatus setAuthenticatorId(int64_t in_id) override;
+ ::ndk::ScopedAStatus setChallenge(int64_t in_challenge) override;
+ ::ndk::ScopedAStatus setOperationAuthenticateFails(bool in_fail) override;
+ ::ndk::ScopedAStatus setOperationAuthenticateLatency(
+ const std::vector<int32_t>& in_latency) override;
+ ::ndk::ScopedAStatus setOperationAuthenticateDuration(int32_t in_duration) override;
+ ::ndk::ScopedAStatus setOperationAuthenticateError(int32_t in_error) override;
+ ::ndk::ScopedAStatus setOperationAuthenticateAcquired(
+ const std::vector<AcquiredInfoAndVendorCode>& in_acquired) override;
+ ::ndk::ScopedAStatus setOperationEnrollError(int32_t in_error) override;
+ ::ndk::ScopedAStatus setOperationEnrollLatency(const std::vector<int32_t>& in_latency) override;
+ ::ndk::ScopedAStatus setOperationDetectInteractionLatency(
+ const std::vector<int32_t>& in_latency) override;
+ ::ndk::ScopedAStatus setOperationDetectInteractionError(int32_t in_error) override;
+ ::ndk::ScopedAStatus setOperationDetectInteractionDuration(int32_t in_duration) override;
+ ::ndk::ScopedAStatus setOperationDetectInteractionAcquired(
+ const std::vector<AcquiredInfoAndVendorCode>& in_acquired) override;
+ ::ndk::ScopedAStatus setLockout(bool in_lockout) override;
+ ::ndk::ScopedAStatus setLockoutEnable(bool in_enable) override;
+ ::ndk::ScopedAStatus setLockoutTimedThreshold(int32_t in_threshold) override;
+ ::ndk::ScopedAStatus setLockoutTimedDuration(int32_t in_duration) override;
+ ::ndk::ScopedAStatus setLockoutPermanentThreshold(int32_t in_threshold) override;
+ ::ndk::ScopedAStatus resetConfigurations() override;
+ ::ndk::ScopedAStatus setType(
+ ::aidl::android::hardware::biometrics::fingerprint::FingerprintSensorType in_type)
+ override;
+ ::ndk::ScopedAStatus setSensorId(int32_t in_id) override;
+ ::ndk::ScopedAStatus setSensorStrength(SensorStrength in_strength) override;
+ ::ndk::ScopedAStatus setMaxEnrollmentPerUser(int32_t in_max) override;
+ ::ndk::ScopedAStatus setSensorLocation(
+ const ::aidl::android::hardware::biometrics::fingerprint::SensorLocation& in_loc)
+ override;
+ ::ndk::ScopedAStatus setNavigationGuesture(bool in_v) override;
+ ::ndk::ScopedAStatus setDetectInteraction(bool in_v) override;
+ ::ndk::ScopedAStatus setDisplayTouch(bool in_v) override;
+ ::ndk::ScopedAStatus setControlIllumination(bool in_v) override;
+
+ private:
+ OptIntVec intVec2OptIntVec(const std::vector<int32_t>& intVec);
+ OptIntVec acquiredInfoVec2OptIntVec(const std::vector<AcquiredInfoAndVendorCode>& intVec);
+ ::ndk::ScopedAStatus sanityCheckLatency(const std::vector<int32_t>& in_latency);
+ Fingerprint* mFp;
+};
+
+} // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/main.cpp b/biometrics/fingerprint/aidl/default/main.cpp
index 7df015b..ba0c8ec 100644
--- a/biometrics/fingerprint/aidl/default/main.cpp
+++ b/biometrics/fingerprint/aidl/default/main.cpp
@@ -15,23 +15,34 @@
*/
#include "Fingerprint.h"
+#include "VirtualHal.h"
#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
using aidl::android::hardware::biometrics::fingerprint::Fingerprint;
+using aidl::android::hardware::biometrics::fingerprint::VirtualHal;
int main() {
LOG(INFO) << "Fingerprint HAL started";
ABinderProcess_setThreadPoolMaxThreadCount(0);
std::shared_ptr<Fingerprint> hal = ndk::SharedRefBase::make<Fingerprint>();
+ auto binder = hal->asBinder();
- const std::string instance = std::string(Fingerprint::descriptor) + "/virtual";
- binder_status_t status =
- AServiceManager_registerLazyService(hal->asBinder().get(), instance.c_str());
- CHECK_EQ(status, STATUS_OK);
- AServiceManager_forceLazyServicesPersist(true);
+ std::shared_ptr<VirtualHal> hal_ext = ndk::SharedRefBase::make<VirtualHal>(hal.get());
+ auto binder_ext = hal_ext->asBinder();
+
+ if (hal->connected()) {
+ CHECK(STATUS_OK == AIBinder_setExtension(binder.get(), binder_ext.get()));
+ const std::string instance = std::string(Fingerprint::descriptor) + "/virtual";
+ binder_status_t status =
+ AServiceManager_registerLazyService(binder.get(), instance.c_str());
+ CHECK_EQ(status, STATUS_OK);
+ AServiceManager_forceLazyServicesPersist(true);
+ } else {
+ LOG(ERROR) << "Fingerprint HAL is not connected";
+ }
ABinderProcess_joinThreadPool();
return EXIT_FAILURE; // should not reach
diff --git a/biometrics/fingerprint/aidl/default/tests/VirtualHalTest.cpp b/biometrics/fingerprint/aidl/default/tests/VirtualHalTest.cpp
new file mode 100644
index 0000000..3fe0b2a
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/tests/VirtualHalTest.cpp
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/binder_process.h>
+#include <fingerprint.sysprop.h>
+#include <gtest/gtest.h>
+
+#include <android-base/logging.h>
+
+#include "Fingerprint.h"
+#include "VirtualHal.h"
+
+using namespace ::android::fingerprint::virt;
+using namespace ::aidl::android::hardware::biometrics::fingerprint;
+
+namespace aidl::android::hardware::biometrics::fingerprint {
+
+class VirtualHalTest : public ::testing::Test {
+ public:
+ static const int32_t STATUS_FAILED_TO_SET_PARAMETER = 2;
+
+ protected:
+ void SetUp() override {
+ mHal = ndk::SharedRefBase::make<Fingerprint>();
+ mVhal = ndk::SharedRefBase::make<VirtualHal>(mHal.get());
+ ASSERT_TRUE(mVhal != nullptr);
+ mHal->resetConfigToDefault();
+ }
+
+ void TearDown() override { mHal->resetConfigToDefault(); }
+
+ std::shared_ptr<VirtualHal> mVhal;
+
+ ndk::ScopedAStatus validateNonNegativeInputOfInt32(const char* name,
+ ndk::ScopedAStatus (VirtualHal::*f)(int32_t),
+ const std::vector<int32_t>& in_good);
+
+ private:
+ std::shared_ptr<Fingerprint> mHal;
+};
+
+ndk::ScopedAStatus VirtualHalTest::validateNonNegativeInputOfInt32(
+ const char* name, ndk::ScopedAStatus (VirtualHal::*f)(int32_t),
+ const std::vector<int32_t>& in_params_good) {
+ ndk::ScopedAStatus status;
+ for (auto& param : in_params_good) {
+ status = (*mVhal.*f)(param);
+ if (!status.isOk()) return status;
+ if (Fingerprint::cfg().get<int32_t>(name) != param) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ VirtualHalTest::STATUS_FAILED_TO_SET_PARAMETER,
+ "Error: fail to set non-negative parameter"));
+ }
+ }
+
+ int32_t old_param = Fingerprint::cfg().get<int32_t>(name);
+ status = (*mVhal.*f)(-1);
+ if (status.isOk()) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ VirtualHalTest::STATUS_FAILED_TO_SET_PARAMETER, "Error: should return NOK"));
+ }
+ if (status.getServiceSpecificError() != IVirtualHal::STATUS_INVALID_PARAMETER) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ VirtualHalTest::STATUS_FAILED_TO_SET_PARAMETER,
+ "Error: unexpected return error code"));
+ }
+ if (Fingerprint::cfg().get<int32_t>(name) != old_param) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ VirtualHalTest::STATUS_FAILED_TO_SET_PARAMETER,
+ "Error: unexpected parameter change on failed attempt"));
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+TEST_F(VirtualHalTest, init) {
+ mVhal->setLockout(false);
+ ASSERT_TRUE(Fingerprint::cfg().get<bool>("lockout") == false);
+ ASSERT_TRUE(Fingerprint::cfg().get<std::string>("type") == "rear");
+ ASSERT_TRUE(Fingerprint::cfg().get<std::int32_t>("sensor_strength") == 2);
+ std::int64_t id = Fingerprint::cfg().get<std::int64_t>("authenticator_id");
+ ASSERT_TRUE(Fingerprint::cfg().get<std::int64_t>("authenticator_id") == 0);
+ ASSERT_TRUE(Fingerprint::cfg().getopt<OptIntVec>("enrollments") == OptIntVec());
+}
+
+TEST_F(VirtualHalTest, enrollment_hit_int32) {
+ mVhal->setEnrollmentHit(11);
+ ASSERT_TRUE(Fingerprint::cfg().get<int32_t>("enrollment_hit") == 11);
+}
+
+TEST_F(VirtualHalTest, next_enrollment) {
+ struct {
+ std::string nextEnrollmentStr;
+ fingerprint::NextEnrollment nextEnrollment;
+ } testData[] = {
+ {"1:20:true", {1, {{20}}, true}},
+ {"1:50,60,70:true", {1, {{50}, {60}, {70}}, true}},
+ {"2:50-[8],60,70-[2,1002,1]:false",
+ {2,
+ {{50, {{AcquiredInfo::START}}},
+ {60},
+ {70, {{AcquiredInfo::PARTIAL}, {1002}, {AcquiredInfo::GOOD}}}},
+ false}},
+ };
+
+ for (auto& d : testData) {
+ mVhal->setNextEnrollment(d.nextEnrollment);
+ ASSERT_TRUE(Fingerprint::cfg().get<std::string>("next_enrollment") == d.nextEnrollmentStr);
+ }
+}
+
+TEST_F(VirtualHalTest, authenticator_id_int64) {
+ mVhal->setAuthenticatorId(12345678900);
+ ASSERT_TRUE(Fingerprint::cfg().get<int64_t>("authenticator_id") == 12345678900);
+}
+
+TEST_F(VirtualHalTest, opeationAuthenticateFails_bool) {
+ mVhal->setOperationAuthenticateFails(true);
+ ASSERT_TRUE(Fingerprint::cfg().get<bool>("operation_authenticate_fails"));
+}
+
+TEST_F(VirtualHalTest, operationAuthenticateAcquired_int32_vector) {
+ using Tag = AcquiredInfoAndVendorCode::Tag;
+ std::vector<AcquiredInfoAndVendorCode> ac{
+ {AcquiredInfo::START}, {AcquiredInfo::PARTIAL}, {1023}};
+ mVhal->setOperationAuthenticateAcquired(ac);
+ OptIntVec ac_get = Fingerprint::cfg().getopt<OptIntVec>("operation_authenticate_acquired");
+ ASSERT_TRUE(ac_get.size() == ac.size());
+ for (int i = 0; i < ac.size(); i++) {
+ int acCode = (ac[i].getTag() == Tag::acquiredInfo) ? (int)ac[i].get<Tag::acquiredInfo>()
+ : ac[i].get<Tag::vendorCode>();
+ ASSERT_TRUE(acCode == ac_get[i]);
+ }
+}
+
+TEST_F(VirtualHalTest, type) {
+ struct {
+ FingerprintSensorType type;
+ const char* typeStr;
+ } typeMap[] = {{FingerprintSensorType::REAR, "rear"},
+ {FingerprintSensorType::POWER_BUTTON, "side"},
+ {FingerprintSensorType::UNDER_DISPLAY_OPTICAL, "udfps"},
+ {FingerprintSensorType::UNDER_DISPLAY_ULTRASONIC, "udfps"},
+ {FingerprintSensorType::UNKNOWN, "unknown"}};
+ for (auto const& x : typeMap) {
+ mVhal->setType(x.type);
+ ASSERT_TRUE(Fingerprint::cfg().get<std::string>("type") == x.typeStr);
+ }
+}
+
+TEST_F(VirtualHalTest, sensorStrength) {
+ SensorStrength strengths[] = {SensorStrength::CONVENIENCE, SensorStrength::WEAK,
+ SensorStrength::STRONG};
+
+ for (auto const& strength : strengths) {
+ mVhal->setSensorStrength(strength);
+ ASSERT_TRUE(Fingerprint::cfg().get<int32_t>("sensor_strength") == (int32_t)(strength));
+ }
+}
+
+TEST_F(VirtualHalTest, sensorLocation) {
+ SensorLocation loc = {.sensorLocationX = 1, .sensorLocationY = 2, .sensorRadius = 3};
+ mVhal->setSensorLocation(loc);
+ ASSERT_TRUE(Fingerprint::cfg().get<std::string>("sensor_location") == "1:2:3");
+}
+
+TEST_F(VirtualHalTest, setLatency) {
+ ndk::ScopedAStatus status;
+ std::vector<int32_t> in_lats[] = {{1}, {2, 3}, {5, 4}};
+ for (auto const& in_lat : in_lats) {
+ status = mVhal->setOperationAuthenticateLatency(in_lat);
+ ASSERT_TRUE(status.isOk());
+ OptIntVec out_lat = Fingerprint::cfg().getopt<OptIntVec>("operation_authenticate_latency");
+ ASSERT_TRUE(in_lat.size() == out_lat.size());
+ for (int i = 0; i < in_lat.size(); i++) {
+ ASSERT_TRUE(in_lat[i] == out_lat[i]);
+ }
+ }
+
+ std::vector<int32_t> bad_in_lats[] = {{}, {1, 2, 3}, {1, -3}};
+ for (auto const& in_lat : bad_in_lats) {
+ status = mVhal->setOperationAuthenticateLatency(in_lat);
+ ASSERT_TRUE(!status.isOk());
+ ASSERT_TRUE(status.getServiceSpecificError() == IVirtualHal::STATUS_INVALID_PARAMETER);
+ }
+}
+
+TEST_F(VirtualHalTest, setOperationAuthenticateDuration) {
+ ndk::ScopedAStatus status = validateNonNegativeInputOfInt32(
+ "operation_authenticate_duration", &IVirtualHal::setOperationAuthenticateDuration,
+ {0, 33});
+ ASSERT_TRUE(status.isOk());
+}
+
+TEST_F(VirtualHalTest, setOperationDetectInteractionDuration) {
+ ndk::ScopedAStatus status = validateNonNegativeInputOfInt32(
+ "operation_detect_interaction_duration",
+ &IVirtualHal::setOperationDetectInteractionDuration, {0, 34});
+ ASSERT_TRUE(status.isOk());
+}
+
+TEST_F(VirtualHalTest, setLockoutTimedDuration) {
+ ndk::ScopedAStatus status = validateNonNegativeInputOfInt32(
+ "lockout_timed_duration", &IVirtualHal::setLockoutTimedDuration, {0, 35});
+ ASSERT_TRUE(status.isOk());
+}
+
+TEST_F(VirtualHalTest, setLockoutTimedThreshold) {
+ ndk::ScopedAStatus status = validateNonNegativeInputOfInt32(
+ "lockout_timed_threshold", &IVirtualHal::setLockoutTimedThreshold, {0, 36});
+ ASSERT_TRUE(status.isOk());
+}
+
+TEST_F(VirtualHalTest, setLockoutPermanentThreshold) {
+ ndk::ScopedAStatus status = validateNonNegativeInputOfInt32(
+ "lockout_permanent_threshold", &IVirtualHal::setLockoutPermanentThreshold, {0, 37});
+ ASSERT_TRUE(status.isOk());
+}
+
+TEST_F(VirtualHalTest, setOthers) {
+ // Verify that there is no CHECK() failures
+ mVhal->setEnrollments({7, 6, 5});
+ mVhal->setChallenge(111222333444555666);
+ mVhal->setOperationAuthenticateError(4);
+ mVhal->setOperationEnrollError(5);
+ mVhal->setOperationEnrollLatency({4, 5});
+ mVhal->setOperationDetectInteractionError(6);
+ mVhal->setOperationDetectInteractionAcquired({{AcquiredInfo::START}, {AcquiredInfo::GOOD}});
+ mVhal->setLockout(false);
+ mVhal->setLockoutEnable(false);
+ mVhal->setSensorId(5);
+ mVhal->setMaxEnrollmentPerUser(6);
+ mVhal->setNavigationGuesture(false);
+ mVhal->setDetectInteraction(false);
+ mVhal->setDisplayTouch(false);
+ mVhal->setControlIllumination(false);
+}
+
+} // namespace aidl::android::hardware::biometrics::fingerprint
+
+int main(int argc, char** argv) {
+ testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_startThreadPool();
+ return RUN_ALL_TESTS();
+}
diff --git a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
index 5002a1a..6783c0f 100644
--- a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
@@ -30,6 +30,8 @@
constexpr uint8_t kLeAudioDirectionSink = 0x01;
constexpr uint8_t kLeAudioDirectionSource = 0x02;
+constexpr uint8_t kIsoDataPathHci = 0x00;
+constexpr uint8_t kIsoDataPathPlatformDefault = 0x01;
const std::map<CodecSpecificConfigurationLtv::SamplingFrequency, uint32_t>
freq_to_support_bitmask_map = {
@@ -85,6 +87,7 @@
std::map<int32_t, CodecSpecificConfigurationLtv::SamplingFrequency>
sampling_freq_map = {
{16000, CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000},
+ {24000, CodecSpecificConfigurationLtv::SamplingFrequency::HZ24000},
{48000, CodecSpecificConfigurationLtv::SamplingFrequency::HZ48000},
{96000, CodecSpecificConfigurationLtv::SamplingFrequency::HZ96000},
};
@@ -175,12 +178,13 @@
if (!metadata.has_value()) continue;
if (metadata.value().getTag() == MetadataLtv::Tag::preferredAudioContexts) {
// Check all pref audio context to see if anything matched
- auto& context = metadata.value()
- .get<MetadataLtv::Tag::preferredAudioContexts>()
- .values;
- if (setting_context.bitmask & context.bitmask) {
+ auto& prefer_context =
+ metadata.value()
+ .get<MetadataLtv::Tag::preferredAudioContexts>()
+ .values;
+ if (setting_context.bitmask & prefer_context.bitmask) {
// New mask with matched capability
- setting_context.bitmask &= context.bitmask;
+ setting_context.bitmask &= prefer_context.bitmask;
return true;
}
}
@@ -219,8 +223,9 @@
/*cfg_channel*/,
CodecSpecificCapabilitiesLtv::SupportedAudioChannelCounts&
/*capability_channel*/) {
+ // Simply ignore.
+ // Later can use additional capabilities to match requirement.
bool isMatched = true;
- // TODO: how to match?
return isMatched;
}
@@ -317,22 +322,34 @@
return true;
}
-bool LeAudioOffloadAudioProvider::isMatchedAseConfiguration(
- LeAudioAseConfiguration setting_cfg,
- LeAudioAseConfiguration requirement_cfg) {
+bool isMonoConfig(
+ CodecSpecificConfigurationLtv::AudioChannelAllocation allocation) {
+ auto channel_count = std::bitset<32>(allocation.bitmask);
+ return (channel_count.count() <= 1);
+}
+
+bool LeAudioOffloadAudioProvider::filterMatchedAseConfiguration(
+ LeAudioAseConfiguration& setting_cfg,
+ const LeAudioAseConfiguration& requirement_cfg) {
// Check matching for codec configuration <=> requirement ASE codec
// Also match if no CodecId requirement
if (requirement_cfg.codecId.has_value()) {
if (!setting_cfg.codecId.has_value()) return false;
if (!isMatchedValidCodec(setting_cfg.codecId.value(),
requirement_cfg.codecId.value())) {
+ LOG(WARNING) << __func__ << ": Doesn't match valid codec, cfg = "
+ << setting_cfg.codecId.value().toString()
+ << ", req = " << requirement_cfg.codecId.value().toString();
return false;
}
}
- if (requirement_cfg.targetLatency ==
- LeAudioAseConfiguration::TargetLatency::UNDEFINED ||
+ if (requirement_cfg.targetLatency !=
+ LeAudioAseConfiguration::TargetLatency::UNDEFINED &&
setting_cfg.targetLatency != requirement_cfg.targetLatency) {
+ LOG(WARNING) << __func__ << ": Doesn't match target latency, cfg = "
+ << int(setting_cfg.targetLatency)
+ << ", req = " << int(requirement_cfg.targetLatency);
return false;
}
// Ignore PHY requirement
@@ -346,11 +363,24 @@
for (auto requirement_cfg : requirement_cfg.codecConfiguration) {
// Directly compare CodecSpecificConfigurationLtv
auto cfg = cfg_tag_map.find(requirement_cfg.getTag());
+ // Config not found for this requirement, cannot match
if (cfg == cfg_tag_map.end()) {
+ LOG(WARNING) << __func__ << ": Config not found for the requirement "
+ << requirement_cfg.toString();
return false;
}
+ // Ignore matching for audio channel allocation
+ // since the rule is complicated. Match outside instead
+ if (requirement_cfg.getTag() ==
+ CodecSpecificConfigurationLtv::Tag::audioChannelAllocation)
+ continue;
+
if (cfg->second != requirement_cfg) {
+ LOG(WARNING) << __func__
+ << ": Config doesn't match the requirement, cfg = "
+ << cfg->second.toString()
+ << ", req = " << requirement_cfg.toString();
return false;
}
}
@@ -395,35 +425,133 @@
}
}
+int getLeAudioAseConfigurationAllocationBitmask(LeAudioAseConfiguration cfg) {
+ for (auto cfg_ltv : cfg.codecConfiguration) {
+ if (cfg_ltv.getTag() ==
+ CodecSpecificConfigurationLtv::Tag::audioChannelAllocation) {
+ return cfg_ltv
+ .get<CodecSpecificConfigurationLtv::Tag::audioChannelAllocation>()
+ .bitmask;
+ }
+ }
+ return 0;
+}
+
+int getCountFromBitmask(int bitmask) {
+ return std::bitset<32>(bitmask).count();
+}
+
+std::optional<AseDirectionConfiguration> findValidMonoConfig(
+ std::vector<AseDirectionConfiguration>& valid_direction_configurations,
+ int bitmask) {
+ for (auto& cfg : valid_direction_configurations) {
+ int cfg_bitmask =
+ getLeAudioAseConfigurationAllocationBitmask(cfg.aseConfiguration);
+ if (getCountFromBitmask(cfg_bitmask) <= 1) {
+ // Modify the bitmask to be the same as the requirement
+ for (auto& codec_cfg : cfg.aseConfiguration.codecConfiguration) {
+ if (codec_cfg.getTag() ==
+ CodecSpecificConfigurationLtv::Tag::audioChannelAllocation) {
+ codec_cfg
+ .get<CodecSpecificConfigurationLtv::Tag::audioChannelAllocation>()
+ .bitmask = bitmask;
+ return cfg;
+ }
+ }
+ }
+ }
+ return std::nullopt;
+}
+
+std::vector<AseDirectionConfiguration> getValidConfigurationsFromAllocation(
+ int req_allocation_bitmask,
+ std::vector<AseDirectionConfiguration>& valid_direction_configurations,
+ bool is_exact) {
+ // Prefer the same allocation_bitmask
+ int channel_count = getCountFromBitmask(req_allocation_bitmask);
+
+ if (is_exact) {
+ for (auto& cfg : valid_direction_configurations) {
+ int cfg_bitmask =
+ getLeAudioAseConfigurationAllocationBitmask(cfg.aseConfiguration);
+ if (cfg_bitmask == req_allocation_bitmask) {
+ LOG(DEBUG)
+ << __func__
+ << ": Found an exact match for the requirement allocation of "
+ << cfg_bitmask;
+ return {cfg};
+ }
+ }
+ return {};
+ }
+ // Not using exact match strategy
+ if (channel_count <= 1) {
+ // Mono requirement matched if cfg is a mono config
+ auto cfg = findValidMonoConfig(valid_direction_configurations,
+ req_allocation_bitmask);
+ if (cfg.has_value()) return {cfg.value()};
+ } else {
+ // Stereo requirement returns 2 mono configs
+ // that has a combined bitmask equal to the stereo config
+ std::vector<AseDirectionConfiguration> temp;
+ for (int bit = 0; bit < 32; ++bit)
+ if (req_allocation_bitmask & (1 << bit)) {
+ auto cfg =
+ findValidMonoConfig(valid_direction_configurations, (1 << bit));
+ if (cfg.has_value()) temp.push_back(cfg.value());
+ }
+ if (temp.size() == channel_count) return temp;
+ }
+ return {};
+}
+
void LeAudioOffloadAudioProvider::filterRequirementAseDirectionConfiguration(
std::optional<std::vector<std::optional<AseDirectionConfiguration>>>&
direction_configurations,
const std::vector<std::optional<AseDirectionRequirement>>& requirements,
std::optional<std::vector<std::optional<AseDirectionConfiguration>>>&
- valid_direction_configurations) {
+ valid_direction_configurations,
+ bool is_exact) {
+ // For every requirement, find the matched ase configuration
+ if (!direction_configurations.has_value()) return;
+
if (!valid_direction_configurations.has_value()) {
valid_direction_configurations =
std::vector<std::optional<AseDirectionConfiguration>>();
}
- // For every requirement, find the matched ase configuration
- if (!direction_configurations.has_value()) return;
+
for (auto& requirement : requirements) {
if (!requirement.has_value()) continue;
+ auto req_allocation_bitmask = getLeAudioAseConfigurationAllocationBitmask(
+ requirement.value().aseConfiguration);
+ auto req_channel_count = getCountFromBitmask(req_allocation_bitmask);
+
+ auto temp = std::vector<AseDirectionConfiguration>();
+
for (auto direction_configuration : direction_configurations.value()) {
if (!direction_configuration.has_value()) continue;
- if (!isMatchedAseConfiguration(
+ if (!filterMatchedAseConfiguration(
direction_configuration.value().aseConfiguration,
requirement.value().aseConfiguration))
continue;
// Valid if match any requirement.
- valid_direction_configurations.value().push_back(direction_configuration);
- break;
+ temp.push_back(direction_configuration.value());
}
- }
- // Ensure that each requirement will have one direction configurations
- if (valid_direction_configurations.value().empty() ||
- (valid_direction_configurations.value().size() != requirements.size())) {
- valid_direction_configurations = std::nullopt;
+
+ // Get the best matching config based on channel allocation
+ auto total_cfg_channel_count = 0;
+ auto req_valid_configs = getValidConfigurationsFromAllocation(
+ req_allocation_bitmask, temp, is_exact);
+ // Count and check required channel counts
+ for (auto& cfg : req_valid_configs) {
+ total_cfg_channel_count += getCountFromBitmask(
+ getLeAudioAseConfigurationAllocationBitmask(cfg.aseConfiguration));
+ valid_direction_configurations.value().push_back(cfg);
+ }
+ if (total_cfg_channel_count != req_channel_count) {
+ valid_direction_configurations = std::nullopt;
+ return;
+ }
}
}
@@ -444,10 +572,6 @@
.flags = setting.flags,
.packing = setting.packing,
};
- // Try to match context in metadata.
- if (!filterCapabilitiesMatchedContext(filtered_setting.audioContext,
- capabilities))
- return std::nullopt;
// Get a list of all matched AseDirectionConfiguration
// for the input direction
@@ -488,8 +612,8 @@
std::optional<LeAudioAseConfigurationSetting>
LeAudioOffloadAudioProvider::getRequirementMatchedAseConfigurationSettings(
IBluetoothAudioProvider::LeAudioAseConfigurationSetting& setting,
- const IBluetoothAudioProvider::LeAudioConfigurationRequirement&
- requirement) {
+ const IBluetoothAudioProvider::LeAudioConfigurationRequirement& requirement,
+ bool is_exact) {
// Try to match context in metadata.
if ((setting.audioContext.bitmask & requirement.audioContext.bitmask) !=
requirement.audioContext.bitmask)
@@ -498,12 +622,6 @@
// Further filter setting's context
setting.audioContext.bitmask &= requirement.audioContext.bitmask;
- // Check requirement for the correct direction
- const std::optional<std::vector<std::optional<AseDirectionRequirement>>>*
- direction_requirement;
- std::vector<std::optional<AseDirectionConfiguration>>*
- direction_configuration;
-
// Create a new LeAudioAseConfigurationSetting to return
LeAudioAseConfigurationSetting filtered_setting{
.audioContext = setting.audioContext,
@@ -514,22 +632,63 @@
if (requirement.sinkAseRequirement.has_value()) {
filterRequirementAseDirectionConfiguration(
setting.sinkAseConfiguration, requirement.sinkAseRequirement.value(),
- filtered_setting.sinkAseConfiguration);
- if (!filtered_setting.sinkAseConfiguration.has_value()) return std::nullopt;
+ filtered_setting.sinkAseConfiguration, is_exact);
+ if (!filtered_setting.sinkAseConfiguration.has_value()) {
+ return std::nullopt;
+ }
}
if (requirement.sourceAseRequirement.has_value()) {
filterRequirementAseDirectionConfiguration(
setting.sourceAseConfiguration,
requirement.sourceAseRequirement.value(),
- filtered_setting.sourceAseConfiguration);
- if (!filtered_setting.sourceAseConfiguration.has_value())
+ filtered_setting.sourceAseConfiguration, is_exact);
+ if (!filtered_setting.sourceAseConfiguration.has_value()) {
return std::nullopt;
+ }
}
return filtered_setting;
}
+std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
+LeAudioOffloadAudioProvider::matchWithRequirement(
+ std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>&
+ matched_ase_configuration_settings,
+ const std::vector<IBluetoothAudioProvider::LeAudioConfigurationRequirement>&
+ in_requirements,
+ bool is_exact) {
+ // Each requirement will match with a valid setting
+ std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting> result;
+ for (auto& requirement : in_requirements) {
+ LOG(INFO) << __func__ << ": Trying to match for the requirement "
+ << requirement.toString();
+ bool is_matched = false;
+
+ for (auto& setting : matched_ase_configuration_settings) {
+ auto filtered_ase_configuration_setting =
+ getRequirementMatchedAseConfigurationSettings(setting, requirement,
+ is_exact);
+ if (filtered_ase_configuration_setting.has_value()) {
+ result.push_back(filtered_ase_configuration_setting.value());
+ LOG(INFO) << __func__ << ": Result = "
+ << filtered_ase_configuration_setting.value().toString();
+ // Found a matched setting, ignore other settings
+ is_matched = true;
+ break;
+ }
+ }
+ if (!is_matched) {
+ // If cannot satisfy this requirement, return an empty result
+ LOG(WARNING) << __func__ << ": Cannot match the requirement "
+ << requirement.toString();
+ result.clear();
+ break;
+ }
+ }
+ return result;
+}
+
// For each requirement, a valid ASE configuration will satify:
// - matched with any sink capability (if presented)
// - OR matched with any source capability (if presented)
@@ -555,31 +714,43 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
- // Each setting consist of source and sink AseDirectionConfiguration vector
- // Filter every sink capability
+ // Split out preferred and non-preferred settings based on context
+ // An example: preferred = MEDIA, available: MEDIA | CONVERSATION
+ // -> preferred list will have settings with MEDIA context
+ // -> non-preferred list will have settings with any context
+ // We want to match requirement with preferred context settings first
std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
matched_ase_configuration_settings;
+ // Matched ASE configuration with non-preferred audio context
+ std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
+ non_prefer_matched_ase_configuration_settings;
- if (in_remoteSinkAudioCapabilities.has_value()) {
+ if (in_remoteSinkAudioCapabilities.has_value())
// Matching each setting with any remote capabilities
- for (auto& setting : ase_configuration_settings) {
+ for (auto& setting : ase_configuration_settings)
for (auto& capability : in_remoteSinkAudioCapabilities.value()) {
if (!capability.has_value()) continue;
auto filtered_ase_configuration_setting =
getCapabilitiesMatchedAseConfigurationSettings(
setting, capability.value(), kLeAudioDirectionSink);
if (filtered_ase_configuration_setting.has_value()) {
- matched_ase_configuration_settings.push_back(
+ // Push to non-prefer first for the broadest matching possible
+ non_prefer_matched_ase_configuration_settings.push_back(
filtered_ase_configuration_setting.value());
+ // Try to filter out prefer context to another vector.
+ if (filterCapabilitiesMatchedContext(
+ filtered_ase_configuration_setting.value().audioContext,
+ capability.value())) {
+ matched_ase_configuration_settings.push_back(
+ filtered_ase_configuration_setting.value());
+ }
}
}
- }
- }
// Combine filter every source capability
- if (in_remoteSourceAudioCapabilities.has_value()) {
+ if (in_remoteSourceAudioCapabilities.has_value())
// Matching each setting with any remote capabilities
- for (auto& setting : ase_configuration_settings) {
+ for (auto& setting : ase_configuration_settings)
for (auto& capability : in_remoteSourceAudioCapabilities.value()) {
if (!capability.has_value()) continue;
auto filtered_ase_configuration_setting =
@@ -588,45 +759,56 @@
if (filtered_ase_configuration_setting.has_value()) {
// Put into the same list
// possibly duplicated, filtered by requirement later
- matched_ase_configuration_settings.push_back(
+ // Push to non-prefer first for the broadest matching possible
+ non_prefer_matched_ase_configuration_settings.push_back(
filtered_ase_configuration_setting.value());
+ // Try to filter out prefer context to another vector.
+ if (filterCapabilitiesMatchedContext(
+ filtered_ase_configuration_setting.value().audioContext,
+ capability.value())) {
+ matched_ase_configuration_settings.push_back(
+ filtered_ase_configuration_setting.value());
+ }
}
}
- }
- }
- if (matched_ase_configuration_settings.empty()) {
- LOG(WARNING) << __func__ << ": No setting matched the capability";
- return ndk::ScopedAStatus::ok();
- }
- // Each requirement will match with a valid setting
- std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting> result;
- for (auto& requirement : in_requirements) {
- LOG(INFO) << __func__ << ": Trying to match for the requirement "
- << requirement.toString();
- bool is_matched = false;
+ // Matching priority list:
+ // Preferred context - exact match with allocation
+ // Any context - exact match with allocation
+ // Preferred context - loose match with allocation
+ // Any context - loose match with allocation
- for (auto& setting : matched_ase_configuration_settings) {
- auto filtered_ase_configuration_setting =
- getRequirementMatchedAseConfigurationSettings(setting, requirement);
- if (filtered_ase_configuration_setting.has_value()) {
- result.push_back(filtered_ase_configuration_setting.value());
- LOG(INFO) << __func__ << ": Result = "
- << filtered_ase_configuration_setting.value().toString();
- // Found a matched setting, ignore other settings
- is_matched = true;
- break;
- }
- }
- if (!is_matched) {
- // If cannot satisfy this requirement, return an empty result
- LOG(WARNING) << __func__ << ": Cannot match the requirement "
- << requirement.toString();
- result.clear();
- break;
- }
+ // A loose match will attempt to return 2 settings with the
+ // combined allocation bitmask equal the required allocation.
+ // For example, we can return 2 link (left link and right link) when
+ // the requirement required 1 (left + right) link.
+ auto result = matchWithRequirement(matched_ase_configuration_settings,
+ in_requirements, true);
+ if (result.empty()) {
+ LOG(WARNING)
+ << __func__
+ << ": Cannot match with preferred context settings - exact match";
+ result = matchWithRequirement(non_prefer_matched_ase_configuration_settings,
+ in_requirements, true);
}
-
+ if (result.empty()) {
+ LOG(WARNING)
+ << __func__
+ << ": Cannot match with non-preferred context settings - exact match";
+ result = matchWithRequirement(matched_ase_configuration_settings,
+ in_requirements, false);
+ }
+ if (result.empty()) {
+ LOG(WARNING) << __func__
+ << ": Cannot match with preferred context settings - "
+ "non-exact match";
+ result = matchWithRequirement(non_prefer_matched_ase_configuration_settings,
+ in_requirements, false);
+ }
+ if (result.empty())
+ LOG(ERROR) << __func__
+ << ": Cannot match with non preferred context settings - "
+ "non-exact match";
*_aidl_return = result;
return ndk::ScopedAStatus::ok();
};
@@ -642,7 +824,6 @@
requirement_qos.maxTransportLatencyMs) {
return false;
}
- // Ignore other parameters, as they are not populated in the setting_qos
return true;
}
@@ -658,7 +839,8 @@
uint8_t direction,
const IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement&
qosRequirement,
- std::vector<LeAudioAseConfigurationSetting>& ase_configuration_settings) {
+ std::vector<LeAudioAseConfigurationSetting>& ase_configuration_settings,
+ bool is_exact) {
std::optional<AseQosDirectionRequirement> direction_qos_requirement =
std::nullopt;
@@ -680,17 +862,26 @@
// Get a list of all matched AseDirectionConfiguration
// for the input direction
- std::vector<std::optional<AseDirectionConfiguration>>*
- direction_configuration = nullptr;
+ std::optional<std::vector<std::optional<AseDirectionConfiguration>>>
+ direction_configuration = std::nullopt;
if (direction == kLeAudioDirectionSink) {
if (!setting.sinkAseConfiguration.has_value()) continue;
- direction_configuration = &setting.sinkAseConfiguration.value();
+ direction_configuration.emplace(setting.sinkAseConfiguration.value());
} else {
if (!setting.sourceAseConfiguration.has_value()) continue;
- direction_configuration = &setting.sourceAseConfiguration.value();
+ direction_configuration.emplace(setting.sourceAseConfiguration.value());
}
- for (auto cfg : *direction_configuration) {
+ if (!direction_configuration.has_value()) {
+ return std::nullopt;
+ }
+
+ // Collect all valid cfg into a vector
+ // Then try to get the best match for audio allocation
+
+ auto temp = std::vector<AseDirectionConfiguration>();
+
+ for (auto& cfg : direction_configuration.value()) {
if (!cfg.has_value()) continue;
// If no requirement, return the first QoS
if (!direction_qos_requirement.has_value()) {
@@ -701,14 +892,30 @@
// Try to match the ASE configuration
// and QoS with requirement
if (!cfg.value().qosConfiguration.has_value()) continue;
- if (isMatchedAseConfiguration(
+ if (filterMatchedAseConfiguration(
cfg.value().aseConfiguration,
direction_qos_requirement.value().aseConfiguration) &&
isMatchedQosRequirement(cfg.value().qosConfiguration.value(),
direction_qos_requirement.value())) {
- return cfg.value().qosConfiguration;
+ temp.push_back(cfg.value());
}
}
+ LOG(WARNING) << __func__ << ": Got " << temp.size()
+ << " configs, start matching allocation";
+
+ int qos_allocation_bitmask = getLeAudioAseConfigurationAllocationBitmask(
+ direction_qos_requirement.value().aseConfiguration);
+ // Get the best matching config based on channel allocation
+ auto req_valid_configs = getValidConfigurationsFromAllocation(
+ qos_allocation_bitmask, temp, is_exact);
+ if (req_valid_configs.empty()) {
+ LOG(WARNING) << __func__
+ << ": Cannot find matching allocation for bitmask "
+ << qos_allocation_bitmask;
+
+ } else {
+ return req_valid_configs[0].qosConfiguration;
+ }
}
return std::nullopt;
@@ -730,15 +937,30 @@
if (in_qosRequirement.sinkAseQosRequirement.has_value()) {
if (!isValidQosRequirement(in_qosRequirement.sinkAseQosRequirement.value()))
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
- result.sinkQosConfiguration = getDirectionQosConfiguration(
- kLeAudioDirectionSink, in_qosRequirement, ase_configuration_settings);
+ {
+ // Try exact match first
+ result.sinkQosConfiguration =
+ getDirectionQosConfiguration(kLeAudioDirectionSink, in_qosRequirement,
+ ase_configuration_settings, true);
+ if (!result.sinkQosConfiguration.has_value()) {
+ result.sinkQosConfiguration = getDirectionQosConfiguration(
+ kLeAudioDirectionSink, in_qosRequirement,
+ ase_configuration_settings, false);
+ }
+ }
}
if (in_qosRequirement.sourceAseQosRequirement.has_value()) {
if (!isValidQosRequirement(
in_qosRequirement.sourceAseQosRequirement.value()))
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
- result.sourceQosConfiguration = getDirectionQosConfiguration(
- kLeAudioDirectionSource, in_qosRequirement, ase_configuration_settings);
+ result.sourceQosConfiguration =
+ getDirectionQosConfiguration(kLeAudioDirectionSource, in_qosRequirement,
+ ase_configuration_settings, true);
+ if (!result.sourceQosConfiguration.has_value()) {
+ result.sourceQosConfiguration = getDirectionQosConfiguration(
+ kLeAudioDirectionSource, in_qosRequirement,
+ ase_configuration_settings, false);
+ }
}
*_aidl_return = result;
@@ -763,28 +985,127 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
};
+LeAudioBroadcastConfigurationSetting getDefaultBroadcastSetting(
+ int context_bitmask, IBluetoothAudioProvider::BroadcastQuality quality) {
+ LeAudioBroadcastConfigurationSetting setting;
+ setting.retransmitionNum = 4;
+ setting.maxTransportLatencyMs = 60;
+ setting.sduIntervalUs = 10000;
+ setting.maxSduOctets = 40;
+
+ if (quality == IBluetoothAudioProvider::BroadcastQuality::HIGH) {
+ LOG(INFO) << __func__ << ": High quality, returning high quality settings";
+ setting.retransmitionNum = 4;
+ setting.maxTransportLatencyMs = 65;
+ setting.maxSduOctets = 200;
+ return setting;
+ }
+
+ // Populate other settings base on context
+ // TODO: Populate with better design
+ if (context_bitmask & (AudioContext::LIVE_AUDIO | AudioContext::GAME)) {
+ setting.retransmitionNum = 2;
+ setting.maxTransportLatencyMs = 10;
+ setting.maxSduOctets = 120;
+ } else if (context_bitmask & (AudioContext::INSTRUCTIONAL)) {
+ setting.retransmitionNum = 2;
+ setting.maxTransportLatencyMs = 10;
+ setting.maxSduOctets = 40;
+ } else if (context_bitmask &
+ (AudioContext::SOUND_EFFECTS | AudioContext::UNSPECIFIED)) {
+ setting.retransmitionNum = 4;
+ setting.maxTransportLatencyMs = 60;
+ setting.maxSduOctets = 80;
+ } else if (context_bitmask &
+ (AudioContext::ALERTS | AudioContext::NOTIFICATIONS |
+ AudioContext::EMERGENCY_ALARM)) {
+ setting.retransmitionNum = 4;
+ setting.maxTransportLatencyMs = 60;
+ setting.maxSduOctets = 40;
+ } else if (context_bitmask & AudioContext::MEDIA) {
+ setting.retransmitionNum = 4;
+ setting.maxTransportLatencyMs = 60;
+ setting.maxSduOctets = 120;
+ }
+
+ return setting;
+}
+void modifySubBISConfigAllocation(
+ IBluetoothAudioProvider::LeAudioSubgroupBisConfiguration& sub_bis_cfg,
+ int allocation_bitmask) {
+ for (auto& codec_cfg : sub_bis_cfg.bisConfiguration.codecConfiguration) {
+ if (codec_cfg.getTag() ==
+ CodecSpecificConfigurationLtv::audioChannelAllocation) {
+ codec_cfg.get<CodecSpecificConfigurationLtv::audioChannelAllocation>()
+ .bitmask = allocation_bitmask;
+ break;
+ }
+ }
+}
+void modifySubgroupConfiguration(
+ IBluetoothAudioProvider::LeAudioBroadcastSubgroupConfiguration&
+ subgroup_cfg,
+ int context_bitmask) {
+ // STEREO configs
+ // Split into 2 sub BIS config, each has numBis = 1
+ if (context_bitmask & (AudioContext::LIVE_AUDIO | AudioContext::GAME |
+ AudioContext::SOUND_EFFECTS |
+ AudioContext::UNSPECIFIED | AudioContext::MEDIA)) {
+ if (subgroup_cfg.bisConfigurations.size() == 1)
+ subgroup_cfg.bisConfigurations.push_back(
+ subgroup_cfg.bisConfigurations[0]);
+
+ subgroup_cfg.bisConfigurations[0].numBis = 1;
+ modifySubBISConfigAllocation(
+ subgroup_cfg.bisConfigurations[0],
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT);
+
+ subgroup_cfg.bisConfigurations[1].numBis = 1;
+ modifySubBISConfigAllocation(
+ subgroup_cfg.bisConfigurations[1],
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT);
+ return;
+ }
+
+ // MONO configs
+ for (auto& sub_bis_cfg : subgroup_cfg.bisConfigurations) {
+ sub_bis_cfg.numBis = 1;
+ modifySubBISConfigAllocation(
+ sub_bis_cfg,
+ CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_CENTER);
+ }
+}
+
void LeAudioOffloadAudioProvider::getBroadcastSettings() {
if (!broadcast_settings.empty()) return;
- LOG(INFO) << __func__ << ": Loading broadcast settings from provider info";
+ LOG(INFO) << __func__
+ << ": Loading basic broadcast settings from provider info";
std::vector<CodecInfo> db_codec_info =
BluetoothAudioCodecs::GetLeAudioOffloadCodecInfo(
SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
+ for (auto x : db_codec_info) {
+ LOG(INFO) << __func__ << ": codec info = " << x.toString();
+ }
broadcast_settings.clear();
- // Default value for unmapped fields
+ // Default value population
CodecSpecificConfigurationLtv::AudioChannelAllocation default_allocation;
default_allocation.bitmask =
CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_CENTER;
CodecSpecificConfigurationLtv::CodecFrameBlocksPerSDU default_frame;
- default_frame.value = 2;
+ default_frame.value = 1;
for (auto& codec_info : db_codec_info) {
if (codec_info.transport.getTag() != CodecInfo::Transport::leAudio)
continue;
auto& transport = codec_info.transport.get<CodecInfo::Transport::leAudio>();
LeAudioBroadcastConfigurationSetting setting;
+ setting.retransmitionNum = 4;
+ setting.maxTransportLatencyMs = 60;
+ setting.sduIntervalUs = 10000;
+ setting.maxSduOctets = 40;
// Default setting
setting.numBis = 1;
setting.phy = {Phy::TWO_M};
@@ -803,13 +1124,15 @@
default_frame,
};
+ // Ignore bis_cfg.metadata
+
// Add information to structure
IBluetoothAudioProvider::LeAudioSubgroupBisConfiguration sub_bis_cfg;
- sub_bis_cfg.numBis = 2;
+ sub_bis_cfg.numBis = 1;
sub_bis_cfg.bisConfiguration = bis_cfg;
IBluetoothAudioProvider::LeAudioBroadcastSubgroupConfiguration sub_cfg;
// Populate the same sub config
- sub_cfg.bisConfigurations = {sub_bis_cfg, sub_bis_cfg};
+ sub_cfg.bisConfigurations = {sub_bis_cfg};
setting.subgroupsConfigurations = {sub_cfg};
broadcast_settings.push_back(setting);
@@ -853,34 +1176,91 @@
return filtered_setting;
}
+std::vector<CodecSpecificConfigurationLtv> getCodecRequirementBasedOnContext(
+ int context_bitmask, IBluetoothAudioProvider::BroadcastQuality quality) {
+ // Default requirement: lc3_stereo_16_2
+ std::vector<CodecSpecificConfigurationLtv> requirement = {
+ CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000,
+ CodecSpecificConfigurationLtv::FrameDuration::US10000,
+ };
+
+ if (quality == IBluetoothAudioProvider::BroadcastQuality::HIGH) {
+ LOG(INFO) << __func__
+ << ": High quality, returning high quality requirement";
+ requirement = {
+ CodecSpecificConfigurationLtv::SamplingFrequency::HZ48000,
+ CodecSpecificConfigurationLtv::FrameDuration::US10000,
+ };
+ return requirement;
+ }
+
+ if (context_bitmask & (AudioContext::LIVE_AUDIO | AudioContext::GAME)) {
+ // lc3_stereo_24_2_1
+ requirement = {
+ CodecSpecificConfigurationLtv::SamplingFrequency::HZ24000,
+ CodecSpecificConfigurationLtv::FrameDuration::US10000,
+ };
+ } else if (context_bitmask & (AudioContext::INSTRUCTIONAL)) {
+ // lc3_mono_16_2
+ requirement = {
+ CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000,
+ CodecSpecificConfigurationLtv::FrameDuration::US10000,
+ };
+ } else if (context_bitmask &
+ (AudioContext::SOUND_EFFECTS | AudioContext::UNSPECIFIED)) {
+ // lc3_stereo_16_2
+ requirement = {
+ CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000,
+ CodecSpecificConfigurationLtv::FrameDuration::US10000,
+ };
+ } else if (context_bitmask &
+ (AudioContext::ALERTS | AudioContext::NOTIFICATIONS |
+ AudioContext::EMERGENCY_ALARM)) {
+ // Default requirement: lc3_stereo_16_2
+ requirement = {
+ CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000,
+ CodecSpecificConfigurationLtv::FrameDuration::US10000,
+ };
+ } else if (context_bitmask & AudioContext::MEDIA) {
+ // Default requirement: lc3_stereo_16_2
+ // Return the 48k requirement
+ requirement = {
+ CodecSpecificConfigurationLtv::SamplingFrequency::HZ24000,
+ CodecSpecificConfigurationLtv::FrameDuration::US10000,
+ };
+ }
+ return requirement;
+}
+
bool LeAudioOffloadAudioProvider::isSubgroupConfigurationMatchedContext(
- AudioContext setting_context,
+ AudioContext requirement_context,
+ IBluetoothAudioProvider::BroadcastQuality quality,
LeAudioBroadcastSubgroupConfiguration configuration) {
// Find any valid context metadata in the bisConfigurations
// assuming the bis configuration in the same bis subgroup
// will have the same context metadata
std::optional<AudioContext> config_context = std::nullopt;
- for (auto& p : configuration.bisConfigurations)
- if (p.bisConfiguration.metadata.has_value()) {
- bool is_context_found = false;
- for (auto& metadata : p.bisConfiguration.metadata.value()) {
- if (!metadata.has_value()) continue;
- if (metadata.value().getTag() ==
- MetadataLtv::Tag::preferredAudioContexts) {
- config_context = metadata.value()
- .get<MetadataLtv::Tag::preferredAudioContexts>()
- .values;
- is_context_found = true;
- break;
- }
- }
- if (is_context_found) break;
- }
+ auto codec_requirement =
+ getCodecRequirementBasedOnContext(requirement_context.bitmask, quality);
+ std::map<CodecSpecificConfigurationLtv::Tag, CodecSpecificConfigurationLtv>
+ req_tag_map;
+ for (auto x : codec_requirement) req_tag_map[x.getTag()] = x;
- // Not found context metadata in any of the bis configuration, assume matched
- if (!config_context.has_value()) return true;
- return (setting_context.bitmask & config_context.value().bitmask);
+ for (auto& bis_cfg : configuration.bisConfigurations) {
+ // Check every sub_bis_cfg to see which match
+ for (auto& x : bis_cfg.bisConfiguration.codecConfiguration) {
+ auto p = req_tag_map.find(x.getTag());
+ if (p == req_tag_map.end()) continue;
+ if (p->second != x) {
+ LOG(WARNING) << __func__ << ": does not match for context "
+ << requirement_context.toString()
+ << ", cfg = " << x.toString();
+ return false;
+ }
+ }
+ }
+ return true;
}
ndk::ScopedAStatus
@@ -900,7 +1280,8 @@
// We will allow empty capability input, match all settings with requirements.
getBroadcastSettings();
std::vector<LeAudioBroadcastConfigurationSetting> filtered_settings;
- if (!in_remoteSinkAudioCapabilities.has_value()) {
+ if (!in_remoteSinkAudioCapabilities.has_value() ||
+ in_remoteSinkAudioCapabilities.value().empty()) {
LOG(INFO) << __func__ << ": Empty capability, get all broadcast settings";
filtered_settings = broadcast_settings;
} else {
@@ -931,45 +1312,72 @@
// Gather these suitable subgroup config in an array.
// If the setting can satisfy all requirement, we can return the setting
// with the filtered array.
- for (auto& setting : filtered_settings) {
- LeAudioBroadcastConfigurationSetting matched_setting(setting);
- matched_setting.subgroupsConfigurations.clear();
- auto total_num_bis = 0;
- bool matched_all_requirement = true;
+ auto context_bitmask =
+ in_requirement.subgroupConfigurationRequirements[0].audioContext.bitmask;
+ auto quality = in_requirement.subgroupConfigurationRequirements[0].quality;
+ LeAudioBroadcastConfigurationSetting return_setting =
+ getDefaultBroadcastSetting(context_bitmask, quality);
+ // Default setting
+ return_setting.numBis = 0;
+ return_setting.subgroupsConfigurations = {};
- for (auto& sub_req : in_requirement.subgroupConfigurationRequirements) {
- bool is_matched = false;
- for (auto& sub_cfg : setting.subgroupsConfigurations) {
- // Match the context
- if (!isSubgroupConfigurationMatchedContext(sub_req.audioContext,
- sub_cfg))
- continue;
- // Matching number of BIS
- if (sub_req.bisNumPerSubgroup != sub_cfg.bisConfigurations.size())
- continue;
- // Currently will ignore quality matching.
- matched_setting.subgroupsConfigurations.push_back(sub_cfg);
- total_num_bis += sub_cfg.bisConfigurations.size();
- is_matched = true;
- break;
+ LeAudioDataPathConfiguration path;
+ path.isoDataPathConfiguration.isTransparent = true;
+ path.dataPathId = kIsoDataPathPlatformDefault;
+
+ // Each subreq, find a setting that match
+ for (auto& sub_req : in_requirement.subgroupConfigurationRequirements) {
+ bool is_setting_matched = false;
+ for (auto setting : filtered_settings) {
+ bool is_matched = true;
+ // Check if every sub BIS config satisfy
+ for (auto& sub_group_config : setting.subgroupsConfigurations) {
+ if (!isSubgroupConfigurationMatchedContext(
+ sub_req.audioContext, sub_req.quality, sub_group_config)) {
+ is_matched = false;
+ break;
+ }
+ path.isoDataPathConfiguration.codecId =
+ sub_group_config.bisConfigurations[0].bisConfiguration.codecId;
+ // Also modify the subgroup config to match the context
+ modifySubgroupConfiguration(sub_group_config, context_bitmask);
}
- // There is an unmatched requirement, this setting cannot be used
- if (!is_matched) {
- matched_all_requirement = false;
+
+ if (is_matched) {
+ is_setting_matched = true;
+ for (auto& sub_group_config : setting.subgroupsConfigurations)
+ return_setting.subgroupsConfigurations.push_back(sub_group_config);
break;
}
}
- if (!matched_all_requirement) continue;
-
- matched_setting.numBis = total_num_bis;
- // Return the filtered setting if all requirement satified
- *_aidl_return = matched_setting;
- return ndk::ScopedAStatus::ok();
+ if (!is_setting_matched) {
+ LOG(WARNING) << __func__
+ << ": Cannot find a setting that match requirement "
+ << sub_req.toString();
+ return ndk::ScopedAStatus::ok();
+ }
}
- LOG(WARNING) << __func__ << ": Cannot match any requirement";
+ // Populate all numBis
+ for (auto& sub_group_config : return_setting.subgroupsConfigurations) {
+ for (auto& sub_bis_config : sub_group_config.bisConfigurations) {
+ return_setting.numBis += sub_bis_config.numBis;
+ }
+ }
+ return_setting.phy = std::vector<Phy>(return_setting.numBis, Phy::TWO_M);
+ // Populate data path config
+ return_setting.dataPathConfiguration = path;
+ // TODO: Workaround for STEREO configs maxSduOctets being doubled
+ if (context_bitmask & (AudioContext::LIVE_AUDIO | AudioContext::GAME |
+ AudioContext::SOUND_EFFECTS |
+ AudioContext::UNSPECIFIED | AudioContext::MEDIA)) {
+ return_setting.maxSduOctets /= 2;
+ }
+ LOG(INFO) << __func__
+ << ": Combined setting that match: " << return_setting.toString();
+ *_aidl_return = return_setting;
return ndk::ScopedAStatus::ok();
};
diff --git a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
index 06cd405..043d923 100644
--- a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
+++ b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
@@ -122,8 +122,9 @@
bool isCapabilitiesMatchedCodecConfiguration(
std::vector<CodecSpecificConfigurationLtv>& codec_cfg,
std::vector<CodecSpecificCapabilitiesLtv> codec_capabilities);
- bool isMatchedAseConfiguration(LeAudioAseConfiguration setting_cfg,
- LeAudioAseConfiguration requirement_cfg);
+ bool filterMatchedAseConfiguration(
+ LeAudioAseConfiguration& setting_cfg,
+ const LeAudioAseConfiguration& requirement_cfg);
bool isMatchedBISConfiguration(
LeAudioBisConfiguration bis_cfg,
const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities);
@@ -138,7 +139,8 @@
direction_configurations,
const std::vector<std::optional<AseDirectionRequirement>>& requirements,
std::optional<std::vector<std::optional<AseDirectionConfiguration>>>&
- valid_direction_configurations);
+ valid_direction_configurations,
+ bool is_exact);
std::optional<LeAudioAseConfigurationSetting>
getCapabilitiesMatchedAseConfigurationSettings(
IBluetoothAudioProvider::LeAudioAseConfigurationSetting& setting,
@@ -148,7 +150,8 @@
getRequirementMatchedAseConfigurationSettings(
IBluetoothAudioProvider::LeAudioAseConfigurationSetting& setting,
const IBluetoothAudioProvider::LeAudioConfigurationRequirement&
- requirement);
+ requirement,
+ bool is_exact);
bool isMatchedQosRequirement(LeAudioAseQosConfiguration setting_qos,
AseQosDirectionRequirement requirement_qos);
std::optional<LeAudioBroadcastConfigurationSetting>
@@ -160,10 +163,20 @@
uint8_t direction,
const IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement&
qosRequirement,
- std::vector<LeAudioAseConfigurationSetting>& ase_configuration_settings);
+ std::vector<LeAudioAseConfigurationSetting>& ase_configuration_settings,
+ bool is_exact);
bool isSubgroupConfigurationMatchedContext(
AudioContext requirement_context,
+ IBluetoothAudioProvider::BroadcastQuality quality,
LeAudioBroadcastSubgroupConfiguration configuration);
+ std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
+ matchWithRequirement(
+ std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>&
+ matched_ase_configuration_settings,
+ const std::vector<
+ IBluetoothAudioProvider::LeAudioConfigurationRequirement>&
+ in_requirements,
+ bool is_exact);
};
class LeAudioOffloadOutputAudioProvider : public LeAudioOffloadAudioProvider {
diff --git a/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
index ec63831..66cca0b 100644
--- a/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
+++ b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
@@ -4177,6 +4177,7 @@
CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies();
sampling_rate.bitmask =
CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ48000 |
+ CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ24000 |
CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ16000;
auto frame_duration =
CodecSpecificCapabilitiesLtv::SupportedFrameDurations();
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.cpp b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.cpp
index 5429a8f..780154a 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.cpp
@@ -267,7 +267,7 @@
ase_configuration_settings_.clear();
configurations_.clear();
auto loaded = LoadContent(kLeAudioSetConfigs, kLeAudioSetScenarios,
- CodecLocation::HOST);
+ CodecLocation::ADSP);
if (!loaded)
LOG(ERROR) << ": Unable to load le audio set configuration files.";
} else
@@ -371,7 +371,6 @@
CodecSpecificConfigurationLtv::CodecFrameBlocksPerSDU();
frame_sdu_structure.value = codec_frames_blocks_per_sdu;
ase.codecConfiguration.push_back(frame_sdu_structure);
- // TODO: Channel count
}
void AudioSetConfigurationProviderJson::populateAseConfiguration(
@@ -415,8 +414,53 @@
}
void AudioSetConfigurationProviderJson::populateAseQosConfiguration(
- LeAudioAseQosConfiguration& qos,
- const le_audio::QosConfiguration* qos_cfg) {
+ LeAudioAseQosConfiguration& qos, const le_audio::QosConfiguration* qos_cfg,
+ LeAudioAseConfiguration& ase) {
+ std::optional<CodecSpecificConfigurationLtv::CodecFrameBlocksPerSDU>
+ frameBlock = std::nullopt;
+ std::optional<CodecSpecificConfigurationLtv::FrameDuration> frameDuration =
+ std::nullopt;
+ std::optional<CodecSpecificConfigurationLtv::AudioChannelAllocation>
+ allocation = std::nullopt;
+ std::optional<CodecSpecificConfigurationLtv::OctetsPerCodecFrame> octet =
+ std::nullopt;
+
+ for (auto& cfg_ltv : ase.codecConfiguration) {
+ auto tag = cfg_ltv.getTag();
+ if (tag == CodecSpecificConfigurationLtv::codecFrameBlocksPerSDU) {
+ frameBlock =
+ cfg_ltv.get<CodecSpecificConfigurationLtv::codecFrameBlocksPerSDU>();
+ } else if (tag == CodecSpecificConfigurationLtv::frameDuration) {
+ frameDuration =
+ cfg_ltv.get<CodecSpecificConfigurationLtv::frameDuration>();
+ } else if (tag == CodecSpecificConfigurationLtv::audioChannelAllocation) {
+ allocation =
+ cfg_ltv.get<CodecSpecificConfigurationLtv::audioChannelAllocation>();
+ } else if (tag == CodecSpecificConfigurationLtv::octetsPerCodecFrame) {
+ octet = cfg_ltv.get<CodecSpecificConfigurationLtv::octetsPerCodecFrame>();
+ }
+ }
+
+ int frameBlockValue = 1;
+ if (frameBlock.has_value()) frameBlockValue = frameBlock.value().value;
+
+ // Populate maxSdu
+ if (allocation.has_value() && octet.has_value()) {
+ auto channel_count = std::bitset<32>(allocation.value().bitmask).count();
+ qos.maxSdu = channel_count * octet.value().value * frameBlockValue;
+ }
+ // Populate sduIntervalUs
+ if (frameDuration.has_value()) {
+ switch (frameDuration.value()) {
+ case CodecSpecificConfigurationLtv::FrameDuration::US7500:
+ qos.sduIntervalUs = 7500;
+ break;
+ case CodecSpecificConfigurationLtv::FrameDuration::US10000:
+ qos.sduIntervalUs = 10000;
+ break;
+ }
+ qos.sduIntervalUs *= frameBlockValue;
+ }
qos.maxTransportLatencyMs = qos_cfg->max_transport_latency();
qos.retransmissionNum = qos_cfg->retransmission_number();
}
@@ -436,7 +480,7 @@
populateAseConfiguration(ase, flat_subconfig, qos_cfg);
// Translate into LeAudioAseQosConfiguration
- populateAseQosConfiguration(qos, qos_cfg);
+ populateAseQosConfiguration(qos, qos_cfg, ase);
// Translate location to data path id
switch (location) {
@@ -453,6 +497,8 @@
path.dataPathId = kIsoDataPathPlatformDefault;
break;
}
+ // Move codecId to iso data path
+ path.isoDataPathConfiguration.codecId = ase.codecId.value();
direction_conf.aseConfiguration = ase;
direction_conf.qosConfiguration = qos;
@@ -678,7 +724,8 @@
media_context.bitmask =
(AudioContext::ALERTS | AudioContext::INSTRUCTIONAL |
AudioContext::NOTIFICATIONS | AudioContext::EMERGENCY_ALARM |
- AudioContext::UNSPECIFIED | AudioContext::MEDIA);
+ AudioContext::UNSPECIFIED | AudioContext::MEDIA |
+ AudioContext::SOUND_EFFECTS);
AudioContext conversational_context = AudioContext();
conversational_context.bitmask =
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.h b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.h
index ce91fca..6639009 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.h
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.h
@@ -79,7 +79,7 @@
static void populateAseQosConfiguration(
LeAudioAseQosConfiguration& qos,
- const le_audio::QosConfiguration* qos_cfg);
+ const le_audio::QosConfiguration* qos_cfg, LeAudioAseConfiguration& ase);
static AseDirectionConfiguration SetConfigurationFromFlatSubconfig(
const le_audio::AudioSetSubConfiguration* flat_subconfig,
diff --git a/bluetooth/finder/aidl/default/BluetoothFinder.cpp b/bluetooth/finder/aidl/default/BluetoothFinder.cpp
index 236a1f8..a43846b 100644
--- a/bluetooth/finder/aidl/default/BluetoothFinder.cpp
+++ b/bluetooth/finder/aidl/default/BluetoothFinder.cpp
@@ -19,7 +19,7 @@
namespace aidl::android::hardware::bluetooth::finder::impl {
::ndk::ScopedAStatus BluetoothFinder::sendEids(const ::std::vector<Eid>& keys) {
- keys_.insert(keys_.end(), keys.begin(), keys.end());
+ keys_.assign(keys.begin(), keys.end());
return ::ndk::ScopedAStatus::ok();
}
diff --git a/broadcastradio/aidl/Android.bp b/broadcastradio/aidl/Android.bp
index 187f283..82ee949 100644
--- a/broadcastradio/aidl/Android.bp
+++ b/broadcastradio/aidl/Android.bp
@@ -36,6 +36,9 @@
sdk_version: "module_current",
min_sdk_version: "Tiramisu",
},
+ rust: {
+ enabled: true,
+ },
},
versions_with_info: [
{
@@ -51,3 +54,27 @@
frozen: true,
}
+
+// Note: This should always be one version ahead of the last frozen version
+latest_android_hardware_broadcastradio = "android.hardware.broadcastradio-V2"
+
+cc_defaults {
+ name: "latest_android_hardware_broadcastradio_ndk_static",
+ static_libs: [
+ latest_android_hardware_broadcastradio + "-ndk",
+ ],
+}
+
+java_defaults {
+ name: "latest_android_hardware_broadcastradio_java_static",
+ static_libs: [
+ latest_android_hardware_broadcastradio + "-java",
+ ],
+}
+
+rust_defaults {
+ name: "latest_android_hardware_broadcastradio_rust",
+ rustlibs: [
+ latest_android_hardware_broadcastradio + "-rust",
+ ],
+}
diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/IdentifierType.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/IdentifierType.aidl
index 4a95a41..4d29743 100644
--- a/broadcastradio/aidl/android/hardware/broadcastradio/IdentifierType.aidl
+++ b/broadcastradio/aidl/android/hardware/broadcastradio/IdentifierType.aidl
@@ -174,7 +174,7 @@
* - 13 bit: Fractional bits of longitude
* - 8 bit: Integer bits of longitude
* - 1 bit: 0 for east and 1 for west for longitude
- * - 1 bit: 0, representing latitude
+ * - 1 bit: 0, representing longitude
* - 5 bit: pad of zeros separating longitude and latitude
* - 4 bit: Bits 4:7 of altitude
* - 13 bit: Fractional bits of latitude
diff --git a/broadcastradio/aidl/default/Android.bp b/broadcastradio/aidl/default/Android.bp
index d7bb751..b620a59 100644
--- a/broadcastradio/aidl/default/Android.bp
+++ b/broadcastradio/aidl/default/Android.bp
@@ -20,14 +20,17 @@
// all of the 'license_kinds' from "hardware_interfaces_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
+ default_team: "trendy_team_aaos_framework",
default_applicable_licenses: ["hardware_interfaces_license"],
}
cc_defaults {
name: "BroadcastRadioHalDefaults",
+ defaults: [
+ "latest_android_hardware_broadcastradio_ndk_static",
+ ],
static_libs: [
- "android.hardware.broadcastradio-V2-ndk",
- "android.hardware.broadcastradio@common-utils-aidl-lib-V2",
+ "android.hardware.broadcastradio@common-utils-aidl-lib-latest",
"android.hardware.broadcastradio@common-utils-lib",
],
shared_libs: [
@@ -79,12 +82,12 @@
// TODO(b/307611931): avoid fuzzing on vendor until hermiticity issue is fixed
// vendor: true,
defaults: [
+ "latest_android_hardware_broadcastradio_ndk_static",
"BroadcastRadioHalDefaults",
"service_fuzzer_defaults",
],
static_libs: [
"DefaultBroadcastRadioHal",
- "android.hardware.broadcastradio-V2-ndk",
],
srcs: [
"fuzzer.cpp",
diff --git a/broadcastradio/aidl/rust_impl/Android.bp b/broadcastradio/aidl/rust_impl/Android.bp
new file mode 100644
index 0000000..d6f984e
--- /dev/null
+++ b/broadcastradio/aidl/rust_impl/Android.bp
@@ -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.
+ */
+
+rust_binary {
+ name: "android.hardware.broadcastradio-rust-service",
+ relative_install_path: "hw",
+ vendor: true,
+ srcs: ["src/*.rs"],
+ crate_root: "src/main.rs",
+ defaults: [
+ "latest_android_hardware_broadcastradio_rust",
+ ],
+ vintf_fragments: ["broadcastradio-rust-service.xml"],
+ init_rc: ["broadcastradio-rust-service.rc"],
+ rustlibs: [
+ "libbinder_rs",
+ ],
+}
diff --git a/broadcastradio/aidl/rust_impl/README.md b/broadcastradio/aidl/rust_impl/README.md
new file mode 100644
index 0000000..17e0c18
--- /dev/null
+++ b/broadcastradio/aidl/rust_impl/README.md
@@ -0,0 +1,13 @@
+# Rust Skeleton BroadcastRadio HAL implementation.
+
+WARNING: This is not a reference BroadcastRadio HAL implementation and does
+not contain any actual implementation.
+
+This folder contains a skeleton broadcast radio HAL implementation in Rust to
+demonstrate how vendor may implement a Rust broadcast radio HAL. To run this
+broadcast radio HAL, include `android.hardware.broadcastradio-rust-service`
+in your image.
+
+This implementation returns `StatusCode::UNKNOWN_ERROR` for all operations
+and does not pass VTS/CTS. Vendor must replace the logic in
+`default_broadcastradio_hal.rs` with the actual implementation
\ No newline at end of file
diff --git a/broadcastradio/aidl/rust_impl/broadcastradio-rust-service.rc b/broadcastradio/aidl/rust_impl/broadcastradio-rust-service.rc
new file mode 100644
index 0000000..4dad616
--- /dev/null
+++ b/broadcastradio/aidl/rust_impl/broadcastradio-rust-service.rc
@@ -0,0 +1,5 @@
+service vendor.broadcastradio-default /vendor/bin/hw/android.hardware.broadcastradio-service.default
+ interface aidl android.hardware.broadcastradio.IBroadcastRadio/amfm
+ class hal
+ user audioserver
+ group audio
diff --git a/broadcastradio/aidl/rust_impl/broadcastradio-rust-service.xml b/broadcastradio/aidl/rust_impl/broadcastradio-rust-service.xml
new file mode 100644
index 0000000..ced2d78
--- /dev/null
+++ b/broadcastradio/aidl/rust_impl/broadcastradio-rust-service.xml
@@ -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.
+ -->
+
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.broadcastradio</name>
+ <version>2</version>
+ <fqname>IBroadcastRadio/amfm</fqname>
+ </hal>
+</manifest>
diff --git a/broadcastradio/aidl/rust_impl/src/default_broadcastradio_hal.rs b/broadcastradio/aidl/rust_impl/src/default_broadcastradio_hal.rs
new file mode 100644
index 0000000..ea2f9d3
--- /dev/null
+++ b/broadcastradio/aidl/rust_impl/src/default_broadcastradio_hal.rs
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+use android_hardware_broadcastradio::aidl::android::hardware::broadcastradio::{
+ AmFmRegionConfig::AmFmRegionConfig,
+ AnnouncementType::AnnouncementType,
+ ConfigFlag::ConfigFlag,
+ DabTableEntry::DabTableEntry,
+ IAnnouncementListener::IAnnouncementListener,
+ IBroadcastRadio::IBroadcastRadio,
+ ICloseHandle::ICloseHandle,
+ ITunerCallback::ITunerCallback,
+ ProgramFilter::ProgramFilter,
+ ProgramSelector::ProgramSelector,
+ Properties::Properties,
+ VendorKeyValue::VendorKeyValue,
+};
+use binder::{Interface, Result as BinderResult, StatusCode, Strong};
+use std::vec::Vec;
+
+/// This struct is defined to implement IBroadcastRadio AIDL interface.
+pub struct DefaultBroadcastRadioHal;
+
+impl Interface for DefaultBroadcastRadioHal {}
+
+impl IBroadcastRadio for DefaultBroadcastRadioHal {
+ fn getAmFmRegionConfig(&self, _full : bool) -> BinderResult<AmFmRegionConfig> {
+ Err(StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn getDabRegionConfig(&self) -> BinderResult<Vec<DabTableEntry>> {
+ Err(StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn getProperties(&self) -> BinderResult<Properties> {
+ Err(StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn getImage(&self, _id : i32) -> BinderResult<Vec<u8>> {
+ Err(StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn setTunerCallback(&self, _callback : &Strong<dyn ITunerCallback>) -> BinderResult<()> {
+ Err(StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn unsetTunerCallback(&self) -> BinderResult<()> {
+ Err(StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn tune(&self, _program : &ProgramSelector) -> BinderResult<()> {
+ Err(StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn seek(&self, _direction_up : bool, _skip_sub_channel : bool) -> BinderResult<()> {
+ Err(StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn step(&self, _direction_up : bool) -> BinderResult<()> {
+ Err(StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn cancel(&self) -> BinderResult<()> {
+ Err(StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn startProgramListUpdates(&self, _filter : &ProgramFilter) -> BinderResult<()> {
+ Err(StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn stopProgramListUpdates(&self) -> BinderResult<()> {
+ Err(StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn isConfigFlagSet(&self, _flag : ConfigFlag) -> BinderResult<bool> {
+ Err(StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn setConfigFlag(&self, _flag : ConfigFlag, _value : bool) -> BinderResult<()> {
+ Err(StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn setParameters(&self, _parameters : &[VendorKeyValue]) -> BinderResult<Vec<VendorKeyValue>> {
+ Err(StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn getParameters(&self, _parameters : &[String]) -> BinderResult<Vec<VendorKeyValue>> {
+ Err(StatusCode::UNKNOWN_ERROR.into())
+ }
+
+ fn registerAnnouncementListener(&self, _listener : &Strong<dyn IAnnouncementListener>,
+ _enabled : &[AnnouncementType]) -> BinderResult<Strong<dyn ICloseHandle>> {
+ Err(StatusCode::UNKNOWN_ERROR.into())
+ }
+}
diff --git a/broadcastradio/aidl/rust_impl/src/main.rs b/broadcastradio/aidl/rust_impl/src/main.rs
new file mode 100644
index 0000000..c0bc055
--- /dev/null
+++ b/broadcastradio/aidl/rust_impl/src/main.rs
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ mod default_broadcastradio_hal;
+
+use android_hardware_broadcastradio::aidl::android::hardware::broadcastradio::IBroadcastRadio::BnBroadcastRadio;
+use crate::default_broadcastradio_hal::DefaultBroadcastRadioHal;
+
+fn main() {
+ binder::ProcessState::start_thread_pool();
+ let my_service = DefaultBroadcastRadioHal;
+ let service_name = "android.hardware.broadcastradio.IBroadcastRadio/amfm";
+ let my_service_binder = BnBroadcastRadio::new_binder(
+ my_service,
+ binder::BinderFeatures::default(),
+ );
+ binder::add_service(service_name, my_service_binder.as_binder())
+ .expect(format!("Failed to register {}?", service_name).as_str());
+ // Does not return.
+ binder::ProcessState::join_thread_pool()
+}
diff --git a/broadcastradio/aidl/vts/Android.bp b/broadcastradio/aidl/vts/Android.bp
index 87e48a9..78c377d 100644
--- a/broadcastradio/aidl/vts/Android.bp
+++ b/broadcastradio/aidl/vts/Android.bp
@@ -18,6 +18,7 @@
// all of the 'license_kinds' from "hardware_interfaces_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
+ default_team: "trendy_team_aaos_framework",
default_applicable_licenses: ["hardware_interfaces_license"],
}
@@ -25,6 +26,7 @@
name: "VtsHalBroadcastradioAidlTargetTest",
defaults: [
"VtsHalTargetTestDefaults",
+ "latest_android_hardware_broadcastradio_ndk_static",
"use_libaidlvintf_gtest_helper_static",
],
tidy_timeout_srcs: ["src/*.cpp"],
@@ -35,9 +37,7 @@
"libxml2",
],
static_libs: [
- "android.hardware.broadcastradio-V2-ndk",
- "android.hardware.broadcastradio@common-utils-aidl-lib-V2",
- "android.hardware.broadcastradio@vts-utils-lib",
+ "android.hardware.broadcastradio@common-utils-aidl-lib-latest",
"libgmock",
],
test_suites: [
diff --git a/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp b/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp
index 9633ebb..ee0c639 100644
--- a/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp
+++ b/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp
@@ -193,7 +193,7 @@
MATCHER_P(InfoHasId, id,
std::string(negation ? "does not contain" : "contains") + " " + id.toString()) {
- vector<int> ids = bcutils::getAllIds(arg.selector, id.type);
+ vector<int64_t> ids = bcutils::getAllIds(arg.selector, id.type);
return ids.end() != find(ids.begin(), ids.end(), id.value);
}
@@ -697,7 +697,7 @@
LOG(DEBUG) << "Current program info: " << infoCb.toString();
// it should tune exactly to what was requested
- vector<int> freqs = bcutils::getAllIds(infoCb.selector, IdentifierType::AMFM_FREQUENCY_KHZ);
+ vector<int64_t> freqs = bcutils::getAllIds(infoCb.selector, IdentifierType::AMFM_FREQUENCY_KHZ);
EXPECT_NE(freqs.end(), find(freqs.begin(), freqs.end(), freq))
<< "FM freq " << freq << " kHz is not sent back by callback.";
}
@@ -829,7 +829,7 @@
LOG(DEBUG) << "Current program info: " << infoCb.toString();
// it should tune exactly to what was requested
- vector<int> freqs = bcutils::getAllIds(infoCb.selector, IdentifierType::DAB_FREQUENCY_KHZ);
+ vector<int64_t> freqs = bcutils::getAllIds(infoCb.selector, IdentifierType::DAB_FREQUENCY_KHZ);
EXPECT_NE(freqs.end(), find(freqs.begin(), freqs.end(), freq))
<< "DAB freq " << freq << " kHz is not sent back by callback.";
}
@@ -1152,7 +1152,7 @@
int expectedResultSize = 0;
uint64_t expectedFreq = 0;
for (const auto& program : *completeList) {
- vector<int> amfmIds =
+ vector<int64_t> amfmIds =
bcutils::getAllIds(program.selector, IdentifierType::AMFM_FREQUENCY_KHZ);
EXPECT_LE(amfmIds.size(), 1u);
if (amfmIds.size() == 0) {
@@ -1238,7 +1238,8 @@
}
for (const auto& program : *list) {
- vector<int> nameIds = bcutils::getAllIds(program.selector, IdentifierType::HD_STATION_NAME);
+ vector<int64_t> nameIds =
+ bcutils::getAllIds(program.selector, IdentifierType::HD_STATION_NAME);
EXPECT_LE(nameIds.size(), 1u);
if (nameIds.size() == 0) {
continue;
diff --git a/broadcastradio/common/utilsaidl/Android.bp b/broadcastradio/common/utilsaidl/Android.bp
index e3bdfdd..d88081f 100644
--- a/broadcastradio/common/utilsaidl/Android.bp
+++ b/broadcastradio/common/utilsaidl/Android.bp
@@ -47,17 +47,28 @@
],
}
+cc_library_static {
+ name: "android.hardware.broadcastradio@common-utils-aidl-lib-latest",
+ defaults: [
+ "BroadcastRadioUtilsDefaults",
+ "latest_android_hardware_broadcastradio_ndk_static",
+ ],
+ srcs: [
+ "src/UtilsV2.cpp",
+ ],
+}
+
cc_test {
name: "broadcastradio_utils_aidl_test",
defaults: [
"BroadcastRadioUtilsDefaults",
+ "latest_android_hardware_broadcastradio_ndk_static",
],
srcs: [
"test/*.cpp",
],
static_libs: [
- "android.hardware.broadcastradio@common-utils-aidl-lib-V2",
- "android.hardware.broadcastradio-V2-ndk",
+ "android.hardware.broadcastradio@common-utils-aidl-lib-latest",
],
test_suites: ["general-tests"],
}
diff --git a/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h b/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h
index 25c96d0..a34ee10 100644
--- a/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h
+++ b/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h
@@ -121,7 +121,7 @@
/**
* Returns all IDs of a given type.
*/
-std::vector<int> getAllIds(const ProgramSelector& sel, const IdentifierType& type);
+std::vector<int64_t> getAllIds(const ProgramSelector& sel, const IdentifierType& type);
/**
* Checks, if a given selector is supported by the radio module.
diff --git a/broadcastradio/common/utilsaidl/src/Utils.cpp b/broadcastradio/common/utilsaidl/src/Utils.cpp
index ddc5b8d..3de1866 100644
--- a/broadcastradio/common/utilsaidl/src/Utils.cpp
+++ b/broadcastradio/common/utilsaidl/src/Utils.cpp
@@ -178,8 +178,8 @@
return getId(sel, type);
}
-vector<int> getAllIds(const ProgramSelector& sel, const IdentifierType& type) {
- vector<int> ret;
+vector<int64_t> getAllIds(const ProgramSelector& sel, const IdentifierType& type) {
+ vector<int64_t> ret;
// iterate through primaryId and secondaryIds
for (auto it = begin(sel); it != end(sel); it++) {
@@ -296,7 +296,12 @@
sel.primaryId.type > IdentifierType::VENDOR_END)) {
return false;
}
- return isValid(sel.primaryId);
+ for (auto it = begin(sel); it != end(sel); it++) {
+ if (!isValid(*it)) {
+ return false;
+ }
+ }
+ return true;
}
ProgramIdentifier makeIdentifier(IdentifierType type, int64_t value) {
diff --git a/broadcastradio/common/utilsaidl/src/UtilsV2.cpp b/broadcastradio/common/utilsaidl/src/UtilsV2.cpp
index 6c75759..56365c5 100644
--- a/broadcastradio/common/utilsaidl/src/UtilsV2.cpp
+++ b/broadcastradio/common/utilsaidl/src/UtilsV2.cpp
@@ -102,15 +102,16 @@
expect(val < 1000u, "SXM channel < 1000");
break;
case IdentifierType::HD_STATION_LOCATION: {
+ val >>= 26;
uint64_t latitudeBit = val & 0x1;
- expect(latitudeBit == 1u, "Latitude comes first");
- val >>= 27;
+ expect(latitudeBit == 0u, "Longitude comes first");
+ val >>= 1;
uint64_t latitudePad = val & 0x1Fu;
- expect(latitudePad == 0u, "Latitude padding");
- val >>= 5;
+ expect(latitudePad == 0u, "Longitude padding");
+ val >>= 31;
uint64_t longitudeBit = val & 0x1;
- expect(longitudeBit == 1u, "Longitude comes next");
- val >>= 27;
+ expect(longitudeBit == 1u, "Latitude comes next");
+ val >>= 1;
uint64_t longitudePad = val & 0x1Fu;
expect(longitudePad == 0u, "Latitude padding");
break;
@@ -135,7 +136,12 @@
sel.primaryId.type > IdentifierType::VENDOR_END)) {
return false;
}
- return isValidV2(sel.primaryId);
+ for (auto it = begin(sel); it != end(sel); it++) {
+ if (!isValidV2(*it)) {
+ return false;
+ }
+ }
+ return true;
}
bool isValidMetadataV2(const Metadata& metadata) {
diff --git a/broadcastradio/common/utilsaidl/test/BroadcastRadioUtilsCommonTest.cpp b/broadcastradio/common/utilsaidl/test/BroadcastRadioUtilsCommonTest.cpp
new file mode 100644
index 0000000..b71bf03
--- /dev/null
+++ b/broadcastradio/common/utilsaidl/test/BroadcastRadioUtilsCommonTest.cpp
@@ -0,0 +1,421 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <broadcastradio-utils-aidl/Utils.h>
+#include <broadcastradio-utils-aidl/UtilsV2.h>
+#include <gtest/gtest.h>
+
+namespace aidl::android::hardware::broadcastradio {
+
+namespace {
+constexpr int64_t kFmFrequencyKHz = 97900;
+constexpr uint32_t kDabSid = 0x0000C221u;
+constexpr int kDabEccCode = 0xE1u;
+constexpr int kDabSCIdS = 0x1u;
+constexpr uint64_t kDabSidExt = static_cast<uint64_t>(kDabSid) |
+ (static_cast<uint64_t>(kDabEccCode) << 32) |
+ (static_cast<uint64_t>(kDabSCIdS) << 40);
+constexpr uint32_t kDabEnsemble = 0xCE15u;
+constexpr uint64_t kDabFrequencyKhz = 225648u;
+constexpr uint64_t kHdStationId = 0xA0000001u;
+constexpr uint64_t kHdSubChannel = 1u;
+constexpr uint64_t kHdStationLocation = 0x44E647003665CF6u;
+constexpr uint64_t kHdStationLocationInvalid = 0x4E647007665CF6u;
+constexpr uint64_t kHdFrequency = 97700u;
+constexpr int64_t kRdsValue = 0xBEEF;
+
+struct IsValidIdentifierTestCase {
+ std::string name;
+ ProgramIdentifier id;
+ bool valid;
+};
+
+std::vector<IsValidIdentifierTestCase> getIsValidIdentifierTestCases() {
+ return std::vector<IsValidIdentifierTestCase>({
+ IsValidIdentifierTestCase{.name = "invalid_id_type",
+ .id = utils::makeIdentifier(IdentifierType::INVALID, 0),
+ .valid = false},
+ IsValidIdentifierTestCase{
+ .name = "invalid_dab_frequency_high",
+ .id = utils::makeIdentifier(IdentifierType::DAB_FREQUENCY_KHZ, 10000000u),
+ .valid = false},
+ IsValidIdentifierTestCase{
+ .name = "invalid_dab_frequency_low",
+ .id = utils::makeIdentifier(IdentifierType::DAB_FREQUENCY_KHZ, 100000u),
+ .valid = false},
+ IsValidIdentifierTestCase{
+ .name = "valid_dab_frequency",
+ .id = utils::makeIdentifier(IdentifierType::DAB_FREQUENCY_KHZ, 1000000u),
+ .valid = true},
+ IsValidIdentifierTestCase{
+ .name = "invalid_am_fm_frequency_high",
+ .id = utils::makeIdentifier(IdentifierType::AMFM_FREQUENCY_KHZ, 10000000u),
+ .valid = false},
+ IsValidIdentifierTestCase{
+ .name = "invalid_am_fm_frequency_low",
+ .id = utils::makeIdentifier(IdentifierType::AMFM_FREQUENCY_KHZ, 100u),
+ .valid = false},
+ IsValidIdentifierTestCase{.name = "valid_am_fm_frequency",
+ .id = utils::makeIdentifier(
+ IdentifierType::AMFM_FREQUENCY_KHZ, kFmFrequencyKHz),
+ .valid = true},
+ IsValidIdentifierTestCase{
+ .name = "drmo_frequency_high",
+ .id = utils::makeIdentifier(IdentifierType::DRMO_FREQUENCY_KHZ, 10000000u),
+ .valid = false},
+ IsValidIdentifierTestCase{
+ .name = "drmo_frequency_low",
+ .id = utils::makeIdentifier(IdentifierType::DRMO_FREQUENCY_KHZ, 100u),
+ .valid = false},
+ IsValidIdentifierTestCase{.name = "valid_drmo_frequency",
+ .id = utils::makeIdentifier(
+ IdentifierType::DRMO_FREQUENCY_KHZ, kFmFrequencyKHz),
+ .valid = true},
+ IsValidIdentifierTestCase{.name = "invalid_rds_low",
+ .id = utils::makeIdentifier(IdentifierType::RDS_PI, 0x0),
+ .valid = false},
+ IsValidIdentifierTestCase{.name = "invalid_rds_high",
+ .id = utils::makeIdentifier(IdentifierType::RDS_PI, 0x10000),
+ .valid = false},
+ IsValidIdentifierTestCase{.name = "valid_rds",
+ .id = utils::makeIdentifier(IdentifierType::RDS_PI, 0x1000),
+ .valid = true},
+ IsValidIdentifierTestCase{
+ .name = "invalid_hd_id_zero",
+ .id = utils::makeSelectorHd(/* stationId= */ 0u, kHdSubChannel, kHdFrequency)
+ .primaryId,
+ .valid = false},
+ IsValidIdentifierTestCase{
+ .name = "invalid_hd_suchannel",
+ .id = utils::makeSelectorHd(kHdStationId, /* subChannel= */ 8u, kHdFrequency)
+ .primaryId,
+ .valid = false},
+ IsValidIdentifierTestCase{
+ .name = "invalid_hd_frequency_low",
+ .id = utils::makeSelectorHd(kHdStationId, kHdSubChannel, /* frequency= */ 100u)
+ .primaryId,
+ .valid = false},
+ IsValidIdentifierTestCase{
+ .name = "valid_hd_id",
+ .id = utils::makeSelectorHd(kHdStationId, kHdSubChannel, kHdFrequency)
+ .primaryId,
+ .valid = true},
+ IsValidIdentifierTestCase{
+ .name = "invalid_hd_station_name",
+ .id = utils::makeIdentifier(IdentifierType::HD_STATION_NAME, 0x41422D464D),
+ .valid = false},
+ IsValidIdentifierTestCase{
+ .name = "valid_hd_station_name",
+ .id = utils::makeIdentifier(IdentifierType::HD_STATION_NAME, 0x414231464D),
+ .valid = true},
+ IsValidIdentifierTestCase{
+ .name = "invalid_dab_sid",
+ .id = utils::makeIdentifier(IdentifierType::DAB_SID_EXT, 0x0E100000000u),
+ .valid = false},
+ IsValidIdentifierTestCase{
+ .name = "invalid_dab_ecc_low",
+ .id = utils::makeIdentifier(IdentifierType::DAB_SID_EXT, 0x0F700000221u),
+ .valid = false},
+ IsValidIdentifierTestCase{
+ .name = "invalid_dab_ecc_high",
+ .id = utils::makeIdentifier(IdentifierType::DAB_SID_EXT, 0x09900000221u),
+ .valid = false},
+ IsValidIdentifierTestCase{
+ .name = "valid_dab_sid_ext",
+ .id = utils::makeIdentifier(IdentifierType::DAB_SID_EXT, kDabSidExt),
+ .valid = true},
+ IsValidIdentifierTestCase{
+ .name = "invalid_dab_ensemble_zero",
+ .id = utils::makeIdentifier(IdentifierType::DAB_ENSEMBLE, 0x0),
+ .valid = false},
+ IsValidIdentifierTestCase{
+ .name = "invalid_dab_ensemble_high",
+ .id = utils::makeIdentifier(IdentifierType::DAB_ENSEMBLE, 0x10000),
+ .valid = false},
+ IsValidIdentifierTestCase{
+ .name = "valid_dab_ensemble",
+ .id = utils::makeIdentifier(IdentifierType::DAB_ENSEMBLE, kDabEnsemble),
+ .valid = true},
+ IsValidIdentifierTestCase{.name = "invalid_dab_scid_low",
+ .id = utils::makeIdentifier(IdentifierType::DAB_SCID, 0xF),
+ .valid = false},
+ IsValidIdentifierTestCase{.name = "invalid_dab_scid_high",
+ .id = utils::makeIdentifier(IdentifierType::DAB_SCID, 0x1000),
+ .valid = false},
+ IsValidIdentifierTestCase{.name = "valid_dab_scid",
+ .id = utils::makeIdentifier(IdentifierType::DAB_SCID, 0x100),
+ .valid = true},
+ IsValidIdentifierTestCase{
+ .name = "invalid_drmo_id_zero",
+ .id = utils::makeIdentifier(IdentifierType::DRMO_SERVICE_ID, 0x0),
+ .valid = false},
+ IsValidIdentifierTestCase{
+ .name = "invalid_drmo_id_high",
+ .id = utils::makeIdentifier(IdentifierType::DRMO_SERVICE_ID, 0x1000000),
+ .valid = false},
+ IsValidIdentifierTestCase{
+ .name = "valid_drmo_id",
+ .id = utils::makeIdentifier(IdentifierType::DRMO_SERVICE_ID, 0x100000),
+ .valid = true},
+ });
+}
+
+std::vector<IsValidIdentifierTestCase> getIsValidIdentifierV2TestCases() {
+ std::vector<IsValidIdentifierTestCase> testcases = getIsValidIdentifierTestCases();
+ std::vector<IsValidIdentifierTestCase> testcasesNew = std::vector<IsValidIdentifierTestCase>({
+ IsValidIdentifierTestCase{
+ .name = "invalid_hd_station_location_id",
+ .id = utils::makeIdentifier(IdentifierType::HD_STATION_LOCATION,
+ kHdStationLocationInvalid),
+ .valid = false},
+ IsValidIdentifierTestCase{
+ .name = "valid_hd_station_location_id",
+ .id = utils::makeIdentifier(IdentifierType::HD_STATION_LOCATION,
+ kHdStationLocation),
+ .valid = true},
+ });
+ testcases.insert(testcases.end(), testcasesNew.begin(), testcasesNew.end());
+ return testcases;
+}
+
+struct IsValidSelectorTestCase {
+ std::string name;
+ ProgramSelector sel;
+ bool valid;
+};
+
+std::vector<IsValidSelectorTestCase> getIsValidSelectorTestCases() {
+ return std::vector<IsValidSelectorTestCase>({
+ IsValidSelectorTestCase{.name = "valid_am_fm_selector",
+ .sel = utils::makeSelectorAmfm(kFmFrequencyKHz),
+ .valid = true},
+ IsValidSelectorTestCase{
+ .name = "valid_hd_selector",
+ .sel = utils::makeSelectorHd(kHdStationId, kHdSubChannel, kHdFrequency),
+ .valid = true},
+ IsValidSelectorTestCase{
+ .name = "valid_dab_selector",
+ .sel = utils::makeSelectorDab(kDabSidExt, kDabEnsemble, kDabFrequencyKhz),
+ .valid = true},
+ IsValidSelectorTestCase{.name = "valid_rds_selector",
+ .sel = ProgramSelector{.primaryId = utils::makeIdentifier(
+ IdentifierType::RDS_PI, 0x1000)},
+ .valid = true},
+ IsValidSelectorTestCase{.name = "selector_with_invalid_id",
+ .sel = utils::makeSelectorHd(kHdStationId, kHdSubChannel,
+ /* frequency= */ 100u),
+ .valid = false},
+ IsValidSelectorTestCase{
+ .name = "selector_with_invalid_primary_id_type",
+ .sel = ProgramSelector{.primaryId = utils::makeIdentifier(
+ IdentifierType::DAB_ENSEMBLE, kDabEnsemble)},
+ .valid = false},
+ IsValidSelectorTestCase{
+ .name = "selector_with_invalid_secondary_id",
+ .sel = ProgramSelector{.primaryId = utils::makeIdentifier(
+ IdentifierType::DAB_SID_EXT, kDabSidExt),
+ .secondaryIds = {utils::makeIdentifier(
+ IdentifierType::DAB_ENSEMBLE, 0x0)}},
+ .valid = false},
+ });
+}
+
+std::vector<IsValidSelectorTestCase> getIsValidSelectorV2TestCases() {
+ ProgramSelector validHdSel = utils::makeSelectorHd(kHdStationId, kHdSubChannel, kHdFrequency);
+ validHdSel.secondaryIds = {
+ utils::makeIdentifier(IdentifierType::HD_STATION_LOCATION, kHdStationLocation)};
+ ProgramSelector invalidHdSel = utils::makeSelectorHd(kHdStationId, kHdSubChannel, kHdFrequency);
+ invalidHdSel.secondaryIds = {
+ utils::makeIdentifier(IdentifierType::HD_STATION_LOCATION, kHdStationLocationInvalid)};
+ std::vector<IsValidSelectorTestCase> testcasesNew = std::vector<IsValidSelectorTestCase>(
+ {IsValidSelectorTestCase{.name = "hd_selector_with_valid_station_location",
+ .sel = validHdSel,
+ .valid = true},
+ IsValidSelectorTestCase{.name = "hd_selector_with_invalid_station_location",
+ .sel = invalidHdSel,
+ .valid = false}});
+ std::vector<IsValidSelectorTestCase> testcases = getIsValidSelectorTestCases();
+ testcases.insert(testcases.end(), testcasesNew.begin(), testcasesNew.end());
+ return testcases;
+}
+
+struct IsValidMetadataTestCase {
+ std::string name;
+ Metadata metadata;
+ bool valid;
+};
+
+std::vector<IsValidMetadataTestCase> getIsValidMetadataTestCases() {
+ return std::vector<IsValidMetadataTestCase>({
+ IsValidMetadataTestCase{.name = "valid_rds_pty",
+ .metadata = Metadata::make<Metadata::rdsPty>(1),
+ .valid = true},
+ IsValidMetadataTestCase{.name = "negative_rds_pty",
+ .metadata = Metadata::make<Metadata::rdsPty>(-1),
+ .valid = false},
+ IsValidMetadataTestCase{.name = "large_rds_pty",
+ .metadata = Metadata::make<Metadata::rdsPty>(256),
+ .valid = false},
+ IsValidMetadataTestCase{.name = "valid_rbds_pty",
+ .metadata = Metadata::make<Metadata::rbdsPty>(1),
+ .valid = true},
+ IsValidMetadataTestCase{.name = "negative_rbds_pty",
+ .metadata = Metadata::make<Metadata::rbdsPty>(-1),
+ .valid = false},
+ IsValidMetadataTestCase{.name = "large_rbds_pty",
+ .metadata = Metadata::make<Metadata::rbdsPty>(256),
+ .valid = false},
+ IsValidMetadataTestCase{
+ .name = "valid_dab_ensemble_name_short",
+ .metadata = Metadata::make<Metadata::dabEnsembleNameShort>("name"),
+ .valid = true},
+ IsValidMetadataTestCase{
+ .name = "too_long_dab_ensemble_name_short",
+ .metadata = Metadata::make<Metadata::dabEnsembleNameShort>("name_long"),
+ .valid = false},
+ IsValidMetadataTestCase{
+ .name = "valid_dab_service_name_short",
+ .metadata = Metadata::make<Metadata::dabServiceNameShort>("name"),
+ .valid = true},
+ IsValidMetadataTestCase{
+ .name = "too_long_dab_service_name_short",
+ .metadata = Metadata::make<Metadata::dabServiceNameShort>("name_long"),
+ .valid = false},
+ IsValidMetadataTestCase{
+ .name = "valid_dab_component_name_short",
+ .metadata = Metadata::make<Metadata::dabComponentNameShort>("name"),
+ .valid = true},
+ IsValidMetadataTestCase{
+ .name = "too_long_dab_component_name_short",
+ .metadata = Metadata::make<Metadata::dabComponentNameShort>("name_long"),
+ .valid = false},
+ });
+}
+
+std::vector<IsValidMetadataTestCase> getIsValidMetadataV2TestCases() {
+ std::vector<IsValidMetadataTestCase> testcases = getIsValidMetadataTestCases();
+ std::vector<IsValidMetadataTestCase> testcasesNew = std::vector<IsValidMetadataTestCase>({
+ IsValidMetadataTestCase{
+ .name = "valid_hd_station_name_short",
+ .metadata = Metadata::make<Metadata::hdStationNameShort>("name_short"),
+ .valid = true},
+ IsValidMetadataTestCase{
+ .name = "too_long_hd_station_name_short",
+ .metadata = Metadata::make<Metadata::hdStationNameShort>("name_too_long"),
+ .valid = false},
+ IsValidMetadataTestCase{.name = "valid_hd_subchannel_available",
+ .metadata = Metadata::make<Metadata::hdSubChannelsAvailable>(1),
+ .valid = true},
+ IsValidMetadataTestCase{
+ .name = "negative_subchannel_available",
+ .metadata = Metadata::make<Metadata::hdSubChannelsAvailable>(-1),
+ .valid = false},
+ IsValidMetadataTestCase{
+ .name = "large_subchannel_available",
+ .metadata = Metadata::make<Metadata::hdSubChannelsAvailable>(256),
+ .valid = false},
+ });
+ testcases.insert(testcases.end(), testcasesNew.begin(), testcasesNew.end());
+ return testcases;
+}
+} // namespace
+
+class IsValidIdentifierTest : public testing::TestWithParam<IsValidIdentifierTestCase> {};
+
+INSTANTIATE_TEST_SUITE_P(IsValidIdentifierTests, IsValidIdentifierTest,
+ testing::ValuesIn(getIsValidIdentifierTestCases()),
+ [](const testing::TestParamInfo<IsValidIdentifierTest::ParamType>& info) {
+ return info.param.name;
+ });
+
+TEST_P(IsValidIdentifierTest, IsValid) {
+ IsValidIdentifierTestCase testcase = GetParam();
+
+ ASSERT_EQ(utils::isValid(testcase.id), testcase.valid);
+}
+
+class IsValidIdentifierV2Test : public testing::TestWithParam<IsValidIdentifierTestCase> {};
+
+INSTANTIATE_TEST_SUITE_P(
+ IsValidIdentifierV2Tests, IsValidIdentifierV2Test,
+ testing::ValuesIn(getIsValidIdentifierV2TestCases()),
+ [](const testing::TestParamInfo<IsValidIdentifierV2Test::ParamType>& info) {
+ return info.param.name;
+ });
+
+TEST_P(IsValidIdentifierV2Test, IsValidV2) {
+ IsValidIdentifierTestCase testcase = GetParam();
+
+ ASSERT_EQ(utils::isValidV2(testcase.id), testcase.valid);
+}
+
+class IsValidSelectorTest : public testing::TestWithParam<IsValidSelectorTestCase> {};
+
+INSTANTIATE_TEST_SUITE_P(IsValidSelectorTests, IsValidSelectorTest,
+ testing::ValuesIn(getIsValidSelectorTestCases()),
+ [](const testing::TestParamInfo<IsValidSelectorTest::ParamType>& info) {
+ return info.param.name;
+ });
+
+TEST_P(IsValidSelectorTest, IsValid) {
+ IsValidSelectorTestCase testcase = GetParam();
+
+ ASSERT_EQ(utils::isValid(testcase.sel), testcase.valid);
+}
+
+class IsValidSelectorV2Test : public testing::TestWithParam<IsValidSelectorTestCase> {};
+
+INSTANTIATE_TEST_SUITE_P(IsValidSelectorV2Tests, IsValidSelectorV2Test,
+ testing::ValuesIn(getIsValidSelectorV2TestCases()),
+ [](const testing::TestParamInfo<IsValidSelectorV2Test::ParamType>& info) {
+ return info.param.name;
+ });
+
+TEST_P(IsValidSelectorV2Test, IsValidV2) {
+ IsValidSelectorTestCase testcase = GetParam();
+
+ ASSERT_EQ(utils::isValidV2(testcase.sel), testcase.valid);
+}
+
+class IsValidMetadataTest : public testing::TestWithParam<IsValidMetadataTestCase> {};
+
+INSTANTIATE_TEST_SUITE_P(IsValidMetadataTests, IsValidMetadataTest,
+ testing::ValuesIn(getIsValidMetadataTestCases()),
+ [](const testing::TestParamInfo<IsValidMetadataTest::ParamType>& info) {
+ return info.param.name;
+ });
+
+TEST_P(IsValidMetadataTest, IsValidMetadata) {
+ IsValidMetadataTestCase testParam = GetParam();
+
+ ASSERT_EQ(utils::isValidMetadata(testParam.metadata), testParam.valid);
+}
+
+class IsValidMetadataV2Test : public testing::TestWithParam<IsValidMetadataTestCase> {};
+
+INSTANTIATE_TEST_SUITE_P(IsValidMetadataV2Tests, IsValidMetadataV2Test,
+ testing::ValuesIn(getIsValidMetadataV2TestCases()),
+ [](const testing::TestParamInfo<IsValidMetadataV2Test::ParamType>& info) {
+ return info.param.name;
+ });
+
+TEST_P(IsValidMetadataV2Test, IsValidMetadataV2) {
+ IsValidMetadataTestCase testParam = GetParam();
+
+ ASSERT_EQ(utils::isValidMetadataV2(testParam.metadata), testParam.valid);
+}
+
+} // namespace aidl::android::hardware::broadcastradio
diff --git a/broadcastradio/common/utilsaidl/test/BroadcastRadioUtilsTest.cpp b/broadcastradio/common/utilsaidl/test/BroadcastRadioUtilsTest.cpp
index a5c9073..81f9470 100644
--- a/broadcastradio/common/utilsaidl/test/BroadcastRadioUtilsTest.cpp
+++ b/broadcastradio/common/utilsaidl/test/BroadcastRadioUtilsTest.cpp
@@ -66,230 +66,6 @@
.frequency = 110000,
.bandResult = utils::FrequencyBand::UNKNOWN}});
}
-
-struct IsValidIdentifierTestCase {
- std::string name;
- ProgramIdentifier id;
- bool valid;
-};
-
-std::vector<IsValidIdentifierTestCase> getIsValidIdentifierTestCases() {
- return std::vector<IsValidIdentifierTestCase>({
- IsValidIdentifierTestCase{.name = "invalid_id_type",
- .id = utils::makeIdentifier(IdentifierType::INVALID, 0),
- .valid = false},
- IsValidIdentifierTestCase{
- .name = "invalid_dab_frequency_high",
- .id = utils::makeIdentifier(IdentifierType::DAB_FREQUENCY_KHZ, 10000000u),
- .valid = false},
- IsValidIdentifierTestCase{
- .name = "invalid_dab_frequency_low",
- .id = utils::makeIdentifier(IdentifierType::DAB_FREQUENCY_KHZ, 100000u),
- .valid = false},
- IsValidIdentifierTestCase{
- .name = "valid_dab_frequency",
- .id = utils::makeIdentifier(IdentifierType::DAB_FREQUENCY_KHZ, 1000000u),
- .valid = true},
- IsValidIdentifierTestCase{
- .name = "invalid_am_fm_frequency_high",
- .id = utils::makeIdentifier(IdentifierType::AMFM_FREQUENCY_KHZ, 10000000u),
- .valid = false},
- IsValidIdentifierTestCase{
- .name = "invalid_am_fm_frequency_low",
- .id = utils::makeIdentifier(IdentifierType::AMFM_FREQUENCY_KHZ, 100u),
- .valid = false},
- IsValidIdentifierTestCase{.name = "valid_am_fm_frequency",
- .id = utils::makeIdentifier(
- IdentifierType::AMFM_FREQUENCY_KHZ, kFmFrequencyKHz),
- .valid = true},
- IsValidIdentifierTestCase{
- .name = "drmo_frequency_high",
- .id = utils::makeIdentifier(IdentifierType::DRMO_FREQUENCY_KHZ, 10000000u),
- .valid = false},
- IsValidIdentifierTestCase{
- .name = "drmo_frequency_low",
- .id = utils::makeIdentifier(IdentifierType::DRMO_FREQUENCY_KHZ, 100u),
- .valid = false},
- IsValidIdentifierTestCase{.name = "valid_drmo_frequency",
- .id = utils::makeIdentifier(
- IdentifierType::DRMO_FREQUENCY_KHZ, kFmFrequencyKHz),
- .valid = true},
- IsValidIdentifierTestCase{.name = "invalid_rds_low",
- .id = utils::makeIdentifier(IdentifierType::RDS_PI, 0x0),
- .valid = false},
- IsValidIdentifierTestCase{.name = "invalid_rds_high",
- .id = utils::makeIdentifier(IdentifierType::RDS_PI, 0x10000),
- .valid = false},
- IsValidIdentifierTestCase{.name = "valid_rds",
- .id = utils::makeIdentifier(IdentifierType::RDS_PI, 0x1000),
- .valid = true},
- IsValidIdentifierTestCase{
- .name = "invalid_hd_id_zero",
- .id = utils::makeSelectorHd(/* stationId= */ 0u, kHdSubChannel, kHdFrequency)
- .primaryId,
- .valid = false},
- IsValidIdentifierTestCase{
- .name = "invalid_hd_suchannel",
- .id = utils::makeSelectorHd(kHdStationId, /* subChannel= */ 8u, kHdFrequency)
- .primaryId,
- .valid = false},
- IsValidIdentifierTestCase{
- .name = "invalid_hd_frequency_low",
- .id = utils::makeSelectorHd(kHdStationId, kHdSubChannel, /* frequency= */ 100u)
- .primaryId,
- .valid = false},
- IsValidIdentifierTestCase{
- .name = "valid_hd_id",
- .id = utils::makeSelectorHd(kHdStationId, kHdSubChannel, kHdFrequency)
- .primaryId,
- .valid = true},
- IsValidIdentifierTestCase{
- .name = "invalid_hd_station_name",
- .id = utils::makeIdentifier(IdentifierType::HD_STATION_NAME, 0x41422D464D),
- .valid = false},
- IsValidIdentifierTestCase{
- .name = "valid_hd_station_name",
- .id = utils::makeIdentifier(IdentifierType::HD_STATION_NAME, 0x414231464D),
- .valid = true},
- IsValidIdentifierTestCase{
- .name = "invalid_dab_sid",
- .id = utils::makeIdentifier(IdentifierType::DAB_SID_EXT, 0x0E100000000u),
- .valid = false},
- IsValidIdentifierTestCase{
- .name = "invalid_dab_ecc_low",
- .id = utils::makeIdentifier(IdentifierType::DAB_SID_EXT, 0x0F700000221u),
- .valid = false},
- IsValidIdentifierTestCase{
- .name = "invalid_dab_ecc_high",
- .id = utils::makeIdentifier(IdentifierType::DAB_SID_EXT, 0x09900000221u),
- .valid = false},
- IsValidIdentifierTestCase{
- .name = "valid_dab_sid_ext",
- .id = utils::makeIdentifier(IdentifierType::DAB_SID_EXT, kDabSidExt),
- .valid = true},
- IsValidIdentifierTestCase{
- .name = "invalid_dab_ensemble_zero",
- .id = utils::makeIdentifier(IdentifierType::DAB_ENSEMBLE, 0x0),
- .valid = false},
- IsValidIdentifierTestCase{
- .name = "invalid_dab_ensemble_high",
- .id = utils::makeIdentifier(IdentifierType::DAB_ENSEMBLE, 0x10000),
- .valid = false},
- IsValidIdentifierTestCase{
- .name = "valid_dab_ensemble",
- .id = utils::makeIdentifier(IdentifierType::DAB_ENSEMBLE, kDabEnsemble),
- .valid = true},
- IsValidIdentifierTestCase{.name = "invalid_dab_scid_low",
- .id = utils::makeIdentifier(IdentifierType::DAB_SCID, 0xF),
- .valid = false},
- IsValidIdentifierTestCase{.name = "invalid_dab_scid_high",
- .id = utils::makeIdentifier(IdentifierType::DAB_SCID, 0x1000),
- .valid = false},
- IsValidIdentifierTestCase{.name = "valid_dab_scid",
- .id = utils::makeIdentifier(IdentifierType::DAB_SCID, 0x100),
- .valid = true},
- IsValidIdentifierTestCase{
- .name = "invalid_drmo_id_zero",
- .id = utils::makeIdentifier(IdentifierType::DRMO_SERVICE_ID, 0x0),
- .valid = false},
- IsValidIdentifierTestCase{
- .name = "invalid_drmo_id_high",
- .id = utils::makeIdentifier(IdentifierType::DRMO_SERVICE_ID, 0x1000000),
- .valid = false},
- IsValidIdentifierTestCase{
- .name = "valid_drmo_id",
- .id = utils::makeIdentifier(IdentifierType::DRMO_SERVICE_ID, 0x100000),
- .valid = true},
- });
-}
-
-struct IsValidSelectorTestCase {
- std::string name;
- ProgramSelector sel;
- bool valid;
-};
-
-std::vector<IsValidSelectorTestCase> getIsValidSelectorTestCases() {
- return std::vector<IsValidSelectorTestCase>({
- IsValidSelectorTestCase{.name = "valid_am_fm_selector",
- .sel = utils::makeSelectorAmfm(kFmFrequencyKHz),
- .valid = true},
- IsValidSelectorTestCase{
- .name = "valid_hd_selector",
- .sel = utils::makeSelectorHd(kHdStationId, kHdSubChannel, kHdFrequency),
- .valid = true},
- IsValidSelectorTestCase{
- .name = "valid_dab_selector",
- .sel = utils::makeSelectorDab(kDabSidExt, kDabEnsemble, kDabFrequencyKhz),
- .valid = true},
- IsValidSelectorTestCase{.name = "valid_rds_selector",
- .sel = ProgramSelector{.primaryId = utils::makeIdentifier(
- IdentifierType::RDS_PI, 0x1000)},
- .valid = true},
- IsValidSelectorTestCase{.name = "selector_with_invalid_id",
- .sel = utils::makeSelectorHd(kHdStationId, kHdSubChannel,
- /* frequency= */ 100u),
- .valid = false},
- IsValidSelectorTestCase{
- .name = "selector_with_invalid_primary_id_type",
- .sel = ProgramSelector{.primaryId = utils::makeIdentifier(
- IdentifierType::DAB_ENSEMBLE, kDabEnsemble)},
- .valid = false},
- });
-}
-
-struct IsValidMetadataTestCase {
- std::string name;
- Metadata metadata;
- bool valid;
-};
-
-std::vector<IsValidMetadataTestCase> getIsValidMetadataTestCases() {
- return std::vector<IsValidMetadataTestCase>({
- IsValidMetadataTestCase{.name = "valid_rds_pty",
- .metadata = Metadata::make<Metadata::rdsPty>(1),
- .valid = true},
- IsValidMetadataTestCase{.name = "negative_rds_pty",
- .metadata = Metadata::make<Metadata::rdsPty>(-1),
- .valid = false},
- IsValidMetadataTestCase{.name = "large_rds_pty",
- .metadata = Metadata::make<Metadata::rdsPty>(256),
- .valid = false},
- IsValidMetadataTestCase{.name = "valid_rbds_pty",
- .metadata = Metadata::make<Metadata::rbdsPty>(1),
- .valid = true},
- IsValidMetadataTestCase{.name = "negative_rbds_pty",
- .metadata = Metadata::make<Metadata::rbdsPty>(-1),
- .valid = false},
- IsValidMetadataTestCase{.name = "large_rbds_pty",
- .metadata = Metadata::make<Metadata::rbdsPty>(256),
- .valid = false},
- IsValidMetadataTestCase{
- .name = "valid_dab_ensemble_name_short",
- .metadata = Metadata::make<Metadata::dabEnsembleNameShort>("name"),
- .valid = true},
- IsValidMetadataTestCase{
- .name = "too_long_dab_ensemble_name_short",
- .metadata = Metadata::make<Metadata::dabEnsembleNameShort>("name_long"),
- .valid = false},
- IsValidMetadataTestCase{
- .name = "valid_dab_service_name_short",
- .metadata = Metadata::make<Metadata::dabServiceNameShort>("name"),
- .valid = true},
- IsValidMetadataTestCase{
- .name = "too_long_dab_service_name_short",
- .metadata = Metadata::make<Metadata::dabServiceNameShort>("name_long"),
- .valid = false},
- IsValidMetadataTestCase{
- .name = "valid_dab_component_name_short",
- .metadata = Metadata::make<Metadata::dabComponentNameShort>("name"),
- .valid = true},
- IsValidMetadataTestCase{
- .name = "too_long_dab_component_name_short",
- .metadata = Metadata::make<Metadata::dabComponentNameShort>("name_long"),
- .valid = false},
- });
-}
} // namespace
class GetBandTest : public testing::TestWithParam<GetBandTestCase> {};
@@ -305,48 +81,6 @@
ASSERT_EQ(utils::getBand(testcase.frequency), testcase.bandResult);
}
-class IsValidMetadataTest : public testing::TestWithParam<IsValidMetadataTestCase> {};
-
-INSTANTIATE_TEST_SUITE_P(IsValidMetadataTests, IsValidMetadataTest,
- testing::ValuesIn(getIsValidMetadataTestCases()),
- [](const testing::TestParamInfo<IsValidMetadataTest::ParamType>& info) {
- return info.param.name;
- });
-
-TEST_P(IsValidMetadataTest, IsValidMetadata) {
- IsValidMetadataTestCase testParam = GetParam();
-
- ASSERT_EQ(utils::isValidMetadata(testParam.metadata), testParam.valid);
-}
-
-class IsValidIdentifierTest : public testing::TestWithParam<IsValidIdentifierTestCase> {};
-
-INSTANTIATE_TEST_SUITE_P(IsValidIdentifierTests, IsValidIdentifierTest,
- testing::ValuesIn(getIsValidIdentifierTestCases()),
- [](const testing::TestParamInfo<IsValidIdentifierTest::ParamType>& info) {
- return info.param.name;
- });
-
-TEST_P(IsValidIdentifierTest, IsValid) {
- IsValidIdentifierTestCase testcase = GetParam();
-
- ASSERT_EQ(utils::isValid(testcase.id), testcase.valid);
-}
-
-class IsValidSelectorTest : public testing::TestWithParam<IsValidSelectorTestCase> {};
-
-INSTANTIATE_TEST_SUITE_P(IsValidSelectorTests, IsValidSelectorTest,
- testing::ValuesIn(getIsValidSelectorTestCases()),
- [](const testing::TestParamInfo<IsValidSelectorTest::ParamType>& info) {
- return info.param.name;
- });
-
-TEST_P(IsValidSelectorTest, IsValid) {
- IsValidSelectorTestCase testcase = GetParam();
-
- ASSERT_EQ(utils::isValid(testcase.sel), testcase.valid);
-}
-
TEST(BroadcastRadioUtilsTest, IdentifierIteratorBegin) {
ProgramSelector sel = {
.primaryId = utils::makeIdentifier(IdentifierType::RDS_PI, kRdsValue),
@@ -503,13 +237,22 @@
sel.secondaryIds.push_back(
utils::makeIdentifier(IdentifierType::AMFM_FREQUENCY_KHZ, secondaryFrequencyKHz));
- std::vector<int> allIds = utils::getAllIds(sel, IdentifierType::AMFM_FREQUENCY_KHZ);
+ std::vector<int64_t> allIds = utils::getAllIds(sel, IdentifierType::AMFM_FREQUENCY_KHZ);
ASSERT_EQ(allIds.size(), 2u);
EXPECT_NE(std::find(allIds.begin(), allIds.end(), kFmFrequencyKHz), allIds.end());
EXPECT_NE(std::find(allIds.begin(), allIds.end(), secondaryFrequencyKHz), allIds.end());
}
+TEST(BroadcastRadioUtilsTest, GetAllIdsWithIdLongerThan32Bit) {
+ ProgramSelector sel = utils::makeSelectorDab(kDabSidExt, kDabEnsemble, kDabFrequencyKhz);
+
+ std::vector<int64_t> allIds = utils::getAllIds(sel, IdentifierType::DAB_SID_EXT);
+
+ ASSERT_EQ(allIds.size(), 1u);
+ EXPECT_NE(std::find(allIds.begin(), allIds.end(), kDabSidExt), allIds.end());
+}
+
TEST(BroadcastRadioUtilsTest, GetAllIdsWithIdNotFound) {
ProgramSelector sel = utils::makeSelectorDab(kDabSidExt, kDabEnsemble, kDabFrequencyKhz);
diff --git a/broadcastradio/common/utilsaidl/test/BroadcastRadioUtilsV2Test.cpp b/broadcastradio/common/utilsaidl/test/BroadcastRadioUtilsV2Test.cpp
deleted file mode 100644
index cf9f9e9..0000000
--- a/broadcastradio/common/utilsaidl/test/BroadcastRadioUtilsV2Test.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <broadcastradio-utils-aidl/UtilsV2.h>
-#include <gtest/gtest.h>
-
-namespace aidl::android::hardware::broadcastradio {
-
-namespace {
-struct IsValidMetadataV2TestCase {
- std::string name;
- Metadata metadata;
- bool valid;
-};
-
-std::vector<IsValidMetadataV2TestCase> getIsValidMetadataV2TestCases() {
- return std::vector<IsValidMetadataV2TestCase>({
- IsValidMetadataV2TestCase{.name = "valid_rds_pty",
- .metadata = Metadata::make<Metadata::rdsPty>(1),
- .valid = true},
- IsValidMetadataV2TestCase{.name = "negative_rds_pty",
- .metadata = Metadata::make<Metadata::rdsPty>(-1),
- .valid = false},
- IsValidMetadataV2TestCase{
- .name = "valid_hd_station_name_short",
- .metadata = Metadata::make<Metadata::hdStationNameShort>("name_short"),
- .valid = true},
- IsValidMetadataV2TestCase{
- .name = "too_long_hd_station_name_short",
- .metadata = Metadata::make<Metadata::hdStationNameShort>("name_too_long"),
- .valid = false},
- IsValidMetadataV2TestCase{
- .name = "valid_hd_subchannel_available",
- .metadata = Metadata::make<Metadata::hdSubChannelsAvailable>(1),
- .valid = true},
- IsValidMetadataV2TestCase{
- .name = "negative_subchannel_available",
- .metadata = Metadata::make<Metadata::hdSubChannelsAvailable>(-1),
- .valid = false},
- IsValidMetadataV2TestCase{
- .name = "large_subchannel_available",
- .metadata = Metadata::make<Metadata::hdSubChannelsAvailable>(256),
- .valid = false},
- });
-}
-} // namespace
-
-class IsValidMetadataV2Test : public testing::TestWithParam<IsValidMetadataV2TestCase> {};
-
-INSTANTIATE_TEST_SUITE_P(IsValidMetadataV2Tests, IsValidMetadataV2Test,
- testing::ValuesIn(getIsValidMetadataV2TestCases()),
- [](const testing::TestParamInfo<IsValidMetadataV2Test::ParamType>& info) {
- return info.param.name;
- });
-
-TEST_P(IsValidMetadataV2Test, IsValidMetadataV2) {
- IsValidMetadataV2TestCase testParam = GetParam();
-
- ASSERT_EQ(utils::isValidMetadataV2(testParam.metadata), testParam.valid);
-}
-
-} // namespace aidl::android::hardware::broadcastradio
diff --git a/camera/device/3.4/default/ExternalCameraUtils.cpp b/camera/device/3.4/default/ExternalCameraUtils.cpp
index 8f4626c..d9610c2 100644
--- a/camera/device/3.4/default/ExternalCameraUtils.cpp
+++ b/camera/device/3.4/default/ExternalCameraUtils.cpp
@@ -108,9 +108,38 @@
return -EINVAL;
}
- uint32_t dataSize = mWidth * mHeight * 3 / 2; // YUV420
- if (mData.size() != dataSize) {
- mData.resize(dataSize);
+ // This frame might be sent to jpeglib to be encoded. Since AllocatedFrame only contains YUV420,
+ // jpeglib expects height and width of Y component to be an integral multiple of 2*DCTSIZE,
+ // and heights and widths of Cb and Cr components to be an integral multiple of DCTSIZE. If the
+ // image size does not meet this requirement, libjpeg expects its input to be padded to meet the
+ // constraints. This padding is removed from the final encoded image so the content in the
+ // padding doesn't matter. What matters is that the memory is accessible to jpeglib at the time
+ // of encoding.
+ // For example, if the image size is 1500x844 and DCTSIZE is 8, jpeglib expects a YUV 420
+ // frame with components of following sizes:
+ // Y: 1504x848 because 1504 and 848 are the next smallest multiples of 2*8
+ // Cb/Cr: 752x424 which are the next smallest multiples of 8
+
+ // jpeglib takes an array of row pointers which makes vertical padding trivial when setting up
+ // the pointers. Padding horizontally is a bit more complicated. AllocatedFrame holds the data
+ // in a flattened buffer, which means memory accesses past a row will flow into the next logical
+ // row. For any row of a component, we can consider the first few bytes of the next row as
+ // padding for the current one. This is true for Y and Cb components and all but last row of the
+ // Cr component. Reading past the last row of Cr component will lead to undefined behavior as
+ // libjpeg attempts to read memory past the allocated buffer. To prevent undefined behavior,
+ // the buffer allocated here is padded such that libjpeg never accesses unallocated memory when
+ // reading the last row. Effectively, we only need to ensure that the last row of Cr component
+ // has width that is an integral multiple of DCTSIZE.
+
+ size_t dataSize = mWidth * mHeight * 3 / 2; // YUV420
+
+ size_t cbWidth = mWidth / 2;
+ size_t requiredCbWidth = DCTSIZE * ((cbWidth + DCTSIZE - 1) / DCTSIZE);
+ size_t padding = requiredCbWidth - cbWidth;
+ size_t finalSize = dataSize + padding;
+
+ if (mData.size() != finalSize) {
+ mData.resize(finalSize);
}
if (out != nullptr) {
diff --git a/camera/device/aidl/android/hardware/camera/device/ICameraDevice.aidl b/camera/device/aidl/android/hardware/camera/device/ICameraDevice.aidl
index 440c2b3..5da515b 100644
--- a/camera/device/aidl/android/hardware/camera/device/ICameraDevice.aidl
+++ b/camera/device/aidl/android/hardware/camera/device/ICameraDevice.aidl
@@ -372,66 +372,13 @@
* the particular StreamConfiguration is supported, the camera HAL must take all
* the keys in sessionParameters into consideration.
*
- * 2. For version 3 of this interface, the camera compliance test will verify that
+ * 2. For version 3 of this interface, the camera compliance tests will verify that
* isStreamCombinationWithSettingsSupported behaves properly for all combinations of
- * below features. This function must return true for all supported combinations,
- * and return false for non-supported feature combinations. The list of features
- * required may grow in future versions. The additional metadata entries in
- * StreamConfiguration::sessionParameters are {CONTROL_AE_TARGET_FPS_RANGE,
- * CONTROL_VIDEO_STABILIZATION_MODE}.
- *
- * - Stream Combinations (a subset of LEGACY device mandatory stream combinations):
- * {
- * // 4:3 16:9
- * // S1440P: 1920 x 1440 2560 x 1440
- * // S1080P: 1440 x 1080 1920 x 1080
- * // S720P: 960 x 720 1280 x 720
- *
- * // Simple preview, GPU video processing, or no-preview video recording
- * {PRIV, MAXIMUM},
- * {PRIV, PREVIEW},
- * {PRIV, S1440P},
- * {PRIV, S1080P},
- * {PRIV, S720P},
- * // In-application video/image processing
- * {YUV, MAXIMUM},
- * {YUV, PREVIEW},
- * {YUV, S1440P},
- * {YUV, S1080P},
- * {YUV, S720P},
- * // Standard still imaging.
- * {PRIV, PREVIEW, JPEG, MAXIMUM},
- * {PRIV, S1440P, JPEG, MAXIMUM},
- * {PRIV, S1080P, JPEG, MAXIMUM},
- * {PRIV, S720P, JPEG, MAXIMUM},
- * {PRIV, S1440P, JPEG, S1440P},
- * {PRIV, S1080P, JPEG, S1080P},
- * {PRIV, S720P, JPEG, S1080P},
- * // In-app processing plus still capture.
- * {YUV, PREVIEW, JPEG, MAXIMUM},
- * {YUV, S1440P, JPEG, MAXIMUM},
- * {YUV, S1080P, JPEG, MAXIMUM},
- * {YUV, S720P, JPEG, MAXIMUM},
- * // Standard recording.
- * {PRIV, PREVIEW, PRIV, PREVIEW},
- * {PRIV, S1440P, PRIV, S1440P},
- * {PRIV, S1080P, PRIV, S1080P},
- * {PRIV, S720P, PRIV, S720P},
- * // Preview plus in-app processing.
- * {PRIV, PREVIEW, YUV, PREVIEW},
- * {PRIV, S1440P, YUV, S1440P},
- * {PRIV, S1080P, YUV, S1080P},
- * {PRIV, S720P, YUV, S720P},
- * }
- * - VIDEO_STABILIZATION_MODES: {OFF, PREVIEW}
- * - AE_TARGET_FPS_RANGE: {{*, 30}, {*, 60}}
- * - DYNAMIC_RANGE_PROFILE: {STANDARD, HLG10}
- *
- * Note: If a combination contains a S1440P, S1080P, or S720P stream,
- * both 4:3 and 16:9 aspect ratio will be considered. For example, for the
- * stream combination of {PRIV, S1440P, JPEG, MAXIMUM}, and if MAXIMUM ==
- * 4032 x 3024, the camera compliance test will verify both
- * {PRIV, 1920 x 1440, JPEG, 4032 x 3024} and {PRIV, 2560 x 1440, JPEG, 4032 x 2268}.
+ * features described in the android.info.sessionConfigurationQueryVersion section of
+ * /system/media/camera/docs/docs.html. This function must
+ * return true for all supported combinations, and return false for non-supported
+ * feature combinations. The list of feature combinations required may grow in future
+ * HAL versions.
*
* @param streams The StreamConfiguration to be tested, with optional CaptureRequest parameters.
*
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index c8e683c..82666ae 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -8140,7 +8140,7 @@
ANDROID_LENS_POSE_REFERENCE, &entry);
if (0 == retcode && entry.count > 0) {
uint8_t poseReference = entry.data.u8[0];
- ASSERT_TRUE(poseReference <= ANDROID_LENS_POSE_REFERENCE_UNDEFINED &&
+ ASSERT_TRUE(poseReference <= ANDROID_LENS_POSE_REFERENCE_AUTOMOTIVE &&
poseReference >= ANDROID_LENS_POSE_REFERENCE_PRIMARY_CAMERA);
}
diff --git a/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp b/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp
index 90ec32c..ad8d4c8 100644
--- a/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp
+++ b/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp
@@ -178,6 +178,9 @@
const camera_metadata_t* staticMeta =
reinterpret_cast<const camera_metadata_t*>(meta.metadata.data());
verifyManualFlashStrengthControlCharacteristics(staticMeta);
+ ret = mSession->close();
+ mSession = nullptr;
+ ASSERT_TRUE(ret.isOk());
}
} else {
ALOGI("validateManualFlashStrengthControlKeys: Test skipped.\n");
@@ -297,6 +300,15 @@
ASSERT_TRUE(ret.isOk());
ASSERT_NE(device, nullptr);
+ int32_t interfaceVersion = -1;
+ ret = device->getInterfaceVersion(&interfaceVersion);
+ ASSERT_TRUE(ret.isOk());
+ bool supportSessionCharacteristics =
+ (interfaceVersion >= CAMERA_DEVICE_API_MINOR_VERSION_3);
+ if (!supportSessionCharacteristics) {
+ continue;
+ }
+
CameraMetadata meta;
openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
&device /*out*/);
@@ -339,6 +351,10 @@
ret = device->getSessionCharacteristics(config, &session_chars);
ASSERT_TRUE(ret.isOk());
verifySessionCharacteristics(session_chars, camera_chars);
+
+ ret = mSession->close();
+ mSession = nullptr;
+ ASSERT_TRUE(ret.isOk());
}
} else {
ALOGI("getSessionCharacteristics: Test skipped.\n");
diff --git a/camera/provider/aidl/vts/camera_aidl_test.cpp b/camera/provider/aidl/vts/camera_aidl_test.cpp
index 1673ab0..1ad5af9 100644
--- a/camera/provider/aidl/vts/camera_aidl_test.cpp
+++ b/camera/provider/aidl/vts/camera_aidl_test.cpp
@@ -695,8 +695,8 @@
retcode = find_camera_metadata_ro_entry(metadata, ANDROID_LENS_POSE_REFERENCE, &entry);
if (0 == retcode && entry.count > 0) {
uint8_t poseReference = entry.data.u8[0];
- ASSERT_TRUE(poseReference <= ANDROID_LENS_POSE_REFERENCE_UNDEFINED &&
- poseReference >= ANDROID_LENS_POSE_REFERENCE_PRIMARY_CAMERA);
+ ASSERT_TRUE(poseReference <= ANDROID_LENS_POSE_REFERENCE_AUTOMOTIVE &&
+ poseReference >= ANDROID_LENS_POSE_REFERENCE_PRIMARY_CAMERA);
}
retcode =
@@ -1205,18 +1205,21 @@
int torchDefRetCode = find_camera_metadata_ro_entry(staticMeta,
ANDROID_FLASH_TORCH_STRENGTH_DEFAULT_LEVEL, &torchDefEntry);
if (torch_supported) {
+ int expectedEntryCount;
if(singleMaxRetCode == 0 && singleDefRetCode == 0 && torchMaxRetCode == 0 &&
torchDefRetCode == 0) {
singleMaxLevel = *singleMaxEntry.data.i32;
singleDefLevel = *singleDefEntry.data.i32;
torchMaxLevel = *torchMaxEntry.data.i32;
torchDefLevel = *torchDefEntry.data.i32;
- ASSERT_TRUE((singleMaxEntry.count == singleDefEntry.count == torchMaxEntry.count
- == torchDefEntry.count == 1));
+ expectedEntryCount = 1;
} else {
- ASSERT_TRUE((singleMaxEntry.count == singleDefEntry.count == torchMaxEntry.count
- == torchDefEntry.count == 0));
+ expectedEntryCount = 0;
}
+ ASSERT_EQ(singleMaxEntry.count, expectedEntryCount);
+ ASSERT_EQ(singleDefEntry.count, expectedEntryCount);
+ ASSERT_EQ(torchMaxEntry.count, expectedEntryCount);
+ ASSERT_EQ(torchDefEntry.count, expectedEntryCount);
// if the device supports this feature default levels should be greater than 0
if (singleMaxLevel > 1) {
ASSERT_GT(torchMaxLevel, 1);
diff --git a/compatibility_matrices/compatibility_matrix.202504.xml b/compatibility_matrices/compatibility_matrix.202504.xml
index 62756bd..1f51d07 100644
--- a/compatibility_matrices/compatibility_matrix.202504.xml
+++ b/compatibility_matrices/compatibility_matrix.202504.xml
@@ -116,7 +116,7 @@
</hal>
<hal format="aidl" updatable-via-apex="true">
<name>android.hardware.biometrics.fingerprint</name>
- <version>3-4</version>
+ <version>3-5</version>
<interface>
<name>IFingerprint</name>
<instance>default</instance>
@@ -529,6 +529,7 @@
<name>ISharedSecret</name>
<instance>default</instance>
<instance>strongbox</instance>
+ <regex-instance>.*</regex-instance>
</interface>
</hal>
<hal format="aidl">
diff --git a/gnss/aidl/vts/gnss_hal_test_cases.cpp b/gnss/aidl/vts/gnss_hal_test_cases.cpp
index 9381a0a..4309187 100644
--- a/gnss/aidl/vts/gnss_hal_test_cases.cpp
+++ b/gnss/aidl/vts/gnss_hal_test_cases.cpp
@@ -1714,7 +1714,8 @@
* 2. verify the SvStatus are received at expected interval
*/
TEST_P(GnssHalTest, TestSvStatusIntervals) {
- if (aidl_gnss_hal_->getInterfaceVersion() <= 2) {
+ // Only runs on devices launched in Android 15+
+ if (aidl_gnss_hal_->getInterfaceVersion() <= 3) {
return;
}
ALOGD("TestSvStatusIntervals");
diff --git a/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl b/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl
index 2985212..1117504 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl
@@ -161,8 +161,7 @@
*
* The allocator should examine the usage bits passed in when allocating a
* buffer with this format, and it should derive the pixel format from
- * those usage flags. This format must never be used with any of the
- * BufferUsage::CPU_* usage flags.
+ * those usage flags.
*
* Even when the internally chosen format has an alpha component, the
* clients must assume the alpha vlaue to be 1.0.
diff --git a/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h b/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h
index 336d15d..6a45987 100644
--- a/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h
+++ b/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h
@@ -33,6 +33,7 @@
#include <string.h>
#include <android/hardware/graphics/composer/2.1/IComposer.h>
+#include <android/hardware/graphics/composer/2.1/IComposerClient.h>
#include <fmq/MessageQueue.h>
#include <log/log.h>
#include <sync/sync.h>
@@ -649,7 +650,8 @@
*outLength = static_cast<uint16_t>(val & length_mask);
if (mDataRead + *outLength > mDataSize) {
- ALOGE("command 0x%x has invalid command length %" PRIu16, *outCommand, *outLength);
+ ALOGE("command %s has invalid command length %" PRIu16,
+ toString(*outCommand).c_str(), *outLength);
// undo the read() above
mDataRead--;
return false;
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/CommandResultPayload.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/CommandResultPayload.aidl
index 106fd87..99c91aa 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/CommandResultPayload.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/CommandResultPayload.aidl
@@ -28,6 +28,10 @@
union CommandResultPayload {
/**
* Indicates an error generated by a command.
+ *
+ * If there is an error from a command, the composer should only respond
+ * with the CommandError, and not with other results
+ * (e.g. ChangedCompositionTypes).
*/
CommandError error;
diff --git a/graphics/composer/aidl/vts/VtsComposerClient.h b/graphics/composer/aidl/vts/VtsComposerClient.h
index fabc82a..da6116f 100644
--- a/graphics/composer/aidl/vts/VtsComposerClient.h
+++ b/graphics/composer/aidl/vts/VtsComposerClient.h
@@ -258,13 +258,13 @@
struct DisplayConfig {
DisplayConfig(int32_t vsyncPeriod_, int32_t configGroup_,
- std::optional<VrrConfig> vrrConfig_ = {})
+ std::optional<VrrConfig> vrrConfigOpt_ = {})
: vsyncPeriod(vsyncPeriod_),
configGroup(configGroup_),
- vrrConfig(std::move(vrrConfig_)) {}
+ vrrConfigOpt(std::move(vrrConfigOpt_)) {}
int32_t vsyncPeriod;
int32_t configGroup;
- std::optional<VrrConfig> vrrConfig;
+ std::optional<VrrConfig> vrrConfigOpt;
};
void addDisplayConfig(int32_t config, DisplayConfig displayConfig) {
@@ -273,6 +273,35 @@
DisplayConfig getDisplayConfig(int32_t config) { return mDisplayConfigs.find(config)->second; }
+ bool isRateSameBetweenConfigs(int config1, int config2) {
+ const auto displayConfig1 = getDisplayConfig(config1);
+ const auto displayConfig2 = getDisplayConfig(config2);
+ const auto vrrConfigOpt1 = displayConfig1.vrrConfigOpt;
+ const auto vrrConfigOpt2 = displayConfig2.vrrConfigOpt;
+
+ if (vrrConfigOpt1 && vrrConfigOpt2 &&
+ vrrConfigOpt1->minFrameIntervalNs == vrrConfigOpt2->minFrameIntervalNs) {
+ return true;
+ } else if (displayConfig1.vsyncPeriod == displayConfig2.vsyncPeriod) {
+ return true;
+ }
+ return false;
+ }
+
+ std::string printConfig(int config) {
+ const auto displayConfig = getDisplayConfig(config);
+ const auto vrrConfigOpt = displayConfig.vrrConfigOpt;
+ std::stringstream ss;
+ if (displayConfig.vrrConfigOpt) {
+ ss << "{Config " << config << ": vsyncPeriod " << displayConfig.vsyncPeriod
+ << ", minFrameIntervalNs " << vrrConfigOpt->minFrameIntervalNs << "}";
+ }
+ else {
+ ss << "{Config " << config << ": vsyncPeriod " << displayConfig.vsyncPeriod << "}";
+ }
+ return ss.str();
+ }
+
std::unordered_map<int32_t, DisplayConfig> getDisplayConfigs() { return mDisplayConfigs; }
private:
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
index d4ce3ba..3d9253f 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
@@ -59,10 +59,12 @@
EXPECT_TRUE(mComposerClient->setPowerMode(getPrimaryDisplayId(), PowerMode::ON).isOk());
+ const auto format = getHasReadbackBuffer() ? mPixelFormat : common::PixelFormat::RGBA_8888;
+
ASSERT_NO_FATAL_FAILURE(
mTestRenderEngine = std::unique_ptr<TestRenderEngine>(new TestRenderEngine(
::android::renderengine::RenderEngineCreationArgs::Builder()
- .setPixelFormat(static_cast<int>(common::PixelFormat::RGBA_8888))
+ .setPixelFormat(static_cast<int>(format))
.setImageCacheSize(TestRenderEngine::sMaxFrameBufferAcquireBuffers)
.setEnableProtectedContext(false)
.setPrecacheToneMapperShaderOnly(false)
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
index f72cf55..ba15421 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
@@ -1603,18 +1603,24 @@
EXPECT_TRUE(mComposerClient->setActiveConfig(&display, config1).isOk());
sendRefreshFrame(display, nullptr);
- const auto displayConfigGroup1 = display.getDisplayConfig(config1);
- int32_t vsyncPeriod1 = displayConfigGroup1.vsyncPeriod;
- int32_t configGroup1 = displayConfigGroup1.configGroup;
+ const auto displayConfig1 = display.getDisplayConfig(config1);
+ int32_t vsyncPeriod1 = displayConfig1.vsyncPeriod;
+ int32_t configGroup1 = displayConfig1.configGroup;
- const auto displayConfigGroup2 = display.getDisplayConfig(config2);
- int32_t vsyncPeriod2 = displayConfigGroup2.vsyncPeriod;
- int32_t configGroup2 = displayConfigGroup2.configGroup;
+ const auto displayConfig2 = display.getDisplayConfig(config2);
+ int32_t vsyncPeriod2 = displayConfig2.vsyncPeriod;
+ int32_t configGroup2 = displayConfig2.configGroup;
if (vsyncPeriod1 == vsyncPeriod2) {
return; // continue
}
+ if ((!displayConfig1.vrrConfigOpt && displayConfig2.vrrConfigOpt) ||
+ (displayConfig1.vrrConfigOpt && !displayConfig2.vrrConfigOpt)) {
+ // switching between vrr to non-vrr modes
+ return; // continue
+ }
+
// We don't allow delayed change when changing config groups
if (params.delayForChange > 0 && configGroup1 != configGroup2) {
return; // continue
@@ -2197,13 +2203,13 @@
TEST_P(GraphicsComposerAidlCommandTest, DisplayDecoration) {
for (VtsDisplay& display : mDisplays) {
- auto& writer = getWriter(display.getDisplayId());
+ const auto displayId = display.getDisplayId();
+ auto& writer = getWriter(displayId);
const auto [layerStatus, layer] =
- mComposerClient->createLayer(display.getDisplayId(), kBufferSlotCount, &writer);
- EXPECT_TRUE(layerStatus.isOk());
+ mComposerClient->createLayer(displayId, kBufferSlotCount, &writer);
+ ASSERT_TRUE(layerStatus.isOk());
- const auto [error, support] =
- mComposerClient->getDisplayDecorationSupport(display.getDisplayId());
+ const auto [error, support] = mComposerClient->getDisplayDecorationSupport(displayId);
const auto format = (error.isOk() && support) ? support->format
: aidl::android::hardware::graphics::common::PixelFormat::RGBA_8888;
@@ -2223,9 +2229,9 @@
configureLayer(display, layer, Composition::DISPLAY_DECORATION, display.getFrameRect(),
display.getCrop());
- writer.setLayerBuffer(display.getDisplayId(), layer, /*slot*/ 0, decorBuffer->handle,
+ writer.setLayerBuffer(displayId, layer, /*slot*/ 0, decorBuffer->handle,
/*acquireFence*/ -1);
- writer.validateDisplay(display.getDisplayId(), ComposerClientWriter::kNoTimestamp,
+ writer.validateDisplay(displayId, ComposerClientWriter::kNoTimestamp,
VtsComposerClient::kNoFrameIntervalNs);
execute();
if (support) {
@@ -2235,6 +2241,7 @@
ASSERT_EQ(1, errors.size());
EXPECT_EQ(IComposerClient::EX_UNSUPPORTED, errors[0].errorCode);
}
+ EXPECT_TRUE(mComposerClient->destroyLayer(displayId, layer, &writer).isOk());
}
}
@@ -2738,7 +2745,7 @@
const auto displayFilter = [&](auto refreshRateChangedDebugData) {
bool nonVrrRateMatching = true;
if (std::optional<VrrConfig> vrrConfigOpt =
- display.getDisplayConfig(configId).vrrConfig;
+ display.getDisplayConfig(configId).vrrConfigOpt;
getInterfaceVersion() >= 3 && !vrrConfigOpt) {
nonVrrRateMatching = refreshRateChangedDebugData.refreshPeriodNanos ==
refreshRateChangedDebugData.vsyncPeriodNanos;
@@ -2836,10 +2843,7 @@
.isOk());
forEachTwoConfigs(displayId, [&](int32_t config1, int32_t config2) {
- const int32_t vsyncPeriod1 = display.getDisplayConfig(config1).vsyncPeriod;
- const int32_t vsyncPeriod2 = display.getDisplayConfig(config2).vsyncPeriod;
-
- if (vsyncPeriod1 == vsyncPeriod2) {
+ if (display.isRateSameBetweenConfigs(config1, config2)) {
return; // continue
}
@@ -2854,6 +2858,7 @@
sendRefreshFrame(display, &timeline);
}
+ const int32_t vsyncPeriod2 = display.getDisplayConfig(config2).vsyncPeriod;
const auto callbackFilter = [displayId,
vsyncPeriod2](auto refreshRateChangedDebugData) {
constexpr int kVsyncThreshold = 1000;
@@ -2872,8 +2877,9 @@
} while (--retryCount > 0);
if (retryCount == 0) {
- GTEST_FAIL() << "failed to get a callback for the display " << displayId
- << " with config " << config2;
+ GTEST_FAIL() << "Failed to get a callback for Display " << displayId
+ << " switching from " << display.printConfig(config1)
+ << " to " << display.printConfig(config2);
}
});
@@ -3002,14 +3008,10 @@
GTEST_SKIP() << "LAYER_LIFECYCLE_BATCH_COMMAND not supported by the implementation";
return;
}
-
auto& writer = getWriter(getPrimaryDisplayId());
- int64_t layer = 5;
- writer.setLayerLifecycleBatchCommandType(getPrimaryDisplayId(), layer,
- LayerLifecycleBatchCommandType::CREATE);
- writer.setNewBufferSlotCount(getPrimaryDisplayId(), layer, 1);
- writer.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ const auto& [status, layer] =
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer);
+ EXPECT_TRUE(status.isOk());
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
}
@@ -3019,15 +3021,13 @@
GTEST_SKIP() << "LAYER_LIFECYCLE_BATCH_COMMAND not supported by the implementation";
return;
}
-
- auto& writer = getWriter(getPrimaryDisplayId());
+ auto& writer = getWriter(getInvalidDisplayId());
int64_t layer = 5;
writer.setLayerLifecycleBatchCommandType(getInvalidDisplayId(), layer,
LayerLifecycleBatchCommandType::CREATE);
- writer.setNewBufferSlotCount(getPrimaryDisplayId(), layer, 1);
- writer.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ writer.setNewBufferSlotCount(getInvalidDisplayId(), layer, 1);
execute();
+
const auto errors = mReader.takeErrors();
ASSERT_TRUE(errors.size() == 1 && errors[0].errorCode == IComposerClient::EX_BAD_DISPLAY);
}
@@ -3037,26 +3037,15 @@
GTEST_SKIP() << "LAYER_LIFECYCLE_BATCH_COMMAND not supported by the implementation";
return;
}
-
auto& writer = getWriter(getPrimaryDisplayId());
- int64_t layer = 5;
- writer.setLayerLifecycleBatchCommandType(getPrimaryDisplayId(), layer,
- LayerLifecycleBatchCommandType::CREATE);
- writer.setNewBufferSlotCount(getPrimaryDisplayId(), layer, 1);
- writer.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
+ const auto& [status, layer] =
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer);
+ EXPECT_TRUE(status.isOk());
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
- writer.setLayerLifecycleBatchCommandType(getPrimaryDisplayId(), layer,
- LayerLifecycleBatchCommandType::DESTROY);
- layer++;
- writer.setLayerLifecycleBatchCommandType(getPrimaryDisplayId(), layer,
- LayerLifecycleBatchCommandType::CREATE);
- writer.setNewBufferSlotCount(getPrimaryDisplayId(), layer, 1);
-
+ EXPECT_TRUE(mComposerClient->destroyLayer(getPrimaryDisplayId(), layer, &writer).isOk());
execute();
- const auto errors = mReader.takeErrors();
- ASSERT_TRUE(errors.size() == 1 && errors[0].errorCode == IComposerClient::EX_BAD_DISPLAY);
+ ASSERT_TRUE(mReader.takeErrors().empty());
}
TEST_P(GraphicsComposerAidlCommandV3Test, DestroyBatchedCommand_BadDisplay) {
@@ -3064,25 +3053,20 @@
GTEST_SKIP() << "LAYER_LIFECYCLE_BATCH_COMMAND not supported by the implementation";
return;
}
-
auto& writer = getWriter(getPrimaryDisplayId());
- int64_t layer = 5;
- writer.setLayerLifecycleBatchCommandType(getPrimaryDisplayId(), layer,
- LayerLifecycleBatchCommandType::CREATE);
- writer.setNewBufferSlotCount(getPrimaryDisplayId(), layer, 1);
- writer.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
- VtsComposerClient::kNoFrameIntervalNs);
- execute();
- ASSERT_TRUE(mReader.takeErrors().empty());
- writer.setLayerLifecycleBatchCommandType(getInvalidDisplayId(), layer,
- LayerLifecycleBatchCommandType::DESTROY);
- layer++;
- writer.setLayerLifecycleBatchCommandType(getInvalidDisplayId(), layer,
- LayerLifecycleBatchCommandType::CREATE);
- writer.setNewBufferSlotCount(getPrimaryDisplayId(), layer, 1);
+ const auto& [status, layer] =
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer);
+ EXPECT_TRUE(status.isOk());
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
+
+ auto& invalid_writer = getWriter(getInvalidDisplayId());
+ invalid_writer.setLayerLifecycleBatchCommandType(getInvalidDisplayId(), layer,
+ LayerLifecycleBatchCommandType::DESTROY);
+ execute();
+ const auto errors = mReader.takeErrors();
+ ASSERT_TRUE(errors.size() == 1 && errors[0].errorCode == IComposerClient::EX_BAD_DISPLAY);
}
TEST_P(GraphicsComposerAidlCommandV3Test, NoCreateDestroyBatchedCommandIncorrectLayer) {
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/ProtectCallback.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/ProtectCallback.h
index 92ed1cd..9a7fe5e 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/ProtectCallback.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/ProtectCallback.h
@@ -56,6 +56,8 @@
// Thread safe class
class DeathMonitor final {
public:
+ explicit DeathMonitor(uintptr_t cookieKey) : kCookieKey(cookieKey) {}
+
static void serviceDied(void* cookie);
void serviceDied();
// Precondition: `killable` must be non-null.
@@ -63,9 +65,18 @@
// Precondition: `killable` must be non-null.
void remove(IProtectedCallback* killable) const;
+ uintptr_t getCookieKey() const { return kCookieKey; }
+
+ ~DeathMonitor();
+ DeathMonitor(const DeathMonitor&) = delete;
+ DeathMonitor(DeathMonitor&&) noexcept = delete;
+ DeathMonitor& operator=(const DeathMonitor&) = delete;
+ DeathMonitor& operator=(DeathMonitor&&) noexcept = delete;
+
private:
mutable std::mutex mMutex;
mutable std::vector<IProtectedCallback*> mObjects GUARDED_BY(mMutex);
+ const uintptr_t kCookieKey;
};
class DeathHandler final {
diff --git a/neuralnetworks/aidl/utils/src/ProtectCallback.cpp b/neuralnetworks/aidl/utils/src/ProtectCallback.cpp
index 54a673c..4a7ac08 100644
--- a/neuralnetworks/aidl/utils/src/ProtectCallback.cpp
+++ b/neuralnetworks/aidl/utils/src/ProtectCallback.cpp
@@ -25,6 +25,7 @@
#include <algorithm>
#include <functional>
+#include <map>
#include <memory>
#include <mutex>
#include <vector>
@@ -33,6 +34,16 @@
namespace aidl::android::hardware::neuralnetworks::utils {
+namespace {
+
+// Only dereference the cookie if it's valid (if it's in this set)
+// Only used with ndk
+std::mutex sCookiesMutex;
+uintptr_t sCookieKeyCounter GUARDED_BY(sCookiesMutex) = 0;
+std::map<uintptr_t, std::weak_ptr<DeathMonitor>> sCookies GUARDED_BY(sCookiesMutex);
+
+} // namespace
+
void DeathMonitor::serviceDied() {
std::lock_guard guard(mMutex);
std::for_each(mObjects.begin(), mObjects.end(),
@@ -40,8 +51,24 @@
}
void DeathMonitor::serviceDied(void* cookie) {
- auto deathMonitor = static_cast<DeathMonitor*>(cookie);
- deathMonitor->serviceDied();
+ std::shared_ptr<DeathMonitor> monitor;
+ {
+ std::lock_guard<std::mutex> guard(sCookiesMutex);
+ if (auto it = sCookies.find(reinterpret_cast<uintptr_t>(cookie)); it != sCookies.end()) {
+ monitor = it->second.lock();
+ sCookies.erase(it);
+ } else {
+ LOG(INFO)
+ << "Service died, but cookie is no longer valid so there is nothing to notify.";
+ return;
+ }
+ }
+ if (monitor) {
+ LOG(INFO) << "Notifying DeathMonitor from serviceDied.";
+ monitor->serviceDied();
+ } else {
+ LOG(INFO) << "Tried to notify DeathMonitor from serviceDied but could not promote.";
+ }
}
void DeathMonitor::add(IProtectedCallback* killable) const {
@@ -57,12 +84,25 @@
mObjects.erase(removedIter);
}
+DeathMonitor::~DeathMonitor() {
+ // lock must be taken so object is not used in OnBinderDied"
+ std::lock_guard<std::mutex> guard(sCookiesMutex);
+ sCookies.erase(kCookieKey);
+}
+
nn::GeneralResult<DeathHandler> DeathHandler::create(std::shared_ptr<ndk::ICInterface> object) {
if (object == nullptr) {
return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
<< "utils::DeathHandler::create must have non-null object";
}
- auto deathMonitor = std::make_shared<DeathMonitor>();
+
+ std::shared_ptr<DeathMonitor> deathMonitor;
+ {
+ std::lock_guard<std::mutex> guard(sCookiesMutex);
+ deathMonitor = std::make_shared<DeathMonitor>(sCookieKeyCounter++);
+ sCookies[deathMonitor->getCookieKey()] = deathMonitor;
+ }
+
auto deathRecipient = ndk::ScopedAIBinder_DeathRecipient(
AIBinder_DeathRecipient_new(DeathMonitor::serviceDied));
@@ -70,8 +110,9 @@
// STATUS_INVALID_OPERATION. We ignore this case because we only use local binders in tests
// where this is not an error.
if (object->isRemote()) {
- const auto ret = ndk::ScopedAStatus::fromStatus(AIBinder_linkToDeath(
- object->asBinder().get(), deathRecipient.get(), deathMonitor.get()));
+ const auto ret = ndk::ScopedAStatus::fromStatus(
+ AIBinder_linkToDeath(object->asBinder().get(), deathRecipient.get(),
+ reinterpret_cast<void*>(deathMonitor->getCookieKey())));
HANDLE_ASTATUS(ret) << "AIBinder_linkToDeath failed";
}
@@ -91,8 +132,9 @@
DeathHandler::~DeathHandler() {
if (kObject != nullptr && kDeathRecipient.get() != nullptr && kDeathMonitor != nullptr) {
- const auto ret = ndk::ScopedAStatus::fromStatus(AIBinder_unlinkToDeath(
- kObject->asBinder().get(), kDeathRecipient.get(), kDeathMonitor.get()));
+ const auto ret = ndk::ScopedAStatus::fromStatus(
+ AIBinder_unlinkToDeath(kObject->asBinder().get(), kDeathRecipient.get(),
+ reinterpret_cast<void*>(kDeathMonitor->getCookieKey())));
const auto maybeSuccess = handleTransportError(ret);
if (!maybeSuccess.ok()) {
LOG(ERROR) << maybeSuccess.error().message;
diff --git a/neuralnetworks/aidl/utils/test/DeviceTest.cpp b/neuralnetworks/aidl/utils/test/DeviceTest.cpp
index 73727b3..ffd3b8e 100644
--- a/neuralnetworks/aidl/utils/test/DeviceTest.cpp
+++ b/neuralnetworks/aidl/utils/test/DeviceTest.cpp
@@ -697,7 +697,8 @@
const auto mockDevice = createMockDevice();
const auto device = Device::create(kName, mockDevice, kVersion).value();
const auto ret = [&device]() {
- DeathMonitor::serviceDied(device->getDeathMonitor());
+ DeathMonitor::serviceDied(
+ reinterpret_cast<void*>(device->getDeathMonitor()->getCookieKey()));
return ndk::ScopedAStatus::ok();
};
EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _))
@@ -846,7 +847,8 @@
const auto mockDevice = createMockDevice();
const auto device = Device::create(kName, mockDevice, kVersion).value();
const auto ret = [&device]() {
- DeathMonitor::serviceDied(device->getDeathMonitor());
+ DeathMonitor::serviceDied(
+ reinterpret_cast<void*>(device->getDeathMonitor()->getCookieKey()));
return ndk::ScopedAStatus::ok();
};
EXPECT_CALL(*mockDevice, prepareModelWithConfig(_, _, _))
@@ -970,7 +972,8 @@
const auto mockDevice = createMockDevice();
const auto device = Device::create(kName, mockDevice, kVersion).value();
const auto ret = [&device]() {
- DeathMonitor::serviceDied(device->getDeathMonitor());
+ DeathMonitor::serviceDied(
+ reinterpret_cast<void*>(device->getDeathMonitor()->getCookieKey()));
return ndk::ScopedAStatus::ok();
};
EXPECT_CALL(*mockDevice, prepareModelFromCache(_, _, _, _, _))
diff --git a/nfc/aidl/vts/functional/Android.bp b/nfc/aidl/vts/functional/Android.bp
index 0dab2d8..d0b684b 100644
--- a/nfc/aidl/vts/functional/Android.bp
+++ b/nfc/aidl/vts/functional/Android.bp
@@ -45,3 +45,48 @@
"vts",
],
}
+
+cc_test {
+ name: "VtsNfcBehaviorChangesTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: [
+ "VtsNfcBehaviorChangesTest.cpp",
+ "CondVar.cpp",
+ ],
+ include_dirs: [
+ "system/nfc/src/gki/common",
+ "system/nfc/src/gki/ulinux",
+ "system/nfc/src/include",
+ "system/nfc/src/nfa/include",
+ "system/nfc/src/nfc/include",
+ "system/nfc/utils/include",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libbinder_ndk",
+ "libnativehelper",
+ "libstatssocket",
+ ],
+ static_libs: [
+ "android.hardware.nfc-V1-ndk",
+ "android.hardware.nfc@1.0",
+ "android.hardware.nfc@1.1",
+ "android.hardware.nfc@1.2",
+ "android_nfc_flags_aconfig_c_lib",
+ "libnfc-nci",
+ "libnfc-nci_flags",
+ "libnfcutils",
+ "libstatslog_nfc",
+ "server_configurable_flags",
+ ],
+ require_root: true,
+ test_options: {
+ vsr_min_shipping_api_level: 202404, // 2024Q2
+ },
+ test_suites: [
+ "vts",
+ ],
+}
diff --git a/nfc/aidl/vts/functional/CondVar.cpp b/nfc/aidl/vts/functional/CondVar.cpp
new file mode 100644
index 0000000..59e5b51
--- /dev/null
+++ b/nfc/aidl/vts/functional/CondVar.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Encapsulate a condition variable for thread synchronization.
+ */
+
+#include "CondVar.h"
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <errno.h>
+#include <string.h>
+
+using android::base::StringPrintf;
+
+/*******************************************************************************
+**
+** Function: CondVar
+**
+** Description: Initialize member variables.
+**
+** Returns: None.
+**
+*******************************************************************************/
+CondVar::CondVar() {
+ pthread_condattr_t attr;
+ pthread_condattr_init(&attr);
+ pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
+ memset(&mCondition, 0, sizeof(mCondition));
+ int const res = pthread_cond_init(&mCondition, &attr);
+ if (res) {
+ LOG(ERROR) << StringPrintf("CondVar::CondVar: fail init; error=0x%X", res);
+ }
+}
+
+/*******************************************************************************
+**
+** Function: ~CondVar
+**
+** Description: Cleanup all resources.
+**
+** Returns: None.
+**
+*******************************************************************************/
+CondVar::~CondVar() {
+ int const res = pthread_cond_destroy(&mCondition);
+ if (res) {
+ LOG(ERROR) << StringPrintf("CondVar::~CondVar: fail destroy; error=0x%X", res);
+ }
+}
+
+/*******************************************************************************
+**
+** Function: wait
+**
+** Description: Block the caller and wait for a condition.
+**
+** Returns: None.
+**
+*******************************************************************************/
+void CondVar::wait(std::mutex& mutex) {
+ int const res = pthread_cond_wait(&mCondition, mutex.native_handle());
+ if (res) {
+ LOG(ERROR) << StringPrintf("CondVar::wait: fail wait; error=0x%X", res);
+ }
+}
+
+/*******************************************************************************
+**
+** Function: wait
+**
+** Description: Block the caller and wait for a condition.
+** millisec: Timeout in milliseconds.
+**
+** Returns: True if wait is successful; false if timeout occurs.
+**
+*******************************************************************************/
+bool CondVar::wait(std::mutex& mutex, long millisec) {
+ bool retVal = false;
+ struct timespec absoluteTime;
+
+ if (clock_gettime(CLOCK_MONOTONIC, &absoluteTime) == -1) {
+ LOG(ERROR) << StringPrintf("CondVar::wait: fail get time; errno=0x%X", errno);
+ } else {
+ absoluteTime.tv_sec += millisec / 1000;
+ long ns = absoluteTime.tv_nsec + ((millisec % 1000) * 1000000);
+ if (ns > 1000000000) {
+ absoluteTime.tv_sec++;
+ absoluteTime.tv_nsec = ns - 1000000000;
+ } else
+ absoluteTime.tv_nsec = ns;
+ }
+
+ int waitResult = pthread_cond_timedwait(&mCondition, mutex.native_handle(), &absoluteTime);
+ if ((waitResult != 0) && (waitResult != ETIMEDOUT))
+ LOG(ERROR) << StringPrintf("CondVar::wait: fail timed wait; error=0x%X", waitResult);
+ retVal = (waitResult == 0); // waited successfully
+ return retVal;
+}
+
+/*******************************************************************************
+**
+** Function: notifyOne
+**
+** Description: Unblock the waiting thread.
+**
+** Returns: None.
+**
+*******************************************************************************/
+void CondVar::notifyOne() {
+ int const res = pthread_cond_signal(&mCondition);
+ if (res) {
+ LOG(ERROR) << StringPrintf("CondVar::notifyOne: fail signal; error=0x%X", res);
+ }
+}
diff --git a/nfc/aidl/vts/functional/CondVar.h b/nfc/aidl/vts/functional/CondVar.h
new file mode 100644
index 0000000..5e0dcf7
--- /dev/null
+++ b/nfc/aidl/vts/functional/CondVar.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Encapsulate a condition variable for thread synchronization.
+ */
+
+#pragma once
+#include <pthread.h>
+
+#include <mutex>
+
+class CondVar {
+ public:
+ /*******************************************************************************
+ **
+ ** Function: CondVar
+ **
+ ** Description: Initialize member variables.
+ **
+ ** Returns: None.
+ **
+ *******************************************************************************/
+ CondVar();
+
+ /*******************************************************************************
+ **
+ ** Function: ~CondVar
+ **
+ ** Description: Cleanup all resources.
+ **
+ ** Returns: None.
+ **
+ *******************************************************************************/
+ ~CondVar();
+
+ /*******************************************************************************
+ **
+ ** Function: wait
+ **
+ ** Description: Block the caller and wait for a condition.
+ **
+ ** Returns: None.
+ **
+ *******************************************************************************/
+ void wait(std::mutex& mutex);
+
+ /*******************************************************************************
+ **
+ ** Function: wait
+ **
+ ** Description: Block the caller and wait for a condition.
+ ** millisec: Timeout in milliseconds.
+ **
+ ** Returns: True if wait is successful; false if timeout occurs.
+ **
+ *******************************************************************************/
+ bool wait(std::mutex& mutex, long millisec);
+
+ /*******************************************************************************
+ **
+ ** Function: notifyOne
+ **
+ ** Description: Unblock the waiting thread.
+ **
+ ** Returns: None.
+ **
+ *******************************************************************************/
+ void notifyOne();
+
+ private:
+ pthread_cond_t mCondition;
+};
diff --git a/nfc/aidl/vts/functional/SyncEvent.h b/nfc/aidl/vts/functional/SyncEvent.h
new file mode 100644
index 0000000..352a549
--- /dev/null
+++ b/nfc/aidl/vts/functional/SyncEvent.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Synchronize two or more threads using a condition variable and a mutex.
+ */
+#pragma once
+#include <mutex>
+
+#include "CondVar.h"
+
+class SyncEvent {
+ public:
+ /*******************************************************************************
+ **
+ ** Function: ~SyncEvent
+ **
+ ** Description: Cleanup all resources.
+ **
+ ** Returns: None.
+ **
+ *******************************************************************************/
+ ~SyncEvent() {}
+
+ /*******************************************************************************
+ **
+ ** Function: start
+ **
+ ** Description: Start a synchronization operation.
+ **
+ ** Returns: None.
+ **
+ *******************************************************************************/
+ void start() { mMutex.lock(); }
+
+ /*******************************************************************************
+ **
+ ** Function: wait
+ **
+ ** Description: Block the thread and wait for the event to occur.
+ **
+ ** Returns: None.
+ **
+ *******************************************************************************/
+ void wait() { mCondVar.wait(mMutex); }
+
+ /*******************************************************************************
+ **
+ ** Function: wait
+ **
+ ** Description: Block the thread and wait for the event to occur.
+ ** millisec: Timeout in milliseconds.
+ **
+ ** Returns: True if wait is successful; false if timeout occurs.
+ **
+ *******************************************************************************/
+ bool wait(long millisec) {
+ bool retVal = mCondVar.wait(mMutex, millisec);
+ return retVal;
+ }
+
+ /*******************************************************************************
+ **
+ ** Function: notifyOne
+ **
+ ** Description: Notify a blocked thread that the event has occurred.
+ *Unblocks it.
+ **
+ ** Returns: None.
+ **
+ *******************************************************************************/
+ void notifyOne() { mCondVar.notifyOne(); }
+
+ /*******************************************************************************
+ **
+ ** Function: end
+ **
+ ** Description: End a synchronization operation.
+ **
+ ** Returns: None.
+ **
+ *******************************************************************************/
+ void end() { mMutex.unlock(); }
+
+ private:
+ CondVar mCondVar;
+ std::mutex mMutex;
+};
+
+/*****************************************************************************/
+/*****************************************************************************/
+
+/*****************************************************************************
+**
+** Name: SyncEventGuard
+**
+** Description: Automatically start and end a synchronization event.
+**
+*****************************************************************************/
+class SyncEventGuard {
+ public:
+ /*******************************************************************************
+ **
+ ** Function: SyncEventGuard
+ **
+ ** Description: Start a synchronization operation.
+ **
+ ** Returns: None.
+ **
+ *******************************************************************************/
+ SyncEventGuard(SyncEvent& event) : mEvent(event) {
+ event.start(); // automatically start operation
+ };
+
+ /*******************************************************************************
+ **
+ ** Function: ~SyncEventGuard
+ **
+ ** Description: End a synchronization operation.
+ **
+ ** Returns: None.
+ **
+ *******************************************************************************/
+ ~SyncEventGuard() {
+ mEvent.end(); // automatically end operation
+ };
+
+ private:
+ SyncEvent& mEvent;
+};
diff --git a/nfc/aidl/vts/functional/VtsNfcBehaviorChangesTest.cpp b/nfc/aidl/vts/functional/VtsNfcBehaviorChangesTest.cpp
new file mode 100644
index 0000000..0b73cc9
--- /dev/null
+++ b/nfc/aidl/vts/functional/VtsNfcBehaviorChangesTest.cpp
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "nfc_behavior_changes_test"
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <android/binder_process.h>
+#include <gtest/gtest.h>
+
+#include <chrono>
+#include <future>
+
+#include "NfcAdaptation.h"
+#include "SyncEvent.h"
+#include "nci_defs.h"
+#include "nfa_api.h"
+#include "nfa_ee_api.h"
+
+using android::base::StringPrintf;
+
+static SyncEvent sNfaEnableEvent; // event for NFA_Enable()
+static SyncEvent sNfaVsCommand; // event for VS commands
+static SyncEvent sNfaEnableDisablePollingEvent;
+static SyncEvent sNfaPowerChangeEvent;
+static bool sIsNfaEnabled;
+static tNFA_STATUS sVSCmdStatus;
+
+static void nfaDeviceManagementCallback(uint8_t dmEvent, tNFA_DM_CBACK_DATA* eventData) {
+ LOG(DEBUG) << StringPrintf("%s: enter; event=0x%X", __func__, dmEvent);
+
+ switch (dmEvent) {
+ case NFA_DM_ENABLE_EVT: /* Result of NFA_Enable */
+ {
+ SyncEventGuard guard(sNfaEnableEvent);
+ LOG(DEBUG) << StringPrintf("%s: NFA_DM_ENABLE_EVT; status=0x%X", __func__,
+ eventData->status);
+ sIsNfaEnabled = eventData->status == NFA_STATUS_OK;
+ sNfaEnableEvent.notifyOne();
+ } break;
+
+ case NFA_DM_DISABLE_EVT: /* Result of NFA_Disable */
+ {
+ SyncEventGuard guard(sNfaEnableEvent);
+ LOG(DEBUG) << StringPrintf("%s: NFA_DM_DISABLE_EVT; status=0x%X", __func__,
+ eventData->status);
+ sIsNfaEnabled = eventData->status == NFA_STATUS_OK;
+ sNfaEnableEvent.notifyOne();
+ } break;
+
+ case NFA_DM_PWR_MODE_CHANGE_EVT: {
+ SyncEventGuard guard(sNfaPowerChangeEvent);
+ LOG(DEBUG) << StringPrintf(
+ "%s: NFA_DM_PWR_MODE_CHANGE_EVT: status=0x%X, power_mode=0x%X", __func__,
+ eventData->status, eventData->power_mode.power_mode);
+
+ sNfaPowerChangeEvent.notifyOne();
+
+ } break;
+ }
+}
+
+static void nfaConnectionCallback(uint8_t connEvent, tNFA_CONN_EVT_DATA* eventData) {
+ LOG(DEBUG) << StringPrintf("%s: event= %u", __func__, connEvent);
+
+ switch (connEvent) {
+ case NFA_LISTEN_DISABLED_EVT: {
+ SyncEventGuard guard(sNfaEnableDisablePollingEvent);
+ sNfaEnableDisablePollingEvent.notifyOne();
+ } break;
+
+ case NFA_LISTEN_ENABLED_EVT: {
+ SyncEventGuard guard(sNfaEnableDisablePollingEvent);
+ sNfaEnableDisablePollingEvent.notifyOne();
+ } break;
+
+ case NFA_RF_DISCOVERY_STARTED_EVT: // RF Discovery started
+ {
+ LOG(DEBUG) << StringPrintf("%s: NFA_RF_DISCOVERY_STARTED_EVT: status = %u", __func__,
+ eventData->status);
+
+ SyncEventGuard guard(sNfaEnableDisablePollingEvent);
+ sNfaEnableDisablePollingEvent.notifyOne();
+ } break;
+
+ case NFA_RF_DISCOVERY_STOPPED_EVT: // RF Discovery stopped event
+ {
+ LOG(DEBUG) << StringPrintf("%s: NFA_RF_DISCOVERY_STOPPED_EVT: status = %u", __func__,
+ eventData->status);
+
+ SyncEventGuard guard(sNfaEnableDisablePollingEvent);
+ sNfaEnableDisablePollingEvent.notifyOne();
+ } break;
+ }
+}
+
+void static nfaVSCallback(uint8_t event, uint16_t /* param_len */, uint8_t* p_param) {
+ switch (event & NCI_OID_MASK) {
+ case NCI_MSG_PROP_ANDROID: {
+ uint8_t android_sub_opcode = p_param[3];
+ switch (android_sub_opcode) {
+ case NCI_ANDROID_PASSIVE_OBSERVE: {
+ sVSCmdStatus = p_param[4];
+ LOG(INFO) << StringPrintf("Observe mode RSP: status: %x", sVSCmdStatus);
+ SyncEventGuard guard(sNfaVsCommand);
+ sNfaVsCommand.notifyOne();
+ } break;
+ case NCI_ANDROID_POLLING_FRAME_NTF: {
+ // TODO
+ } break;
+ default:
+ LOG(WARNING) << StringPrintf("Unknown Android sub opcode %x",
+ android_sub_opcode);
+ }
+ } break;
+ default:
+ break;
+ }
+}
+
+/*
+ * Enable passive observe mode.
+ */
+tNFA_STATUS static nfaObserveModeEnable(bool enable) {
+ tNFA_STATUS status = NFA_STATUS_FAILED;
+
+ status = NFA_StopRfDiscovery();
+ if (status == NFA_STATUS_OK) {
+ if (!sNfaEnableDisablePollingEvent.wait(1000)) {
+ LOG(WARNING) << "Timeout waiting to disable NFC RF discovery";
+ return NFA_STATUS_TIMEOUT;
+ }
+ }
+
+ uint8_t cmd[] = {(NCI_MT_CMD << NCI_MT_SHIFT) | NCI_GID_PROP, NCI_MSG_PROP_ANDROID,
+ NCI_ANDROID_PASSIVE_OBSERVE_PARAM_SIZE, NCI_ANDROID_PASSIVE_OBSERVE,
+ static_cast<uint8_t>(enable ? NCI_ANDROID_PASSIVE_OBSERVE_PARAM_ENABLE
+ : NCI_ANDROID_PASSIVE_OBSERVE_PARAM_DISABLE)};
+
+ status = NFA_SendRawVsCommand(sizeof(cmd), cmd, nfaVSCallback);
+
+ if (status == NFA_STATUS_OK) {
+ if (!sNfaVsCommand.wait(1000)) {
+ LOG(WARNING) << "Timeout waiting for NFA VS command response";
+ return NFA_STATUS_TIMEOUT;
+ }
+ }
+
+ return status;
+}
+
+class NfcBehaviorChanges : public testing::Test {
+ protected:
+ void SetUp() override {
+ tNFA_STATUS status = NFA_STATUS_OK;
+
+ sIsNfaEnabled = false;
+ sVSCmdStatus = NFA_STATUS_OK;
+
+ NfcAdaptation& theInstance = NfcAdaptation::GetInstance();
+ theInstance.Initialize(); // start GKI, NCI task, NFC task
+
+ {
+ SyncEventGuard guard(sNfaEnableEvent);
+ tHAL_NFC_ENTRY* halFuncEntries = theInstance.GetHalEntryFuncs();
+
+ NFA_Init(halFuncEntries);
+
+ status = NFA_Enable(nfaDeviceManagementCallback, nfaConnectionCallback);
+ ASSERT_EQ(status, NFA_STATUS_OK);
+
+ // wait for NFA command to finish
+ ASSERT_TRUE(sNfaEnableEvent.wait(1000))
+ << "Timeout waiting for NFA command on NFA_Enable";
+ }
+
+ ASSERT_TRUE(sIsNfaEnabled) << "Could not initialize NFC controller";
+
+ status = NFA_StartRfDiscovery();
+ ASSERT_EQ(status, NFA_STATUS_OK);
+ ASSERT_TRUE(sNfaEnableDisablePollingEvent.wait(1000)) << "Timeout starting RF discovery";
+ }
+};
+
+/*
+ * ObserveModeEnable:
+ * Attempts to enable observe mode. Does not test Observe Mode functionality,
+ * but simply verifies that the enable command responds successfully.
+ *
+ * @VsrTest = GMS-VSR-3.2.8-001
+ */
+TEST_F(NfcBehaviorChanges, ObserveModeEnableDisable) {
+ tNFA_STATUS status = nfaObserveModeEnable(true);
+ ASSERT_EQ(status, NFA_STATUS_OK);
+
+ status = nfaObserveModeEnable(false);
+ ASSERT_EQ(status, NFA_STATUS_OK);
+}
+
+int main(int argc, char** argv) {
+ testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_startThreadPool();
+ std::system("/system/bin/svc nfc disable"); /* Turn off NFC service */
+ sleep(5);
+ int status = RUN_ALL_TESTS();
+ LOG(INFO) << "Test result = " << status;
+ std::system("/system/bin/svc nfc enable"); /* Turn on NFC service */
+ sleep(5);
+ return status;
+}
diff --git a/power/aidl/android/hardware/power/SessionConfig.aidl b/power/aidl/android/hardware/power/SessionConfig.aidl
index 93dc9a2..ca89183 100644
--- a/power/aidl/android/hardware/power/SessionConfig.aidl
+++ b/power/aidl/android/hardware/power/SessionConfig.aidl
@@ -25,6 +25,9 @@
/**
* The session's unique ID, used to identify the session for debugging and
* for multiplexing on the per-process FMQ channel.
+ *
+ * Values that fit in the 32-bit int range value must be provided when using
+ * the FMQ API, as the FMQ messages can only accept 32-bit Session IDs.
*/
long id;
}
diff --git a/radio/aidl/android/hardware/radio/network/SecurityAlgorithm.aidl b/radio/aidl/android/hardware/radio/network/SecurityAlgorithm.aidl
index 01f7327..451eaa9 100644
--- a/radio/aidl/android/hardware/radio/network/SecurityAlgorithm.aidl
+++ b/radio/aidl/android/hardware/radio/network/SecurityAlgorithm.aidl
@@ -62,7 +62,7 @@
// IMS and SIP layer security (See 3GPP TS 33.203)
// No IPsec config
SIP_NO_IPSEC_CONFIG = 66,
- IMS_NULL = 67,
+ IMS_NULL = 67, // Deprecated. Use SIP_NO_IPSEC_CONFIG and SIP_NULL instead.
// Has IPsec config
SIP_NULL = 68,
diff --git a/radio/aidl/vts/radio_config_test.cpp b/radio/aidl/vts/radio_config_test.cpp
index 6f18d18..e7214e5 100644
--- a/radio/aidl/vts/radio_config_test.cpp
+++ b/radio/aidl/vts/radio_config_test.cpp
@@ -278,7 +278,14 @@
EXPECT_LT(logicalSlotId, slotPortMappingList.size());
if (logicalSlotId >= 0 && logicalSlotId < slotPortMappingList.size()) {
slotPortMappingList[logicalSlotId].physicalSlotId = i;
- slotPortMappingList[logicalSlotId].portId = j;
+ if (radioRsp_config->simSlotStatus[i].supportedMepMode ==
+ MultipleEnabledProfilesMode::MEP_A1 ||
+ radioRsp_config->simSlotStatus[i].supportedMepMode ==
+ MultipleEnabledProfilesMode::MEP_A2) {
+ slotPortMappingList[logicalSlotId].portId = j + 1;
+ } else {
+ slotPortMappingList[logicalSlotId].portId = j;
+ }
}
}
}
diff --git a/sensors/aidl/default/include/sensors-impl/Sensors.h b/sensors/aidl/default/include/sensors-impl/Sensors.h
index e270d96..2adbc9d 100644
--- a/sensors/aidl/default/include/sensors-impl/Sensors.h
+++ b/sensors/aidl/default/include/sensors-impl/Sensors.h
@@ -119,6 +119,8 @@
// Utility function to delete the Event Flag
void deleteEventFlag() {
+ // Hold the lock to ensure we don't delete the flag while it's being used in postEvents()
+ std::lock_guard<std::mutex> lock(mWriteLock);
if (mEventQueueFlag != nullptr) {
status_t status = EventFlag::deleteEventFlag(&mEventQueueFlag);
if (status != OK) {
diff --git a/thermal/aidl/vts/VtsHalThermalTargetTest.cpp b/thermal/aidl/vts/VtsHalThermalTargetTest.cpp
index 4208d09..7f33e2d 100644
--- a/thermal/aidl/vts/VtsHalThermalTargetTest.cpp
+++ b/thermal/aidl/vts/VtsHalThermalTargetTest.cpp
@@ -25,6 +25,7 @@
#define LOG_TAG "thermal_aidl_hal_test"
+#include <VtsCoreUtil.h>
#include <aidl/Gtest.h>
#include <aidl/Vintf.h>
#include <aidl/android/hardware/thermal/BnCoolingDeviceChangedCallback.h>
@@ -70,6 +71,16 @@
.timeWindowMs = 7000,
};
+static const std::string FEATURE_WATCH = "android.hardware.type.watch";
+static const std::string FEATURE_TELEVISION = "android.hardware.type.television";
+static const std::string FEATURE_LEANBACK = "android.software.leanback";
+static const std::string FEATURE_AUTOMOTIVE = "android.hardware.type.automotive";
+static const std::string FEATURE_PC = "android.hardware.type.pc";
+static const std::string FEATURE_EMBEDDED = "android.hardware.type.embedded";
+static const std::string kNonHandheldFeatures[] = {FEATURE_AUTOMOTIVE, FEATURE_LEANBACK,
+ FEATURE_PC, FEATURE_TELEVISION,
+ FEATURE_WATCH, FEATURE_EMBEDDED};
+
// Callback class for receiving thermal event notifications from main class
class ThermalCallback : public BnThermalChangedCallback {
public:
@@ -341,8 +352,13 @@
// @VsrTest = VSR-3.2.5-002
TEST_P(ThermalAidlTest, SkinTemperatureThresholdsTest) {
auto apiLevel = ::android::base::GetIntProperty<int32_t>("ro.vendor.api_level", 0);
- if (apiLevel < 35) {
- GTEST_SKIP() << "Skipping test as the vendor level is below 35: " << apiLevel;
+ if (apiLevel < 202404) {
+ GTEST_SKIP() << "Skipping test as the vendor level is below 202404: " << apiLevel;
+ }
+ for (const auto& feature : kNonHandheldFeatures) {
+ if (::testing::deviceSupportsFeature(feature.c_str())) {
+ GTEST_SKIP() << "Skipping test as the device has feature: " << feature;
+ }
}
std::vector<Temperature> temperatures;
::ndk::ScopedAStatus status =
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index 6c6846f..db474d6 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -41,6 +41,8 @@
using android::hardware::vibrator::PrimitivePwle;
using std::chrono::high_resolution_clock;
+using namespace ::std::chrono_literals;
+
const std::vector<Effect> kEffects{android::enum_range<Effect>().begin(),
android::enum_range<Effect>().end()};
const std::vector<EffectStrength> kEffectStrengths{android::enum_range<EffectStrength>().begin(),
@@ -71,6 +73,9 @@
static_cast<CompositePrimitive>(static_cast<int32_t>(kCompositePrimitives.back()) + 1),
};
+// Timeout to wait for vibration callback completion.
+static constexpr auto VIBRATION_CALLBACK_TIMEOUT = 100ms;
+
class CompletionCallback : public BnVibratorCallback {
public:
CompletionCallback(const std::function<void()> &callback) : mCallback(callback) {}
@@ -221,7 +226,7 @@
sp<CompletionCallback> callback =
new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
uint32_t durationMs = 250;
- std::chrono::milliseconds timeout{durationMs * 2};
+ auto timeout = std::chrono::milliseconds(durationMs) + VIBRATION_CALLBACK_TIMEOUT;
EXPECT_TRUE(vibrator->on(durationMs, callback).isOk());
EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready);
EXPECT_TRUE(vibrator->off().isOk());
@@ -288,10 +293,10 @@
if (!status.isOk())
continue;
- //TODO(b/187207798): revert back to conservative timeout values once
- //latencies have been fixed
- std::chrono::milliseconds timeout{lengthMs * 8};
+ auto timeout = std::chrono::milliseconds(lengthMs) + VIBRATION_CALLBACK_TIMEOUT;
EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready);
+
+ EXPECT_TRUE(vibrator->off().isOk());
}
}
}
@@ -619,9 +624,7 @@
EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, callback).exceptionCode())
<< toString(primitive);
- // TODO(b/261130361): Investigate why latency from driver and hardware will cause test
- // to fail when wait duration is ~40ms or less.
- EXPECT_EQ(completionFuture.wait_for(duration + std::chrono::milliseconds(50)),
+ EXPECT_EQ(completionFuture.wait_for(duration + VIBRATION_CALLBACK_TIMEOUT),
std::future_status::ready)
<< toString(primitive);
end = high_resolution_clock::now();
@@ -782,9 +785,7 @@
int32_t segmentDurationMaxMs;
vibrator->getPwlePrimitiveDurationMax(&segmentDurationMaxMs);
uint32_t durationMs = segmentDurationMaxMs * 2 + 100; // Sum of 2 active and 1 braking below
- //TODO(b/187207798): revert back to conservative timeout values once
- //latencies have been fixed
- std::chrono::milliseconds timeout{durationMs * 4};
+ auto timeout = std::chrono::milliseconds(durationMs) + VIBRATION_CALLBACK_TIMEOUT;
ActivePwle active = composeValidActivePwle(vibrator, capabilities);
diff --git a/vibrator/bench/benchmark.cpp b/vibrator/bench/benchmark.cpp
index b96e06d..deaa6f2 100644
--- a/vibrator/bench/benchmark.cpp
+++ b/vibrator/bench/benchmark.cpp
@@ -20,6 +20,8 @@
#include <android/hardware/vibrator/BnVibratorCallback.h>
#include <android/hardware/vibrator/IVibrator.h>
#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <future>
using ::android::enum_range;
using ::android::sp;
@@ -31,9 +33,8 @@
using ::benchmark::kMicrosecond;
using ::benchmark::State;
using ::benchmark::internal::Benchmark;
-using ::std::chrono::duration;
-using ::std::chrono::duration_cast;
-using ::std::chrono::high_resolution_clock;
+
+using namespace ::std::chrono_literals;
namespace Aidl = ::android::hardware::vibrator;
namespace V1_0 = ::android::hardware::vibrator::V1_0;
@@ -41,14 +42,28 @@
namespace V1_2 = ::android::hardware::vibrator::V1_2;
namespace V1_3 = ::android::hardware::vibrator::V1_3;
+// Fixed number of iterations for benchmarks that trigger a vibration on the loop.
+// They require slow cleanup to ensure a stable state on each run and less noisy metrics.
+static constexpr auto VIBRATION_ITERATIONS = 500;
+
+// Timeout to wait for vibration callback completion.
+static constexpr auto VIBRATION_CALLBACK_TIMEOUT = 100ms;
+
+// Max duration the vibrator can be turned on, in milliseconds.
+static constexpr uint32_t MAX_ON_DURATION_MS = UINT16_MAX;
+
template <typename I>
class BaseBench : public Fixture {
public:
+ void SetUp(State& /*state*/) override {
+ android::ProcessState::self()->setThreadPoolMaxThreadCount(1);
+ android::ProcessState::self()->startThreadPool();
+ }
+
void TearDown(State& /*state*/) override {
- if (!mVibrator) {
- return;
+ if (mVibrator) {
+ mVibrator->off();
}
- mVibrator->off();
}
static void DefaultConfig(Benchmark* b) { b->Unit(kMicrosecond); }
@@ -66,7 +81,19 @@
template <typename I>
class VibratorBench : public BaseBench<I> {
public:
- void SetUp(State& /*state*/) override { this->mVibrator = I::getService(); }
+ void SetUp(State& state) override {
+ BaseBench<I>::SetUp(state);
+ this->mVibrator = I::getService();
+ }
+
+ protected:
+ bool shouldSkipWithError(State& state, const android::hardware::Return<V1_0::Status>&& ret) {
+ if (!ret.isOk()) {
+ state.SkipWithError(ret.description());
+ return true;
+ }
+ return false;
+ }
};
enum class EmptyEnum : uint32_t;
@@ -118,16 +145,25 @@
});
if (!supported) {
- state->SkipWithMessage("performApi returned UNSUPPORTED_OPERATION");
+ state->SkipWithMessage("effect unsupported");
return;
}
for (auto _ : *state) {
- state->ResumeTiming();
- (*this->mVibrator.*performApi)(effect, strength,
- [](Status /*status*/, uint32_t /*lengthMs*/) {});
+ // Test
+ auto ret = (*this->mVibrator.*performApi)(
+ effect, strength, [](Status /*status*/, uint32_t /*lengthMs*/) {});
+
+ // Cleanup
state->PauseTiming();
- this->mVibrator->off();
+ if (!ret.isOk()) {
+ state->SkipWithError(ret.description());
+ return;
+ }
+ if (this->shouldSkipWithError(*state, this->mVibrator->off())) {
+ return;
+ }
+ state->ResumeTiming();
}
}
@@ -157,24 +193,38 @@
using VibratorBench_V1_0 = VibratorBench<V1_0::IVibrator>;
BENCHMARK_WRAPPER(VibratorBench_V1_0, on, {
- uint32_t ms = UINT32_MAX;
+ auto ms = MAX_ON_DURATION_MS;
for (auto _ : state) {
- state.ResumeTiming();
- mVibrator->on(ms);
+ // Test
+ if (shouldSkipWithError(state, mVibrator->on(ms))) {
+ return;
+ }
+
+ // Cleanup
state.PauseTiming();
- mVibrator->off();
+ if (shouldSkipWithError(state, mVibrator->off())) {
+ return;
+ }
+ state.ResumeTiming();
}
});
BENCHMARK_WRAPPER(VibratorBench_V1_0, off, {
- uint32_t ms = UINT32_MAX;
+ auto ms = MAX_ON_DURATION_MS;
for (auto _ : state) {
+ // Setup
state.PauseTiming();
- mVibrator->on(ms);
+ if (shouldSkipWithError(state, mVibrator->on(ms))) {
+ return;
+ }
state.ResumeTiming();
- mVibrator->off();
+
+ // Test
+ if (shouldSkipWithError(state, mVibrator->off())) {
+ return;
+ }
}
});
@@ -185,20 +235,23 @@
});
BENCHMARK_WRAPPER(VibratorBench_V1_0, setAmplitude, {
+ auto ms = MAX_ON_DURATION_MS;
uint8_t amplitude = UINT8_MAX;
if (!mVibrator->supportsAmplitudeControl()) {
- state.SkipWithMessage("Amplitude control unavailable");
+ state.SkipWithMessage("amplitude control unavailable");
return;
}
- mVibrator->on(UINT32_MAX);
-
- for (auto _ : state) {
- mVibrator->setAmplitude(amplitude);
+ if (shouldSkipWithError(state, mVibrator->on(ms))) {
+ return;
}
- mVibrator->off();
+ for (auto _ : state) {
+ if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) {
+ return;
+ }
+ }
});
using VibratorEffectsBench_V1_0 = VibratorEffectsBench<V1_0::IVibrator, V1_0::Effect>;
@@ -218,7 +271,15 @@
BENCHMARK_WRAPPER(VibratorEffectsBench_V1_2, perform_1_2,
{ performBench(&state, &V1_2::IVibrator::perform_1_2); });
-using VibratorBench_V1_3 = VibratorBench<V1_3::IVibrator>;
+class VibratorBench_V1_3 : public VibratorBench<V1_3::IVibrator> {
+ public:
+ void TearDown(State& state) override {
+ VibratorBench::TearDown(state);
+ if (mVibrator) {
+ mVibrator->setExternalControl(false);
+ }
+ }
+};
BENCHMARK_WRAPPER(VibratorBench_V1_3, supportsExternalControl, {
for (auto _ : state) {
@@ -227,18 +288,23 @@
});
BENCHMARK_WRAPPER(VibratorBench_V1_3, setExternalControl, {
- bool enable = true;
-
if (!mVibrator->supportsExternalControl()) {
state.SkipWithMessage("external control unavailable");
return;
}
for (auto _ : state) {
- state.ResumeTiming();
- mVibrator->setExternalControl(enable);
+ // Test
+ if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) {
+ return;
+ }
+
+ // Cleanup
state.PauseTiming();
- mVibrator->setExternalControl(false);
+ if (shouldSkipWithError(state, mVibrator->setExternalControl(false))) {
+ return;
+ }
+ state.ResumeTiming();
}
});
@@ -248,13 +314,13 @@
return;
}
- mVibrator->setExternalControl(true);
+ if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) {
+ return;
+ }
for (auto _ : state) {
mVibrator->supportsAmplitudeControl();
}
-
- mVibrator->setExternalControl(false);
});
BENCHMARK_WRAPPER(VibratorBench_V1_3, setExternalAmplitude, {
@@ -265,7 +331,9 @@
return;
}
- mVibrator->setExternalControl(true);
+ if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) {
+ return;
+ }
if (!mVibrator->supportsAmplitudeControl()) {
state.SkipWithMessage("amplitude control unavailable");
@@ -273,10 +341,10 @@
}
for (auto _ : state) {
- mVibrator->setAmplitude(amplitude);
+ if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) {
+ return;
+ }
}
-
- mVibrator->setExternalControl(false);
});
using VibratorEffectsBench_V1_3 = VibratorEffectsBench<V1_3::IVibrator, V1_3::Effect, V1_2::Effect>;
@@ -286,9 +354,42 @@
class VibratorBench_Aidl : public BaseBench<Aidl::IVibrator> {
public:
- void SetUp(State& /*state*/) override {
+ void SetUp(State& state) override {
+ BaseBench::SetUp(state);
this->mVibrator = android::waitForVintfService<Aidl::IVibrator>();
}
+
+ void TearDown(State& state) override {
+ BaseBench::TearDown(state);
+ if (mVibrator) {
+ mVibrator->setExternalControl(false);
+ }
+ }
+
+ protected:
+ int32_t hasCapabilities(int32_t capabilities) {
+ int32_t deviceCapabilities = 0;
+ this->mVibrator->getCapabilities(&deviceCapabilities);
+ return (deviceCapabilities & capabilities) == capabilities;
+ }
+
+ bool shouldSkipWithError(State& state, const android::binder::Status&& status) {
+ if (!status.isOk()) {
+ state.SkipWithError(status.toString8().c_str());
+ return true;
+ }
+ return false;
+ }
+
+ static void SlowBenchConfig(Benchmark* b) { b->Iterations(VIBRATION_ITERATIONS); }
+};
+
+class SlowVibratorBench_Aidl : public VibratorBench_Aidl {
+ public:
+ static void DefaultConfig(Benchmark* b) {
+ VibratorBench_Aidl::DefaultConfig(b);
+ SlowBenchConfig(b);
+ }
};
class HalCallback : public Aidl::BnVibratorCallback {
@@ -296,30 +397,70 @@
HalCallback() = default;
~HalCallback() = default;
- android::binder::Status onComplete() override { return android::binder::Status::ok(); }
+ android::binder::Status onComplete() override {
+ mPromise.set_value();
+ return android::binder::Status::ok();
+ }
+
+ void waitForComplete() {
+ // Wait until the HAL has finished processing previous vibration before starting a new one,
+ // so the HAL state is consistent on each run and metrics are less noisy. Some of the newest
+ // HAL implementations are waiting on previous vibration cleanup and might be significantly
+ // slower, so make sure we measure vibrations on a clean slate.
+ mPromise.get_future().wait_for(VIBRATION_CALLBACK_TIMEOUT);
+ }
+
+ private:
+ std::promise<void> mPromise;
};
-BENCHMARK_WRAPPER(VibratorBench_Aidl, on, {
- int32_t capabilities = 0;
- mVibrator->getCapabilities(&capabilities);
-
- int32_t ms = INT32_MAX;
- auto cb = (capabilities & Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr;
+BENCHMARK_WRAPPER(SlowVibratorBench_Aidl, on, {
+ auto ms = MAX_ON_DURATION_MS;
for (auto _ : state) {
- state.ResumeTiming();
- mVibrator->on(ms, cb);
+ auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr;
+
+ // Test
+ if (shouldSkipWithError(state, mVibrator->on(ms, cb))) {
+ return;
+ }
+
+ // Cleanup
state.PauseTiming();
- mVibrator->off();
+ if (shouldSkipWithError(state, mVibrator->off())) {
+ return;
+ }
+ if (cb) {
+ cb->waitForComplete();
+ }
+ state.ResumeTiming();
}
});
-BENCHMARK_WRAPPER(VibratorBench_Aidl, off, {
+BENCHMARK_WRAPPER(SlowVibratorBench_Aidl, off, {
+ auto ms = MAX_ON_DURATION_MS;
+
for (auto _ : state) {
+ auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr;
+
+ // Setup
state.PauseTiming();
- mVibrator->on(INT32_MAX, nullptr);
+ if (shouldSkipWithError(state, mVibrator->on(ms, cb))) {
+ return;
+ }
state.ResumeTiming();
- mVibrator->off();
+
+ // Test
+ if (shouldSkipWithError(state, mVibrator->off())) {
+ return;
+ }
+
+ // Cleanup
+ state.PauseTiming();
+ if (cb) {
+ cb->waitForComplete();
+ }
+ state.ResumeTiming();
}
});
@@ -327,76 +468,97 @@
int32_t capabilities = 0;
for (auto _ : state) {
- mVibrator->getCapabilities(&capabilities);
+ if (shouldSkipWithError(state, mVibrator->getCapabilities(&capabilities))) {
+ return;
+ }
}
});
BENCHMARK_WRAPPER(VibratorBench_Aidl, setAmplitude, {
- int32_t capabilities = 0;
- mVibrator->getCapabilities(&capabilities);
- if ((capabilities & Aidl::IVibrator::CAP_AMPLITUDE_CONTROL) == 0) {
+ auto ms = MAX_ON_DURATION_MS;
+ float amplitude = 1.0f;
+
+ if (!hasCapabilities(Aidl::IVibrator::CAP_AMPLITUDE_CONTROL)) {
state.SkipWithMessage("amplitude control unavailable");
return;
}
- float amplitude = 1.0f;
- mVibrator->on(INT32_MAX, nullptr);
-
- for (auto _ : state) {
- mVibrator->setAmplitude(amplitude);
+ auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr;
+ if (shouldSkipWithError(state, mVibrator->on(ms, cb))) {
+ return;
}
- mVibrator->off();
+ for (auto _ : state) {
+ if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) {
+ return;
+ }
+ }
});
BENCHMARK_WRAPPER(VibratorBench_Aidl, setExternalControl, {
- int32_t capabilities = 0;
- mVibrator->getCapabilities(&capabilities);
- if ((capabilities & Aidl::IVibrator::CAP_EXTERNAL_CONTROL) == 0) {
+ if (!hasCapabilities(Aidl::IVibrator::CAP_EXTERNAL_CONTROL)) {
state.SkipWithMessage("external control unavailable");
return;
}
for (auto _ : state) {
- state.ResumeTiming();
- mVibrator->setExternalControl(true);
+ // Test
+ if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) {
+ return;
+ }
+
+ // Cleanup
state.PauseTiming();
- mVibrator->setExternalControl(false);
+ if (shouldSkipWithError(state, mVibrator->setExternalControl(false))) {
+ return;
+ }
+ state.ResumeTiming();
}
});
BENCHMARK_WRAPPER(VibratorBench_Aidl, setExternalAmplitude, {
- int32_t capabilities = 0;
- mVibrator->getCapabilities(&capabilities);
- if ((capabilities & Aidl::IVibrator::CAP_EXTERNAL_CONTROL) == 0 ||
- (capabilities & Aidl::IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL) == 0) {
+ auto externalControl = static_cast<int32_t>(Aidl::IVibrator::CAP_EXTERNAL_CONTROL);
+ auto externalAmplitudeControl =
+ static_cast<int32_t>(Aidl::IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL);
+ if (!hasCapabilities(externalControl | externalAmplitudeControl)) {
state.SkipWithMessage("external amplitude control unavailable");
return;
}
- float amplitude = 1.0f;
- mVibrator->setExternalControl(true);
-
- for (auto _ : state) {
- mVibrator->setAmplitude(amplitude);
+ if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) {
+ return;
}
- mVibrator->setExternalControl(false);
+ float amplitude = 1.0f;
+ for (auto _ : state) {
+ if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) {
+ return;
+ }
+ }
});
BENCHMARK_WRAPPER(VibratorBench_Aidl, getSupportedEffects, {
std::vector<Aidl::Effect> supportedEffects;
for (auto _ : state) {
- mVibrator->getSupportedEffects(&supportedEffects);
+ if (shouldSkipWithError(state, mVibrator->getSupportedEffects(&supportedEffects))) {
+ return;
+ }
}
});
BENCHMARK_WRAPPER(VibratorBench_Aidl, getSupportedAlwaysOnEffects, {
+ if (!hasCapabilities(Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL)) {
+ state.SkipWithMessage("always on control unavailable");
+ return;
+ }
+
std::vector<Aidl::Effect> supportedEffects;
for (auto _ : state) {
- mVibrator->getSupportedAlwaysOnEffects(&supportedEffects);
+ if (shouldSkipWithError(state, mVibrator->getSupportedAlwaysOnEffects(&supportedEffects))) {
+ return;
+ }
}
});
@@ -404,7 +566,9 @@
std::vector<Aidl::CompositePrimitive> supportedPrimitives;
for (auto _ : state) {
- mVibrator->getSupportedPrimitives(&supportedPrimitives);
+ if (shouldSkipWithError(state, mVibrator->getSupportedPrimitives(&supportedPrimitives))) {
+ return;
+ }
}
});
@@ -427,12 +591,30 @@
auto getStrength(const State& state) const {
return static_cast<Aidl::EffectStrength>(this->getOtherArg(state, 1));
}
+
+ bool isEffectSupported(const Aidl::Effect& effect) {
+ std::vector<Aidl::Effect> supported;
+ mVibrator->getSupportedEffects(&supported);
+ return std::find(supported.begin(), supported.end(), effect) != supported.end();
+ }
+
+ bool isAlwaysOnEffectSupported(const Aidl::Effect& effect) {
+ std::vector<Aidl::Effect> supported;
+ mVibrator->getSupportedAlwaysOnEffects(&supported);
+ return std::find(supported.begin(), supported.end(), effect) != supported.end();
+ }
+};
+
+class SlowVibratorEffectsBench_Aidl : public VibratorEffectsBench_Aidl {
+ public:
+ static void DefaultConfig(Benchmark* b) {
+ VibratorEffectsBench_Aidl::DefaultConfig(b);
+ SlowBenchConfig(b);
+ }
};
BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, alwaysOnEnable, {
- int32_t capabilities = 0;
- mVibrator->getCapabilities(&capabilities);
- if ((capabilities & Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL) == 0) {
+ if (!hasCapabilities(Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL)) {
state.SkipWithMessage("always on control unavailable");
return;
}
@@ -441,25 +623,28 @@
auto effect = getEffect(state);
auto strength = getStrength(state);
- std::vector<Aidl::Effect> supported;
- mVibrator->getSupportedAlwaysOnEffects(&supported);
- if (std::find(supported.begin(), supported.end(), effect) == supported.end()) {
- state.SkipWithMessage("always on effects unavailable");
+ if (!isAlwaysOnEffectSupported(effect)) {
+ state.SkipWithMessage("always on effect unsupported");
return;
}
for (auto _ : state) {
- state.ResumeTiming();
- mVibrator->alwaysOnEnable(id, effect, strength);
+ // Test
+ if (shouldSkipWithError(state, mVibrator->alwaysOnEnable(id, effect, strength))) {
+ return;
+ }
+
+ // Cleanup
state.PauseTiming();
- mVibrator->alwaysOnDisable(id);
+ if (shouldSkipWithError(state, mVibrator->alwaysOnDisable(id))) {
+ return;
+ }
+ state.ResumeTiming();
}
});
BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, alwaysOnDisable, {
- int32_t capabilities = 0;
- mVibrator->getCapabilities(&capabilities);
- if ((capabilities & Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL) == 0) {
+ if (!hasCapabilities(Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL)) {
state.SkipWithMessage("always on control unavailable");
return;
}
@@ -468,42 +653,55 @@
auto effect = getEffect(state);
auto strength = getStrength(state);
- std::vector<Aidl::Effect> supported;
- mVibrator->getSupportedAlwaysOnEffects(&supported);
- if (std::find(supported.begin(), supported.end(), effect) == supported.end()) {
- state.SkipWithMessage("always on effects unavailable");
+ if (!isAlwaysOnEffectSupported(effect)) {
+ state.SkipWithMessage("always on effect unsupported");
return;
}
for (auto _ : state) {
+ // Setup
state.PauseTiming();
- mVibrator->alwaysOnEnable(id, effect, strength);
+ if (shouldSkipWithError(state, mVibrator->alwaysOnEnable(id, effect, strength))) {
+ return;
+ }
state.ResumeTiming();
- mVibrator->alwaysOnDisable(id);
+
+ // Test
+ if (shouldSkipWithError(state, mVibrator->alwaysOnDisable(id))) {
+ return;
+ }
}
});
-BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, perform, {
- int32_t capabilities = 0;
- mVibrator->getCapabilities(&capabilities);
-
+BENCHMARK_WRAPPER(SlowVibratorEffectsBench_Aidl, perform, {
auto effect = getEffect(state);
auto strength = getStrength(state);
- auto cb = (capabilities & Aidl::IVibrator::CAP_PERFORM_CALLBACK) ? new HalCallback() : nullptr;
- int32_t lengthMs = 0;
- std::vector<Aidl::Effect> supported;
- mVibrator->getSupportedEffects(&supported);
- if (std::find(supported.begin(), supported.end(), effect) == supported.end()) {
- state.SkipWithMessage("effects unavailable");
+ if (!isEffectSupported(effect)) {
+ state.SkipWithMessage("effect unsupported");
return;
}
+ int32_t lengthMs = 0;
+
for (auto _ : state) {
- state.ResumeTiming();
- mVibrator->perform(effect, strength, cb, &lengthMs);
+ auto cb = hasCapabilities(Aidl::IVibrator::CAP_PERFORM_CALLBACK) ? new HalCallback()
+ : nullptr;
+
+ // Test
+ if (shouldSkipWithError(state, mVibrator->perform(effect, strength, cb, &lengthMs))) {
+ return;
+ }
+
+ // Cleanup
state.PauseTiming();
- mVibrator->off();
+ if (shouldSkipWithError(state, mVibrator->off())) {
+ return;
+ }
+ if (cb) {
+ cb->waitForComplete();
+ }
+ state.ResumeTiming();
}
});
@@ -520,13 +718,29 @@
auto getPrimitive(const State& state) const {
return static_cast<Aidl::CompositePrimitive>(this->getOtherArg(state, 0));
}
+
+ bool isPrimitiveSupported(const Aidl::CompositePrimitive& primitive) {
+ std::vector<Aidl::CompositePrimitive> supported;
+ mVibrator->getSupportedPrimitives(&supported);
+ return std::find(supported.begin(), supported.end(), primitive) != supported.end();
+ }
+};
+
+class SlowVibratorPrimitivesBench_Aidl : public VibratorPrimitivesBench_Aidl {
+ public:
+ static void DefaultConfig(Benchmark* b) {
+ VibratorPrimitivesBench_Aidl::DefaultConfig(b);
+ SlowBenchConfig(b);
+ }
};
BENCHMARK_WRAPPER(VibratorBench_Aidl, getCompositionDelayMax, {
int32_t ms = 0;
for (auto _ : state) {
- mVibrator->getCompositionDelayMax(&ms);
+ if (shouldSkipWithError(state, mVibrator->getCompositionDelayMax(&ms))) {
+ return;
+ }
}
});
@@ -534,14 +748,14 @@
int32_t size = 0;
for (auto _ : state) {
- mVibrator->getCompositionSizeMax(&size);
+ if (shouldSkipWithError(state, mVibrator->getCompositionSizeMax(&size))) {
+ return;
+ }
}
});
BENCHMARK_WRAPPER(VibratorPrimitivesBench_Aidl, getPrimitiveDuration, {
- int32_t capabilities = 0;
- mVibrator->getCapabilities(&capabilities);
- if ((capabilities & Aidl::IVibrator::CAP_COMPOSE_EFFECTS) == 0) {
+ if (!hasCapabilities(Aidl::IVibrator::CAP_COMPOSE_EFFECTS)) {
state.SkipWithMessage("compose effects unavailable");
return;
}
@@ -549,22 +763,20 @@
auto primitive = getPrimitive(state);
int32_t ms = 0;
- std::vector<Aidl::CompositePrimitive> supported;
- mVibrator->getSupportedPrimitives(&supported);
- if (std::find(supported.begin(), supported.end(), primitive) == supported.end()) {
- state.SkipWithMessage("supported primitives unavailable");
+ if (!isPrimitiveSupported(primitive)) {
+ state.SkipWithMessage("primitive unsupported");
return;
}
for (auto _ : state) {
- mVibrator->getPrimitiveDuration(primitive, &ms);
+ if (shouldSkipWithError(state, mVibrator->getPrimitiveDuration(primitive, &ms))) {
+ return;
+ }
}
});
-BENCHMARK_WRAPPER(VibratorPrimitivesBench_Aidl, compose, {
- int32_t capabilities = 0;
- mVibrator->getCapabilities(&capabilities);
- if ((capabilities & Aidl::IVibrator::CAP_COMPOSE_EFFECTS) == 0) {
+BENCHMARK_WRAPPER(SlowVibratorPrimitivesBench_Aidl, compose, {
+ if (!hasCapabilities(Aidl::IVibrator::CAP_COMPOSE_EFFECTS)) {
state.SkipWithMessage("compose effects unavailable");
return;
}
@@ -574,22 +786,33 @@
effect.scale = 1.0f;
effect.delayMs = 0;
- std::vector<Aidl::CompositePrimitive> supported;
- mVibrator->getSupportedPrimitives(&supported);
- if (std::find(supported.begin(), supported.end(), effect.primitive) == supported.end()) {
- state.SkipWithMessage("supported primitives unavailable");
+ if (effect.primitive == Aidl::CompositePrimitive::NOOP) {
+ state.SkipWithMessage("skipping primitive NOOP");
+ return;
+ }
+ if (!isPrimitiveSupported(effect.primitive)) {
+ state.SkipWithMessage("primitive unsupported");
return;
}
- auto cb = new HalCallback();
std::vector<Aidl::CompositeEffect> effects;
effects.push_back(effect);
for (auto _ : state) {
- state.ResumeTiming();
- mVibrator->compose(effects, cb);
+ auto cb = new HalCallback();
+
+ // Test
+ if (shouldSkipWithError(state, mVibrator->compose(effects, cb))) {
+ return;
+ }
+
+ // Cleanup
state.PauseTiming();
- mVibrator->off();
+ if (shouldSkipWithError(state, mVibrator->off())) {
+ return;
+ }
+ cb->waitForComplete();
+ state.ResumeTiming();
}
});
diff --git a/wifi/aidl/default/aidl_struct_util.cpp b/wifi/aidl/default/aidl_struct_util.cpp
index d9e023c..d82450e 100644
--- a/wifi/aidl/default/aidl_struct_util.cpp
+++ b/wifi/aidl/default/aidl_struct_util.cpp
@@ -525,6 +525,7 @@
return true;
}
+// Only use to prepare parameters for Gscan.
legacy_hal::wifi_band convertAidlWifiBandToLegacy(WifiBand band) {
switch (band) {
case WifiBand::BAND_UNSPECIFIED:
@@ -541,6 +542,15 @@
return legacy_hal::WIFI_BAND_ABG;
case WifiBand::BAND_24GHZ_5GHZ_WITH_DFS:
return legacy_hal::WIFI_BAND_ABG_WITH_DFS;
+ case WifiBand::BAND_6GHZ:
+ case WifiBand::BAND_60GHZ:
+ case WifiBand::BAND_5GHZ_6GHZ:
+ case WifiBand::BAND_24GHZ_5GHZ_6GHZ:
+ case WifiBand::BAND_24GHZ_5GHZ_6GHZ_60GHZ:
+ case WifiBand::BAND_24GHZ_5GHZ_WITH_DFS_6GHZ:
+ case WifiBand::BAND_24GHZ_5GHZ_WITH_DFS_6GHZ_60GHZ:
+ LOG(INFO) << "WifiBand mapping may be incorrect, since 6GHz is not supported by legacy";
+ return legacy_hal::WIFI_BAND_UNSPECIFIED;
default:
CHECK(false);
return {};
diff --git a/wifi/aidl/default/wifi_legacy_hal.cpp b/wifi/aidl/default/wifi_legacy_hal.cpp
index cf86120..bd92a20 100644
--- a/wifi/aidl/default/wifi_legacy_hal.cpp
+++ b/wifi/aidl/default/wifi_legacy_hal.cpp
@@ -2012,7 +2012,7 @@
}
wifi_error WifiLegacyHal::setScanMode(const std::string& iface_name, bool enable) {
- return global_func_table_.wifi_set_scan_mode(iface_name.c_str(), enable);
+ return global_func_table_.wifi_set_scan_mode(getIfaceHandle(iface_name), enable);
}
wifi_error WifiLegacyHal::setDtimConfig(const std::string& iface_name, uint32_t multiplier) {
diff --git a/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp b/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp
index c87fe13..f659bf6 100644
--- a/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp
+++ b/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp
@@ -148,7 +148,7 @@
* Ensures the APF packet filter is fully supported as required in VSR 14:
* https://docs.partner.android.com/gms/policies/vsr/vsr-14
*/
-// @VsrTest = 5.3.12
+// @VsrTest = VSR-5.3.12-001|VSR-5.3.12-003|VSR-5.3.12-004|VSR-5.3.12-009
TEST_P(WifiStaIfaceAidlTest, CheckApfIsSupported) {
const std::string oem_key1 = getPropertyString("ro.oem.key1");
if (isTvDevice()) {
diff --git a/wifi/legacy_headers/include/hardware_legacy/wifi_hal.h b/wifi/legacy_headers/include/hardware_legacy/wifi_hal.h
index e770777..9baa2c7 100644
--- a/wifi/legacy_headers/include/hardware_legacy/wifi_hal.h
+++ b/wifi/legacy_headers/include/hardware_legacy/wifi_hal.h
@@ -715,7 +715,7 @@
/* Wi-Fi coex channel avoidance support */
-#define WIFI_COEX_NO_POWER_CAP (int32_t)0x7FFFFFF
+#define WIFI_COEX_NO_POWER_CAP (int32_t)0x7FFFFFFF
typedef enum {
WIFI_AWARE = 1 << 0,
@@ -1386,7 +1386,7 @@
* @param enable true if current is scan only mode
* @return Synchronous wifi_error
*/
- wifi_error (*wifi_set_scan_mode)(const char * ifname, bool enable);
+ wifi_error (*wifi_set_scan_mode)(wifi_interface_handle iface, bool enable);
wifi_error (*wifi_nan_pairing_end)(transaction_id id,
wifi_interface_handle iface,